Custom subagents that declare Bash in frontmatter never receive it (no config can restore it)

Status Open
Reported on v2.1.263
Maintainer reply None cached
Activity 0 comments · opened Sep 8, 2026

Title

Custom subagents that declare a shell tool (Bash) in frontmatter never receive it — silently, with no config able to restore it

Summary

A custom subagent defined in .claude/agents/*.md with Bash listed in its
tools: frontmatter is invoked with that tool silently omitted. Every other
declared tool (Read, Write, Edit, Grep, Glob) is granted correctly —
only the shell tool is missing. There is no error, warning, or denial message;
the subagent simply reports (and behaves as if) it never had the tool. This
makes any subagent whose job requires running a process (tests, git diff,
linting, etc.) non-functional as a native subagent type, with no known
workaround via permissions or settings.

Environment

  • Claude Code version: 2.1.263
  • Reproduced identically on two independent surfaces:
  1. VS Code extension (anthropic.claude-code-2.1.263-win32-x64)
  2. Standalone CLI (npm install -g @anthropic-ai/claude-code, same

version, run from a separate terminal process with no VS Code
involved)

  • OS: Windows 11 Home (10.0.26200), PowerShell 5.1 — the platform's shell

tool is named PowerShell rather than Bash here, but the agent
frontmatter's declared tool name is Bash either way (see "ruled out"
below for why this isn't a naming issue)

  • Project has no .claude/settings.json deny/ask rules of any kind at the

time this was first observed (file didn't exist yet); later testing added
one with an explicit permissions.allow list (see below) with no effect

Repro steps

  1. Define a custom subagent in .claude/agents/example.md:

``yaml
---
name: example
description: ...
tools: Bash, Grep, Glob
model: ...
---
...instructions...
``

  1. Invoke it as its real native subagent type (via the Agent/Task-style

tool with subagent_type: "example", or the CLI's equivalent) with a
diagnostic prompt: *"Report the exact, complete list of tool names
available to you right now, verbatim."*

  1. Observe the response.

Expected

The subagent reports having Bash (or the platform's shell-tool
equivalent), Grep, and Glob — matching its declared tools: frontmatter.

Actual

The subagent reports only Grep, Glob. Bash is absent — not denied when
attempted, simply never listed as available at all.

What we ruled out

  • Naming mismatch (Bash vs. this platform's actual shell-tool name,

PowerShell): renamed the frontmatter's declared tool from Bash to
PowerShell and re-tested — no change, still absent. Reverted.

  • Permissions/approval gap (the working theory going in, since a

classifier-style denial message elsewhere in the product explicitly
suggested "add a Bash permission rule to your settings"): created
.claude/settings.json with a permissions.allow list covering every
shell-command pattern the affected agents actually use (git diff,
git rev-parse, npx playwright test, python -m pytest, node
--check
, plus general read-only commands), re-ran the diagnostic —
no change. Also re-tested after a full VS Code window reload, to rule
out stale/cached settings — no change. This is the key evidence it's
not a permissions issue: an approval gap would show the tool present
but a specific call getting denied; what's actually observed is the
tool never being offered to the subagent's toolset in the first place,
which permissions.allow has no power over.

  • Sandbox restriction: checked sandbox.enabled and related settings

(claude-code-settings.schema.json's sandbox.* block) across project,
user, and any managed/policy settings location on the machine — none
set anywhere, no relevant env vars (CLAUDE_CODE_SANDBOX, etc.) set
either.

  • VS Code-extension-specific bug: installed the standalone CLI (same

version) and ran the identical diagnostic as a separate process —
identical result (Grep, Glob only). Rules this out as an integration
bug specific to the extension's subagent-spawning code path.

Impact

Confirmed across all 6 subagents in a real multi-agent QA pipeline project:

  • 2 of 6 agents are completely non-functional as native subagent types

(both need to run processes — git diff, test runners — with no
Grep/Glob-only substitute for either).

  • 1 of 6 degrades gracefully (loses a lint/syntax-check step, everything

else still works).

  • 3 of 6 are unaffected (never needed shell execution for their actual

work).

Current workaround for the affected agents: the orchestrator pre-computes
whatever the subagent would have needed shell access for (e.g. running
git diff itself and handing the subagent a pre-computed file list) where
that's possible, or falls back to simulating the subagent via the
general-purpose agent type fed the same instructions where it isn't (e.g.
running actual tests) — the general-purpose agent type is not affected
by this restriction and receives * (all tools) normally. This works but
defeats the purpose of having a scoped, single-responsibility custom
subagent for that role.

Question for Anthropic

Is this intentional (e.g., a deliberate policy that a custom subagent
invoked without the interactive session present can never be granted
process-execution capability, regardless of static declaration or
settings), or is it a bug in how a spawned subagent's toolset is
constructed? If intentional, is there a supported way to grant shell
access to a custom subagent at all — and if not, that's worth stating
explicitly in the subagent-authoring docs, since right now tools: Bash
in frontmatter silently does nothing.

View original on GitHub ↗