[BUG] Discord plugin: /discord:access skill writes to the default access.json, ignoring DISCORD_STATE_DIR (server.ts honors it)

Status Open
Reported on v2.1.220
Maintainer reply None cached
Activity 1 comment · opened Aug 1, 2026

What's Wrong?

server.ts correctly resolves the state directory from DISCORD_STATE_DIR:

// plugins/.../discord/0.0.4/server.ts
const STATE_DIR = process.env.DISCORD_STATE_DIR ?? join(homedir(), '.claude', 'channels', 'discord')
const ACCESS_FILE = join(STATE_DIR, 'access.json')

But the /discord:access skill that manages that file still hardcodes the default path.
skills/access/SKILL.md contains four references to ~/.claude/channels/discord/access.json
and never mentions DISCORD_STATE_DIR:

line 22: `~/.claude/channels/discord/access.json`. You never talk to Discord — you
line 31: `~/.claude/channels/discord/access.json`:
line 60: 1. Read `~/.claude/channels/discord/access.json` (handle missing file).
line 66: 1. Read `~/.claude/channels/discord/access.json`.

Because SKILL.md is the instruction file the model follows, running /discord:access inside a
session that sets DISCORD_STATE_DIR edits the shared default file rather than that
session's own. The reader and the writer disagree about which file is authoritative.

Consequence: the channel is attached to the wrong agent. Messages posted in the new channel are
delivered to whichever session uses the default state dir, and the session that was supposed to
own the channel receives nothing. Nothing errors out — it just silently routes to the wrong place.

This looks like a leftover from #38312 (server side fixed, skill side not updated).

What Should Happen?

/discord:access should operate on the access file of the current session:
$DISCORD_STATE_DIR/access.json when the variable is set, falling back to
~/.claude/channels/discord/access.json otherwise — matching server.ts.

Error Messages/Logs

No error is produced. The only visible signal is the skill reporting a group count that belongs
to the default file. In our case the session was correctly running with
DISCORD_STATE_DIR=~/.claude/channels/discord-knitpix (verified with ps eww), yet the skill
reported "now 6 groups" — the count of the default file, which had 5 before.

Observed afterwards:

~/.claude/channels/discord/access.json           groups: 7   # ← both new channels landed here
~/.claude/channels/discord-knitpix/access.json   (does not exist)
~/.claude/channels/discord-kasanezu/access.json  (does not exist)

Steps to Reproduce

  1. Create a per-agent state dir with a bot token:

``bash
mkdir -p ~/.claude/channels/discord-foo
cp ~/.claude/channels/discord/.env ~/.claude/channels/discord-foo/.env
``

  1. Start a session bound to it:

``bash
DISCORD_STATE_DIR=~/.claude/channels/discord-foo \
claude --channels plugin:discord@claude-plugins-official
``

  1. In that session, run:

``
/discord:access group add <channelId> --no-mention
``

  1. Observe:
  • ~/.claude/channels/discord-foo/access.json is not created
  • ~/.claude/channels/discord/access.json gained <channelId>
  • the channel's messages go to the default-state-dir session, not to this one

Environment

  • Claude Code 2.1.220
  • macOS 26.4.1 (Apple Silicon)
  • plugin discord@claude-plugins-official 0.0.4

Related

  • #38312 — same env var ignored in server.ts; that part is fixed, this one was missed
  • #41768 — DISCORD_STATE_DIR not forwarded to the plugin subprocess

Workaround

Patch skills/access/SKILL.md (both the plugins/cache/... and plugins/marketplaces/...
copies) to resolve the path from DISCORD_STATE_DIR before reading/writing. The patch is lost
whenever the marketplace re-syncs, so it needs to be re-applied.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗