--- 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.