|
| 1 | +# pi-bash-bg |
| 2 | + |
| 3 | +Makes `command &` work in pi's bash tool by detaching background processes from pipes. |
| 4 | + |
| 5 | +## Problem |
| 6 | + |
| 7 | +The bash tool pipes stdout/stderr from the spawned shell. When a command backgrounds a process with `&`, the background process inherits these pipe file descriptors and keeps them open. Node.js waits for all pipe readers to close, so the tool hangs until the background process exits. |
| 8 | + |
| 9 | +## Solution |
| 10 | + |
| 11 | +This extension intercepts bash tool calls, parses the command with [@aliou/sh](https://github.com/nicolo-ribaudo/sh) to detect background processes (`stmt.background === true`), appends background-job guidance to the bash tool description, and rewrites the command to: |
| 12 | + |
| 13 | +1. **Redirect output** to temp log files with human-readable names based on the command label, so background processes release the pipes |
| 14 | +2. **Add `disown`** to detach from job control (if not already present) |
| 15 | +3. **Append echo** reporting PID, label, and log path |
| 16 | + |
| 17 | +The agent sees something like: |
| 18 | + |
| 19 | +``` |
| 20 | +[bg] pid=12345 label=npm run dev log=/tmp/pi-bg-npm-run-dev-1.log |
| 21 | +``` |
| 22 | + |
| 23 | +It can then `cat` the log file or `kill` the PID. |
| 24 | + |
| 25 | +## Install |
| 26 | + |
| 27 | +```bash |
| 28 | +pi install pi-bash-bg |
| 29 | +``` |
| 30 | + |
| 31 | +## How it works |
| 32 | + |
| 33 | +### Simple commands |
| 34 | + |
| 35 | +```bash |
| 36 | +# Before: |
| 37 | +npm run dev & |
| 38 | +# After: |
| 39 | +npm run dev > /tmp/pi-bg-npm-run-dev-1.log 2>&1 & disown $!; |
| 40 | +echo "[bg] pid=$! label=npm run dev log=/tmp/pi-bg-npm-run-dev-1.log" |
| 41 | +``` |
| 42 | + |
| 43 | +### Compound commands (&&, ||, pipelines) |
| 44 | + |
| 45 | +Compound commands are wrapped in braces so the redirect applies to the entire background subshell, not just the last command in the chain: |
| 46 | + |
| 47 | +```bash |
| 48 | +# Before: |
| 49 | +cd /app && npm start & |
| 50 | +# After: |
| 51 | +{ cd /app && npm start; } > /tmp/pi-bg-npm-start-2.log 2>&1 & disown $!; |
| 52 | +echo "[bg] pid=$! label=npm start log=/tmp/pi-bg-npm-start-2.log" |
| 53 | +``` |
| 54 | + |
| 55 | +### Existing redirections |
| 56 | + |
| 57 | +If a simple command already redirects both stdout and stderr, the extension only adds `disown` (no log file is created): |
| 58 | + |
| 59 | +```bash |
| 60 | +# Before: |
| 61 | +node server.js > /dev/null 2>&1 & |
| 62 | +# After: |
| 63 | +node server.js > /dev/null 2>&1 & disown $!; |
| 64 | +echo "[bg] pid=$! label=node server.js" |
| 65 | +``` |
| 66 | + |
| 67 | +Compound commands are always wrapped in braces, even if their inner commands have redirections. This is necessary because the background subshell itself holds the pipe file descriptors open regardless of what its child commands do: |
| 68 | + |
| 69 | +```bash |
| 70 | +# Before: |
| 71 | +cd /app && npm start > /dev/null 2>&1 & |
| 72 | +# After: |
| 73 | +{ cd /app && npm start > /dev/null 2>&1; } > /tmp/pi-bg-npm-start-3.log 2>&1 & disown $!; |
| 74 | +echo "[bg] pid=$! label=npm start log=/tmp/pi-bg-npm-start-3.log" |
| 75 | +``` |
| 76 | + |
| 77 | +### Existing disown |
| 78 | + |
| 79 | +If the command already has `disown` after the `&`, no duplicate is added. |
| 80 | + |
| 81 | +### Bash tool description |
| 82 | + |
| 83 | +The extension appends a short background-job summary to the bash tool description, so the model sees it directly in tool metadata. |
| 84 | + |
| 85 | +## Supported patterns |
| 86 | + |
| 87 | +| Pattern | Handled | |
| 88 | +|---------|---------| |
| 89 | +| `npm run dev &` | Yes | |
| 90 | +| `cd /dir && npm start &` | Yes (wrapped in braces) | |
| 91 | +| `tail -f log \| grep error &` | Yes (wrapped in braces) | |
| 92 | +| `nohup node server.js &` | Yes | |
| 93 | +| `PORT=3000 node server.js &` | Yes | |
| 94 | +| `while true; do sleep 1; done &` | Yes (wrapped in braces) | |
| 95 | +| `(sleep 10 && echo done) &` | Yes (wrapped in braces) | |
| 96 | +| `cmd &> /dev/null &` | Yes (skips adding redirects for simple commands) | |
| 97 | +| `cmd & disown $!` | Yes (skips adding disown) | |
| 98 | +| `echo "foo & bar"` | Ignored (& inside string) | |
| 99 | +| `cmd1 && cmd2` | Ignored (no background) | |
0 commit comments