[BUG] CLAUDE_ENV_FILE not sourced for `!`cmd`` template expansion in slash commands
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report
- [x] I am using the latest version of Claude Code
What's Wrong?
Environment variables written to CLAUDE_ENV_FILE by a SessionStart hook are correctly sourced for regular Bash tool calls, but are not sourced for shell commands executed via the ` !cmd ` template-expansion syntax inside slash command markdown files.
This causes any environment variable (e.g. custom IDs, cached paths, tokens) set during session start to be unavailable to template-expanded shells, forcing workarounds where the value must be passed by-value through the prompt chain instead of relying on the env.
Related but distinct:
- #27987 — env file not sourced for Bash tool calls on Windows (closed)
- #15840 — env file not provided to hooks (macOS)
- #14433 — not sourced after
/clear - #9354 —
${CLAUDE_PLUGIN_ROOT}not substituted in command markdown
None of the above cover the ` !cmd ` template-expansion case specifically.
Reproduction Steps
- Create a
SessionStarthook that writes toCLAUDE_ENV_FILE:
{
"hooks": {
"SessionStart": [{
"hooks": [{
"type": "command",
"command": "node -e \"const fs=require('fs'); if(process.env.CLAUDE_ENV_FILE) fs.appendFileSync(process.env.CLAUDE_ENV_FILE, 'export MY_TEST_VAR=hello\\n');\""
}]
}]
}
}
- Create a slash command at
.claude/commands/envtest.md:
---
description: Reproduce CLAUDE_ENV_FILE not sourced in template expansion
---
From a Bash tool call the variable is visible:
- Bash tool: `echo "bash: $MY_TEST_VAR"`
From !backtick template expansion it is NOT:
- Template: !`echo "template: $MY_TEST_VAR"`
- Start a new session, run
/envtest.
Expected Behavior
Both lines should print hello. Per the hooks documentation, env vars written to CLAUDE_ENV_FILE should persist across shell invocations spawned by Claude Code — including the ` !cmd ` template-expansion mechanism in slash commands.
Actual Behavior
- Regular Bash tool call:
bash: hello✅ - Template expansion:
template:(empty) ❌
The template-expansion shell does not source CLAUDE_ENV_FILE, so the variable is unset.
Impact
Slash-command authors who want to pass session-scoped state (unique IDs, cached paths, per-run tokens) from a SessionStart hook to a template-expanded command cannot rely on environment variables. They must pass the value by-value through the prompt chain (e.g. emit the value in prompt output and have the model re-inject it as an argument), which is race-prone when multiple slash-command invocations run concurrently.
Environment
- Claude Code version: 2.1.112
- OS: macOS (Darwin 25.4.0)
- Shell: zsh
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗