Ultraplan just shipped as a research preview and it changes how you plan complex work. The core idea: offload the planning phase to a cloud session on Claude Code on the web, iterate on the plan through a rich browser interface with inline comments, then execute it — either in the cloud or teleported back to your terminal. Your terminal stays free the entire time.
How It Works
sequenceDiagram
participant T as Your Terminal
participant C as Cloud Session
participant B as Browser
T->>C: /ultraplan migrate auth to JWTs
Note over T: ◇ ultraplan (researching)
C->>C: Read codebase, draft plan
Note over T: ◇ ultraplan needs your input
C->>B: Plan ready for review
Note over T: ◆ ultraplan ready
B->>B: Inline comments, revisions
alt Execute on web
B->>C: Approve → implement in cloud
C->>C: Code, open PR
else Teleport to terminal
B->>T: Approve → send plan back
T->>T: Implement locally
end
Three Ways to Launch
- Command:
/ultraplan migrate the auth service from sessions to JWTs - Keyword: Just include the word
ultraplanin any normal prompt - Escalation: When Claude finishes a local plan, choose "Refine with Ultraplan on Claude Code on the web" from the approval dialog
Terminal Status Indicators
While the cloud session works, your CLI prompt shows real-time status:
| Status | Meaning |
|---|---|
◇ ultraplan | Claude is researching your codebase and drafting |
◇ ultraplan needs your input | Clarifying question — open the session link |
◆ ultraplan ready | Plan is ready for browser review |
Run /tasks and select the ultraplan entry to see the session link, agent activity, and a Stop ultraplan action.
The Browser Review Surface
This is where ultraplan earns its keep. The plan appears in a dedicated review view with:
- Inline comments — highlight any passage, leave a comment for Claude to address
- Emoji reactions — signal approval or concern without writing a full comment
- Outline sidebar — jump between sections of a long plan
You iterate as many times as needed. Claude revises the plan after each round of feedback.
Execution: Two Paths
Execute on the web: Claude implements the plan in the same cloud session. Your terminal shows confirmation, the status indicator clears. When done, review the diff and create a PR from the web interface.
Teleport back to terminal: The cloud session archives. Your terminal shows the plan with three options:
- Implement here — inject into current conversation
- Start new session — clear context, begin fresh with just the plan
- Cancel — save plan to a file, return to it later
If you start a new session, Claude prints a claude --resume command so you can return to your previous conversation.
Requirements and Gotchas
- Requires a Claude Code on the web account and a GitHub repository
- Remote Control disconnects when ultraplan starts (both occupy the claude.ai/code interface)
- The cloud session runs in your account's default cloud environment
- Known issue: #43576 — plan mode can be violated after ultraplan approval, with the model editing source files instead of the plan file
Why This Matters
Your claude -p agents handle execution well. But complex planning — the kind where you'd normally spend 20 minutes outlining an approach before writing the first prompt — is where ultraplan fits. Spin up the cloud planner for your next multi-agent refactor, review the architecture in the browser with inline comments, then teleport the plan back to your terminal for local execution. The cloud does the thinking; your machine does the doing.
Yesterday we covered Agent Teams for multi-session coordination. Today we go one level deeper: the custom subagent system. This is the single most powerful extension point in Claude Code. You define markdown files with YAML frontmatter. Claude delegates to them automatically based on task descriptions. Each subagent gets its own context window, tools, model, permissions, hooks, MCP servers, persistent memory, and skills. Here's the complete architecture.
The 17 Frontmatter Fields
Every subagent is a .md file. The YAML frontmatter configures it; the markdown body becomes the system prompt.
| Field | Required | What it does |
|---|---|---|
name | Yes | Unique identifier (lowercase + hyphens) |
description | Yes | When Claude should delegate (write this well — it drives auto-delegation) |
tools | No | Allowlist of tools. Inherits all if omitted |
disallowedTools | No | Denylist. Applied before tools resolution |
model | No | sonnet, opus, haiku, full model ID, or inherit (default) |
permissionMode | No | default, acceptEdits, auto, dontAsk, bypassPermissions, plan |
maxTurns | No | Cap on agentic turns before forced stop |
skills | No | Skills injected into context at startup (full content, not just names) |
mcpServers | No | MCP servers — inline definitions or name references to shared servers |
hooks | No | Lifecycle hooks scoped to this subagent only |
memory | No | Persistent directory: user, project, or local scope |
background | No | true to always run as background task |
effort | No | Effort level override: low, medium, high, max (Opus 4.6 only) |
isolation | No | worktree for git worktree isolation |
color | No | UI color: red, blue, green, yellow, purple, orange, pink, cyan |
initialPrompt | No | Auto-submitted first user turn when running as --agent |
The 5-Level Scope Hierarchy
Subagents are discovered through a priority cascade. Higher priority wins when names collide:
graph TD
M["1. Managed Settings
(org-wide, highest priority)"] --> C
C["2. --agents CLI flag
(session-only, JSON)"] --> P
P["3. .claude/agents/
(project-level, version-controlled)"] --> U
U["4. ~/.claude/agents/
(user-level, all projects)"] --> PL
PL["5. Plugin agents/ directory
(lowest priority)"]
Key insight: Project subagents (.claude/agents/) are discoverable by walking up from the working directory. Directories added with --add-dir are NOT scanned — they grant file access only.
Advanced Patterns
Spawn restrictions with Agent(type):
name: coordinator
description: Coordinates work across specialized agents
tools: Agent(worker, researcher), Read, Bash
---
Only worker and researcher subagents can be spawned. This is an allowlist. Omit Agent entirely to prevent all spawning.
MCP server scoping — keep tools out of the main context:
name: browser-tester
description: Tests features in a real browser using Playwright
mcpServers:
- playwright:
type: stdio
command: npx
args: ["-y", "@playwright/mcp@latest"]
- github # reference to already-configured server
---
Inline MCP definitions connect when the subagent starts, disconnect when it finishes. The parent conversation never sees these tools — saving context.
PreToolUse hooks for conditional validation:
name: db-reader
description: Execute read-only database queries
tools: Bash
hooks:
PreToolUse:
- matcher: "Bash"
hooks:
- type: command
command: "./scripts/validate-readonly-query.sh"
---
The validation script receives JSON on stdin with tool_name and tool_input, exits with code 2 to block.
Persistent memory across sessions:
name: code-reviewer
description: Reviews code for quality and best practices
memory: project
---
You are a code reviewer. Update your agent memory with patterns,
conventions, and recurring issues you discover across reviews.
Memory scopes:
user→~/.claude/agent-memory/(all projects)/ project→.claude/agent-memory/(version-controllable)/ local→.claude/agent-memory-local/(gitignored)/
When enabled, the subagent auto-loads the first 200 lines of MEMORY.md from its memory directory and has Read/Write/Edit tools force-enabled.
Skills injection — preload domain knowledge:
name: api-developer
description: Implement API endpoints following team conventions
skills:
- api-conventions
- error-handling-patterns
---
Full skill content is injected at startup. Subagents don't inherit skills from the parent — you must list them explicitly.
Model Resolution Order
When Claude invokes a subagent, the model is resolved in this order:
CLAUDE_CODE_SUBAGENT_MODELenv var (if set)- Per-invocation
modelparameter (Claude's choice at dispatch time) - Subagent definition's
modelfrontmatter - Main conversation's model
This means you can globally force all subagents to Haiku for cost control:
Session-as-Subagent Mode
Run an entire session using a subagent's configuration:
The subagent's system prompt replaces the default Claude Code system prompt entirely. CLAUDE.md files and project memory still load normally. Make it the default for a project:
"agent": "code-reviewer"
}
The @ label appears in the startup header so you know which agent is active.
Your ~/.claude/ directory is the most sensitive folder on your machine and Anthropic hasn't documented it. GitHub issue #43675 laid this bare on April 4: there is zero official documentation for the directory that stores every conversation, every prompt, and every secret that's ever passed through Claude Code. This matters especially if you're running autonomous agents that handle real credentials and system operations.
What's In There (Plaintext, Unencrypted)
| Path | What it stores | Risk |
|---|---|---|
projects/ | Complete conversation history in JSONL — every message, every tool result | Any secret that appeared in output is on disk |
history.jsonl | Every prompt you've ever typed | Command history with potential secrets |
shell-snapshots/ | Environment variables at execution time | AWS keys, GitHub tokens, API secrets in $ENV |
.meta.json files | Sub-agent task descriptions | Internal architecture exposed |
stats-cache.json | Token counts and usage metrics | Usage patterns visible |
todos/ | Abandoned task lists | Historical work context |
| Statsig stable ID | Persistent anonymous identifier | Cross-session tracking |
Every JSONL line is a separate JSON object:
{"role":"assistant","content":"I'll use that token to...","timestamp":"..."}
No encryption. No sanitization. Readable by any process with your user's file permissions.
The CVE Story: Hooks and MCP as Attack Vectors
Check Point Research disclosed two CVEs in 2026 that exploit the .claude/ directory structure:
CVE-2025-59536 — Hook-Based RCE: The .claude/settings.json file supports hooks that execute shell commands at lifecycle events. A malicious repo could inject a SessionStart hook that runs arbitrary code — and the commands execute before the user can meaningfully review the trust dialog.
CVE-2026-21852 — MCP Consent Bypass + API Key Exfiltration: The ANTHROPIC_BASE_URL field in .claude/settings.json routes API traffic through attacker-controlled servers. Combined with enableAllProjectMcpServers, this bypasses consent dialogs and exfiltrates plaintext API keys before the user clicks anything.
Impact: Reverse shells, credential theft, workspace access, billing fraud. All exploitable via malicious repositories — the supply chain attack surface for AI coding tools.
What was fixed: Anthropic deferred MCP initialization until after user approval and postponed all API requests until explicit consent. But the underlying storage model — plaintext, undocumented, unencrypted — remains unchanged.
The Documentation Gap
The official security docs mention "Secure credential storage: API keys and tokens are encrypted" but say nothing about:
- Session transcripts stored in plaintext
- Shell environment snapshots capturing secrets
- No documented wipe mechanism
- No retention policy for local data
- No encryption at rest for conversation history
The community response from issue #43675: "How is this not documented?"
Hardening Your Setup
If you're running agents with claude -p, each one generates session transcripts in ~/.claude/projects/. Here's how to reduce exposure:
1. Prune transcripts on a schedule:
0 3 * * * find ~/.claude/projects/ -name "*.jsonl" -mtime +14 -delete
2. Block sensitive directory access via deny rules in ~/.claude/settings.json:
"permissions": {
"deny": [
"Bash(cat ~/.ssh/*)",
"Bash(cat ~/.aws/*)",
"Bash(cat */.env*)",
"Read(~/.claude/projects/*)"
]
}
}
3. Audit config changes with a ConfigChange hook:
"hooks": {
"ConfigChange": [
{
"hooks": [
{
"type": "command",
"command": "echo \"[$(date)] Config changed: $HOOK_EVENT\" >> ~/.claude/audit.log"
}
]
}
]
}
}
4. Never pass secrets via environment variables to claude -p:
Instead of GITHUB_TOKEN=xxx claude -p "deploy", use a vault or secrets manager. Any env var visible at runtime gets snapshotted to shell-snapshots/.
5. Set restrictive permissions on the directory:
chmod 600 ~/.claude/projects/*/*.jsonl
The Operator's Takeaway
"Secure credential storage" in the official docs refers to your Anthropic API key and OAuth tokens — not your session data. Everything that flows through Claude Code's tools — every cat .env, every curl response, every database query result — lives in plaintext JSONL on your filesystem. Until Anthropic ships encryption at rest and documented retention controls, treat ~/.claude/ as you'd treat your browser profile: assume it contains everything and protect it accordingly.
Conductor is the most architecturally ambitious community project I've seen this quarter. It turns a single Claude Code session into a control plane that monitors, approves, blocks, and sends tasks to all your other sessions. Built by rmindgh, it requires Claude Code v2.1.92+ and implements a four-layer orchestration stack using an MCP bridge server and the undocumented Remote Control WebSocket API.
Four-Layer Architecture
graph LR
subgraph Layer1["Layer 1: Awareness"]
direction TB
LS[list_sessions] --> GA[get_activity]
GA --> GS[get_status]
GS --> GAW[get_all_waiting]
end
subgraph Layer2["Layer 2: Decisions"]
direction TB
SG[set_goal] --> GG[get_goals]
GG --> MD[make_decision]
MD --> LE[log_event]
end
subgraph Layer3["Layer 3: Guardrails"]
direction TB
SF[set_flag] --> CF[clear_flag]
CF --> GF[get_flags]
end
subgraph Layer4["Layer 4: Remote Control"]
direction TB
DR[discover_rc_sessions] --> ST[send_task]
end
Layer1 --> Layer2
Layer2 --> Layer3
Layer3 --> Layer4
style Layer1 fill:#1a1a2e
style Layer2 fill:#16213e
style Layer3 fill:#0f3460
style Layer4 fill:#533483
13 MCP tools spread across four categories, exposed via bridge-server.py (Python).
How It Works
bridge-server.py — the MCP server. Registers as conductor in your project's MCP config. Exposes awareness, decision, guardrail, and remote control tools. Stores state in ~/.claude/conductor/ (goals.json, decisions.json, log.md, flags/).
conductor-guard.js — a PreToolUse hook. Evaluates every tool call against dangerous patterns (SQL injections, git push --force, rm -rf, DROP TABLE) and per-session flag files. Blocks with {"decision": "block"} on exit code 0.
remote-control.py — WebSocket service. Subscribes to wss://api.anthropic.com/v1/sessions/ws/{id}/subscribe. Handles tool approval/denial via control_response and message injection via POST /v1/sessions/{id}/events.
Stall Detection
Conductor detects stuck sessions through three mechanisms:
- Tool requests without results (
stop_reason: "tool_use"with no follow-up) - No progress events for 90+ seconds (configurable)
- Empty hook artifacts masking session state
Orchestration Patterns
Sequential workflow: "Send 'run test suite' to the rentcompare session" — one completes, then the next receives instructions.
Monitoring loop: /loop 3m check all sessions, report changes, approve safe stalls — periodic polling with automated risk-based decisions.
Task chaining: Session A finishes → results forwarded to Session B automatically.
Risk-based auto-approval: Goals registered with risk levels inform whether Conductor auto-approves tool calls or escalates to you.
Setup
"mcpServers": {
"conductor": {
"command": "python",
"args": ["/path/to/.claude/conductor/bridge-server.py"]
}
}
}
Register the guard hook for PreToolUse matching Bash|Write|Edit|Agent. Start managed sessions with claude --rc to enable WebSocket subscriptions.
Limitations Worth Knowing
- Built on undocumented APIs — Anthropic hasn't officially published the Remote Control WebSocket protocol
- WebSocket must connect before approval prompts appear (no retroactive approval)
- JSONL logs show tool names incompletely; WebSocket provides full context
- OAuth token refresh reads from
~/.claude/.credentials.json(couples to internal file format) - MIT license, but caveat emptor on API stability
Why This Matters
If you're running multiple agents, Conductor is the missing control plane. Instead of SSH-ing into tmux panes to check on each agent, you'd have a single Conductor session monitoring all of them — detecting stalls, approving safe operations, blocking dangerous commands, and chaining workflows. The architecture is sound even if the underlying APIs are unofficial. Watch for official Remote Control API docs to stabilize this approach.
You've read the subagent architecture deep dive. Now build three specialized subagents that directly improve your agent operations: a security auditor, a cost-conscious researcher, and a system health checker. Each one demonstrates different advanced features.
Prerequisites
- Claude Code v2.1.92+
- A project directory (we'll use
~/agents/claude-mastery/as the target) - Familiarity with YAML frontmatter and hooks
Part 1: The Security Auditor (15 min)
This subagent scans for secrets in files and outputs, uses read-only tools, validates its own Bash commands with a PreToolUse hook, and builds persistent memory of findings.
Step 1 — Create the hook script:
cat > ~/agents/claude-mastery/.claude/hooks/validate-readonly.sh << 'HOOK'
#!/bin/bash
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty')
# Block any write operations
if echo "$COMMAND" | grep -iE '\b(rm|mv|cp|dd|mkfs|write|>|>>|tee|install|apt|pip|npm)\b' > /dev/null; then
echo "Blocked: Security auditor is read-only" >&2
exit 2
fi
# Block network access
if echo "$COMMAND" | grep -iE '\b(curl|wget|nc|ssh|scp|rsync)\b' > /dev/null; then
echo "Blocked: Security auditor cannot access network" >&2
exit 2
fi
exit 0
HOOK
chmod +x ~/agents/claude-mastery/.claude/hooks/validate-readonly.sh
Step 2 — Create the subagent file:
Write this to ~/agents/claude-mastery/.claude/agents/security-auditor.md:
name: security-auditor
description: "Scans project files and Claude session data for exposed secrets, credentials, and sensitive patterns. Use proactively before commits or when reviewing agent output."
tools: Read, Grep, Glob, Bash
model: haiku
permissionMode: dontAsk
memory: project
color: red
effort: high
hooks:
PreToolUse:
- matcher: "Bash"
hooks:
- type: command
command: ".claude/hooks/validate-readonly.sh"
---
You are a security auditor for a server running autonomous Claude Code agents.
## Your Job
Scan for exposed secrets, credentials, API keys, tokens, and sensitive data in:
1. Project files (*.env, config files, scripts)
2. Claude session transcripts (~/.claude/projects/ JSONL files)
3. Shell environment snapshots
4. Git history (check for accidentally committed secrets)
## Patterns to Flag
- API keys: patterns like `sk-`, `ghp_`, `AKIA`, `xoxb-`, `Bearer `
- Passwords in plaintext
- Private keys (BEGIN RSA/EC/OPENSSH PRIVATE KEY)
- Database connection strings with credentials
- JWT tokens
- Hardcoded IPs with credentials
## Output Format
For each finding:
- **File**: path and line number
- **Type**: what kind of secret
- **Risk**: HIGH/MEDIUM/LOW
- **Action**: recommended remediation
Update your agent memory with:
- Patterns you've seen in this project
- False positives to skip next time
- Recurring issues to flag proactively
Step 3 — Verify it loads:
You should see security-auditor listed under project agents. Test it:
Part 2: The Cost-Conscious Researcher (10 min)
A Haiku-powered research subagent that runs in the background, preserving your main context window. Uses effort: low to minimize token spend.
Write to ~/agents/claude-mastery/.claude/agents/quick-researcher.md:
name: quick-researcher
description: "Fast, cheap research agent for codebase exploration and documentation lookups. Runs on Haiku to minimize cost."
tools: Read, Grep, Glob, Bash, WebFetch, WebSearch
model: haiku
background: true
effort: low
maxTurns: 15
color: blue
memory: project
---
You are a fast research agent. Your job is to find information quickly
and return concise, actionable answers.
Rules:
- Never modify files
- Summarize findings in under 200 words
- Include file paths and line numbers for code references
- If you can't find it in 10 turns, say so and suggest where to look
- Update your memory with useful codebase landmarks you discover
Part 3: The System Health Checker (15 min)
This one demonstrates MCP server scoping and the initialPrompt field. It runs as a standalone agent via claude --agent.
Write to ~/agents/claude-mastery/.claude/agents/health-checker.md:
name: health-checker
description: "Checks system health: Docker containers, systemd services, disk usage, memory, and agent processes."
tools: Read, Bash, Glob, Grep
model: sonnet
permissionMode: acceptEdits
maxTurns: 20
color: green
memory: user
initialPrompt: "Run a full system health check on this server. Check Docker containers, systemd services, disk usage, RAM, and any running claude processes. Report issues and compare against your memory of previous checks."
---
You are a system health monitor for a Linux server.
## Services to Check
- Docker: list your containers (e.g., `docker ps --format 'table {{.Names}}\t{{.Status}}'`)
- Systemd: list your key services (e.g., `systemctl is-active <service-name>`)
- Resources: RAM (alert if >85%), disk (alert if >80%), CPU load
## Health Check Protocol
1. Run `docker ps --format 'table {{.Names}}\t{{.Status}}'`
2. Run `systemctl is-active <your-services>`
3. Run `free -h` and `df -h /`
4. Run `ps aux | grep 'claude' | grep -v grep`
5. Compare results against your memory of previous checks
6. Flag any new issues or improvements since last run
## Output Format
Use a table with Service | Status | Notes columns.
End with an overall health score (GREEN/YELLOW/RED).
Update your agent memory with current baselines after each check.
Part 4: Test the Fleet (10 min)
Test 1 — Security auditor (foreground, explicit @-mention):
Expected: Haiku runs in foreground, reads JSONL files, reports findings using the specified format.
Test 2 — Quick researcher (background):
Expected: Runs in background (blue indicator). Returns a concise summary. Your main conversation stays unblocked.
Test 3 — Health checker as standalone agent:
Expected: Launches with the initialPrompt auto-submitted. Sonnet runs the full health check protocol. Green @health-checker label in the startup header.
Test 4 — Verify persistent memory after all three:
ls -la ~/.claude/agent-memory/
Expected: security-auditor/ and quick-researcher/ under .claude/agent-memory/ (project scope). health-checker/ under ~/.claude/agent-memory/ (user scope).
Architecture Discussion
graph LR
YOU[You / Main Session] --> SA["security-auditor
Haiku · read-only · hooks"]
YOU --> QR["quick-researcher
Haiku · background · low effort"]
YOU --> HC["health-checker
Sonnet · standalone · user memory"]
SA --> PM1["project memory
.claude/agent-memory/security-auditor/"]
QR --> PM2["project memory
.claude/agent-memory/quick-researcher/"]
HC --> UM["user memory
~/.claude/agent-memory/health-checker/"]
Why these model choices matter:
- Security auditor on Haiku: Pattern matching (grep for
sk-,ghp_) doesn't need Opus-level reasoning. Haiku is fast and cheap for scanning. - Quick researcher on Haiku: Background research should be fast and context-light. Low effort keeps token spend minimal.
- Health checker on Sonnet: Needs to interpret
docker psoutput, compare against baselines, make judgment calls. Sonnet balances capability and speed.
Why persistent memory matters:
- The security auditor learns your project's false positives across sessions
- The researcher maps your codebase's landmarks — saves re-exploration
- The health checker tracks baselines — "RAM was 72% last time, now it's 91%" requires history
Why hook-based validation matters:
- The security auditor is read-only by design, but it has
Bashaccess for runninggrep,find,git log. The PreToolUse hook ensures it can't escalate to writes or network access — a "wall" rather than a "sign" (see Issue #2).
Verification Checklist
- [ ] All three agents appear in
claude agentsoutput - [ ] Security auditor blocks write commands (try: tell it to
rma file) - [ ] Quick researcher runs in background (blue indicator)
- [ ] Health checker launches with
--agentand auto-runs the initial prompt - [ ] Memory directories exist after first run
- [ ] Second run of security auditor references findings from first run
## Newsflash
v2.1.92 shipped April 4: forceRemoteSettingsRefresh (fail-closed policy for managed settings), interactive Bedrock setup wizard, per-model /cost breakdown with cache-hit stats, Write tool 60% faster, /tag and /vim commands removed. Minor release — no new paradigms.
MemoryBank (github.com/feelingsonice/MemoryBank): Rust-based unified memory across Claude Code, Codex, Gemini CLI, and OpenCode. SQLite + vector embeddings, MCP integration for all agents. Hooks capture events, retrieve_memory MCP calls for recall. The mb CLI handles setup, monitoring, and config. Worth watching as multi-tool development becomes standard.
Yoink (github.com/theogbrand/yoink): AI agent that reimplements only the functionality you need from a dependency, eliminating the package entirely. Python only for now. Install as a Claude Code plugin: /plugin marketplace add theogbrand/yoink. The supply chain security angle is real — fewer dependencies = smaller attack surface.
*Next issue: Monday, April 7. Weekday mode — lighter, faster, focused.*