[BUG] Claude code web Setup scripts: a failed script is recorded as success, its env exports don't reach agent shells, and its output is never logged
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
Cloud-environment setup scripts have three compounding defects:
A. A setup script that installs nothing is recorded as a successful init. A failed curl ... | bash exits 0 — the pipeline's exit status is bash's (empty stdin → exit 0), not curl's — and with no set -o pipefail the failure is masked. The environment manager logs "Successfully executed init script" / env_success: true and records no exit code at all.
B. Environment variables a setup script exports never reach the agent's shells. The Bash tool runs commands in a non-login, non-interactive bash -c that sources a shell snapshot instead of the profile files. The snapshot captures functions, aliases, and PATH only — no arbitrary env exports — and doesn't source ~/.profile or ~/.bashrc. So export FOO=bar in a setup script has nowhere to land.
C. Setup-script stdout/stderr is not captured in any readable log. The env-manager logs only structured lifecycle lines; the script's own output (and any curl/installer error) is discarded.
Together they compound: a failure is mislabelled a success (A), its side effects silently don't apply (B), and the evidence needed to notice either is unavailable (C).
What Should Happen?
A. A setup script that exits non-zero — or whose curl/installer fails — should be surfaced as an initialization failure, not logged as "Successfully executed init script". The exit code should be recorded explicitly (as it already is for language installs).
B. Environment variables exported by a setup script should reach the agent's shells through a supported mechanism.
C. Setup-script stdout/stderr should be persisted to a readable log and surfaced to the user, so setup-phase failures can be diagnosed.
Error Messages/Logs
Env-manager record for a setup script that installed nothing (~40 ms, no exit code):
{"msg":"Running initialization script","script_length":122}
{"msg":"Successfully executed init script"}
{"msg":"Parallel initialization completed","env_success":true}
Pipeline exit semantics that mask the failure:
$ curl -fsSL https://nonexistent-host.example/install.sh | bash; echo "exit: $?"
curl: (6) Could not resolve host: nonexistent-host.example
exit: 0
$ bash -c 'set -o pipefail; false | bash; echo "exit: $?"'
exit: 1
Env-var propagation — `export BUG_REPRO_VAR=hello` added to ~/.profile and ~/.bashrc:
bash -c (non-login, non-interactive) BUG_REPRO_VAR=[]
bash -lc (login) BUG_REPRO_VAR=[hello]
bash -ic (interactive) BUG_REPRO_VAR=[hello]
agent Bash-tool shell BUG_REPRO_VAR=[]
The shell snapshot (~/.claude/shell-snapshots/snapshot-bash-*.sh) contains
function/alias definitions and exactly one `export` (the standard PATH);
no arbitrary env exports, and it does not source ~/.profile or ~/.bashrc.
Steps to Reproduce
- Create a cloud environment with this setup script (unresolvable host, so it installs nothing):
#!/bin/bash
curl -fsSL https://nonexistent-host.example/install.sh | bash
echo "setup-script-reached-end"
- Start a session. Observe the environment manager logs (/tmp/env-manager.log,
/tmp/environment-manager.out): the init script is recorded as "Successfully
executed", env_success: true, in ~40 ms, with no exit code. (Defect A.)
- In the session, append
export BUG_REPRO_VAR=helloto ~/.profile and ~/.bashrc.
Run bash -c 'echo $BUG_REPRO_VAR' — empty. bash -lc and bash -ic — both
show "hello". The agent's own shell — empty. (Defect B.)
- grep the script's stdout marker ("setup-script-reached-end") and stderr
("Could not resolve host") across /tmp, /var/log, /root, /home — no match in
any execution log; only the agent transcript (which quotes the script). (Defect C.)
Claude Model
Not sure / Multiple models
Is this a regression?
No, this never worked
Last Working Version
_No response_
Claude Code Version
2.1.42
Platform
Anthropic API
Operating System
Ubuntu/Debian Linux
Terminal/Shell
Non-interactive/CI environment
Additional Information
Workarounds:
- A: adding
set -o pipefailto the setup script makes a failedcurl | bashabort instead of exiting 0. - B: a SessionStart hook in ~/.claude/settings.json that appends exports to $CLAUDE_ENV_FILE does reach the agent's shells — currently the only working channel. Premex maintains a one-line script to bootstrap Java and Android development environments in sandboxed environments (premex.se/android) that registers exactly such a hook to work around B.
- C: none — setup output simply isn't retained.
Suggested fixes:
- Run init scripts with
set -o pipefail, capture the real exit code, and surface non-zero as an initialization failure. - Warn when a setup script pipes a download into an interpreter and the fetch produced no output / a non-zero curl.
- Provide a supported mechanism for setup scripts to export env vars into the agent's shells (bake into the snapshot, or a file the Bash-tool shells source).
- Persist setup-script stdout/stderr to a readable log.
Environment: Claude Code on the web cloud environment, Linux x86-64. Agent Bash tool is a non-login, non-interactive bash -c child of the claude process, sourcing ~/.claude/shell-snapshots/snapshot-bash-*.sh.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗