Summary
Netclaw's approval gate, hard-deny rules, safe-verb list, and verb-chain extraction all assume a POSIX shell — specifically Bash, via BashParser from ShellSyntaxTree. The daemon doesn't check what shell the operator is actually using; it just hands every shell_execute call through the Bash-shaped pipeline. On Windows, on a pwsh-default operator's machine, or in a container that uses dash/ash/fish, this produces silent mismatches:
- The parser may parse a PowerShell or fish command as if it were Bash, succeed, and run the wrong shell-quoting/redirection semantics under the hood.
- The hard-deny rules and safe-verb list are POSIX-shaped (
rm -rf /, dd, :(){:|:&};:) and miss equivalents in other shells (Remove-Item, Get-ChildItem | Remove-Item -Recurse -Force, etc.).
- The verb-chain extraction treats
Invoke-Expression, &, |, and ; differently from how PowerShell actually evaluates them.
What we should detect
At daemon startup (or on first shell_execute per session), determine:
- Operator's preferred shell — read
$SHELL on POSIX, COMSPEC/parent process on Windows, or fall back to platform default (bash on Linux/macOS, pwsh on Windows when present, cmd otherwise).
- Whether the agent is actually running through that shell —
ShellTool currently spawns bash -c (or equivalent); if we change it to honor the detected shell, the parser/gate need to change too.
The detection result becomes part of ToolExecutionContext or a new ShellEnvironment service consumed by ShellTool, ShellCommandPolicy, and ToolAccessPolicy.
Why now
Blocks #SHELL-POWERSHELL — we can't ship a PowerShell-aware approval gate until we can tell which shell to apply. Also closes a real failure mode for Windows operators today: the daemon currently assumes Bash on every platform.
Out of scope
- The PowerShell-specific parser, hard-deny rules, and safe-verb list — separate issue.
- Multi-shell support per session (e.g.,
shell_execute accepting a Shell arg). Probably YAGNI; one shell per operator session is enough.
Summary
Netclaw's approval gate, hard-deny rules, safe-verb list, and verb-chain extraction all assume a POSIX shell — specifically Bash, via
BashParserfrom ShellSyntaxTree. The daemon doesn't check what shell the operator is actually using; it just hands everyshell_executecall through the Bash-shaped pipeline. On Windows, on apwsh-default operator's machine, or in a container that usesdash/ash/fish, this produces silent mismatches:rm -rf /,dd,:(){:|:&};:) and miss equivalents in other shells (Remove-Item,Get-ChildItem | Remove-Item -Recurse -Force, etc.).Invoke-Expression,&,|, and;differently from how PowerShell actually evaluates them.What we should detect
At daemon startup (or on first
shell_executeper session), determine:$SHELLon POSIX,COMSPEC/parent process on Windows, or fall back to platform default (bashon Linux/macOS,pwshon Windows when present,cmdotherwise).ShellToolcurrently spawnsbash -c(or equivalent); if we change it to honor the detected shell, the parser/gate need to change too.The detection result becomes part of
ToolExecutionContextor a newShellEnvironmentservice consumed byShellTool,ShellCommandPolicy, andToolAccessPolicy.Why now
Blocks #SHELL-POWERSHELL — we can't ship a PowerShell-aware approval gate until we can tell which shell to apply. Also closes a real failure mode for Windows operators today: the daemon currently assumes Bash on every platform.
Out of scope
shell_executeaccepting aShellarg). Probably YAGNI; one shell per operator session is enough.