Skip to content

21. Tool scoping

Evidence for ADR 0022. Tests how Claude Code enforces tool restrictions when agents are launched with claude --agent.

Summary

MechanismParameterized?--agent sessionSubagent
tools in frontmatterNoNo effectRestricts to listed tools
disallowedTools in frontmatterNoNo effectRemoves listed tools
permissions.allow in settings.jsonYesEnforced (with dontAsk)
permissions.deny in settings.jsonYesEnforced (even with --dangerously-skip-permissions)
bypassPermissions modeN/APartial — auto-approves some tools, denies others

1. Frontmatter scoping (tools, disallowedTools)

tools and disallowedTools in agent frontmatter have no effect in --agent sessions. They only work when the agent runs as a subagent spawned via the Agent tool.

--agent sessions: tools neither restricts nor grants

TestAgent configActionResultEvidence
tools-bash-skiptools: Bash + --dangerously-skip-permissionsWrite fileSucceededtools didn't block Write
tools-write-try-bashtools: Write + bypassPermissionsRun echo hello via BashSucceededtools didn't block Bash
tools-write-try-writetools: Write + bypassPermissionsWrite fileDeniedtools didn't grant Write (denied by bypassPermissions)
tools-bash-allow-writetools: Bash + bypassPermissions + allow: Write(*)Write fileSucceededtools didn't block Write when permissions.allow set

Agents: tools-bash-skip.md, tools-write.md, tools-bash.md Results: frontmatter-tools-bash-skip.json, frontmatter-tools-write-try-bash.json, frontmatter-tools-write-try-write.json, frontmatter-tools-bash-allow-write.json

--agent sessions: disallowedTools has no effect

TestAgent configActionResultEvidence
disallowed-bashdisallowedTools: Bash + --dangerously-skip-permissionsRun echo helloSucceededdisallowedTools didn't remove Bash

Agent: disallowed-bash.md Result: frontmatter-disallowed-bash.json

Subagents: both mechanisms work

TestSubagent configActionResultEvidence
subagent-disallowed-bashdisallowedTools: BashRun echo helloDenied — Bash not availabledisallowedTools works for subagents
subagent-tools-bashtools: BashWrite fileDenied — Write not availabletools works for subagents

Agents: coordinator-disallowed.md + subagent-disallowed-bash.md, coordinator-tools.md + subagent-tools-bash.md Results: subagent-disallowed-bash.json, subagent-tools-bash.json

2. permissions.deny with --dangerously-skip-permissions

permissions.deny in .claude/settings.json hard-blocks matching patterns even with --dangerously-skip-permissions.

TestConfigecho hellols /tmp
permissions-deny--dangerously-skip-permissions + deny: Bash(ls *)SucceededDenied

Agent: deny-test.md Settings: deny-bash-ls.json Result: permissions-deny.json

3. permissions.allow with dontAsk

permissions.allow in .claude/settings.json combined with permissionMode: dontAsk enforces parameterized patterns — only matching tool calls are auto-approved, everything else is auto-denied.

TestConfigecho hellols /tmp
permissions-allowdontAsk + allow: Bash(echo *)SucceededDenied

Agent: dontask.md Settings: allow-bash-echo.json Result: permissions-allow.json

4. bypassPermissions partial bypass

permissionMode: bypassPermissions auto-approves some tools but not others. Bash is auto-approved; Write is denied unless supplemented by permissions.allow.

TestConfigWriteEvidence
bypass-no-tools-writebypassPermissions (no tools)DeniedbypassPermissions doesn't auto-approve Write
bypass-allow-writebypassPermissions + allow: Write(*)Succeededpermissions.allow supplements bypassPermissions

Agent: bypass-no-tools.md Settings: allow-write.json Results: bypass-no-tools-write.json, bypass-allow-write.json

How to reproduce

See HOW_TO.md.

Environment

  • Claude CLI version: 2.1.118
  • Date: 2026-04-23
  • OS: Linux 6.19.11-200.fc43.x86_64 (Fedora 43)