[FEATURE] Support variable substitution in env block of settings.json
Preflight Checklist
- [x] I have searched existing requests and this feature hasn't been requested yet
- [x] This is a single feature request (not multiple features)
Problem Statement
The env block in ~/.claude/settings.json treats values as literal strings, so it's not possible to reference other environment variables. This makes it awkward to share settings across machines (where absolute paths differ) and, more importantly, impossible to augment variables like PATH — any value I set replaces the inherited one rather than prepending to it. In practice I end up either hardcoding machine-specific absolute paths or giving up on using the env block for anything that depends on the user's existing environment.
Proposed Solution
Expand $VAR / ${VAR} references inside env values when Claude Code loads settings.json. Substitution should see both the process environment and keys already defined earlier in the same env block, so entries can build on each other:
{
"env": {
"MY_TOOL_HOME": "$HOME/.mytool",
"PATH": "${MY_TOOL_HOME}/bin:${PATH}"
}
}
After expansion, PATH would be prepended with ~/.mytool/bin instead of clobbered, and MY_TOOL_HOME would resolve per user. Unknown variables could either expand to empty (shell-style) or be left literal — either is fine as long as it's documented.
Alternative Solutions
- Hardcoding absolute paths per machine and keeping separate
settings.jsonfiles — works but doesn't travel. - Wrapping
claudein a shell script that exports the variables before launch — works but defeats the point of having anenvblock insettings.json. - Using a hook to mutate the environment — heavier than needed for static config.
Priority
Medium - Would be very helpful
Feature Category
Configuration and settings
Use Case Example
- I use Claude Code on two machines with different home directories and different locations for a local toolchain I want on
PATH. - I'd like a single
~/.claude/settings.json(checked into my dotfiles) that works on both. - With substitution I can write
"PATH": "${HOME}/.mytool/bin:${PATH}"once and have it resolve correctly on each machine, without clobbering thePATHI already have from my shell. - Today I either maintain per-machine copies of
settings.jsonor skip theenvblock entirely for anything path-related.
Additional Context
Most config systems that expose an env block (docker-compose, systemd unit files, direnv, VS Code terminal.integrated.env.*) support some form of variable expansion, so the ergonomics would match what users already expect.
Related / prior art:
- #43693 — requests
${VAR}expansion in the MCP serverenvblocks of user-scope.claude.json. Same substitution pattern, sibling config file; this issue asks for the equivalent insettings.json's top-levelenvblock. - #2065 — established
${VAR}expansion for project-scope.mcp.json, which is the precedent cited in #43693. - #23642 — narrower request for 1Password
op://secret references in thesettings.jsonenv section; general variable substitution would compose with or subsume that use case. - #46577 — env substitution in HTTP hook
urlfield; different location but same underlying gap.
This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗