Feature Summary
Let users extend the environment allowlist that Emdash applies when it spawns an agent (or opt in to inheriting the login shell environment), so credentials that MCP configs reference as ${VAR} reach the agent.
Problem or Use Case
buildAllowlistedAgentEnv (packages/core/src/primitives/agent-env/api/index.ts) builds the agent process env from fixed lists (AGENT_ENV_VARS, GLOBAL_AGENT_ENV_VARS, DISPLAY_ENV_VARS, plus PATH/HOME/TMPDIR/SSH_AUTH_SOCK). Nothing else from the host environment is passed through, and there is no setting to add names.
Our team repo generates .mcp.json / .cursor/mcp.json / .codex/config.toml with entries like "Authorization": "Bearer ${SUPABASE_ACCESS_TOKEN}" and bearer_token_env_var = "LINEAR_PAT". Those variables live in each developer's ~/.zshenv. In a terminal, Claude Code and Codex connect fine. Spawned from Emdash 1.2.2, every ${VAR} expands to an empty string and all credentialed MCP servers fail with 401 (JWT could not be decoded, Authorization header is badly formatted, ...). The Bash tool inside the agent still sees the variables because it runs through the user's zsh, which makes the failure confusing to diagnose.
The allowlist is a sensible default for not leaking secrets into worktrees, but the whitelisted set is vendor keys only. Anyone who wires MCP servers through env-referenced tokens hits this.
Proposed Solution
One of:
- A host setting (and
.emdash.json key) with extra env var names to pass through, e.g. agentEnvPassthrough: ["SUPABASE_ACCESS_TOKEN", "LINEAR_PAT"], merged into the allowlist by name only. Values are never stored by Emdash.
- An opt-in toggle "inherit login shell environment" that runs the provider through
$SHELL -lc (or sources the user's shell env) before exec.
Alternatives Considered
- Per-provider "Environment variables" in Settings works but requires pasting every secret value into Emdash, per developer, and keeping it in sync on rotation.
- Workaround we are using now:
.emdash.json shellSetup: "[ -f \"$HOME/.zshenv\" ] && . \"$HOME/.zshenv\" || true". Because a non-empty shellSetup makes resolvePosixSpawn wrap the agent in <shell> -c "<setup> && <agent>", the sourced variables reach the agent. It works, but it is undocumented behaviour of a field meant for nvm use, and it silently re-opens the whole environment rather than a named set.
emdash Version
v1.2.2 (macOS 26.6, zsh)
Feature Summary
Let users extend the environment allowlist that Emdash applies when it spawns an agent (or opt in to inheriting the login shell environment), so credentials that MCP configs reference as
${VAR}reach the agent.Problem or Use Case
buildAllowlistedAgentEnv(packages/core/src/primitives/agent-env/api/index.ts) builds the agent process env from fixed lists (AGENT_ENV_VARS,GLOBAL_AGENT_ENV_VARS,DISPLAY_ENV_VARS, plus PATH/HOME/TMPDIR/SSH_AUTH_SOCK). Nothing else from the host environment is passed through, and there is no setting to add names.Our team repo generates
.mcp.json/.cursor/mcp.json/.codex/config.tomlwith entries like"Authorization": "Bearer ${SUPABASE_ACCESS_TOKEN}"andbearer_token_env_var = "LINEAR_PAT". Those variables live in each developer's~/.zshenv. In a terminal, Claude Code and Codex connect fine. Spawned from Emdash 1.2.2, every${VAR}expands to an empty string and all credentialed MCP servers fail with 401 (JWT could not be decoded,Authorization header is badly formatted, ...). The Bash tool inside the agent still sees the variables because it runs through the user's zsh, which makes the failure confusing to diagnose.The allowlist is a sensible default for not leaking secrets into worktrees, but the whitelisted set is vendor keys only. Anyone who wires MCP servers through env-referenced tokens hits this.
Proposed Solution
One of:
.emdash.jsonkey) with extra env var names to pass through, e.g.agentEnvPassthrough: ["SUPABASE_ACCESS_TOKEN", "LINEAR_PAT"], merged into the allowlist by name only. Values are never stored by Emdash.$SHELL -lc(or sources the user's shell env) before exec.Alternatives Considered
.emdash.jsonshellSetup: "[ -f \"$HOME/.zshenv\" ] && . \"$HOME/.zshenv\" || true". Because a non-emptyshellSetupmakesresolvePosixSpawnwrap the agent in<shell> -c "<setup> && <agent>", the sourced variables reach the agent. It works, but it is undocumented behaviour of a field meant fornvm use, and it silently re-opens the whole environment rather than a named set.emdash Version
v1.2.2 (macOS 26.6, zsh)