From the Inside Claude Code: The Claude Code Ecosystem architecture map
Every defence against hidden instructions rests on one small sanitizer
sanitizer.ts is imported by 8 files across 7 modules: the prompt builder, the context formatter, the tracking comment, the comment and inline comment MCP servers, post-run reporting and the run orchestrator. It is a list of regexes with no other layer behind it, so a regression silently reopens every inbound and outbound path at once.
Impact: A missed pattern, such as a new Unicode tag block or an HTML construct, lets hidden instructions reach Claude everywhere at once.
Recommendation (small effort): Add a shared fixture test of known hiding tricks that runs against sanitizeContent and against each caller's output, so a gap fails CI at every entry point.
The trail
Open on the mapMore from this board
- Session Store is a single point of failure for 7 modules, from the clients to the package exports
- Optional SessionStore methods raise instead of being absent, so a change in Types reaches 13 modules
- Interrupt and other control calls stall when nobody is reading messages
- Day 1: start with marketplace.json, the contract everything else serves
- Day 2: follow the install path from Claude Code into one plugin
- Session Store is shared by three groups of code, so a change to it reaches all of them
- Every SDK module imports its exceptions from one file, _errors.py
- can_use_tool is a ready gate seam with subagent provenance
- PR-controlled agent config is restored from the base branch before Claude starts
- Start with the gate order in the Run Orchestrator
- Then follow untrusted text from GitHub into the prompt
- The action and the base action share an untyped prompt-file contract
- The transport is the only translator from options to Claude Code CLI flags
- Both public entry points share one control-protocol engine
- Learn issue automation as one loop from GitHub event back to GitHub
- The gh.sh wrapper is the safety contract both Claude jobs rest on
- The triage and dedupe agents are boxed in identity, tools and network
- Claude jobs reach GitHub only through a read-only wrapper and event-bound writes
- Day 3: the chat-channel flow shows the only long-running code
- Day 4: CI keeps the catalogue honest and current
- Public API code reaches straight into Session Store instead of going through a session entry point
- A failed SessionStore append is retried, then dropped; mirror_error is the only signal
- Channel messages carry sender identity, giving the session provenance
- CI already gates external plugins with an agent and reverts on failure
- Sessions copies the CLI's folder-naming hash, and 6 modules depend on that copy
- Spend and run length are bounded at the transport
- Tag mode gives Claude a narrow, workspace-bound tool list
- Skip post-run reporting and branch plumbing at first
- Command-line construction is hardened against argument injection
- Tool permission requests fail closed
- Skip the engine, mods and examples when the goal is issue automation
- Lifecycle timeouts are restated outside their single source of truth
- The duplicate comment script is pinned to the upstream repository
- Every agent-driven closure has a human override before it happens
- Skip for now: config-only integrations, CI plumbing and single-file plugins
- Key vocabulary: marketplace entry, plugin, channel, pairing, permission relay, SHA bump
- Plugins are fully independent and deploy on their own
- External-PR workflows never execute contributor code
- Channel servers keep bot tokens owner-only and refuse injected pairing requests