[BUG] Discord plugin: /discord:access skill writes to the default access.json, ignoring DISCORD_STATE_DIR (server.ts honors it)
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 withDISCORD_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
- 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
- Start a session bound to it:
``bash``
DISCORD_STATE_DIR=~/.claude/channels/discord-foo \
claude --channels plugin:discord@claude-plugins-official
- In that session, run:
````
/discord:access group add <channelId> --no-mention
- Observe:
~/.claude/channels/discord-foo/access.jsonis not created~/.claude/channels/discord/access.jsongained<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-official0.0.4
Related
- #38312 — same env var ignored in
server.ts; that part is fixed, this one was missed - #41768 —
DISCORD_STATE_DIRnot 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.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗