The agents in From Function Calling to the Agent Loop and Engineering Around the Model had a handful of tools and short tasks. A coding agent works in a repository of thousands of files, with tools that can run anything a developer can, on tasks that take dozens of steps. It is the most demanding agent harness in wide use, and also the one with the best feedback: code can be compiled and tested, so “done” can be checked by a program. This post describes how two widely used coding agents work, Anthropic’s Claude Code and Cursor’s agent, using only what their documentation and engineering posts state, as of October 2026. Both products change quickly; the design questions they answer don’t.
A coding agent is a harness around a model: what it sees is managed, what it does passes through controls outside the model, and tests make “done” a check rather than a claim. Hooks run every time but are not a boundary on their own; the sandbox is what contains a command.
- A coding agent is a harness around a model: five groups of tools (files, search, execution, web, code intelligence) in a gather-act-verify loop, with executable checks that make “done” real.
- Both Claude Code and Cursor now find code with fast exact search driven by the model, plus exploration subagents. Cursor reported a 12.5% gain from its embedding index in 2025 and dropped the index in 2026, saying models had become good enough with grep.
- Controls sit outside the model: permission modes, sandboxing, and checkpoints, kept about 30 days, that undo file edits but not shell or remote side effects.
- Hooks run every time but are not a security boundary alone: the one here blocked 4 of 8 pending commands, and let a Python delete of the same directory through.
Table of contents
Open Table of contents
The loop and its tools
Claude Code’s documentation describes its loop in three phases that blend together: gather context, take action, verify results. A question about the code may need only the first; a bug fix cycles through all three. “Claude Code is the layer around the model that provides the tools and manages the context the model sees,” in the documentation’s words: the harness. Its built-in tools fall into five groups:
| Group | What the model can do |
|---|---|
| File operations | Read files, edit code, create and reorganize files |
| Search | Find files by pattern, search content with regular expressions |
| Execution | Run shell commands: builds, tests, git, servers |
| Web | Search the web, fetch documentation |
| Code intelligence | Type errors after edits, jump to definition, find references (via plugins) |
Plus tools for orchestration: spawning subagents, asking the user a question. “Fix the failing tests” becomes, in the documentation’s own example: run the test suite, read the failures, search for the relevant source files, read them, edit, run the tests again. Each tool result decides the next step, the loop of From Function Calling to the Agent Loop with a real development environment as its world.
The three phases blend; each tool result decides the next step.
Finding code: grep or an embedding index
Before an agent can change code, it has to find it. There are two approaches, and the two products show both, at different times.
Agentic search. Claude Code’s search tools are pattern matching on
file names and regular-expression search over contents, the tools a
developer uses from a terminal. The model decides what to search for,
reads what it finds, and searches again: retrieval as a loop, the
agentic retrieval of Beyond Vector RAG, with grep as the retriever. There is no
index to build or keep fresh, exact identifiers are found exactly, and
nothing about the code leaves the machine except what the model reads.
An embedding index, alongside grep. Cursor’s agent used both. Its engineering posts describe splitting each file into syntactic chunks, embedding them with a model of its own (trained on what agents should have retrieved in real sessions), and keeping the index current with a Merkle tree: a hash of every file, and of every folder from its children’s hashes, so comparing two trees finds exactly which files changed (Semantic and Hybrid Search’s semantic search, applied to code). In November 2025 Cursor reported that adding semantic search to grep improved its agent’s answers by 12.5% on average (6.5% to 23.5% depending on the model), and that the combination worked best.
How Cursor’s index stayed current: compare hash trees and re-embed only the files on changed paths. The tree is schematic.
By July 2026 it had turned the embedding index off. Its documentation now describes the agent’s search as Instant Grep, a regular-expression search whose index is built and queried on the user’s machine, and states that Cursor “does not upload file paths or code to build a search index, and it does not store embeddings of your codebase for search” (files the agent opens are still sent to the model, as with any coding agent). For broad questions, the agent can spawn an Explore subagent, running a faster model, that does many searches in its own context and returns only the findings. Cursor’s staff gave the reason on its forum: models “have gotten really good at using grep / indexed search, so the older dedicated semantic search path was rapidly no longer helping in a meaningful way.”
So in mid-2026 both products search the same way: fast exact search driven by the model, with subagents to keep exploration out of the main context. My reading of why that suffices for code (not a reason either company gave): identifiers and error strings are exact, so exact search finds them, and a capable model compensates for not knowing a name by searching again with what it learned. Semantic search helped most when models were worse at that loop.
Two products, one destination: exact search, driven by a model good enough to search again with what it learned.
Verification: a definition of done that runs
What makes coding agents work better than most agents is that their
output can be checked mechanically. Tests pass or fail; code compiles or
doesn’t; a type checker reports errors. Claude Code’s code-intelligence
tools surface type errors and warnings after each edit, and its loop
treats running the tests as part of the task, not a separate step. Its
best-practices guide gives the same advice first: give the agent a way to
verify its work (a test command, an expected output, a screenshot to
compare against). It also offers ways to make the check binding rather
than a request: a goal condition that a separate evaluator re-checks
after every turn, or a hook on the Stop event that runs the check and
refuses to let the turn end until it passes. A coding agent without a check is a
generator of plausible diffs; with one, it’s a loop that converges.
Memory and context
A coding session can run for hours over a codebase far larger than any context window, which makes context management (Context Engineering) central.
- Project memory files. Claude Code reads
CLAUDE.mdfiles (project instructions, conventions, commands) into every session, and can readAGENTS.md, the convention other coding agents use. It also keeps auto memory, notes it saves as it works, of which the first 200 lines or 25 KB load at the start of each session. Cursor’s equivalent is rules files, and its documentation lists the same extension points this post describes for Claude Code: skills, subagents, hooks, MCP and worktrees. - Compaction. As the window fills, Claude Code first clears older tool
outputs, then summarizes the conversation; the documentation warns that
detailed early instructions can be lost, which is why persistent rules
belong in
CLAUDE.md. - Loading on demand. Tool definitions from MCP servers (Giving Agents Tools and Knowledge) are deferred and loaded through a tool search; skills show only their descriptions until used; subagents work in their own context window and return a summary. Each keeps something out of the main context until it’s needed.
Permissions and checkpoints
A coding agent can run any command its user can, so both products put controls around actions.
- Permission modes. Claude Code offers several, cycled with a key: a
mode where a classifier reviews actions in the background and blocks
risky ones; a manual mode that asks before edits and commands; one that
accepts file edits but asks for other commands; and a plan mode that
explores and proposes without editing. (The edit-accepting mode also
runs common file-system commands like
mkdirandmvwithout asking.) Specific commands (npm test,git status) can be allowed in a settings file shared with the team. - Sandboxing. The containment layer underneath: operating-system-level limits on which files and network destinations commands can reach, so a command that slips past every other check still can’t touch what’s outside the sandbox.
- Checkpoints. Each prompt that starts a turn creates a checkpoint, and files are snapshotted before the agent’s edits, so changes can be rewound; snapshots are kept for about 30 days. The documentation is explicit about the limits: checkpoints track only changes made through the file-editing tools, not files changed by shell commands; most edits made by subagents aren’t restored by a rewind; and actions on remote systems (databases, APIs, deployments) can’t be undone at all, which is what permissions are for. Checkpoints don’t replace git.
Defense in depth: each outer layer bounds what the inner one misses.
Subagents and hooks
Subagents are agents the main agent starts for a delegated task, each with its own context, tools and instructions (Many Agents’s many-agent patterns, built into the product). Their value is mostly context hygiene: a search that reads fifty files happens in a subagent, and the main conversation gets a summary.
Hooks are where a team’s rules become code. Claude Code runs a hook at
fixed points in its lifecycle (before and after each tool call, when the
user submits a prompt, when the agent stops, before compaction, and more),
and a hook can be a shell command, an HTTP endpoint, an MCP tool call, a
model prompt or a subagent. A command hook receives the event as JSON on
standard input; for a PreToolUse event, exiting with code 2 blocks the
pending tool call, and whatever it printed is shown to the model as the
reason (a JSON reply with a “deny” decision is the structured
alternative). A small one that stops recursive force deletes and force
pushes, registered for the Bash tool in the project’s
.claude/settings.json:
{
"hooks": {
"PreToolUse": [
{ "matcher": "Bash", "hooks": [{ "type": "command", "command": "python3 .claude/hooks/guard.py" }] }
]
}
}
The hook, guard.py:
#!/usr/bin/env python3
# A PreToolUse hook for Claude Code: it receives the pending tool call as
# JSON on stdin; exit code 2 blocks the call, and what it prints to stderr
# is shown to the model as the reason. Exit 0 lets the call proceed.
# A check like this shows the mechanism; it is not a security boundary (a
# command can always be written another way).
import json
import re
import shlex
import sys
def dangerous(command):
try:
words = shlex.split(command)
except ValueError:
return False
for i, w in enumerate(words):
args = []
for a in words[i + 1:]: # this command's arguments end at a separator
if a in ("&&", "||", "|", ";"):
break
args.append(a)
if a.endswith(";"): # "main;" ends the command too
break
flags = "".join(a.lstrip("-") for a in args if a.startswith("-") and not a.startswith("--"))
long = {a for a in args if a.startswith("--")}
if w == "rm" and ("r" in flags.lower() or "--recursive" in long) and ("f" in flags or "--force" in long):
return True # rm -rf, -fr, -r -f, -Rf, --recursive --force
if w == "push" and i > 0 and words[i - 1] == "git":
if "f" in flags or "--force" in long or any(re.match(r"\+", a) for a in args):
return True # force push (--force-with-lease is allowed)
return False
event = json.load(sys.stdin)
if event.get("tool_name") == "Bash" and dangerous(event.get("tool_input", {}).get("command", "")):
print("Blocked by project policy: recursive force delete or force push. Ask the user first.", file=sys.stderr)
sys.exit(2)
sys.exit(0)
try_guard.py feeds it some pending calls, as Claude Code would:
import json
import subprocess
import sys
# Feed the hook pending tool calls, as Claude Code would.
for command in ("npm test", "rm -rf build/", "rm -fr build/", "rm -r -f build/", "rm build/old.log",
"git push --force-with-lease", "git push -f origin main", "python -c 'import shutil; shutil.rmtree(\"build\")'"):
event = {"hook_event_name": "PreToolUse", "tool_name": "Bash", "tool_input": {"command": command}}
r = subprocess.run([sys.executable, "guard.py"], input=json.dumps(event), capture_output=True, text=True)
print(f"{command!r:58s} -> {'allowed' if r.returncode == 0 else 'blocked (exit 2)'}")
'npm test' -> allowed
'rm -rf build/' -> blocked (exit 2)
'rm -fr build/' -> blocked (exit 2)
'rm -r -f build/' -> blocked (exit 2)
'rm build/old.log' -> allowed
'git push --force-with-lease' -> allowed
'git push -f origin main' -> blocked (exit 2)
'python -c \'import shutil; shutil.rmtree("build")\'' -> allowed
A hook is deterministic where an instruction in CLAUDE.md is only a
request: the model may forget a rule after compaction, but the hook runs
every time. Running every time isn’t the same as being unbypassable,
though: the last case deletes the same directory through Python, and the
hook can’t see it. A hook like this catches mistakes; containment against
a determined or manipulated agent comes from sandboxing and permissions.
That’s the general lesson of Guardrails and Prompt Injection
applied to a coding agent: enforce what must hold outside the model, at
the layer that actually bounds it.
The hook catches every spelling of the shell command it knows, and none of the other ways to do the same thing.
Data: the output aboveCursor’s other models: tab and apply
Cursor’s agent is one part of an editor built around several specialized models.
- Tab predicts the developer’s next edit, not just the next tokens at the cursor, and offers it inline. Cursor reported training it with online reinforcement learning on users’ accept and reject signals, rolling out a new checkpoint every hour and a half to two hours; the resulting model made 21% fewer suggestions with a 28% higher acceptance rate. Knowing when not to suggest is half the job.
- Apply turns a model’s proposed change into an edit of the actual file. Cursor’s 2024 post describes a fine-tuned 70B model that rewrites the whole file at about 1,000 tokens per second using speculative edits: speculative decoding (Speculative Decoding, Derived) where the draft is the original file itself, since most of an edited file is unchanged and the model mostly confirms it.
Speculative decoding with the file itself as the draft model. The tokens are illustrative.
Where this leads
- Evaluating and Observing Agents measures agents like these: SWE-bench, pass@k against pass^k, and traces of every step.
- Guardrails and Prompt Injection takes up what hooks and permissions only reduce: injected instructions in files and tool results, and the architecture that bounds them.
- Computer-Use Agents applies the same harness design to an agent whose tools are a screen, a mouse and a keyboard.
Takeaways
- A coding agent is a harness around a model: tools for files, search, execution, web and code intelligence, in a gather-act-verify loop.
- Claude Code searches with grep and glob driven by the model; Cursor used grep plus an embedding index (+12.5% in 2025) and dropped the index in 2026, saying models had become good enough with grep. Both now use exact search plus exploration subagents.
- Executable checks (tests, type checkers) make the definition of done real, and they’re why coding agents converge.
- Project memory files, compaction, deferred tool loading and subagents manage a context far smaller than the codebase.
- Permission modes, allowlists and sandboxing control actions; checkpoints undo the agent’s own file edits but not shell changes or remote side effects; hooks run deterministically outside the model but are not a security boundary on their own.
- Cursor’s tab model was tuned with online RL to suggest less and be accepted more; its apply model uses the original file as a speculative draft.
References
Start with Claude Code’s How Claude Code works and Best practices, then Cursor’s semantic-search post and its current Search documentation, read together for the change between them.
- Anthropic, How Claude Code works, Best practices, Hooks reference (documentation, 2026): the loop and its tools, the advice to give the agent a way to verify, and the hook events and exit codes the guard uses.
- Anthropic, Checkpointing (documentation, 2026): what a rewind restores, and what it can’t.
- Cursor, Search (documentation, 2026); Improving agent with semantic search (2025); Securely indexing large codebases (2026); staff statements on removing the index (forum, July 2026): Instant Grep, the 12.5% gain, the Merkle-tree index, and why the index was removed.
- Cursor, Editing Files at 1000 Tokens per Second (2024) and Improving Cursor Tab with online RL (2025): speculative edits in the apply model, and the tab model’s online RL.