Summary
secondwind hook prefixes the agent's Bash command with secondwind exec . exec then joins its argv with spaces and runs the result through sh -c. The command therefore passes two shell parses. Quoted metacharacters lose their quotes, and a compound command splits, so only its first segment reaches the optimizer.
Environment
- secondwind 0.3.2, built from git
ab3888a with cargo install --git
- Claude Code 2.1.220, Arch Linux, fish 4.x as the user shell
- Hook installed with
secondwind setup --hook
Repro 1: the quotes are lost
The agent runs this Bash command:
Result:
sh: line 1: b: command not found
Expected output: a|b.
The outer shell parses secondwind exec echo 'a|b' and passes a|b as one argv item. exec rebuilds the string echo a|b and gives it to sh -c, where | is a pipe again.
Repro 2: a compound command splits
Result: the original working directory, not /tmp.
The shell reads this as (secondwind exec cd /tmp) && pwd. The cd runs in the child process of secondwind and is lost. A variable assignment before ; is lost the same way. In a pipeline such as fd . | head -400, only fd is wrapped, so the recorded token count is the output before head, not the output the agent receives.
Impact
A Bash command with a quoted metacharacter fails. A command that depends on cd, on an assignment, or on a pipeline returns a wrong result, and the hook still reports success. The agent sees a shell error or wrong data, so the cause is hard to attribute to secondwind.
Code
crates/cli/src/main.rs:869: format!("secondwind exec {command}")
crates/cli/src/main.rs:880-884: command.join(" "), then sh -c
crates/cli/src/main.rs:110-113: Exec { command: Vec<String> } with trailing_var_arg
Suggested fix
Keep one shell parse. Emit the command as a single argument from the hook, shell-quoted, and run that argument verbatim in exec with no join. For example secondwind exec --command '<quoted command>', where exec gives the value of --command to sh -c unchanged.
Summary
secondwind hookprefixes the agent's Bash command withsecondwind exec.execthen joins its argv with spaces and runs the result throughsh -c. The command therefore passes two shell parses. Quoted metacharacters lose their quotes, and a compound command splits, so only its first segment reaches the optimizer.Environment
ab3888awithcargo install --gitsecondwind setup --hookRepro 1: the quotes are lost
The agent runs this Bash command:
Result:
Expected output:
a|b.The outer shell parses
secondwind exec echo 'a|b'and passesa|bas one argv item.execrebuilds the stringecho a|band gives it tosh -c, where|is a pipe again.Repro 2: a compound command splits
Result: the original working directory, not
/tmp.The shell reads this as
(secondwind exec cd /tmp) && pwd. Thecdruns in the child process of secondwind and is lost. A variable assignment before;is lost the same way. In a pipeline such asfd . | head -400, onlyfdis wrapped, so the recorded token count is the output beforehead, not the output the agent receives.Impact
A Bash command with a quoted metacharacter fails. A command that depends on
cd, on an assignment, or on a pipeline returns a wrong result, and the hook still reports success. The agent sees a shell error or wrong data, so the cause is hard to attribute to secondwind.Code
crates/cli/src/main.rs:869:format!("secondwind exec {command}")crates/cli/src/main.rs:880-884:command.join(" "), thensh -ccrates/cli/src/main.rs:110-113:Exec { command: Vec<String> }withtrailing_var_argSuggested fix
Keep one shell parse. Emit the command as a single argument from the hook, shell-quoted, and run that argument verbatim in
execwith no join. For examplesecondwind exec --command '<quoted command>', whereexecgives the value of--commandtosh -cunchanged.