[BUG] CLAUDE_ENV_FILE not sourced for `!`cmd`` template expansion in slash commands

Resolved 💬 1 comment Opened Apr 17, 2026 by sstraus Closed May 25, 2026

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

  1. Create a SessionStart hook that writes to CLAUDE_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');\""
      }]
    }]
  }
}
  1. 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"`
  1. 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

View original on GitHub ↗

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