Published: 2026-06-17
Deep dive

Claude Code 2.1.178: Faster Search, Granular Permissions, Safer Sub-Agents

Chapters / key moments (click to jump — plays here on the page)

Julian Goldie's update walks through Claude Code 2.1.178, which lands three changes that matter for anyone running real agent workflows: a faster ripgrep-based search, a more surgical permission syntax, and — most importantly — sub-agent spawns that are now checked against your permission rules before they launch. Together they push multi-agent Claude Code toward something trustworthy enough for production work, not just experiments.

Source video

"NEW Claude Code Update Changes EVERYTHING!" by Julian Goldie SEOWatch on YouTube →

Key Takeaways

  • 1. Faster search via ripgrep. Tool descriptions now recommend a ripgrep-based grep. Install ripgrep and Claude Code uses it automatically, making file searches ~5–10× faster in large projects. It respects .gitignore, so the agent skips folders that don't matter. Because every task involves dozens of background searches, this compounds across a whole session.
  • 2. Granular Tool(param:value) permissions. Permission rules now accept a Tool(param:value) syntax with a * wildcard to block specific tool inputs — not just whole tools. You can allow Edit only in one folder, or block Bash commands that touch a given directory. You can also control which sub-agents spawn with Task(agent_name), and disable agents at startup with the --disallow-tools CLI flag.
  • 3. Sub-agents are checked before they launch. Previously a sub-agent could be spawned before the permission system evaluated it, leaving a gap where it might bypass the parent's rules. In 2.1.178 sub-agent spawns are evaluated by the classifier before launch. Sub-agents can't show interactive permission prompts, and a blocked tool call is treated as denied. Recommended pattern: keep sub-agents read-only and defer all editing to the parent agent that can handle approvals.
  • Bundled bug fixes: completed sessions now retire even when an idle sub-agent is parked or a backgrounded shell leaked; background work trees are no longer orphaned after the 30-day job-retention sweep; background sessions reattached after sleep/wake now get the correct date; sub-agents now inherit dynamically injected MCP servers; and isolated-worktree sub-agents are no longer denied read/edit access inside their own worktree.
  • Why it matters: faster search + precise permissions + rule-abiding sub-agents means you can define rules once at the top level and have them hold all the way down — the reliability foundation needed to scale multi-agent workflows instead of babysitting them.

Commands & Code Mentioned

# Update Claude Code to 2.1.178
npm update @anthropic-ai/claude-code

# Granular permission rule shape (block/allow specific tool inputs)
Tool(param:value)        # with * wildcard to match a category of inputs
Task(agent_name)         # control which sub-agents can spawn

# Disable specific agents/tools at startup
claude --disallow-tools <tool-or-agent>

See our changelog for the full 2.1.176–179 release notes, and OpenClaw configuration and security for permission-rule details.

Deep dive: a least-privilege settings.json

The video shows the new permission syntax; here's how to turn it into a rule set you can commit to a repo. Claude Code reads permission rules from a permissions block in three files, in increasing specificity: ~/.claude/settings.json (your global defaults), .claude/settings.json (checked into the project, shared with the team), and .claude/settings.local.json (project-local, git-ignored, for personal overrides). Each rule is a Tool(specifier) string. The specifier is gitignore-style globs for file tools (Read, Edit) and a command prefix for Bash, where :* means "any arguments after this prefix."

// .claude/settings.json — commit this so every teammate (and every
// sub-agent) inherits the same guardrails.
{
  "permissions": {
    "allow": [
      "Read(./src/**)",
      "Edit(./src/**)",
      "Bash(npm run test:*)",
      "Bash(npm run lint)",
      "Bash(git status)",
      "Bash(git diff:*)"
    ],
    "ask": [
      "Bash(git push:*)",
      "Edit(./.github/workflows/**)"
    ],
    "deny": [
      "Read(./.env)",
      "Read(./.env.*)",
      "Read(./secrets/**)",
      "Bash(curl:*)",
      "Bash(rm:*)"
    ],
    "defaultMode": "acceptEdits"
  }
}

Three rules to internalise:

  • Deny always wins. A path in deny overrides any allow that would also match it — so Read(./.env) stays blocked even though Read(./src/**) is permitted. Put secrets and destructive commands in deny and stop worrying about whether an allow is too broad.
  • ask still prompts in auto-accept modes. Even with "defaultMode": "acceptEdits", anything in ask pauses for confirmation. Use it for one-way doors: pushing, editing CI, touching infra.
  • Audit before you trust. Run /permissions inside a session to see the effective merged rule set. As of 2.1.193 a denied call also shows why it was denied, so you can tell a missing allow from an explicit deny.

The read-only sub-agent pattern

This is the change that makes 2.1.178 matter. Because a sub-agent can't surface an interactive permission prompt, any tool call it makes that isn't covered by an allow rule is treated as denied — and now that check happens before the sub-agent launches, not after. The safe design that falls out of this: give exploration sub-agents read-only tools and let the parent (which can prompt you) do every write.

Define the agent once in .claude/agents/explorer.md. The tools frontmatter is a hard allowlist — the agent literally cannot call anything outside it:

---
name: explorer
description: Read-only codebase search and fan-out. Use for "where is X",
  "how does Y work", broad sweeps. Never edits.
tools: Read, Grep, Glob
---
You are a read-only exploration agent. Locate code and report findings
with file:line references. You have no Edit, Write, or Bash access by
design — if a change is needed, hand the conclusion back to the parent.

Pair that with a Task deny rule if you want to stop a class of agents from spawning at all, or pass --disallowedTools at startup for a one-off locked-down session:

# Block a named sub-agent from being spawned this session
claude --disallowedTools "Task(deploy-agent)"

# Belt-and-suspenders: a deny rule in settings.json applies to the
# parent AND every sub-agent it spawns, all the way down.
#   "deny": ["Edit(./infra/**)", "Bash(terraform:*)"]

The payoff is inheritance: define guardrails once at the top level and they hold across the whole agent tree. That's the reliability foundation that lets you scale to dozens of agents instead of babysitting each one. See our security hardening guide for the cross-platform version of this pattern.

Errors & Fixes

The mistakes people hit in the first hour after wiring up granular permissions:

SymptomCauseFix
Sub-agent stalls or returns "permission denied" immediately It tried a tool with no matching allow rule; sub-agents can't prompt, so the call is auto-denied. Add the tool to the agent's tools frontmatter and an allow rule, or restructure so the parent does that step.
A rule you added in allow is ignored A broader deny matches the same path. Deny takes precedence. Narrow the deny, or run /permissions to see which rule is winning and from which settings file.
Bash(npm test) still prompts every time Exact-match rule doesn't cover arguments. npm test -- --watch is a different command string. Use a prefix wildcard: Bash(npm run test:*).
Search misses files you know exist The ripgrep-based grep respects .gitignore by design. Intended behaviour — un-ignore the path, or search it explicitly if it's genuinely needed.
Personal overrides keep getting committed You edited .claude/settings.json (the shared file) instead of the local one. Put machine-specific or experimental rules in .claude/settings.local.json — it's git-ignored.

Weekly Digest — In Your Inbox

Get the week's top AI agent news, updates, and guides — every Friday.