Shell snapshot enables set -o monitor and set -o onecmd in every Bash tool shell (grep "on" matches option names)
Summary
The shell snapshot captures shell options with:
set -o | grep "on" | awk '{print "set -o " $1}' | head -n 1000 >> "$SNAPSHOT_FILE"
grep "on" is meant to keep options whose state is on, but it matches the substring anywhere in the line. Two option names contain "on": monitor and onecmd. Both are written to the snapshot as set -o monitor and set -o onecmd even when they are off, so every Bash tool shell runs with job control and onecmd enabled.
This appears to be the root cause of #47689 and #19057 (see also #17534 and #16231), which report set -o onecmd in snapshots on shells where it is off.
Reproduction
In a clean bash:
$ env -i bash --norc --noprofile -c 'set -o | grep -E "^(monitor|onecmd)\s"'
monitor off
onecmd off
$ env -i bash --norc --noprofile -c 'set -o | grep "on" | awk "{print \"set -o \" \$1}"'
set -o braceexpand
set -o hashall
set -o interactive-comments
set -o monitor
set -o onecmd
In Claude Code, ~/.claude/shell-snapshots/snapshot-bash-*.sh contains set -o monitor and set -o onecmd, and echo $- in a Bash tool call prints hmtBc (m is monitor, t is onecmd).
Effects
monitorin a non-interactive shell puts each background job in its own process group, and bash prints job-status lines such as[1]+ Done sleep 0.1into tool output.onecmd: the linked issues report Bash tool calls returning no output.
Suggested fix
Match the state column instead of the substring:
set -o | awk '$2 == "on" {print "set -o " $1}' | head -n 1000 >> "$SNAPSHOT_FILE"
With this change, the clean-shell output above contains only braceexpand, hashall, and interactive-comments.
Environment
- Claude Code 2.1.283