On this page
A coding agent is two things: a model and a harness. The model proposes text and tool calls. The harness does everything else: it builds the context, defines the tools, decides which calls run, runs them somewhere, feeds the results back, and keeps the whole thing inside a context window. Most of what makes one agent better or safer than another lives in the harness, and most harnesses are now open source or documented in enough detail to read.
This post reads Codex CLI, Claude Code, Cursor's agent, OpenCode, Aider, Goose, Cline and Roo Code, and T3 Code from public sources only: code on GitHub, official documentation and engineering blogs. Every claim links to its source; where a source is silent, so is this post. The second half places Loams Studio and its agent daemon, loams-agentd, using only the Loams repository, with each part labelled by what it is today.
| Harnesses read | openai/codex, Claude Code docs, Cursor docs, anomalyco/opencode, Aider-AI/aider, aaif-goose/goose, cline/cline, RooCodeInc/Roo-Code (shut down in May 2026; its docs are still online), pingdotgg/t3code |
| Read on | 2026-10-18. Documentation moves quickly; check the linked page before relying on a detail |
| In Loams | Loams Studio and loams-agentd: Experimental in 0.1.0. loams-sandbox: Planned. Places and the Jailer: Proposed |
The loop
Every harness runs the same loop. Claude Code's documentation describes it as three blended phases, gathering context, taking action and verifying results, where each tool result feeds the next step and the person can interrupt at any point (how Claude Code works). The model returns either text or one or more tool calls. Text ends the turn. A tool call goes through the harness's gate, runs, and its output is appended to the context, which goes back to the model. The loop repeats until the model stops asking for tools, the person interrupts, or a limit fires.
The differences between harnesses are in what surrounds that loop: how tools are declared, who answers the gate, where commands run, what the model sees of their output, and what happens when the context fills up.
How tools are declared. Most harnesses now pass tools to the provider's API as JSON Schema definitions and get structured tool calls back. That was not always the default. Cline used to describe its tools in the system prompt and parse XML-style calls out of the model's text; version 3.35 moved to native tool calling, which the Cline team says cut malformed responses, allowed parallel tool calls and shrank the system prompt, with text-based calls kept for models that lack native support (Cline v3.35). Aider went the other way early: its 2023 benchmarks found OpenAI function calling produced worse edits than plain-text formats for every model it tried, with the model stuffing whole files into arguments or inventing function names (Aider benchmarks, 2023), so Aider asks for edits in text and parses them.
What the tools are. The core set has converged: read, search by name and content, edit, write, run a shell command, fetch a URL. Claude Code's list (Bash, Read, Edit, Write, Glob, Grep, WebFetch, WebSearch, Agent and others) doubles as the vocabulary of its permission rules and hooks (tools reference). OpenCode's grep and glob are built on ripgrep and respect .gitignore (tools). Codex's handlers add apply_patch, a plan tool, request_permissions, tool search and multi-agent handlers (handlers module).
Where the loop runs. OpenCode is a server with clients: opencode starts an HTTP server and a terminal UI that talks to it, and opencode serve runs it headless with an OpenAPI spec and a server-sent event stream (server). T3 Code is one level up. It is not an agent but an "agent harness control surface" over Claude Code, Codex, Cursor, OpenCode and others, on the subscriptions you already have (README). A Node WebSocket server wraps the provider CLIs behind adapters that emit normalized events, and orchestration is event-sourced, with events, projections and an outbox committed in one transaction (internals, providers). Loams Studio follows that pattern, a harness of harnesses.
The gate: approvals and permission modes
Every harness has a setting for how much the agent may do without asking. The names differ; the ladder is the same.
| Harness | Modes, most careful to least |
|---|---|
| Codex | Sandbox read-only, workspace-write (default in a git folder), danger-full-access; approvals on-request or never; an auto_review reviewer (approvals and security) |
| Claude Code | plan, default (Manual), acceptEdits, auto (a classifier model reviews actions), dontAsk, bypassPermissions. Deny rules apply in every mode (permission modes) |
| Cursor | Auto-review (a classifier, plus the sandbox), Allowlist, Run Everything (run modes) |
| OpenCode | Per-tool allow, ask or deny, with glob patterns (permissions) |
| Goose | Chat Only, Manual Approval, Smart Approval, Completely Autonomous (the default) (permissions) |
| Cline | Per-tool auto-approve toggles, up to YOLO (auto-approve) |
| T3 Code | Supervised, Auto-accept edits, Auto (the provider's own review) and Full access, which is the initial default for new threads (permission modes) |
Two trends stand out. First, plan modes: a read-only phase before any edit. Cline's Plan mode cannot edit or run commands and can use a different model from Act (Plan and Act); Aider's architect mode has one model propose and an editor model write the edits (chat modes).
Second, a model in the gate. Claude Code's auto mode, Cursor's Auto-review and Codex's auto_review all put a second model between the agent and the person, so routine calls stop interrupting. Each vendor is explicit that this is not the boundary: Codex's documentation says safety monitoring does not replace the sandbox (approvals and security), and Cursor calls terminal approvals best-effort rather than a hard boundary (Cursor security). Hooks are the deterministic counterpart. Claude Code's PreToolUse hook can allow, deny or ask, and can rewrite a tool's input before it runs; an exit status of 2 blocks the call (hooks).
The sandbox, per operating system
A gate decides whether a command runs. A sandbox decides what an approved command can reach. Three of the harnesses ship an OS sandbox, and they have converged on the same primitives.
macOS: Seatbelt. Codex, Claude Code and Cursor all use Apple's Seatbelt through sandbox-exec with a generated profile (Codex, Claude Code, Cursor).
Linux: namespaces, Landlock and seccomp. Codex's Linux helper now uses bubblewrap for filesystem and namespace isolation and seccomp for system calls, keeping its earlier Landlock code as the legacy path (linux-sandbox README). Claude Code uses bubblewrap with socat on Linux and WSL2 (sandboxing). Cursor uses Landlock plus seccomp, which needs kernel 6.2 or later with Landlock v3 and unprivileged user namespaces; without them it falls back to asking (run modes, sandboxing post).
Windows. This is where they differ most. Codex documents its own Windows modes (approvals and security). Claude Code's sandbox does not run on native Windows (sandboxing). Cursor runs its Linux sandbox inside WSL2 (sandboxing post).
The network. Filesystem rules stop an agent from writing outside the project. The network is how data leaves. Codex turns network access off in workspace-write unless you enable it (approvals and security). Claude Code routes sandboxed traffic through a host proxy that checks each domain against an allow-list that starts empty, and can give sandboxed commands a placeholder in place of a credential, which the proxy swaps for the real value only on requests to allowed hosts (sandboxing). Cursor has three network modes, from its sandbox.json only to allow all (run modes).
What a sandbox covers. Read the scope carefully. Claude Code's sandbox covers shell commands; file tools, MCP servers and hooks run outside it, and a command that fails inside the sandbox can be retried outside it if permissions allow, which an allowUnsandboxedCommands: false setting turns off (sandboxing). Codex keeps .git and its own config directories read-only even inside writable roots (approvals and security). OpenCode, Aider, Goose and Cline ship no OS sandbox; they rely on the gate, or on you running the agent in a container or VM. Roo Code's docs called its ignore file "not a system-level sandbox" (.rooignore).
Sandboxing also cuts interruptions: Anthropic reports 84% fewer permission prompts internally (engineering blog), and Cursor says sandboxed agents stop to ask 40% less often (sandboxing post). Fewer prompts is a security property: people stop reading the fortieth.
Context and compaction
A long session outgrows the context window. Every harness compacts, and they differ in what they throw away first.
- Claude Code clears older tool outputs first, then summarizes. If the context refills right after each summary, auto-compaction stops after a few attempts with an error rather than looping. (how Claude Code works).
- Codex runs a summarization prompt, which a
compact_promptsetting can replace, and has a token limit setting for when auto-compaction fires (compact.rs). - OpenCode compacts automatically by default, can prune old tool outputs, keeps a reserved token buffer, and runs compaction through a hidden system agent (config, agents).
- Goose compacts at the earlier of 80% of the window or 225,000 tokens (context management).
- Roo Code reserved 30% of the window and, on an overflow error, cut the context by 25% and retried (condensing).
- Aider keeps a recent tail of the chat verbatim, summarizes the older head with a model, recurses up to three levels, and drops whatever exceeds the summarizer's own input limit (history.py).
Aider also works from the input side: its repo map sends the files' key symbols and signatures, ranked over a tree-sitter dependency graph, in about a thousand tokens by default (repo map).
Compaction is lossy, and it is the harness deciding what the model remembers. That makes it part of the security surface: anything a summary keeps verbatim, including instructions planted in a file the agent read, carries into every later turn.
Edit formats
How a model expresses a change matters more than it looks. There are four families.
- Exact string replacement. Claude Code's Edit tool takes an old string and a new string; the old string must match exactly and be unique in the file unless a replace-all flag is set, with no regex or fuzzy matching (tools reference). OpenCode's edit tool is the same kind of exact-text swap (tools). The uniqueness rule is the point: an ambiguous edit fails loudly instead of landing in the wrong place.
- Patch envelopes. Codex's apply_patch takes one patch wrapped in begin and end markers, with add-file, delete-file and update-file sections and an optional rename; update hunks use context anchors and lines prefixed with plus, minus or a space, and no line numbers. The parser is deliberately lenient about whitespace around the markers because some models need it (parser.rs). OpenCode offers apply_patch too (tools).
- Search/replace blocks in text. Aider's
diffformat asks for search and replace blocks in the reply, with variants that put the path inside the fence or use only the edit part of the prompt (edit formats). - Unified diffs and whole files. Aider's
udiffis a simplified unified diff without line numbers. On Aider's refactoring benchmark it raised GPT-4 Turbo from 20% to 61% and cut "lazy" placeholder comments from 12 tasks to 4 (unified diffs).wholereturns the entire file, which is slow but the most reliable; the best result in Aider's architect benchmark used it (architect mode).
The common lessons: no line numbers, enough context to anchor an edit, and a failed match that the model can read and retry. Aider reports, per model, how often it produced a well-formed edit (leaderboards).
Undo: checkpoints, worktrees and git
Sandboxes limit what an agent can reach. Undo limits what a bad turn costs.
Checkpoints. Claude Code checkpoints each prompt, keeps 100, and /rewind restores code, conversation or both; Bash changes and most subagent edits are not tracked (checkpointing). Cursor snapshots files locally, outside git (overview). Cline, Roo Code and OpenCode keep a shadow git repository (Cline, Roo Code, OpenCode). T3 Code writes hidden git refs, so nothing lands on your branch, and refuses a revert if the provider cannot also roll back its conversation (internals).
Git itself. Aider commits every edit, with a message written by a weak model and "(aider)" appended to the author name, commits your own dirty changes separately first, and /undo reverts its last commit (git). Then it runs your linter and tests and feeds failures back to the model (lint and test).
Worktrees. Parallel agents need separate checkouts. claude --worktree <name> creates one on its own branch, and while isolated Claude Code blocks edits and commands aimed at the main checkout (worktrees). Cursor gives each agent a worktree and runs /best-of-n across models, one worktree each (worktrees). A worktree separates edits. It does not contain processes.
MCP and subagents
MCP. Every harness here is a Model Context Protocol client. Goose is built on it: its extensions are MCP servers (extensions). OpenCode warns that every server's tools consume context (MCP servers); Claude Code loads tool definitions on demand, caps MCP output at 25,000 tokens by default, and needs approval for project-scoped servers (MCP); Cursor asks before each MCP call by default (MCP). Claude Code and T3 Code also run as MCP servers, so outside agents can drive them (outside agents).
The specification itself says tools are model-controlled, that a person should always be able to deny an invocation, that clients must treat tool annotations from untrusted servers as untrusted, and that clients should show tool inputs before calling them to avoid exfiltration (MCP tools). Our MCP post covers the protocol itself.
Subagents. A subagent is a fresh context that returns only a summary, keeping the parent's window clean. Claude Code ships Explore, Plan and general-purpose subagents and caps nesting at three levels (subagents). OpenCode's permission.task decides which subagents an agent may call (agents). Roo Code's Orchestrator had no tools of its own and delegated subtasks with isolated histories (boomerang tasks). Goose subagents default to 25 turns and cannot spawn their own (subagents).
Telemetry
What leaves your machine besides the model calls:
- Codex has an OpenTelemetry crate that exports logs, traces and metrics over OTLP. Logging prompts is off by default and logging responses is a separate opt-in (codex-otel); an
[analytics]setting turns off OpenAI's own analytics (config types). - Claude Code exports OpenTelemetry only when you set
CLAUDE_CODE_ENABLE_TELEMETRY=1(monitoring). - Goose usage data is opt-in and excludes chats, code and tool inputs (usage data).
We did not find a public page describing Cursor's agent telemetry, so this post says nothing about it.
Failure modes
Prompt injection through the repository. A model cannot reliably tell instructions to follow from text it should only read, and agents read files, issues and web pages all day. OWASP lists prompt injection first, says the injected content need not be visible to a person, and says it may not be fully preventable (OWASP LLM01). Simon Willison's "lethal trifecta" names the combination that turns injection into theft: access to private data, exposure to untrusted content, and a way to send data out. His advice is not to combine all three, and he cites a GitHub MCP case where one server held all three (the lethal trifecta).
The harnesses' answers line up with the layers in the diagram above. Network egress off or allow-listed removes the third leg (Codex, Claude Code). Claude Code's WebFetch runs a separate model call over the fetched page and the agent sees only that answer, and a workspace trust dialog guards untrusted folders (security). Goose can scan tool calls for risky patterns and pause for a person, and calls it a safeguard, not a guarantee (prompt injection detection). Rules files (AGENTS.md, .cursor/rules, .clinerules) are repository content the harness loads into the prompt by design (Cursor rules, Cline rules), so cloning a repository and starting an agent in it is trusting that repository's authors.
Runaway loops. OpenCode has a doom_loop permission that fires when the same tool call repeats three times with identical input, and it asks by default (permissions). Goose asks to continue after 1,000 consecutive actions (context management). Claude Code stops auto-compaction that thrashes (how Claude Code works). Cursor found its agents retrying a command the sandbox had blocked, and fixed it by having the shell tool's output name the sandbox constraint, sometimes with a suggestion to escalate (sandboxing post). That last one is the general rule: a denial the model can read is a denial it can act on; a silent failure becomes a retry loop.
Where Loams Studio and loams-agentd fit
Loams Studio is the agentic development environment in the Loams console. Like T3 Code, it is a harness of harnesses: it drives the agents you already use, Claude Code, Codex, opencode, Pi, agents that speak the Agent Client Protocol (ACP), and Loams' own agent, each thread in its own git worktree (Studio guides). Everything it does goes through loams-agentd, a per-user daemon. In 0.1.0, Studio is Experimental: Loams Desktop opens in it, and in a browser it runs against a remote daemon behind an instance feature that no Loams server sets yet (0.1.0 release notes).
One daemon, native wires. loams-agentd-harness drives each agent over its own protocol: Claude Code over stream-json, Codex over its app-server JSON-RPC, opencode over its HTTP and server-sent events server, Pi over JSONL RPC, and ACP only for agents built on ACP. Its documentation records why ACP adapters for Claude Code and Codex were retired: they held turns open and reported wrong done states (harness crate). Studio talks to the daemon over a Connect API (design 53 §6.1). On the desktop, Electron's main process forwards calls to the daemon's loopback listener and adds the daemon's token, so the page never sees it; in a browser, a remote daemon you run with serve --remote accepts only TLS, only your configured console origins, and only access tokens from your issuer for your own subject (remote agentd).
Approvals. Each thread is supervised or full access, and the daemon's default is supervised, on your own machine as well as remotely; full access is only ever asked for (approvals). Supervision maps onto each harness's own gate: Claude Code runs in its default permission mode and each request waits for you, Codex runs with on-request and the thread's sandbox level, opencode's permission events wait, and ACP permission requests map to allow-once or reject. Pi has no way to ask, so the daemon refuses to run it in a supervised thread. "Always for this thread" is remembered by the daemon, not the agent, so an agent's own "always" cannot reach past the thread. A side chat inherits its parent's mode, and an unanswered approval is denied after 30 minutes by default. Destructive git actions (commit, push, merge, discard, restore) always ask in Studio, whatever the mode. This shipped as a behaviour change: existing local users now see approval prompts for threads that used to run unattended (0.1.0 release notes).
Checkpoints and worktrees. The daemon writes a hidden commit of the checkout at the start and end of every turn, under refs/loams/checkpoints/<thread>/turn/<n>/pre and post, through a temporary index so your index, HEAD and branches are untouched. It is T3 Code's scheme, rewritten in Rust. Restoring a turn refuses with stale_diff if the checkout changed since you looked at it (checkpoints). The UI components Studio takes from T3 Code are vendored under its MIT licence and rebuilt on Loams' own UI stack, with provenance recorded per file; Studio does not run T3 Code's server (design 53 §9).
Parallel runs. A run group sends one prompt to two to four agents, each in its own worktree from the same base commit, with an optional check such as your tests in each. You compare the variants side by side, optionally ask a read-only judge thread, and merge one or open a pull request from it. Nothing merges without your click, and nothing is force-pushed (parallel runs).
MCP. Every run gets an MCP server, a stdio shim that calls back into the daemon with a per-run token in the mcp role. Its tools are chat operations, so one agent can start others and wait for them. That token cannot answer approvals or switch a thread to full access, and destructive git actions are never offered through it (approvals, our MCP post).
What Loams does not do yet
The approvals guide says it plainly: the daemon does no OS-level confinement today, supervision is the guard, and full access is for work you would leave unattended. Worktrees keep agents' edits apart; they do not contain processes, so the remote daemon's guide recommends running it in a container with only your project directories mounted (approvals, remote agentd). Three designs address that, at different stages.
loams-sandbox (design 56, Planned; the direction is approved and the plan runs after 0.1.0-preview.3). One crate built around a declarative spec covering filesystem paths, network, a system-call profile, resources and identity, compiled by adapters into their own mechanisms: linux (user, mount, PID and network namespaces, cgroup v2, Landlock, seccomp, no capabilities) as the default, seatbelt on macOS through sandbox-exec as Codex does, appcontainer on Windows, and gvisor and microvm for multi-tenant code. The proposed rule is fail-closed: an adapter that cannot enforce a field refuses to start. For Studio, the thread's sandbox level becomes a spec that Loams enforces around the whole harness process instead of trusting each harness's own sandbox, with the network going through an allow-list forwarder to the model provider and, for workspace-write, package registries. Supervision is unchanged; the sandbox bounds what an approved call can reach (design 56 §1.1, §8.5, §13.3).
Places (design 60, Proposed; nothing built). A Place bundles a data scope, an allow-list of tools, roles, an approval policy and budgets. An agent entering a Place gets the intersection of its own grants and the Place's, computed before the run starts and shown in the composer; when the agent and the Place disagree, the more restrictive side wins. What the agent leaves behind is recorded, so it can be promoted or discarded as a unit (design 60 D1087–D1089).
The Jailer (design 61, Proposed). A supervisor in three layers: a deterministic process that is the policy decision point and the parent of the sandbox; sensors and actuators in the kernel, the VMM and the network; and an LLM overseer that sees only cases the policy marks ambiguous and may only make outcomes stricter. The design takes the same position as the vendors above: the deterministic layer and the sandbox are the boundary, the overseer is a filter that saves clicks, and it ships in shadow mode, logging only, until its false-positive rate is measured. A proposed circuit breaker pauses a run after repeated denials (design 61 §1, D1094–D1100).
| Part | Status |
|---|---|
| Studio: threads, worktrees, diffs and review, git actions, checkpoints, terminals, preview, run groups | Experimental in 0.1.0; on by default in Loams Desktop |
| Supervised approvals, supervised by default | Experimental in 0.1.0 |
Studio in a browser against a remote loams-agentd | Experimental, behind the instance feature studio; a sign-in that issues the daemon token is pending |
| A per-thread approval mode switch in the thread header | Pending |
loams-sandbox around harness runs (design 56) | Planned |
| Places (design 60) | Proposed |
| The Jailer (design 61) | Proposed |
What we take from the teardown
- The harness is the product. Models change monthly; the gate, the sandbox, the edit format, compaction and undo decide whether a run is useful and safe, and they are ordinary software you can read.
- The model in the gate is not the boundary. Every vendor that ships a reviewer says so. Loams' approvals are deterministic, and its proposed overseer may only tighten.
- The sandbox has to wrap the network, or the trifecta's third leg stays open.
- Say what is not there. The most useful lines in this research were the limits each project documents about itself. Loams' guides say that the daemon does not confine processes yet, and that is why
loams-sandboxis next.