Session-env snapshot file breaks when sourced: unquoted LS_COLORS/SSH_CONNECTION/LESSCLOSE spam 'command not found' on every Bash call

Status Fixed / completed
Reported on v2.1.206
Maintainer reply ✓ Yes — bcherny
Activity 3 comments · opened Jul 10, 2026 · closed Aug 17, 2026
💡 Likely answer: A maintainer (bcherny, collaborator) responded on this thread — see the highlighted reply below.

Bug description

Every Bash tool call in a Claude Code session (VS Code extension) prints a wall of spurious command not found / fg: %s: no such job errors to stderr before the actual command runs. It happens even for a no-op (:), confirming it fires during shell/session setup rather than being caused by anything the user typed.

Root cause

~/.claude/session-env/<session-id>/sessionstart-hook-0.sh is written as a raw KEY=VALUE dump (looks like unquoted env output — one env var per line, no shell quoting) and is apparently later sourced as a bash script to replay the session's environment into each new shell. Several completely standard env vars contain shell metacharacters that break when parsed as code instead of data:

| Var | Example value | What happens when sourced |
|---|---|---|
| LS_COLORS | rs=0:di=01;34:ln=01;36:... | Unquoted ; is a command separator. Bash parses LS_COLORS=rs=0:di=01 as a harmless assignment, then hits ;, then tries to run 34:ln=01 as a command → command not found. Repeats for every ;-delimited chunk in the value (~140 errors from one line). |
| SSH_CONNECTION | fe80::...%eth0 59598 fe80::...%eth0 22 | Unquoted spaces. Bash assigns the first token, then tries to run the bare word 59598 as a command → 59598: command not found. |
| LESSCLOSE | /usr/bin/lesspipe %s %s | Same issue, then hits bare word %s. In an interactive shell a bare %s at command position is job-control shorthand for fg %s → fg: %s: no such job. |
| SSH_CLIENT | fe80::...%eth0 59598 22 | Same as SSH_CONNECTION → another 59598: command not found. |

None of these are misconfigured — they're standard dircolors/OpenSSH/lesspipe defaults present on any Debian/Ubuntu box. The bug is in how the harness serializes and replays the env snapshot, not anything under the user's control.

Reproduction

  1. Open a repo in VS Code with the Claude Code extension, in an environment reached over SSH (so SSH_CONNECTION/SSH_CLIENT are set) with a normal dircolors-enabled shell.
  2. Ask Claude to run any Bash command, e.g. hostname.
  3. Observe ~150 lines of command not found / fg: %s: no such job on stderr before the command's real output.
  4. Inspect ~/.claude/session-env/<session-id>/sessionstart-hook-0.sh — it's a plain unquoted KEY=VALUE dump containing the offending lines.

Expected behavior

No stderr noise from internal session-state plumbing. Any env var value, regardless of content, should round-trip safely.

Suggested fix

When generating sessionstart-hook-0.sh (or wherever it's consumed), either:

  • Serialize with export -p / declare -p output (already properly shell-quoted), or
  • Quote each value when writing, e.g. printf '%s=%q\n' "$k" "$v", or
  • Parse the file as data instead of sourcing it as code: while IFS='=' read -r k v; do export "$k=$v"; done < "$file".

Environment

  • Claude Code CLI/extension: 2.1.206 (claude-vscode entrypoint, Agent SDK 0.3.206)
  • OS: Linux (Debian/Ubuntu-based), bash
  • dircolors: uutils coreutils 0.8.0 (produces correctly-quoted output itself — confirmed not the source of the bug)

View original on GitHub ↗

3 Comments

bcherny collaborator · 1 month ago

Tried to reproduce this on Linux with the released 2.1.233 build: fresh config dir, a SessionStart hook (echo hi), and LS_COLORS='rs=0:di=01;34:ln=01;36', LESSCLOSE='/usr/bin/lesspipe %s %s', SSH_CONNECTION='1.2.3.4 5 6.7.8.9 22' exported before launch, then ran : with the Bash tool.

Result: no errors at all, and session-env/<session-id>/ stayed empty — Claude Code never wrote a sessionstart-hook-0.sh on its own. That file is only populated by what your hook writes into $CLAUDE_ENV_FILE, and its contents then run as a bash preamble before each Bash command. When I changed the hook to env >> "$CLAUDE_ENV_FILE", I got your exact symptoms (34:ln=01: command not found, fg: %s: no such job, ...).

So an unquoted env-style dump in that file is the culprit, but it isn't Claude Code writing it. The docs recommend writing export statements, or an export -p before/after diff (which quotes values correctly): https://code.claude.com/docs/en/hooks#persist-environment-variables

Could you share (redact values as needed):

  • your SessionStart hook config from every settings scope (~/.claude/settings.json, project .claude/settings.json and settings.local.json, managed settings), and
  • the contents of ~/.claude/session-env/<session-id>/sessionstart-hook-0.sh?

If a hook or wrapper there is dumping raw env output, switching it to export -p-style output fixes this.

🤖 Generated with Claude Code

github-actions[bot] · 1 month ago

We weren't able to reproduce this. Could you provide steps to trigger the issue — what you ran, what happened, and what you expected? This issue will be closed automatically if there's no activity within 7 days.

github-actions[bot] · 8 days ago

This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.