cap makes common shell commands and pipelines more efficient for coding agents.
It uses native implementations for supported command shapes.
It runs other commands with their normal shell behavior.
Commands keep the caller's priority. Memory use and CPU load do not delay, pause, or kill commands. Cap does not stop other processes to reclaim memory. Use an explicit timeout flag when a command needs a time limit.
Run cargo test -p cap for the complete local test gate.
Run cargo test -p cap --test behavior_cap_unrestricted_shell for direct-run,
legacy-config, priority, and explicit-timeout checks.
Run cargo bench -p cap --bench command_resources for efficiency measurements.
The recorded benchmarks in BENCHMARKS.md are historical measurements.
A promise with no gate under it is not claimed.
Nothing reads the tables below. The capability gate that validated their
shape was deleted with the aw binary, so the shape is convention now and
the commands named in each row are the only part that runs.
| Capability | Root WI | Notes |
|---|---|---|
| Agent Hook Installation | - | cargo test -p cap --test behavior_cap_agent_hook_installation |
| Standard Agent CLI Operations | #477 | cargo test -p cap --test behavior_cap_standard_agent_cli_operations |
| Efficient Shell Execution | - | cargo test -p cap --test behavior_cap_unrestricted_shell |
| Daemon Lifecycle and Status | - | cargo test -p cap --test behavior_cap_daemon_lifecycle_and_status |
| Config and Logging | - | cargo test -p cap --test behavior_cap_config_logging_and_reap_policy |
cap on installs and cap off removes global PreToolUse hook snippets for
Claude Code, Codex CLI, and AGY, preserving unrelated user configuration.
Claude/Codex route Bash through cap; AGY applies the destructive-command guard
to run_command. Agent hooks deny destructive commands they cannot prove stay
inside the current Git workspace; cap status reports global hook state
alongside optional daemon status.
- Root WI: none; this capability predates the tracker.
- Surfaces: CLI:
cap on+cap off+cap status+cap hook+cap run '<command string>'- Global agent-hook lifecycle, status, and adapter routing.; AgentHook:Claude Code PreToolUse+Codex CLI PreToolUse+AGY PreToolUse- Global snippets preserve unrelated user config; Claude/Codex rewrite Bash through cap and AGY applies the destructive-command guard torun_command. - Gate — behavior:
cap- global three-agent hook installation, command-string rewrite adapters, destructive-command guard, recursion prevention, and fail-open routing behavior - Gate:
cargo test -p cap --test behavior_cap_agent_hook_installation - Gate:
cargo test -p cap --test behavior_cap_agent_hook_installation
| Work Root | Kind | WI | Gate / Evidence |
|---|---|---|---|
| Claude, Codex, and AGY hook installation | epic | - | cargo test -p cap --test behavior_cap_agent_hook_installation |
| Hook payload rewrite adapters | epic | - | cargo test -p cap --test behavior_cap_hook_payload_rewrite_adapters |
Cap exposes the repo-wide standard agent commands through the shared cli-std
implementation: llm for offline guidance, upgrade for cap release updates,
and issue for tracker search/view/create with app:cap diagnostics.
- Root WI: #477
- Surfaces: CLI:
cap llm+cap upgrade+cap issue search/view/create+cap report-issue- Repo-wide agent-facing self-documentation, self-update, and diagnostics-rich issue filing throughcli-std;report-issueis a deprecated compatibility alias for older issue text. - Gate — behavior:
cap- standard CLI command registration, offline LLM docs, release upgrade routing, and project-scoped issue diagnostics - Gate:
cargo test -p cap --test behavior_cap_standard_agent_cli_operations - Gate:
cargo test -p cap --test behavior_cap_standard_agent_cli_operations - Gate:
cargo build -p cap --features release - Evidence:
cargo test -p cap --test behavior_cap_standard_agent_cli_operationscargo test -p cap --test behavior_cap_standard_agent_cli_operations
cap run selects native implementations for supported commands and pipelines.
Other commands run directly with inherited input, output, and environment.
The direct path does not start or contact the daemon.
An old daemon cannot apply resource limits to these commands.
--timeout <secs> limits elapsed run time for an external command.
--idle-timeout <secs> stops an external command after that many seconds
without observed CPU progress.
Both flags are off when omitted. An explicit 0 also disables the trigger.
These flags use SIGTERM, a grace period, and then SIGKILL if needed.
They return structured timeout diagnostics.
Native replacements keep their existing execution path.
- Root WI: none; this capability predates the tracker.
- Surfaces:
cap run '<command string>',cap run -- <argv...>,cap <passthrough...>,cap --trace-routing <command...>, andcap explain [--json] -- <argv...>. - Gate — behavior: command output, errors, exit status, shell fallback, direct execution without resource limits, and explicit external-command timeouts.
- Gate — efficiency: CPU time and peak resident memory measurements for native replacements.
- Gate:
cargo test -p cap --test behavior_cap_unrestricted_shell - Gate:
cargo test -p cap --test behavior_cap_tool_routing - Gate:
cargo test -p cap --test behavior_cap_command_replacement_parity - Gate:
cargo test -p cap --lib command_planner - Gate:
cargo bench -p cap --bench command_resources
The daemon remains available for clients that register command leases. A lease is a record of a running command. The daemon records status and enforces requested timeouts. It has no memory or CPU limits.
cap status and cap ps show agent hooks and leases registered with the daemon.
Normal direct commands do not register with the daemon.
cap wait is a compatibility command. It returns success at once.
- Root WI: none; this capability predates the tracker.
- Surfaces:
cap daemon,cap status,cap ps,cap ping, andcap wait. - Gate:
cargo test -p cap --test behavior_cap_daemon_lifecycle_and_status - Gate:
cargo test -p cap --test behavior_cap_cli_status_and_wait_surfaces - Gate:
cargo test -p cap --lib throttle
Cap reads local configuration and can append JSONL records for external commands. JSONL stores one JSON record per line. Old resource-control keys remain readable for upgrade compatibility. They do not control command admission, priority, memory, or CPU use.
- Root WI: none; this capability predates the tracker.
- Surfaces:
cap config,~/.cap/config.toml, and the JSONL run log. - Gate:
cargo test -p cap --test behavior_cap_config_logging_and_reap_policy - Gate:
cargo test -p cap --test behavior_cap_run_log_persistence - Gate:
cargo test -p cap --test behavior_cap_unrestricted_shell
Coding agents run many short shell commands. Repeated shell and process startup can cost more than the work itself. Cap reduces that cost with native commands and supported pipeline fusion. Pipeline fusion runs several command stages in one process.
Build + install, then run cap on:
# 1. build & put `cap` on your PATH (e.g. ~/.local/bin)
CAP_INSTALL="$HOME/.local/bin" ./build.sh debug
# 2. enable the PreToolUse hook in your agents (user-global)
cap on # enables Claude Code, Codex CLI, and AGY globallycap on with no arguments registers global hooks in
~/.claude/settings.json, ~/.codex/config.toml, and AGY's global hooks
configuration (~/.gemini/config/hooks.json, or its existing legacy path).
Claude/Codex Bash commands are transparently rewritten to:
/abs/path/to/cap run '<original Bash command>'
The hook uses cap's absolute path (not a bare cap), so it works
regardless of the agent shell's PATH. It does not decide whether find,
grep, pipes, or any other command should be optimized. That decision belongs
inside cap.
Standard agent commands:
| Command | Purpose |
|---|---|
cap llm [--topic <topic>] [--format md|json] |
Offline self-documentation for agents. |
cap upgrade [--version <tag>] [--check] |
Self-update from cap@* GitHub releases through cli-std. |
cap issue search [query] / view <n> / create [--title <t>] [message...] |
Search, read, and file app:cap issues with build diagnostics. |
cap report-issue --dry-run ... |
Deprecated compatibility alias for older automation; prefer cap issue create. |
Cap's planner owns automatic command replacement. It preserves the familiar command shape while selecting native implementations for safe shell-free subsets. Tiny safe workloads are still allowed to use cap's native path: the fixed process overhead is acceptable for interactive agent use, and keeping the same path warm matters more than winning a micro-benchmark. Unknown, risky, or shell-sensitive workloads still stay on the original command path. Resource benchmarks remain a regression and capacity signal, but they no longer decide whether a small safe same-name command is admitted to the native path.
Hook boundary:
| Layer | Responsibility |
|---|---|
| Agent Bash hook | Receives the Bash tool's command string and rewrites it to cap run '<original>'. It should stay thin: empty-command and recursion prevention only. |
cap run "<command string>" |
Owns command-string wrapping. A resident light-shell session captures the current cwd/env, attempts conservative in-process native stages for proven shell-free commands and selected fused pipelines, and dynamically falls back to bash -c <original> for redirects, unsupported pipes, globs, shell variables, shell builtins, and unproven command shapes. cd <dir> && <tail> is now recognized as a native-plannable prefix when <tail> alone is native-plannable (the resolved <dir> becomes a per-invocation cwd override for the re-planned tail); any other cd-involving shape, or a <tail> that isn't independently native-plannable, still falls back to bash -c <original> unchanged. |
cap run -- <argv...> |
Manual explicit argv mode. It skips shell-string parsing and plans the exact argv the user supplied. |
| cap command planner | Owns same-name native dispatch decisions, behavior parity, and fallback behavior. |
For example, the hook emits cap run 'find . -type f -name "*.txt"'; cap
parses that string internally and can run the same native find replacement as
cap find . -type f -name "*.txt". For an unsupported pipe such as
find . -type f | sort | sed -n '1,10p', cap detects shell syntax and wraps the
original string as bash -c internally so the shell keeps pipe behavior. The
resident layer is an optimizer boundary, not a sandbox or replacement shell:
unsupported syntax must delegate to Bash rather than fail as command-not-found.
Session queueing is opt-in through CAP_SESSION_ID. When it is set, cap can
queue profiled no-observe side effects and return job metadata immediately;
the first slice only queues simple touch <path...> commands. Observe commands
such as ls, cat, grep, and find act as same-session barriers: they wait
for earlier queued jobs before returning their own result, and if a prior job
failed they report that job id and stderr instead of hiding the cause behind
the observe command. Without CAP_SESSION_ID, or for unknown/risky command
strings, cap run keeps the existing synchronous behavior.
Active same-name replacements are conservative native fast paths:
| Command | Replaced subset | Notes |
|---|---|---|
true, false |
any args | In-process exit primitives. |
pwd |
no flags | Prints cap's current working directory. |
echo |
plain args or echo -n with non-option args |
Joins args with spaces; option-sensitive forms such as -e stay original. |
printf |
exact %s or %s\n format with string args; one no-conversion literal format arg with \\, \n, \t, or \r escapes |
Narrow string/literal emitter; conversion formats and unsupported escapes stay original. |
seq |
one, two, or three integer args without flags; nonzero step | Narrow integer range generator. |
whoami |
no flags | Prints the effective user name. |
id |
no flags, or exact -u, -un, -g, -gn, -G, or -Gn |
Effective uid/gid, supplementary group-list, and default identity summary lookups; unsupported flags stay original. |
uname |
no flags or exact -s, -n, -r, -v, -m, -p, -a |
Narrow utsname and processor field rendering. |
hostname |
no args | In-process kernel hostname output; flags and hostname mutation stay original. |
test, [ |
unary file/string predicates, string equality/inequality, integer comparisons, optional leading !; [ requires trailing ] in argv mode |
Narrow predicate evaluator; compound expressions and shell-string [ ... ] stay original. |
basename |
one path plus optional suffix | Simple path primitive. |
dirname |
one path | Simple path primitive. |
ls |
simple ls -1 / ls -a / ls -A over one path |
Directory listing; unsupported long/options stay original. |
cat |
regular file arguments without flags | Streams regular files in process. |
head |
default lines, positive -n <n> or -c <n> over one file or stdin with no file operand |
Simple line/byte windows; zero counts stay original on macOS. |
tail |
default lines, -n <n>, or -c <n> over one file or stdin with no file operand |
Simple line/byte windows, including zero-count success. |
mkdir |
plain paths or mkdir -p <path...> |
Simple directory creation. |
touch |
plain paths without flags | Create/update path timestamps. |
uniq |
one input file or stdin with no file operand; exact uniq -c <large NUL-free regular file> |
Adjacent duplicate filtering; counted mode keeps small, binary, and stdin inputs on the original command. |
find |
simple root plus optional `-type f | dand-name ` |
du |
du -sk <root> |
Includes stdout-discard fast path; missing-root errors are parity-tested. |
sort |
one regular file or stdin with no file operand in a C/POSIX collation locale |
Buffered bytewise line sorting; locale-aware sort invocations stay original. |
nl |
exact nl -ba <large regular file> |
Numbers every input record with BSD default width and tab separator; small files and other options stay original. |
rev |
exact rev <large valid-UTF-8 regular file> in a UTF-8 locale |
Reverses Unicode characters within each record; non-UTF-8 locales, invalid UTF-8, small files, stdin, and options stay original. |
paste |
exact paste <two or three regular files totaling at least 1 MiB>, paste -d<one ASCII delimiter> <two or three regular files totaling at least 1 MiB>, or serial paste -s [-d<one ASCII delimiter>] <one regular file of at least 1 MiB> |
Joins corresponding records or serializes one file with the default tab or one explicit delimiter; small inputs, stdin, four or more parallel inputs, multi-file serial mode, delimiter lists, and other options stay original. |
comm |
exact comm -12 <two sorted regular files totaling at least 1 MiB> in a C/POSIX collation locale |
Streams the common sorted records (including duplicates) with standard final-newline output; other column selections, options, locales, small inputs, and stdin stay original. |
join |
exact join -t<one ASCII delimiter> <two sorted regular files totaling at least 1 MiB> (or -t <delimiter>) in a C/POSIX collation locale |
Streams matching record groups, preserving duplicate-key cross products and empty fields; the default whitespace grammar, custom key fields/output lists, options, other locales, small inputs, and stdin stay original. |
expand |
exact expand <large 7-bit-ASCII regular file> |
Expands default 8-column tab stops; options, small files, stdin, and high-bit bytes stay original. |
fold |
exact fold <large printable-ASCII regular file>, fold -w <positive> <large printable-ASCII regular file>, or fold -w<positive> <large printable-ASCII regular file> |
Wraps fixed byte columns (default 80); small files, whitespace folding, controls, non-ASCII, stdin, and other options stay original. |
unexpand |
exact unexpand <large printable-ASCII regular file> or unexpand -a <large printable-ASCII regular file> |
Contracts default 8-column tab stops, at line starts or across all spaces with -a; tabs, controls, non-ASCII, small files, stdin, and other options stay original. |
cut |
one regular file or stdin with no file operand, using single -f <field> and optional single-byte -d <char> delimiter; exact contiguous -f<start>-<end> or an ascending comma-separated list of 2–32 fields over a large regular file; exact -c <start>-<end>, -c <start>-, or -c -<end> (including attached forms) over a large ASCII regular file |
Single-field extractor plus selected field and character ranges; field ranges/lists on small files, descending/repeated or over-32 field lists, character ranges on small/non-ASCII inputs, and byte/char/suppress forms stay original. |
tr |
ASCII byte translate sets such as a-z A-Z, exact [:lower:]/[:upper:]/[:digit:] sets, tr -d <set>, or direct tr -s <set> |
Streaming stdin transformer; squeeze preserves repeat state across input buffers. Other classes, escapes, complement, combined flags, and padded sets stay original. |
sed |
sed -n <start>,<end>p <file> or sed s/<literal>/<replacement>/[g] <file> |
Ranged line printing and one-file literal substitution; regex, escaped, capture, and other flag forms stay original. |
grep |
literal grep <pattern> over stdin, literal grep <pattern> <file> over one regular file, grep -F <pattern> <large-file>, grep -Fx / grep -xF <non-empty pattern> <large-file>, grep -Fn / grep -nF <pattern> <large-file>, grep -Fv / grep -vF <pattern> <large-file>, grep -Fl / grep -lF <pattern> <large-file>, ASCII-only grep -Fi / grep -iF <pattern> <large-file>, and recursive literal grep -R <pattern> <root> subset |
Large fixed-string scans use cap's in-tree BMH search over a mapped regular text file; small, NUL-bearing, or unmappable inputs execute the original grep. Case-insensitive fixed-string mode requires an ASCII pattern and file so locale semantics remain exact. Stdin/single-file grep emits matching lines without path prefixes; recursive grep preserves path-prefixed output. No-match and missing-root behavior are parity-tested. |
wc |
default line/word/byte counts or wc -l/-c/-w, over stdin or regular files |
Unsupported options and non-file operands stay original. |
awk |
exact /NEEDLE/ { c++ } END { print c }; exact END { print NR } / END{print NR} over a large regular file; whitespace variants of { print $<field> } and /NEEDLE/ { print $<field> }; -F<one non-whitespace byte> fixed-field extraction over a large regular file; and -F<one non-whitespace byte> '{ print $<field>, $<field> }' over a large regular file |
Narrow counted-match, record-count, and fixed-field scanners; small files/stdin, regex/multi-byte separators, custom output separators, and general awk language stay original. |
xargs |
exact xargs, xargs echo, xargs -n <positive> [echo] / xargs -n<positive> [echo], and xargs wc -l |
Batches stdin tokens, emits fixed-size token batches, or batches stdin path lists in-process; other xargs options stay original. |
which |
one or more command names, optionally with -a |
PATH executable lookup matching Bash /usr/bin/which stdout and quiet misses; -a scans all PATH matches. |
command |
exact command -v <name...> |
Bash-style shell word and PATH lookup; other command forms stay original. |
env |
no args | Prints the inherited environment for same-name/direct command-string execution; assignment, option, and command wrapper forms stay original. |
printenv |
no args or one non-option name | Prints the inherited environment or a single value; flags and multi-name platform-specific forms stay original. |
Active fused pipeline replacements:
Pipelines containing sort use the native path only in a C/POSIX collation locale; other locales keep the original shell pipeline.
| Command string | Replacement behavior |
|---|---|
| `echo <args...> | wc -l/-c/-w` |
| `echo [-n] <args...> | head -n ` |
| `echo [-n] <args...> | tail -n ` |
| `echo [-n] <args...> | tr ` |
| `echo [-n] <args...> | awk '{ print $ }' [ |
| `echo [-n] <args...> | xargs echo` |
| `echo [-n] <args...> | xargs -n [echo]` |
| `echo [-n] <paths...> | xargs wc -l` |
| `xargs [echo] | wc -l` |
| `xargs -n [echo] | wc -l` |
| `xargs [echo] | grep [ |
| `xargs -n [echo] | grep [ |
| `grep | ...` |
| `printf | ...` |
| `printf '%s\n' <args...> | wc -l/-c/-w` |
| `printf '%s\n' <args...> | head -n ` |
| `printf '%s\n' <args...> | tail -n ` |
| `printf '%s\n' <args...> | awk '{ print $ }' [ |
| `printf '%s\n' <args...> | grep ` |
| `printf '%s\n' <args...> | grep |
| `printf '%s\n' <args...> | grep |
| `printf '%s\n' <args...> | grep |
| `printf '%s\n' <args...> | grep |
| `printf '%s\n' <args...> | grep |
| `printf '%s\n' <args...> | grep |
| `printf '%s\n' <args...> | grep |
| `printf '%s\n' <args...> | grep |
| `printf '%s\n' <args...> | grep |
| `printf '%s\n' <args...> | grep |
| `printf '%s\n' <args...> | grep |
| `printf '%s\n' <args...> | grep |
| `printf '%s\n' <args...> | tr ` |
| `printf '%s\n' <args...> | sort` |
| `printf '%s\n' <args...> | sort |
| `printf '%s\n' <args...> | sort |
| `printf '%s\n' <args...> | sort |
| `printf '%s\n' <args...> | sort |
| `printf '%s\n' <args...> | sort |
| `printf '%s\n' <args...> | sort |
| `printf '%s\n' <args...> | sort |
| `printf '%s\n' <args...> | sort |
| `printf '%s\n' <paths...> | sort |
| `printf '%s\n' <args...> | xargs echo` |
| `printf '%s\n' <args...> | xargs -n [echo]` |
| `printf '%s\n' <paths...> | xargs wc -l` |
| `seq | wc -l/-c/-w` |
| `seq | head -n ` |
| `seq | tail -n ` |
| `seq | sort` |
| `seq | sort |
| `seq | sort |
| `seq | sort |
| `seq | sort |
| `seq | sort |
| `seq | sort |
| `seq | sort |
| `seq | sort |
| `seq | grep ` |
| `seq | grep |
| `seq | grep |
| `seq | grep |
| `seq | grep |
| `seq | grep |
| `seq | grep |
| `seq | grep |
| `seq | grep |
| `seq | grep |
| `seq | grep |
| `seq | grep |
| `seq | grep |
| `seq | xargs echo` |
| `seq | xargs -n [echo]` |
| `yes [word] | head -n ` |
| ` | wc -l` |
| ` | head -n ` |
| ` | tail -n ` |
| ` | sort` |
| ` | xargs echo` |
| ` | xargs wc -l` |
| ` | grep ` |
| ` | grep |
| `sed -n p | ...` |
| `sed -n p | grep |
| `cat | sed -n p` |
| `cat | sed -n p |
| `cat | sed -n p |
| `awk '{ print $ }' | ...` |
| `cat | awk '{ print $ }'` |
| `cat | awk '{ print $ }' |
| `cat | awk '{ print $ }' |
| `cat | awk '/NEEDLE/ { print $ }'` |
| `cat | awk '/NEEDLE/ { print $ }' |
| `cut -d -f [] | ...` |
| `cut -d -f [] | grep |
| `cat | cut -d -f |
| `cat | cut -d -f |
| `cat | tr |
| `cat | tr |
| `ls [-1 | -a |
| `ls [-1 | -a |
| `ls [-1 | -a |
| `ls [-1 | -a |
| `ls [-1 | -a |
| `ls [-1 | -a |
| `ls [-1 | -a |
| `ls [-1 | -a |
| `ls [-1 | -a |
| `ls [-1 | -a |
| `ls [-1 | -a |
| `ls [-1 | -a |
| `ls [-1 | -a |
| `ls [-1 | -a |
| `ls [-1 | -a |
| `ls [-1 | -a |
| `ls [-1 | -a |
| `ls [-1 | -a |
| `ls [-1 | -a |
| `sort | uniq` |
| `sort | uniq |
| `sort | uniq |
| `sort | uniq |
| `sort | grep |
| `sort | head -n ` |
| `sort | tail -n ` |
| `sort | wc -l` |
| `sort | xargs echo` |
| `sort | xargs wc -l` |
| `head -n [] | wc -l` |
| `head -n [] | head -n ` |
| `head -n [] | tail -n ` |
| `head -n [] | sort` |
| `head -n [] | sort |
| `head -n [] | sort |
| `head -n [] | sort |
| `head -n [] | sort |
| `head -n [] | sort |
| `head -n [] | xargs echo` |
| `head -n [] | xargs wc -l` |
| `head -n [] | sort |
| `head -n [] | sort |
| `head -n [] | grep ` |
| `head -n [] | grep |
| `head -n [] | grep |
| `head -n [] | grep |
| `head -n [] | grep |
| `head -n [] | grep |
| `head -n [] | grep |
| `head -n [] | grep |
| `head -n [] | grep |
| `head -n [] | grep |
| `head -n [] | grep |
| `head -n [] | grep |
| `head -n [] | grep |
| `head -n [] | grep |
| `tail -n [] | wc -l` |
| `tail -n [] | head -n ` |
| `tail -n [] | tail -n ` |
| `tail -n [] | sort` |
| `tail -n [] | sort |
| `tail -n [] | sort |
| `tail -n [] | sort |
| `tail -n [] | sort |
| `tail -n [] | sort |
| `tail -n [] | xargs echo` |
| `tail -n [] | xargs wc -l` |
| `tail -n [] | sort |
| `tail -n [] | sort |
| `tail -n [] | grep ` |
| `tail -n [] | grep |
| `tail -n [] | grep |
| `tail -n [] | grep |
| `tail -n [] | grep |
| `tail -n [] | grep |
| `tail -n [] | grep |
| `tail -n [] | grep |
| `tail -n [] | grep |
| `tail -n [] | grep |
| `tail -n [] | grep |
| `tail -n [] | grep |
| `tail -n [] | grep |
| `tail -n [] | grep |
| `cat | wc -l` |
| `cat | head -n ` |
| `cat | head [-n] |
| `cat | tail -n ` |
| `cat | tail [-n] |
| `cat | grep ` |
| `cat | grep |
| `cat | grep |
| `cat | grep |
| `cat | grep |
| `cat | grep |
| `cat | grep |
| `cat | grep |
| `cat | grep |
| `cat | grep |
| `cat | grep |
| `cat | grep |
| `cat | grep |
| `cat | grep |
| `cat | grep |
| `cat | cut -d -f ` |
| `cat | tr ` |
| `cat | tr |
| `cat | tr |
| `cat | xargs echo` |
| `cat | xargs wc -l` |
| `cat | uniq` |
| `cat | uniq |
| `cat | uniq |
| `cat | uniq |
| `cat | sort` |
| `cat | sort |
| `cat | sort |
| `cat | sort |
| `cat | sort |
| `cat | sort |
| `cat | sort |
| `cat | sort |
| `cat | sort |
| `cat | sort |
| `cat | sort |
| `grep | ...` |
| `grep | wc -l` |
| `grep | head -n ` |
| `grep | tail -n ` |
| `grep | sort` |
| `grep | sort |
| `grep | sort |
| `grep | sort |
| `grep | sort |
| `grep | sort |
| `grep | sort |
| `grep | xargs echo` |
| `grep | xargs wc -l` |
| `grep | sort |
| `grep | sort |
| `grep | cut -d -f ` |
| `grep | cut -d -f |
| `grep | awk '{ print $ }'` |
| `grep | awk '{ print $ }' |
| `grep -R | head -n ` |
| `grep -R | tail -n ` |
| `grep -R | sort` |
| `grep -R | sort |
| `grep -R | sort |
| `grep -R | sort |
| `grep -R | sort |
| `grep -R | sort |
| `grep -R | sort |
| `grep -R | wc -l` |
| `awk '{ print $ }' | ...` |
| `awk '{ print $ }' | grep |
| `awk '/NEEDLE/ { print $ }' | wc -l` |
| `awk '/NEEDLE/ { print $ }' | head -n ` |
| `awk '/NEEDLE/ { print $ }' | tail -n ` |
| `awk '/NEEDLE/ { print $ }' | sort` |
| `awk '/NEEDLE/ { print $ }' | sort |
| `awk '/NEEDLE/ { print $ }' | sort |
| `awk '/NEEDLE/ { print $ }' | sort |
| `awk '/NEEDLE/ { print $ }' | sort |
| `awk '/NEEDLE/ { print $ }' | sort |
| `awk '/NEEDLE/ { print $ }' | sort |
| `awk '/NEEDLE/ { print $ }' | xargs echo` |
| `awk '/NEEDLE/ { print $ }' | xargs wc -l` |
| `awk '/NEEDLE/ { print $ }' | sort |
| `awk '/NEEDLE/ { print $ }' | sort |
| `which [-a] <name...> | wc -l` |
| `which [-a] <name...> | head -n ` |
| `which [-a] <name...> | tail -n ` |
| `which [-a] <name...> | grep |
| `which [-a] <name...> | xargs echo` |
| `which [-a] <name...> | sort |
| `command -v <name...> | wc -l` |
| `command -v <name...> | head -n ` |
| `command -v <name...> | tail -n ` |
| `command -v <name...> | grep |
| `command -v <name...> | xargs echo` |
| `command -v <name...> | sort |
| `printenv | wc -l` |
| `printenv | head -n ` |
| `printenv | tail -n ` |
| `printenv | grep ` |
| `printenv | grep |
| `printenv | sort` |
| `printenv | xargs echo` |
| `printenv | sort |
| `true | false |
| `true | false |
| `mkdir [-p] <path...> | ...` |
| `touch <path...> | ...` |
| `test | .../[ ] |
| `wc -l/-c/-w [regular-file...] | ...` |
| `du -sk | ...` |
| `hostname | wc -l` |
| `hostname | head -n ` |
| `hostname | tail -n ` |
| `hostname | grep ` |
| `hostname | grep |
| `hostname | sort` |
| `hostname | xargs echo` |
| `hostname | sort |
| `find -maxdepth -type f [-name ] | ...` |
| `find -type f [-name ] | xargs wc -l` |
| `find -type f [-name ] | xargs echo` |
| `find -type f [-name ] | xargs` |
| `find -type f [-name ] | grep ` |
| `find -type f [-name ] | grep |
| `find -type f [-name ] | grep |
| `find -type f [-name ] | grep |
| `find -type f [-name ] | grep |
| `find -type f [-name ] | grep |
| `find -type f [-name ] | wc -l` |
| `find -type f [-name ] | head -n ` |
| `find -type f [-name ] | tail -n ` |
| `find -type f [-name ] | sort` |
| `find -type f [-name ] | sort |
| `find -type f [-name ] | sort |
| `find -type f [-name ] | sort |
| `find -type f [-name ] | sort |
| `find -type f [-name ] | sort |
| `find -type f [-name ] | sort |
| `find -type f [-name ] | sort |
| `find -type f [-name ] | sort |
| `find -type f [-name ] | sort |
Native dispatch requires behavior parity. The installed binary shape is tested
against system commands for successful stdout, nonzero exit codes, missing-path
stderr diagnostics, and quiet nonzero cases such as recursive grep no-match.
Unsupported options, unsupported stdin-dependent forms, shell syntax, and risky
path shapes keep the original command path.
In the fused pipe tables, <single-line-cmd> currently means supported
pwd, basename, dirname, whoami, id, or uname forms that produce one
stdout line.
For fused find ... -type f [-name <glob>] pipelines, omitted -name matches
all regular files. When -name is present, <glob> is a single safe basename
pattern. Empty patterns, option-looking patterns, path separators, and bracket
classes stay on the original shell path.
The same grammar also supports -maxdepth <positive> immediately after the
root for bounded file scans.
Pipe behavior is deliberately shape-aware:
| Input shape | Current hook rewrite | Replacement behavior |
|---|---|---|
| `echo <args...> | wc -l` | cap run '<original>' |
| `echo [-n] <args...> | head -n ` | cap run '<original>' |
| `echo [-n] <args...> | tail -n ` | cap run '<original>' |
| `echo [-n] <args...> | tr ` | cap run '<original>' |
| `echo [-n] <args...> | awk '{ print $ }' [ | ...]` |
| `echo [-n] <args...> | xargs echo` | cap run '<original>' |
| `echo [-n] <paths...> | xargs wc -l` | cap run '<original>' |
| `printf | ...` | cap run '<original>' |
| `printf '%s\n' <args...> | wc -l` | cap run '<original>' |
| `printf '%s\n' <args...> | head -n ` | cap run '<original>' |
| `printf '%s\n' <args...> | tail -n ` | cap run '<original>' |
| `printf '%s\n' <args...> | awk '{ print $ }' [ | ...]` |
| `printf '%s\n' <args...> | grep ` | cap run '<original>' |
| `printf '%s\n' <args...> | grep | wc -l` |
| `printf '%s\n' <args...> | grep | head -n ` |
| `printf '%s\n' <args...> | grep | tail -n ` |
| `printf '%s\n' <args...> | grep | sort` |
| `printf '%s\n' <args...> | grep | sort |
| `printf '%s\n' <args...> | grep | sort |
| `printf '%s\n' <args...> | grep | sort |
| `printf '%s\n' <args...> | grep | sort |
| `printf '%s\n' <args...> | grep | sort |
| `printf '%s\n' <args...> | grep | sort |
| `printf '%s\n' <args...> | grep | xargs echo` |
| `printf '%s\n' <args...> | tr ` | cap run '<original>' |
| `printf '%s\n' <args...> | sort` | cap run '<original>' |
| `printf '%s\n' <args...> | sort | uniq` |
| `printf '%s\n' <args...> | sort | uniq |
| `printf '%s\n' <args...> | sort | wc -l` |
| `printf '%s\n' <args...> | sort | head -n ` |
| `printf '%s\n' <args...> | sort | tail -n ` |
| `printf '%s\n' <args...> | sort | xargs echo` |
| `printf '%s\n' <paths...> | sort | xargs wc -l` |
| `printf '%s\n' <args...> | xargs echo` | cap run '<original>' |
| `printf '%s\n' <paths...> | xargs wc -l` | cap run '<original>' |
| `seq | wc -l` | cap run '<original>' |
| `seq | head -n ` | cap run '<original>' |
| `seq | tail -n ` | cap run '<original>' |
| `seq | sort` | cap run '<original>' |
| `seq | sort | uniq` |
| `seq | sort | uniq |
| `seq | sort | wc -l` |
| `seq | sort | head -n ` |
| `seq | sort | tail -n ` |
| `seq | sort | xargs echo` |
| `seq | grep ` | cap run '<original>' |
| `seq | grep | wc -l` |
| `seq | grep | head -n ` |
| `seq | grep | tail -n ` |
| `seq | grep | sort` |
| `seq | grep | sort |
| `seq | grep | sort |
| `seq | grep | sort |
| `seq | grep | sort |
| `seq | grep | sort |
| `seq | grep | sort |
| `seq | grep | xargs echo` |
| `seq | xargs echo` | cap run '<original>' |
| `xargs [echo] | wc -l` | cap run '<original>' |
| `yes [word] | head -n ` | cap run '<original>' |
| ` | wc/head/tail/sort/xargs echo/xargs wc -l` | cap run '<original>' |
| ` | grep [ | downstream]` |
| `ls [-1 | -a | -A] |
| `ls [-1 | -a | -A] |
| `ls [-1 | -a | -A] |
| `ls [-1 | -a | -A] |
| `ls [-1 | -a | -A] |
| `ls [-1 | -a | -A] |
| `ls [-1 | -a | -A] |
| `ls [-1 | -a | -A] |
| `ls [-1 | -a | -A] |
| `ls [-1 | -a | -A] |
| `ls [-1 | -a | -A] |
| `ls [-1 | -a | -A] |
| `ls [-1 | -a | -A] |
| `ls [-1 | -a | -A] |
| `ls [-1 | -a | -A] |
| `ls [-1 | -a | -A] |
| `ls [-1 | -a | -A] |
| `ls [-1 | -a | -A] |
| `ls [-1 | -a | -A] |
| `sort | uniq` | cap run '<original>' |
| `sort | uniq | wc -l` |
| `sort | uniq | ...` |
| `sort | uniq | grep |
| `sort | head -n ` | cap run '<original>' |
| `sort | tail -n ` | cap run '<original>' |
| `sort | wc -l` | cap run '<original>' |
| `sort | xargs echo` | cap run '<original>' |
| `sort | xargs wc -l` | cap run '<original>' |
| `sort | xargs wc -l | ...` |
| `sed -n p | ...` | cap run '<original>' |
| `sed -n p | grep | ...` |
| `cat | sed -n p` | cap run '<original>' |
| `cat | sed -n p | ...` |
| `cat | sed -n p | grep |
| `awk '{ print $ }' | ...` | cap run '<original>' |
| `cat | awk '{ print $ }'` | cap run '<original>' |
| `cat | awk '{ print $ }' | ...` |
| `cat | awk '{ print $ }' | grep |
| `cat | awk '/NEEDLE/ { print $ }'` | cap run '<original>' |
| `cat | awk '/NEEDLE/ { print $ }' | ...` |
| `cut -d -f [] | ...` | cap run '<original>' |
| `cut -d -f [] | grep | ...` |
| `cat | cut -d -f | ...` |
| `cat | cut -d -f | grep |
| `cat | tr | ...` |
| `cat | tr | grep |
| `head -n [] | wc -l` | cap run '<original>' |
| `head -n [] | head -n ` | cap run '<original>' |
| `head -n [] | tail -n ` | cap run '<original>' |
| `head -n [] | sort` | cap run '<original>' |
| `head -n [] | sort | uniq` |
| `head -n [] | sort | uniq |
| `head -n [] | sort | wc -l` |
| `head -n [] | sort | head -n ` |
| `head -n [] | sort | tail -n ` |
| `head -n [] | xargs echo` | cap run '<original>' |
| `head -n [] | xargs wc -l` | cap run '<original>' |
| `head -n [] | sort | xargs echo` |
| `head -n [] | sort | xargs wc -l` |
| `head -n [] | grep ` | cap run '<original>' |
| `head -n [] | grep | wc -l` |
| `head -n [] | grep | head -n ` |
| `head -n [] | grep | tail -n ` |
| `head -n [] | grep | sort` |
| `head -n [] | grep | sort |
| `head -n [] | grep | sort |
| `head -n [] | grep | sort |
| `head -n [] | grep | sort |
| `head -n [] | grep | sort |
| `head -n [] | grep | xargs echo` |
| `head -n [] | grep | xargs wc -l` |
| `head -n [] | grep | sort |
| `head -n [] | grep | sort |
| `tail -n [] | wc -l` | cap run '<original>' |
| `tail -n [] | head -n ` | cap run '<original>' |
| `tail -n [] | tail -n ` | cap run '<original>' |
| `tail -n [] | sort` | cap run '<original>' |
| `tail -n [] | sort | uniq` |
| `tail -n [] | sort | uniq |
| `tail -n [] | sort | wc -l` |
| `tail -n [] | sort | head -n ` |
| `tail -n [] | sort | tail -n ` |
| `tail -n [] | xargs echo` | cap run '<original>' |
| `tail -n [] | xargs wc -l` | cap run '<original>' |
| `tail -n [] | sort | xargs echo` |
| `tail -n [] | sort | xargs wc -l` |
| `tail -n [] | grep ` | cap run '<original>' |
| `tail -n [] | grep | wc -l` |
| `tail -n [] | grep | head -n ` |
| `tail -n [] | grep | tail -n ` |
| `tail -n [] | grep | sort` |
| `tail -n [] | grep | sort |
| `tail -n [] | grep | sort |
| `tail -n [] | grep | sort |
| `tail -n [] | grep | sort |
| `tail -n [] | grep | sort |
| `tail -n [] | grep | xargs echo` |
| `tail -n [] | grep | xargs wc -l` |
| `tail -n [] | grep | sort |
| `tail -n [] | grep | sort |
| `cat | wc -l` | cap run '<original>' |
| `cat | head -n ` | cap run '<original>' |
| `cat | head [-n] | ...` |
| `cat | tail -n ` | cap run '<original>' |
| `cat | tail [-n] | ...` |
| `cat | grep ` | cap run '<original>' |
| `cat | grep | wc -l` |
| `cat | grep | head -n ` |
| `cat | grep | tail -n ` |
| `cat | grep | sort` |
| `cat | grep | sort |
| `cat | grep | sort |
| `cat | grep | sort |
| `cat | grep | sort |
| `cat | grep | sort |
| `cat | grep | sort |
| `cat | grep | xargs echo` |
| `cat | grep | xargs wc -l` |
| `cat | grep | sort |
| `cat | grep | sort |
| `cat | cut -d -f ` | cap run '<original>' |
| `cat | tr ` | cap run '<original>' |
| `cat | tr | ...` |
| `cat | tr | grep |
| `cat | xargs echo` | cap run '<original>' |
| `cat | xargs wc -l` | cap run '<original>' |
| `cat | xargs wc -l | ...` |
| `cat | uniq` | cap run '<original>' |
| `cat | uniq | wc -l` |
| `cat | uniq | ...` |
| `cat | uniq | grep |
| `uniq | ...` | cap run '<original>' |
| `uniq | grep | ...` |
| `cat | sort` | cap run '<original>' |
| `cat | sort | uniq` |
| `cat | sort | uniq |
| `cat | sort | uniq |
| `cat | sort | uniq |
| `cat | sort | wc -l` |
| `cat | sort | head -n ` |
| `cat | sort | tail -n ` |
| `cat | sort | xargs echo` |
| `cat | sort | xargs wc -l` |
| `cat | sort | xargs wc -l |
| `find -maxdepth -type f [-name ] | ...` | cap run '<original>' |
| `find -type f [-name ] | xargs wc -l` | cap run '<original>' |
| `find -type f [-name ] | xargs wc -l | ...` |
| `find -type f [-name ] | xargs echo` | cap run '<original>' |
| `find -type f [-name ] | xargs` | cap run '<original>' |
| `find -type f [-name ] | grep ` | cap run '<original>' |
| `find -type f [-name ] | grep | ...` |
| `find -type f [-name ] | grep | xargs echo` |
| `find -type f [-name ] | grep | xargs wc -l` |
| `find -type f [-name ] | grep | sort |
| `find -type f [-name ] | grep | sort |
| `find -type f [-name ] | grep | sort |
| `find -type f [-name ] | grep | sort |
| `find -type f [-name ] | wc -l` | cap run '<original>' |
| `find -type f [-name ] | head -n ` | cap run '<original>' |
| `find -type f [-name ] | tail -n ` | cap run '<original>' |
| `find -type f [-name ] | sort` | cap run '<original>' |
| `find -type f [-name ] | sort | uniq` |
| `find -type f [-name ] | sort | uniq |
| `find -type f [-name ] | sort | uniq |
| `find -type f [-name ] | sort | uniq |
| `find -type f [-name ] | sort | uniq |
| `find -type f [-name ] | sort | wc -l` |
| `find -type f [-name ] | sort | xargs echo` |
| `find -type f [-name ] | sort | xargs wc -l` |
| `find -type f [-name ] | sort | xargs wc -l |
| `find -type f [-name ] | sort | head -n ` |
| `find -type f [-name ] | sort | tail -n ` |
| `xargs [echo] | grep [ | ...]` |
| `grep | ...` | cap run '<original>' |
| `grep | wc -l` | cap run '<original>' |
| `grep | head -n ` | cap run '<original>' |
| `grep | tail -n ` | cap run '<original>' |
| `grep | sort` | cap run '<original>' |
| `grep | sort | uniq` |
| `grep | sort | uniq |
| `grep | sort | uniq |
| `grep | sort | wc -l` |
| `grep | sort | head -n ` |
| `grep | sort | tail -n ` |
| `grep | xargs echo` | cap run '<original>' |
| `grep | xargs wc -l` | cap run '<original>' |
| `grep | xargs wc -l | ...` |
| `grep | sort | xargs echo` |
| `grep | sort | xargs wc -l` |
| `grep | sort | xargs wc -l |
| `grep | cut -d -f ` | cap run '<original>' |
| `grep | cut -d -f | ...` |
| `grep | awk '{ print $ }'` | cap run '<original>' |
| `grep | awk '{ print $ }' | ...` |
| `grep -R | head -n ` | cap run '<original>' |
| `grep -R | tail -n ` | cap run '<original>' |
| `grep -R | sort` | cap run '<original>' |
| `grep -R | sort | uniq` |
| `grep -R | sort | uniq |
| `grep -R | sort | uniq |
| `grep -R | sort | wc -l` |
| `grep -R | sort | head -n ` |
| `grep -R | sort | tail -n ` |
| `grep -R | wc -l` | cap run '<original>' |
| `awk '{ print $ }' | ...` | cap run '<original>' |
| `awk '{ print $ }' | grep | ...` |
| `awk '/NEEDLE/ { print $ }' | wc -l` | cap run '<original>' |
| `awk '/NEEDLE/ { print $ }' | head -n ` | cap run '<original>' |
| `awk '/NEEDLE/ { print $ }' | tail -n ` | cap run '<original>' |
| `awk '/NEEDLE/ { print $ }' | sort` | cap run '<original>' |
| `awk '/NEEDLE/ { print $ }' | sort | uniq` |
| `awk '/NEEDLE/ { print $ }' | sort | uniq |
| `awk '/NEEDLE/ { print $ }' | sort | uniq |
| `awk '/NEEDLE/ { print $ }' | sort | wc -l` |
| `awk '/NEEDLE/ { print $ }' | sort | head -n ` |
| `awk '/NEEDLE/ { print $ }' | sort | tail -n ` |
| `awk '/NEEDLE/ { print $ }' | xargs echo` | cap run '<original>' |
| `awk '/NEEDLE/ { print $ }' | xargs wc -l` | cap run '<original>' |
| `awk '{ print $ }' | xargs wc -l | ...` |
| `awk '/NEEDLE/ { print $ }' | sort | xargs echo` |
| `awk '/NEEDLE/ { print $ }' | sort | xargs wc -l` |
| `awk '{ print $ }' | sort | xargs wc -l |
| `which [-a] <name...> | wc -l` | cap run '<original>' |
| `which [-a] <name...> | head -n ` | cap run '<original>' |
| `which [-a] <name...> | tail -n ` | cap run '<original>' |
| `which [-a] <name...> | grep | ...` |
| `which [-a] <name...> | xargs echo` | cap run '<original>' |
| `which [-a] <name...> | sort | ...` |
| `command -v <name...> | wc -l` | cap run '<original>' |
| `command -v <name...> | head -n ` | cap run '<original>' |
| `command -v <name...> | tail -n ` | cap run '<original>' |
| `command -v <name...> | grep | ...` |
| `command -v <name...> | xargs echo` | cap run '<original>' |
| `command -v <name...> | sort | ...` |
| `printenv | wc -l` | cap run '<original>' |
| `printenv | head -n ` | cap run '<original>' |
| `printenv | tail -n ` | cap run '<original>' |
| `printenv | grep ` | cap run '<original>' |
| `printenv | grep | ...` |
| `printenv | sort` | cap run '<original>' |
| `printenv | xargs echo` | cap run '<original>' |
| `printenv | sort | xargs echo` |
| `true | false | ...` |
| `true | false | grep |
| `mkdir [-p] <path...> | ...` | cap run '<original>' |
| `touch <path...> | ...` | cap run '<original>' |
| `test | .../[ ] |
...` |
| `wc -l/-c/-w [regular-file...] | ...` | cap run '<original>' |
| `printf | ...` | cap run '<original>' |
| `du -sk | ...` | cap run '<original>' |
| `hostname | wc -l` | cap run '<original>' |
| `hostname | head -n ` | cap run '<original>' |
| `hostname | tail -n ` | cap run '<original>' |
| `hostname | grep ` | cap run '<original>' |
| `hostname | grep | ...` |
| `hostname | sort` | cap run '<original>' |
| `hostname | xargs echo` | cap run '<original>' |
| `hostname | sort | xargs echo` |
| other pipe-shaped commands | cap run '<original>' |
Cap falls back to bash -c to preserve shell semantics. |
The hook does not currently rewrite each pipeline segment into cap find | cap xargs, no matter how many commands appear in the pipe. Instead, cap either
recognizes the whole command string as one fused pipeline or keeps the whole
string under bash -c. That avoids subtle shell-behavior drift around quoting,
file descriptors, SIGPIPE, xargs batching, empty input, and per-segment exit
status.
Still not replaced by default:
| Command / shape | Status | Reason |
|---|---|---|
option-sensitive echo and conversion/unsupported printf formats |
compatibility fallback | Shells differ on echo flags and printf is a formatting language; only exact %s/%s\n and one-arg no-conversion literal formats with supported escapes are native. |
non-integer or zero-step seq |
compatibility fallback | General seq formatting/floating-point behavior stays with the system command. |
unsupported id flags, unsupported uname flags, and hostname flags/arguments |
compatibility fallback | Platform-specific fields beyond the listed uname subset and hostname mutation/format variants stay with the system commands until explicitly parity-covered. |
compound test / [ expressions, shell-string [ ... ], and missing ] argv forms |
compatibility fallback | The native path only owns simple predicates; shell syntax and compound boolean semantics stay with Bash/system test. |
unsupported wc pipe forms and non-regular explicit operands |
compatibility fallback | The native pipe path owns stdin or explicit regular-file operands only for supported downstream shapes; richer wc options and non-regular operands stay with Bash/system wc. |
du forms outside `du -sk |
...` | compatibility fallback |
general awk programs and xargs options outside the listed narrow subsets |
compatibility fallback | These are language / option surfaces; only the listed narrow subsets are native. |
which flags other than -a and general command builtin forms |
compatibility fallback | The native path owns plain PATH lookup, which -a, and command -v; execution and environment-sensitive command builtin behavior stay with Bash/system commands. |
env assignments/options/command-wrapper forms, printenv flags/multiple names, and full-environment pipes such as `env |
wc -lorprintenv |
sort` |
| `ls | xargs wc -land other cwd-sensitivels |
xargs` consumers |
sort options and sort pipelines outside the listed uniq/head/tail/wc -l/xargs producer forms |
compatibility fallback | Sort flags, locale-specific behavior, and richer downstream commands stay with the system pipeline until parity-covered. |
general cut forms |
compatibility fallback | Byte/char extraction, ranges, multi-field lists, suppress-undelimited mode, and multiple files stay with the system command. |
general tr forms |
compatibility fallback | Character classes other than exact [:lower:]/[:upper:]/[:digit:], escape sequences, complement, squeeze, descending ranges, duplicate source sets, and string2 padding stay with the system command. |
multi-operand or option-looking yes pipeline producers |
compatibility fallback | Platform yes operand semantics differ; only bare yes and single non-option operand forms fuse with head. |
| unsupported shell pipes | compatibility fallback | The hook emits cap run '<original>'; cap internally keeps shell semantics through bash -c unless a fused whole-pipeline shape matches. |
Use cap explain -- <command> ... to see whether a command will use a native
implementation or the original command.
The routing pilot covers compatible cat, wc -l, and wc -c calls with stdin
or small regular files. Put --trace-routing before the command to write one
JSON route record to stderr. Normal tool stdout stays unchanged. The record
contains tool, backend, implementation, and a stable reason.
cap --trace-routing cat file
cap --trace-routing run 'wc -l file'
cap explain --json -- cat filetool is cat, wc-lines, wc-bytes, or null outside the pilot. Backends
include c-tiny, c-fast, rust-native, original, and bash. Entry paths can
select different backends. For the pilot, JSON explanation reports the same
route decision without executing the command. Other tools keep the existing
planner explanation. Unsupported command forms use the original command or
Bash. Native input and file errors keep their normal error and exit behavior.
A pass over the resource gates surfaced where the 1:1 same-name replacement model runs out of road, and where the real wins actually are. The following are the planned edges beyond conservative same-name takeover:
-
Pure-Rust front-end (removing the C dispatcher) — deferred. A
no_std, no-startfiles Rust front-end was prototyped and is functionally identical tocap_frontend.c(full parity) with the same direct-syscall shape. It lands within ~16 KB of the C binary — but that ~16 KB is exactly one 16 KiB page, and it is enough to lose the razor-thincatgate (Rust ties systemcatat 1.00x where C wins at 0.99x). The page is Rust-runtime/dyld overhead that survivesfixup_chains, LTO, strip, reloc, and zero-import builds. Conclusion: the C hot path stays for now, and the language question becomes moot once the work moves to pipeline scale — 16 KB is <2% of one process floor. -
Pipeline fusion — active for narrow shapes; broader support planned. The large savings are not in replacing individual cheap commands but in collapsing a shell pipeline
A | B | Cinto a single in-process streaming pipeline. A shell pipeline pays N process floors (~1.3 MiB each) plus OS pipe overhead and N fork/execs; one fused process pays one floor and none of the pipe cost. Rough envelope:A | B≈ 0.54x RSS,A | B | C≈ 0.36x — a 2–3x win, not a 0.99x near-tie. cap now fuses representativecat|wc,cat|head,cat|tail,cat|grep,cat|cut,cat|cut|wc/head/tail/sort,cat|cut|sort|uniq,cat|cut|sort|uniq|wc,cat|cut|xargs,cat|cut|grep|wc/head/tail/sort,cat|cut|grep|sort|xargs,cat|tr,cat|tr|wc/head/tail/sort,cat|tr|sort|uniq,cat|tr|xargs,cat|tr|grep|wc/head/tail/sort,cat|tr|grep|sort|xargs,cat|sort,cat|uniq,cat|uniq|wc,cat|uniq|head/tail/sort,cat|uniq|xargs,cat|uniq|grep|wc/head/tail/sort,cat|uniq|grep|sort|xargs,uniq|wc/head/tail/sort/xargs,uniq|grep|wc/head/tail/sort,uniq|grep|sort|xargs,cat|xargs|echo,cat|xargs|wc,cat|sort|uniq,cat|sort|uniq|wc,cat|sort|uniq|head/tail/sort,cat|sort|uniq|xargs,cat|sort|uniq|grep|wc/head/tail/sort,cat|sort|uniq|grep|sort|xargs,cat|sort|wc,cat|sort|head,cat|sort|tail,cat|grep|wc/head/tail/sort,cat|grep|xargs|echo,cat|grep|xargs|wc,cat|grep|sort|xargs,cat|sort|xargs|echo,cat|sort|xargs|wc,echo|wc,echo|head,echo|tail,echo|tr,echo|xargs|echo,echo|xargs|wc,printf|wc,printf|head,printf|tail,printf|grep,printf|grep|wc/head/tail/sort,printf|grep|sort|uniq,printf|grep|sort|uniq|wc,printf|grep|sort|wc/head/tail,printf|grep|sort|xargs|echo,printf|grep|xargs|echo,printf|tr,printf|sort,printf|sort|uniq,printf|sort|uniq|wc,printf|sort|wc,printf|sort|head,printf|sort|tail,printf|sort|xargs|echo,printf|sort|xargs|wc,printf|xargs|echo,printf|xargs|wc, literalprintfproducers,seq|wc,seq|head,seq|tail,seq|xargs|echo,xargs|wc,xargs|grep|wc/head/tail/sort/xargs,yes|head,ls|wc,ls|head,ls|tail,ls|sort,ls|sort|uniq,ls|sort|uniq|wc,ls|sort|wc,ls|sort|head,ls|sort|tail,ls|grep,ls|grep|wc,ls|grep|xargs|echo,ls|grep|sort|xargs|echo,ls|xargs|echo,sort|uniq,sort|uniq|wc,sort|uniq|head/tail/sort,sort|uniq|xargs,sort|uniq|grep|wc/head/tail/sort,sort|uniq|grep|sort|xargs,sort|head,sort|tail,sort|wc,sort|xargs|echo,sort|xargs|wc,head|wc,head|head,head|tail,head|sort,head|sort|uniq,head|sort|uniq|wc,head|sort|wc,head|sort|head,head|sort|tail,head|xargs|echo,head|xargs|wc,head|sort|xargs|echo,head|sort|xargs|wc,head|grep,head|grep|wc,head|grep|head,head|grep|tail,head|grep|sort,head|grep|sort|uniq,head|grep|sort|uniq|wc,head|grep|sort|wc,head|grep|sort|head,head|grep|sort|tail,head|grep|xargs|echo,head|grep|xargs|wc,head|grep|sort|xargs|echo,head|grep|sort|xargs|wc, stdin, single-file, and recursivegrep|head,grep|tail,grep|sort,grep|sort|uniq,grep|sort|uniq|wc,grep|sort|wc,grep|sort|head,grep|sort|tail,grep|wc,grep|xargs|echo,grep|xargs|wc,grep|sort|xargs|echo,grep|sort|xargs|wc,sed|wc/head/tail/sort,sed|sort|uniq,sed|sort|uniq|wc,sed|sort|wc/head/tail,sed|xargs|echo,sed|xargs|wc,sed|grep,sed|grep|wc/head/tail/sort,sed|grep|sort|uniq,sed|grep|sort|uniq|wc,sed|grep|sort|wc/head/tail,sed|grep|xargs|echo,sed|grep|xargs|wc,sed|grep|sort|xargs,cut|wc/head/tail/sort,cut|sort|uniq,cut|sort|uniq|wc,cut|sort|wc/head/tail,cut|xargs|echo,cut|xargs|wc,cut|grep,cut|grep|wc/head/tail/sort,cut|grep|sort|uniq,cut|grep|sort|uniq|wc,cut|grep|sort|wc/head/tail,cut|grep|xargs|echo,cut|grep|xargs|wc,cut|grep|sort|xargs,awk|wc/head/tail/sort,awk|xargs|echo,awk|xargs|wc,awk|sort|xargs,which|wc,which|head,which|tail,which|xargs,which|sort,which|grep|wc/head/tail/sort/xargs,which-a|wc/xargs/sort-xargs,command-v|wc,command-v|head,command-v|tail,command-v|xargs,command-v|sort,command-v|grep|wc/head/tail/sort/xargs,env,printenv,hostname,printenv|wc,printenv|head,printenv|tail,printenv|grep,printenv|grep|wc/head/tail/sort/xargs,printenv|sort,printenv|xargs,printenv|sort|xargs,hostname|wc,hostname|head,hostname|tail,hostname|grep,hostname|grep|wc/head/tail/sort/xargs,hostname|sort,hostname|xargs,hostname|sort|xargs,mkdir|wc/head/tail/sort/xargs/grep,touch|wc/head/tail/sort/xargs/grep,test|wc/head/tail/sort/xargs/grep,bracket-test|wc/head/tail/sort/xargs/grep,wc-file|wc/head/tail/sort/xargs/grep,find|xargs|wc,find|xargs|wc|sort,find|xargs|echo,find|grep|xargs|echo,find|grep|xargs|wc,find|grep|sort|xargs|echo,find|grep|sort|xargs|wc,find|grep|sort|xargs|wc|sort,find|grep|sort|uniq|xargs|wc|sort,find|wc,find|head,find|tail,find|sort,find|sort|uniq,find|sort|uniq|wc,find|sort|uniq|xargs|wc|sort,find|sort|wc,find|sort|xargs|echo,find|sort|xargs|wc,find|sort|head, andfind|sort|tailshapes, withbash -cfallback for unfusable stages and byte-for-byte parity tests guarding correctness. Broader fusion work should factor more commands into reusable pull-based stream stages.
Command replacement is resource-benchmarked, not assumed. The benchmark compares
both public surfaces, cap <cmd> and hook-emitted cap run "<command string>",
against the original system command with CPU time (user + system) and peak
RSS as the decision metrics:
cargo bench -p cap --bench command_resourcesThe latest baseline and interpretation live in BENCHMARKS.md.
Narrowing it down:
cap on claude # enable just Claude Code
cap on codex # enable just Codex CLI
cap on agy # enable just AGY globally
cap on --print # print the snippets, touch nothing
cap off codex # remove only cap's Codex hook
cap off agy # remove only cap's AGY hook
cap status # optional daemon leases and global hook statecap on and cap off are idempotent and preserve unrelated hooks already in
the file. cap init remains a deprecated compatibility alias for cap on.
When installed through cap on, all three agent hooks reject rm targets outside the
current Git workspace (including the workspace root), ambiguous destructive
shell forms, find -delete, forceful git clean, git reset --hard, and
privileged or disk-destructive commands such as sudo, dd, mkfs, and
diskutil. Claude/Codex also route commands through cap's optimizer; AGY's
adapter currently uses the guard without rewriting its command. This guard applies only to agent hook calls; direct terminal
cap run retains its normal shell behavior.
The hook sends Bash calls through cap's command planner.
Supported commands use native implementations.
Other commands use the original command or bash -c when shell syntax is needed.
Command execution does not need the daemon.
agent command or terminal command
|
cap planner
| |
supported other command
| |
native tool direct child process
or pipeline or Bash fallback
|
explicit timeout, if set
Cap preserves command input, output, errors, and exit status. External commands run without host-capacity admission checks. The local supervisor forwards terminal signals to the child process group. Only requested timeouts can stop a command through cap's own timeout path.
# explicit form
cap run --label "mamba build" -- cargo build -p mamba
# default form — anything after `cap` is treated as the command
cap cargo test
cap uv run pytest
# optional external-command time limits
cap run --timeout 120 -- cargo test
cap run --idle-timeout 30 -- cargo test
# compatibility command; returns success without waiting
cap wait
# optional daemon lifecycle
cap daemon start
cap daemon status
cap daemon stop
# inspect
cap status # optional daemon leases and global hook state
cap ps # alias of status
cap ping
# config
cap config init # write default ~/.cap/config.toml
cap config showNote: in the default form, cap's own subcommand names shadow programs of the same name —
cap statusalways means cap's status, never the systemstatusbinary. Usecap run -- <cmd>to be unambiguous. The agent hook always emitscap run '<original Bash command>'; cap then parses shell-free strings internally or falls back tobash -cwhen shell semantics are required, so hook-wrapped commands are not affected by cap subcommand shadowing.
~/.cap/config.toml (or $CAP_HOME/config.toml) stores optional settings.
cap config init writes the active defaults.
[protect]
kill_grace_secs = 3 # wait after timeout SIGTERM before SIGKILL
sample_interval_ms = 500 # timeout observation interval
default_timeout_secs = 0 # optional daemon-client default only
default_idle_timeout_secs = 0 # optional daemon-client default only
[log]
enabled = true # write external-command run recordsThe [protect] name remains for compatibility.
Old memory floors, load thresholds, reap settings, and [defaults] nice keys
have no effect and are omitted from new config output.
Old default_timeout_secs and default_idle_timeout_secs settings remain
available to daemon clients. Direct CLI runs require explicit timeout flags.
External commands can append one JSON record to
~/.cap/logs/events-YYYY-MM-DD.jsonl when they finish.
Native replacements use their existing fast path and do not create these records.
Set [log] enabled = false to disable the log.
A log write failure does not change the command's exit status.
The record keeps the existing field names for compatibility.
duration_ms records elapsed run time. paused_ms is always zero.
queue_ms records local setup time, without a capacity wait.
Direct runs do not sample memory.
Their memory fields are compatibility placeholders, not measured usage.
kill_classification is absolute_timeout or idle_timeout when an explicit
timeout stops the command. Memory competition no longer produces a kill record.
New cap run commands bypass an old running daemon.
After replacing the binaries, stop an old daemon so any library clients can
start the new daemon with the updated policy:
cap daemon stopCommands already registered with an old daemon remain under that daemon's policy until it stops. This change does not alter a process that is already running.
- Cap does not provide memory or CPU resource protection.
- Explicit timeout flags apply to external commands. Native replacements keep their existing execution path.
cap statuslists daemon leases. It does not list normal direct commands.- Unsupported command shapes keep shell fallback.
- The next efficiency work is resident light-shell pipeline fusion with dynamic Bash fallback. See Deferred and planned direction.