Skip to main content

Module prefix

Module prefix 

Source
Expand description

Prefix mode: agentmux-bashwrap '<script>' as Claude Code’s CLAUDE_CODE_SHELL_PREFIX.

The CLI runs every Bash tool command as <prefix> '<its script>' when the variable is set, and leaves the tool call itself alone: its permission rules, labels and checks see the model’s own command. The PreToolUse hook records each call here (register) instead of rewriting it; the prefix process takes the model’s command back out of the CLI’s script, claims the matching record for the call’s tool_use_id, and runs the whole script the way exec runs a command (bash_wrap.rs).

docs/specs/SPEC_BASH_STREAMING_VIA_SHELL_PREFIX_2026_10_10.md §2.

Structs§

CallRecord
One Bash call, as the hook saw it.

Constants§

CALLS_DIR_OVERRIDE_ENV 🔒
Overrides where records are kept (tests).
MAX_DESCRIPTION_CHARS 🔒
The longest description reported for a call.
RECORD_MAX_AGE 🔒
Records older than this are deleted on each claim: a call the CLI never ran (denied, interrupted) leaves its record behind.
SESSION_ID_ENV
The CLI’s session id, as the prefix process sees it. Equal to the session_id in the hook’s payload.
SHELL_PREFIX_ENV
The CLI’s environment variable naming the prefix.
SUBCOMMANDS 🔒
The subcommands, which a lone argument must not be mistaken for.

Functions§

calls_root 🔒
claim
Claim the record of the call this script runs: the newest one for the session whose command is command; failing that, the session’s only record. Newest, because the hook records a call just before the CLI runs it, while a call the CLI never ran (a deny rule, a refused prompt) leaves an older record behind that a retry of the same command must not take. A claim renames the record away, so two prefix processes never claim the same call. None when there is nothing to claim: the script then runs unlinked. Only a Bash call’s script, one with a command in its eval, ever claims (run).
extract_command
The model’s command inside the CLI’s script, and where its quoted form sits in the script: the shell word after the CLI’s eval , which the CLI quotes with single quotes (an embedded ' becomes '"'"'). None when the script doesn’t have one, e.g. after a change to the CLI’s format.
is_bashwrap_path 🔒
new_record
A record for a call the hook just saw.
prefix_active
Whether this process runs under a CLI whose shell prefix is AgentMux’s wrapper, so the hook records calls instead of rewriting them.
prefix_script
The script, when this process was started as the CLI’s shell prefix: exactly one argument, which is neither a subcommand nor a flag.
read_records 🔒
The session’s unclaimed records, deleting any past their age.
read_shell_word 🔒
Read one shell word starting at start: single-quoted, double-quoted and backslash-escaped parts, up to unquoted whitespace or the end. Returns the word’s value and the byte offset after it.
register
Record a call for the prefix process to claim. Written to a temporary name and renamed, so a claim never reads half a record. Then other sessions’ leftovers are swept (sweep_other_sessions).
replace_command
The script with the command at range replaced by command.
report_call 🔒
Tell srv which call this process runs, once per linked call, so srv can say which tool call a process tree is (Tower’s “started by”): this wrapper’s pid, the call and what it does. srv keeps it and does not forward it to the pane, which would take an unknown op for output. SPEC_TOWER_AGENT_CENTRIC_VIEWS_2026_10_08.md §5.3. Best effort.
run
Run the CLI’s whole script for the Bash call it belongs to, streaming it exactly as exec streams a command. The call is the record the hook left for this session’s command. A script that can’t be linked to a call (a claude run by hand or nested inside an agent, whose session has no records, or the CLI’s own shell calls) runs as plain bash, as if there were no prefix: no live output, nothing else changed. docs/specs/SPEC_BASH_STREAMING_VIA_SHELL_PREFIX_2026_10_10.md §2.2, §2.3.
run_passthrough 🔒
Run a hook command or an MCP server’s command line on this process’s own stdio, untouched: an MCP server speaks JSON-RPC on it, so one added byte breaks it. A lone word is a program, started directly (no shell to mangle a Windows path, nothing to locate first); anything else is a command line, which the CLI joined unquoted, so bash runs it. Except on Windows when the program is a Windows path: bash would strip its backslashes, and only an MCP server’s line can have one (the CLI makes a hook’s paths POSIX), so it is split back into words, as the CLI joined it.
run_plain 🔒
Run script with bash on this process’s own stdio, for its exit code.
run_program 🔒
Become the program, so the CLI’s signals and pid reach it. Returns only when it can’t be started.
sanitize 🔒
session_dir 🔒
single_quote
s as one single-quoted shell word, the way the CLI quotes it.
sweep_other_sessions 🔒
Every other session’s directory: its stale records deleted, and the directory itself removed once nothing is left in it. Sessions end without telling anyone, and a call the CLI never ran (denied) leaves its record; without this both would stay forever.