---
name: bash-tool-shell-gotchas
description: Bash-tool zsh has noclobber ON; pi --mode json hangs on stdin (fix: </dev/null); workarounds
metadata: 
  node_type: memory
  type: feedback
  originSessionId: ba4a4349-3947-4bfe-87fc-2d6e99001352
---

The Bash tool runs a zsh where `noclobber` is ON, and it is NOT set in any user rc
file (`~/.zshrc`, `~/.zshenv`, etc. — grep finds nothing). So the harness/wrapper
sets it; editing `~/.zshrc` does NOT turn it off. Symptom: `cmd > existing_file`
fails with `file exists: <path>` and writes 0 bytes.

Two recurring consequences and fixes:

1. **`pi --mode json` HANGS waiting on stdin in the Bash tool** (exit 124 on timeout,
   0 bytes, even on a fast valid model; text mode works fine). The earlier "writes to
   tty" diagnosis was wrong. Real fix: redirect `</dev/null` so pi sees EOF on stdin and
   runs non-interactively. Full working recipe (external-review skill + the one missing bit):
   `pi --model openrouter/<slug> --no-tools --no-skills -nc --system-prompt "$SYS" -p "$P" --mode json </dev/null | jq -j --unbuffered 'select(.type=="message_update" and .assistantMessageEvent.type=="text_delta") | .assistantMessageEvent.delta' | tee out.md`
   tee is correct (skill uses it); do NOT pkill -f (kills the launching shell). Slugs: verify
   with `pi --list-models | grep ^openrouter` — a bad slug ALSO hangs silently. panel_direct.py
   (HTTP direct, reads /root/.env) stays a fallback but `</dev/null` makes plain pi work.

2. **noclobber refuses `>` onto existing files.** Use `>|` to force-overwrite, or
   `rm -f` first, or have the program write the file itself (Python `Path.write_text`,
   `tee` both work; `>` redirect does not).

**Why:** wasted ~an hour chasing 0-byte panel output that looked like an auth/model
problem but was noclobber + pi-tty. **How to apply:** when a `>` redirect or a piped
CLI returns 0 bytes, suspect these two before debugging the tool itself.

Also: batching many Bash calls in one message causes cascade-cancellation — if the
first errors (e.g. the noclobber test exits 2), the rest are all cancelled. Run
diagnostics sequentially. See [[projected-grpo-rebuild-from-pseudocode]].
