diff options
Diffstat (limited to 'skills/command-composition-rules.md')
| -rw-r--r-- | skills/command-composition-rules.md | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/skills/command-composition-rules.md b/skills/command-composition-rules.md new file mode 100644 index 0000000..aa218e7 --- /dev/null +++ b/skills/command-composition-rules.md @@ -0,0 +1,54 @@ +--- +name: command-composition-rules +description: The terminal has no shell: what is refused, what works, and how to verify a result that looks plausible +tags: [terminal, shell, composition, safety, agent] +category: system +--- +## The rule + +This terminal does not spawn a shell. The line is split into argv and handed to **one** command +handler. \`;\`, \`&&\`, \`||\` and redirection are not interpreted. Since v4.6.58 they are refused: + + wc -l file && grep -c pattern file + -> warning: No shell here — \`&&\` is not interpreted. Run one command per line. + +## Why the refusal exists + +Before v4.6.58 \`&&\` failed silently: the right-hand tokens were appended to the left command's +argv, unknown tokens were dropped, and valid flags were absorbed. + + wc -l f && grep -c x f -> "42 42" (grep's -c became a wc flag) + wc -l f && grep -n x f -> "42" (-n is not a wc flag, so it was dropped) + wc -c a b -> "34138 a" (second path dropped, exit code 0) + +The worst case was an empty pattern: \`grep "" file\` matches every line and returns a plausible +count. A clean exit code is not evidence that the command did what you asked. + +## What works + +- One command per call. Two files means two calls, unless the command documents multiple paths. +- \`wc\` accepts multiple paths since v4.6.58: \`wc -c a b\` prints one line per file plus \`total\`. +- A single \`cmd | cmd\` pipeline works in the **interactive** terminal. It does **not** work through + the AI \`run_command\` tool, which bypasses the pipe splitter — there \`|\` is refused too. +- Operators inside quotes are untouched: \`echo "a && b"\` prints \`a && b\`. + +## Verifying your own result + +- Ask for two things, count that you got two lines back. +- A suspiciously round or empty count means a broken probe, not a clean system. +- \`ls\` prints text since v4.6.57 (it used to render chips only, so captured output was empty); + \`list_files\` remains the reliable enumerator. +- An invalid \`grep\` pattern now returns \`grep: invalid pattern: …\` and does not enter the error + ledger — if you see a pattern exception, something regressed. + +## Pitfalls + +- A refusal is not a failed command: nothing ran. Split it and run both halves. +- \`;\` used to fail loudly ("No such file: x;"). That loudness is gone in favour of an explicit + refusal — do not "fix" a refusal by re-joining the commands differently. +- \`>\` is handled by \`echo\` only (\`echo hi > file\`). It is not a general redirect. + +## History + +Replaces \`terminal-commands-silently-failing\` and \`command-composition-rules\`, merged 2026-10-23 +after the behaviour itself was fixed in v4.6.58.
\ No newline at end of file |