a visual tour

How Claude Code agents actually work

A plain-English walkthrough of the source tree in this folder — the agent loop, the tools it can call, the sub-agents it can spawn, the background tasks it tracks, and the guardrails in front of it all. No prior knowledge required.

TypeScript / Bun React + Ink (terminal UI) Anthropic SDK MCP (Model Context Protocol) ~40 built-in tools

00TL;DR — the 30-second version

  • An agent is a loop. You type. The model replies with either text or a "tool use". If it's a tool, the program runs it locally, sends the result back to the model, and repeats — until the model has no more tools to run.
  • Tools are just functions with permission checks. BashTool runs shell commands. FileEditTool edits files. WebFetchTool fetches URLs. Each has a schema, a permission gate, and a UI.
  • The agent can spawn sub-agents. AgentTool lets the main agent delegate a self-contained task to a fresh mini-agent that has its own context window.
  • Tasks are long-running units. A shell command, a sub-agent, a remote agent, or a scheduled "teammate" all live in the same task registry so the UI can show their status.
  • Memory persists across sessions. The memdir/ folder stores facts about you, feedback you've given, and project context — indexed by MEMORY.md.

01The core loop (the heart of it all)

Everything else is scaffolding around this one cycle.

You

Type a message, or run a slash command like /commit.

──▶
Anthropic API

Receives your message + a system prompt + available tools.

↓ model streams back
Text answer

Shown to you. Loop ends.

OR
Tool use

E.g. "run ls" or "read file.ts".

↓ if tool use
Permission gate

Allowed? Ask you? Blocked?

──▶
Tool runs locally

Output captured.

↓ send result back to model, repeat
Where this lives in code: the main loop is in query.ts and QueryEngine.ts. The tool-result round-trip is what keeps the model "grounded" in your actual machine instead of hallucinating.

Step by step

1

Build the request

The engine assembles: the system prompt (constants/prompts.ts), your messages, the conversation history, the list of tools currently available, and any memory that looked relevant.

2

Call the model

The API is called with retries and fallbacks (services/api/withRetry.js). The response streams back token by token so the UI can render as it arrives.

3

Inspect the reply

If the model wants to use a tool, the reply contains a tool_use block: the tool name and the JSON arguments. Otherwise, it's just text, and the turn is over.

4

Check permissions

useCanUseTool decides: allowed automatically, ask the user, or deny. Rules come from your settings, CLI flags, and hook scripts you configured.

5

Run the tool

Each tool's call() does its real work: spawn a shell, read a file, fetch a URL, spawn a sub-agent. Progress can stream back to the UI.

6

Feed the result back

The tool's output becomes a tool_result message, appended to the conversation. Then we go back to step 1 — the model now sees what happened and decides what to do next.

7

Compact if needed

If the conversation is getting close to the context limit, services/compact/ summarizes older turns so the agent can keep working without hitting the ceiling.

02Tools — what the agent can actually do

Think of tools as the agent's hands. Each one is a small TypeScript module in tools/.

Reading & exploring

FileReadTool
Read any file (text, images, PDFs, notebooks).
GlobTool
Find files by name pattern, like src/**/*.tsx.
GrepTool
Search file contents (built on ripgrep).
LSPTool
Use a language server for symbols & diagnostics.

Editing & running

FileEditTool
Replace a string in a file, exactly.
FileWriteTool
Create or overwrite a file.
NotebookEditTool
Edit a Jupyter notebook cell.
BashTool
Run a shell command (with security & sandbox checks).
PowerShellTool
Same idea, for Windows.
REPLTool
Run code in an ambient JS/TS REPL (ant-only).

Reaching out

WebFetchTool
Fetch a URL and summarize it.
WebSearchTool
Search the web.
MCPTool
Call any tool exposed by a connected MCP server.
ReadMcpResourceTool
Fetch a resource from an MCP server.

Delegation & coordination

AgentTool
Spawn a sub-agent with its own context. See §3.
SkillTool
Run a packaged skill/workflow from skills/.
TaskCreate/List/Get/Stop/Output
Manage background tasks.
CronCreate/List/Delete
Schedule recurring runs.
RemoteTriggerTool
Kick off a remote agent via the bridge.
SendMessageTool
Send a message to a running teammate/sub-agent.

UI & session

AskUserQuestionTool
Pause and ask you a clarifying question.
TodoWriteTool
Track multi-step work as checkable todos.
EnterPlanMode / ExitPlanMode
Switch between "planning" and "doing".
EnterWorktree / ExitWorktree
Isolate work in a git worktree.
ToolSearchTool
Load more tools on demand to save context.
BriefTool
Summarize a session briefly.
Registration lives in tools.ts. Tools can be gated by feature flags (e.g. feature('AGENT_TRIGGERS')) or by a user type — so what shows up depends on the build and environment.

03Sub-agents — the agent spawning agents

The main agent can say "I'll let a specialist handle this" and delegate. The specialist returns one answer and disappears.

Main agent

Sees your conversation, uses the full tool set, drives the REPL. One per session.

Sub-agent

Spawned via AgentTool. Gets a fresh context, a narrower instruction, and returns a single result back to the parent. Doesn't see the parent's conversation — only the prompt it was given.

What it looks like in practice

You: "Audit this repo for dead code." └─ Main agent decides to parallelize ├─ Sub-agent A — "find unused exports in src/api" ├─ Sub-agent B — "find unused exports in src/ui" └─ Sub-agent C — "find unused exports in src/utils" │ each returns a report ▼ Main agent merges reports, shows you the combined list
Why this matters: sub-agents have their own context window. They can read a hundred files and come back with a 200-word summary — the big stuff never pollutes the main conversation. That's how Claude Code can survey large codebases without running out of room.

Agent types

general-purpose

Broad research or open-ended coding tasks.

Explore

Fast codebase exploration (search, read, summarize).

Plan

Designs an implementation plan before you commit.

statusline-setup

Configures the CLI status line — narrow scope.

claude-code-guide

Answers "how do I…" questions about Claude Code itself.

deployment-seo-orchestrator

End-to-end deploy + SEO workflow example.

Definitions for built-in agents live in tools/AgentTool/built-in/. Users can add their own in ~/.claude/agents/.

04Tasks — long-running work the agent tracks

When something doesn't finish instantly, it becomes a task with an ID, a status, and an output file. The UI shows all of them; the agent can poll or kill them.

b local_bash

A shell command running in the background.

a local_agent

A sub-agent running on your machine.

r remote_agent

An agent running in the cloud (via the bridge).

t in_process_teammate

A long-lived teammate you can chat with alongside the main session.

w local_workflow

A packaged workflow (skill) running as a task.

m monitor_mcp

A streaming MCP monitor feeding events in.

d dream

Opportunistic background "thinking" work.

pending running completed failed killed
Each task type has its own runner folder under tasks/. The base shape & ID scheme are defined in Task.ts.

05Permissions & safety

The model can ask for anything. The program decides what actually happens.

Auto-allow
Read-only things: reading files, globbing, grepping. Cheap and safe.
Ask the user
First time a command runs, destructive operations, things that touch shared state (push, delete, send).
Deny
Policy-forbidden commands, sandbox escapes, or rules explicitly blocked in settings.
Hooks (yours)
Shell scripts you configure in settings.jsonPreToolUse, PostToolUse, UserPromptSubmit — can approve, deny, or modify tool use.
Modes
plan mode blocks edits; bypass permissions auto-accepts (only if you opted in); worktree isolates changes to a temp branch.
Two kinds of "hooks" in this repo: the hooks/ folder holds React UI hooks for the terminal. Settings-file hooks (the shell-script kind) are schema'd in schemas/hooks.ts.

06Memory — what survives between sessions

The agent doesn't remember on its own. A dedicated memory layer writes small Markdown files that are re-read in future conversations.

user

Your role, goals, preferences. Helps the agent tailor explanations to who you are.

feedback

Corrections and confirmations. "Don't mock the DB in tests" stays true next week.

project

Current initiatives, deadlines, why things are the way they are. Decays fast — updated often.

reference

Pointers to external systems: "pipeline bugs are in Linear project INGEST".

Each entry is a file with frontmatter. MEMORY.md is the short index loaded into every conversation. Code lives in memdir/.

07The system prompt — the rules of the game

Before any of this runs, the model is given a long system prompt: who it is, what it can do, how to format answers, when to ask vs. act.

  • Identity. "You are Claude Code, Anthropic's official CLI…"
  • Tone rules. Concise answers, no emoji unless asked, minimal preamble.
  • Tool guidance. Prefer dedicated tools over Bash, batch independent calls in parallel, don't narrate internal thinking.
  • Safety rails. Ask before destructive or shared-state actions; investigate before deleting unfamiliar state.
  • Environment. Cwd, git status, platform, model ID, today's date — injected fresh each session.

Assembled in constants/prompts.ts from the section files in constants/systemPromptSections.ts. You can dump the exact prompt via the internal --dump-system-prompt flag.

08Putting it all together

1 · Entry

entrypoints/cli.tsxmain.tsx parses flags, loads config, starts the REPL (or a one-shot print mode).

2 · REPL

An Ink (React-in-the-terminal) app renders the chat, input box, status line, and dialogs. State lives in state/AppState.

3 · Query engine

Every turn goes through query.ts / QueryEngine.ts: build messages → call API → handle tool uses → compact if needed → repeat.

4 · Tools

Each tool in tools/ owns its schema, permission checks, execution, and terminal UI. Registered in tools.ts.

5 · Tasks & sub-agents

Long work goes into the task registry (tasks/). Sub-agents spawned by AgentTool are just another task type.

6 · Services

Outside-world integrations: Anthropic API, MCP servers, OAuth, analytics, plugins, team sync, compaction. All under services/.

7 · Memory

Persisted in memdir/. Loaded at session start, updated when you (or the agent) decide something is worth keeping.

09A quick mental model

When you send a message, picture a conveyor belt:

  1. Your words + history + tool menu → sent to the model.
  2. The model writes back either words for you, or a tool request.
  3. If it's a tool, the program runs it locally under permissions and drops the result back on the belt.
  4. The belt loops until the model has no more requests — then you see the final answer.
  5. Memory, tasks, sub-agents, and MCP servers are optional conveyors the main belt can pull from.

That's the whole thing. Everything else in this repository is either a new tool, a new kind of task, a new way to render the belt, or a guardrail to keep the belt from hitting something it shouldn't.