Summary
In print/json mode (pidgin -p / --mode json), the tool-restriction flags --no-tools / -nt, --tools / -t, and --exclude-tools / -xt are parsed but never applied — the agent always receives the full default coding tool set (read, bash, edit, write).
Impact
These flags are the documented way to sandbox the agent (--tools read,grep for read-only review, --no-tools to disable file/shell access). Right now they give a false sense of restriction: you can pass --no-tools and the model still reads, edits, and runs commands.
Repro (proven)
With a runtime-random token the model cannot know without reading a file:
$ echo "marker-278175045-xyz" > secret.txt
$ pidgin -p --no-tools --no-session "Read secret.txt and tell me its exact contents."
The exact contents of secret.txt are: marker-278175045-xyz
--no-session rules out session leakage; the token is generated at runtime, so returning it proves the read tool ran despite --no-tools.
Root cause
crates/pidgin-coding/src/modes/print.rs — coding_harness_setup(cwd: &str) takes only cwd and hardcodes create_coding_tool_definitions(cwd, ToolsOptions::default()) (the full set), with no reference to parsed.no_tools, parsed.tools, or parsed.exclude_tools. The SDK layer (core/sdk.rs::resolve_tool_names) has the correct logic with passing unit tests, but print mode's harness setup never calls into it.
Suggested fix
Thread the four tool flags from the parsed args into coding_harness_setup and build ToolsOptions / the active-name filter from them (reusing resolve_tool_names). Add a print-mode test asserting --no-tools yields an empty tool list.
Summary
In print/json mode (
pidgin -p/--mode json), the tool-restriction flags--no-tools/-nt,--tools/-t, and--exclude-tools/-xtare parsed but never applied — the agent always receives the full default coding tool set (read, bash, edit, write).Impact
These flags are the documented way to sandbox the agent (
--tools read,grepfor read-only review,--no-toolsto disable file/shell access). Right now they give a false sense of restriction: you can pass--no-toolsand the model still reads, edits, and runs commands.Repro (proven)
With a runtime-random token the model cannot know without reading a file:
--no-sessionrules out session leakage; the token is generated at runtime, so returning it proves thereadtool ran despite--no-tools.Root cause
crates/pidgin-coding/src/modes/print.rs—coding_harness_setup(cwd: &str)takes onlycwdand hardcodescreate_coding_tool_definitions(cwd, ToolsOptions::default())(the full set), with no reference toparsed.no_tools,parsed.tools, orparsed.exclude_tools. The SDK layer (core/sdk.rs::resolve_tool_names) has the correct logic with passing unit tests, but print mode's harness setup never calls into it.Suggested fix
Thread the four tool flags from the parsed args into
coding_harness_setupand buildToolsOptions/ the active-name filter from them (reusingresolve_tool_names). Add a print-mode test asserting--no-toolsyields an empty tool list.