Same Job, Opposite Bets: Cline vs OpenCode vs Pi

Type "fix the failing test" into any of these three tools and the same thing happens: an AI reads your files, edits code, runs the test, and fixes it. All three are open source. All three work with any model. And yet they could not be more different.

One is a batteries-included platform that runs in your terminal, your IDE, and a background daemon (a long-running process that keeps working after you close the window) — and can coordinate a whole team of agents. One is built like a proper web service — a single engine that a terminal, a desktop app, and a web UI all talk to over HTTP. And one is deliberately tiny — it ships four tools and dares you to build the rest yourself.

Same job. Opposite bets. This post compares Cline, OpenCode, and Pi head-to-head — their philosophies, their guts, and which bet is right for you.

New to coding agents? Read the next section, skim the head-to-head rounds, and jump to Which One Is Right for You? for the recommendation. The "Under the Hood" section goes deep on architecture — it's there if you want it, but you don't need it to choose.

First: What Even Is a Coding Agent?#

A chatbot replies once; you copy-paste. An agent acts in a loop: it calls a tool (read a file, run a command), sees the result, and decides the next move — repeating until the job is done.

You:   "Fix the failing test in auth.ts"
Agent: reads auth.ts             (acts)
       runs the test, sees fail  (acts + observes)
       edits the code            (acts)
       re-runs the test — passes (observes)
       "Fixed — the token check was inverted." (reports)

A few words we'll reuse: a tool call is one request from the model to run a tool. The context window is the model's limited short-term memory, measured in tokens. A provider is the company hosting the model (Anthropic, OpenAI, Google…). MCP (Model Context Protocol) is a standard plug for external tools. A subagent is a helper agent that another agent hands work to.

Here's the key idea: the model is the brain; the agent harness is everything around it — the loop, the tools, the safety, the memory, the UI. Cline, OpenCode, and Pi are three very different harnesses around the same kind of brain. The difference isn't what they do — it's their philosophy.

Meet the Contenders#

Cline — "The Batteries-Included Platform"#

Cline (Apache-2.0, TypeScript) ships as a CLI, a VS Code extension, a JetBrains plugin, a Kanban web board, and an embeddable SDK — all on one shared engine. It's human-in-the-loop by design (approval prompts, Plan/Act modes, checkpoints that undo any change) and goes big: a background Hub daemon shares live sessions across apps, plus agent teams, subagents, chat connectors (Slack/Telegram/…), scheduled/cron automation, and plugins, hooks, rules, skills, workflows, MCP.

  • Interfaces: CLI, VS Code, JetBrains, Kanban, SDK
  • License: Apache-2.0
  • One-liner: "The one that does everything and runs everywhere"

OpenCode — "The Client/Server Engine"#

OpenCode (MIT, TypeScript on the Effect framework + Bun) is architected as one server with many front-ends: a terminal UI, a desktop app (beta), a web UI, IDE integration via ACP (Agent Client Protocol — a standard way for editors to talk to agents), and SDK consumers. It has a first-class permission system (allow/ask/deny), 38 language servers built in, and a durable "V2" session core where sessions survive crashes and context is assembled from cache-friendly, composable pieces.

  • Interfaces: TUI, web, desktop (beta), editor (ACP), server, SDK
  • License: MIT
  • One-liner: "The one built like a real product — an engine with clients"

Pi — "The Minimal Core You Reshape"#

Pi (MIT, TypeScript) is a stack of small libraries — pi-ai (talk to any model), pi-agent-core (the loop), and pi-tui (the terminal UI) — under a thin pi CLI. Its core is radically minimal: four built-in tools (read/write/edit/bash) plus three optional read-only ones. No MCP, no subagents, no plan mode, no to-dos, no permission pop-ups, no background bash — on purpose. Everything "missing" is a short TypeScript extension you drop in (no build step), and the repo ships ~78 examples. Sessions are a branchable tree in one file (/tree, /fork, /clone).

  • Interfaces: CLI (interactive / print / JSON / RPC), SDK
  • License: MIT
  • One-liner: "The one that hands you a scalpel and gets out of the way"

Head-to-Head Showdown#

Round 1: The Core Philosophy#

ToolHow it's built
ClineA layered SDK: shared (contracts) → llms (provider gateway) → agents (a stateless run loop) → core (stateful sessions, tools, hub, automation) → host apps. Separates "how to run one turn" from "everything durable around it," so the same engine runs in-process, in a daemon, or remotely.
OpenCodeA client/server split: the API is authored once as a contract, bound to handlers, served over HTTP; every UI is just a client. Strict dependency layering (schema → core/protocol → server → binary). SDK clients are code-generated from the API so they never drift.
PiA stack of independently useful libraries with the CLI as a thin top layer. The defining bet: keep the core minimal and make everything else an extension point, so you never have to fork it.

Takeaway: Cline optimizes for reuse across many surfaces; OpenCode for one engine, many clients, clean contracts; Pi for a small core you can understand and reshape.

Round 2: The Agent Loop & Tools#

ToolDefault toolboxExecution style
ClineRich: read_files, search_codebase, run_commands, fetch_web_content, apply_patch/editor, skills, ask_question, submit_and_exit, plus provider-native web_search.Sequential by default; a "finish" tool ends the run. Streaming with retries and overflow recovery.
OpenCodeRich, assembled per model: bash, read, glob, grep, edit, write, apply_patch, task, webfetch, websearch, todowrite, skill, question, lsp, plan (some GPT models get apply_patch instead of edit/write).Tool output is size-bounded — a preview stays in history, the full text spills to a file.
PiMinimal: four tools (read, write, edit, bash) + three optional (grep, find, ls).Parallel within a batch by default (file writes serialized). Output capped at 50 KB / 2000 lines. A "pluggable operations" seam swaps a tool's backend to run over SSH or in a sandbox without rewriting it.

Takeaway: Cline and OpenCode hand the model a big toolbox out of the box; Pi hands it a sharp minimal set and expects you to add the rest. Pi's parallel-tools-in-one-context is its built-in form of "do sub-tasks at once."

Round 3: Multi-Agent & Task Decomposition#

This is where the philosophies really split.

ToolMulti-agent story
ClineThe richest. Three mechanisms: throwaway spawn_agent subagents; persistent agent teams (a lead + teammates, 18 team_* tools, a mailbox, a mission log, dependency-gated tasks) whose state survives restarts; and configured file-defined agents (subagent_<name>). Teams are SDK/CLI/Kanban only.
OpenCodeClean and contained: the task tool spawns a subagent in its own child session with its own model, tools, and permissions. Only the subagent's final text returns (wrapped in a <task> envelope) — the child transcript stays isolated. Permissions are contained (child inherits parent's denies, can't spawn further subagents by default). Depth-limited.
PiNone of this is in the core — the product creates exactly one agent, on purpose ("many ways to do this, no single right answer"). One agent decomposes via its turn loop; true subagents are the subagent example extension that spawns throwaway child pi processes (single / parallel / chain modes).

Takeaway: need coordinated multi-agent work with persistence? Cline. Need clean, isolated, permission-contained delegation? OpenCode. Prefer to compose it yourself (or just run agents in tmux panes)? Pi.

Round 4: Safety & Permissions#

An agent that can run rm -rf and edit files needs a safety story — and one of these is deliberately unsafe by default.

ToolSafety model
ClineThe most layered: per-tool approval (auto-approve categories you toggle), Plan mode (can't edit files / run mutating commands, enforced by a command-guard blacklist), Act/Yolo/Zen modes, and checkpoints — every tool use saves a snapshot of your files to a hidden backup (a shadow git repo kept separate from your real git history), so /undo rolls back any file change (not external side effects like a sent request or dropped table). Caveat: "safe vs approval-required" is the model's judgment, not a fixed allowlist.
OpenCodeA formal permission engine: every action is allow/ask/deny, matched by glob patterns (wildcard rules like *.ts) where the last matching rule wins, with different rulesets per agent (plan denies edits; explore denies all then re-allows read-only). Bash matched by command prefix; "always" grants persist per project. But it's not a sandbox — tools run on the host.
PiThe honest outlier: no built-in permission system and no sandbox. The only core gates are the --tools allow/deny list and the extension tool_call hook. "Project trust" gates loading a folder's config — not what tools can do. Permissions are an extension you add: permission-gate, protected-paths; real isolation comes from sandbox/, gondolin/, Docker.

Takeaway: Cline has the most guard-rails-out-of-the-box; OpenCode has the most principled, configurable policy engine; Pi is the most powerful and the most dangerous. But note: all three ultimately run on your machine — none is a true sandbox. Pi is just the most explicit about it, arguing that a half-sandbox living inside the app would feel like a boundary while still leaning on your shell and credentials — so real isolation must come from the OS.

Round 5: Models & Provider Freedom#

ToolProvider approach
ClineA gateway over ~50 hand-written + ~170 code-generated providers (catalog generated from models.dev). Default cline usage-billing provider + ClinePass subscription + BYO-key for Anthropic, OpenAI, Gemini, Bedrock, Vertex, OpenRouter, Ollama/LM Studio, any OpenAI-compatible endpoint. Runs on the Vercel AI SDK.
OpenCodeResolves models from the models.dev catalog; bundles many provider factories and installs unbundled ones from npm on demand — so new models.dev providers work with zero new code. OAuth + API-key + well-known credentials; auth stored 0600.
PiIts own unified pi-ai layer for 30+ providers, tool-capable models only. Standout tricks: switch models mid-conversation (it rewrites messages so the new provider understands them) and fully serializable conversations (save/resume by JSON.stringify). Subscriptions + local via llama.cpp.

Takeaway: all three are strongly multi-provider. Cline has the biggest generated catalog; OpenCode's on-demand npm install is the most future-proof; Pi's mid-chat model switching and serializable sessions are the slickest for experimentation.

Round 6: Context Management#

Every long task eventually overflows the context window (the model's limited short-term memory). The fix is compaction — summarizing the old part of the conversation so it still fits. Each tool does it a little differently.

ToolContext strategy
ClineCompaction with two strategies: basic (deterministic, no LLM) and agentic (LLM summarization, can use a different model), plus a one-shot overflow recovery. Summaries live in a separate sidecar file from the canonical transcript, so deleting them is always safe.
OpenCodeThe most sophisticated: the system prompt is built from independently-observed Context Sources (date, env, instructions, skills) that are re-checked between turns and updated only when something changes. Because the unchanging part stays byte-for-byte identical, the model provider can cache that prefix and skip reprocessing it — cheaper and faster on long sessions. Plus the usual compaction and oversized-output trimming.
PiCompaction on by default (keep ~20k recent tokens, 16k safety buffer), proactive + reactive-on-overflow. Produces a structured summary (Goal/Constraints/Progress/Decisions/Next Steps/Files). Lossy for context, lossless for history — the full tree stays in the file, recoverable via /tree. Replaceable by an extension.

Takeaway: OpenCode's cache-friendly Context Sources are the most advanced (and save real money on long sessions); Cline's separated sidecar is a clean safety design; Pi's tree means compaction is never truly destructive.

Round 7: Extensibility#

ToolHow you extend it
ClineThe widest menu: plugins (sandboxed subprocess, 9 capabilities), in-process + file-based hooks, rules / skills / workflows (file-based, watcher-loaded, live-reload), MCP servers, chat connectors, cron/automation, and the SDK (Agent for a light loop, ClineCore for the full runtime). Reads Cursor/Windsurf/AGENTS.md formats too.
OpenCodePlugins (auth methods, tools, TUI hooks), custom tools (dropped into {tool,tools}/), custom agents (JSON or Markdown), skills (SKILL.md, incl. remote pull), MCP, LSP, plus commands. Config merges across a rich precedence chain up to org-managed MDM.
PiExtensibility is the product. One .ts file exporting a function that receives the pi API can add tools, /commands, keyboard shortcuts, CLI flags, custom UI (dialogs, widgets, overlays — even DOOM), providers, and hook into ~every lifecycle event. Loaded via jiti — no build step. Shareable as pi packages over npm/git.

Takeaway: Cline and OpenCode give you structured, well-typed extension systems; Pi gives you raw, immediate extensibility (write TypeScript, it runs). If your workflow needs something none of them ship, Pi is the fastest to bend.

Round 8: Interfaces & How You Run It#

ToolWays to run it
ClineCLI (interactive TUI + one-shot + --json + --yolo + --zen fire-and-forget), VS Code, JetBrains, Kanban board (many agents in parallel, each in its own isolated git checkout), SDK. Feature availability is uneven across surfaces — teams, plugins, and schedules are CLI/SDK/Kanban-only, and chat connectors are CLI-only today.
OpenCodeInteractive TUI (default), one-shot run, headless serve, web UI, desktop app (beta), acp for editors, GitHub/GitLab automation, session sharing, attach to a running server. One engine backs them all consistently.
PiFour modes off one engine — Interactive, Print (-p), JSON (--mode json), RPC (--mode rpc) — plus the SDK. Terminal-first, with a flicker-free UI (differential rendering + synchronized output) and reliable key detection via the Kitty keyboard protocol (tmux needs config).

Takeaway: want an IDE plus a Kanban board of agents? Cline. Want a server other tools attach to? OpenCode. Want a scriptable terminal tool and an embeddable engine? Pi.

Scoreboard#

RoundClineOpenCodePi
Core philosophyLayered SDK, many surfacesServer + clientsMinimal core + extensions
Tools out of the boxRichRich (per-model)Minimal (4+3)
Multi-agentTeams + subagents (richest)Clean contained subagentsNot built-in (extension)
Safety by defaultApproval + plan + checkpointsPrincipled permission engineNone (sandbox it yourself)
Provider freedomBiggest catalogOn-demand npm installMid-chat switching
Context managementSidecar compactionCache-friendly Context SourcesStructured + lossless tree
ExtensibilityWidest structured menuStructured (plugins/LSP/skills)Rawest, fastest to bend
InterfacesCLI/IDE/Kanban/SDKTUI/web/desktop/ACP/serverCLI/print/JSON/RPC/SDK

Under the Hood: How Each System Is Designed#

This section is for the curious — it's the "how is it actually built inside" tour, and it gets more technical than the rest. If you just want a recommendation, skip to Which One Is Right for You?. Still here? Each design teaches a real system-design pattern you can reuse.

Cline — The Stateless-Loop + Stateful-Host Stack#

Cline is a one-directional dependency stack (shared → llms → agents → core → apps) where a stateless run loop is wrapped by a stateful manager. One RuntimeHost interface lets a task run locally, in a background hub daemon, or against a remote server — unchanged.

Rendering diagram...

Key design decisions:

  • Stateless loop + stateful host — The hard part of "run one turn" is a pure loop; everything durable lives above it. That's why the same loop runs in-process, in the hub, or remotely.
  • One execution boundary (RuntimeHost)LocalRuntimeHost / HubRuntimeHost / RemoteRuntimeHost; the top-level object never branches on "local or remote."
  • The Hub daemon — A background process (like tmux for agents) that owns live sessions and shares them over WebSockets; apps attach/detach without killing the work. Secured with a per-process auth token and "build-identity fencing" so two installed versions don't fight.
  • Generated provider catalog — Adding a model shouldn't touch the loop; the catalog is code-generated from models.dev.
  • Lazy persistence — A brand-new session lives only in memory until its first completed turn, so there's no empty-session clutter.

OpenCode — The One-Contract, Many-Clients Server#

OpenCode authors its HTTP API once as an Effect contract, binds it to handlers, serves it over a Node HTTP server, and consumes it via code-generated SDK clients. A TUI, a web app, a desktop app, and editors are all just clients of the same engine.

Rendering diagram...

Key design decisions:

  • Strict dependency directionschema → core/protocol → server → binary; clients may depend only on schema+protocol, never core/server.
  • Contract-first + codegen — One API definition; Promise and Effect clients are auto-generated and a guard forbids hand-editing them, so they never drift.
  • Permission engine as a core serviceallow/ask/deny, glob, last-match-wins, per-agent rulesets, persistent "always" grants.
  • V2 durable session runtime — Prompts are admitted to a durable inbox before running; a serialized "Session Drain" promotes input at safe boundaries; System Context is composable Context Sources with a baseline reused for provider prefix caching.
  • Embedded modesdk-next runs the whole server's router in memory — real API behavior, no network.

Pi — The Minimal Core With Everything as an Extension Point#

Pi is a stack of independently useful libraries where the product creates exactly one agent, stores conversations as a branchable tree, and exposes rich extension points instead of baking features in.

Rendering diagram...

Key design decisions:

  • Minimal core, extension-first — Features other tools hard-code (subagents, plan mode, to-dos, MCP, permission pop-ups) are deliberately out; each is an example extension instead. The core stays small and understandable.
  • Serializable everything — The conversation and model descriptor are plain JSON → save/resume by JSON.stringify, and switch models mid-chat (pi-ai rewrites messages for the new provider).
  • Sessions as a tree in one JSONL file — Every entry has id/parentId; /tree, /fork, /clone are just tree operations. Compaction is lossy for context but lossless for history.
  • Pluggable tool operations — A tool accepts an *Operations interface, so read/bash can run locally, over SSH, or in a sandbox without rewriting the tool.
  • Trust guards loading, not running — and there's no sandbox by design; isolation is the OS's job. Supply-chain hardening (exact-pinned deps, release-age delay, --ignore-scripts installs) is built in.

Architecture Comparison#

DimensionClineOpenCodePi
ShapeLayered SDK (stateless loop + stateful host)Client/server (one HTTP API, many clients)Stack of libraries, single agent
StackTypeScript, Vercel AI SDK, Bun workspaceTypeScript + Effect + Bun, Drizzle/SQLiteTypeScript, jiti (no build step)
PersistenceSQLite + files (~/.cline)SQLite via DrizzleOne JSONL file per session (tree); optional SQLite
Multi-processHub daemon shares live sessions (WebSocket)Headless server clients attach to (HTTP/SSE)Child pi processes (via extension); experimental remote stack
PermissionsApproval categories + Plan/Act guard + checkpointsallow/ask/deny glob engine, per-agent, persistent grantsNone built-in (trust gates loading; sandbox externally)
Multi-agentsubagents + persistent teams (18 tools) + configured agentstask tool → isolated child sessions, contained permsNot in core; example extension spawns child processes
Context mgmtbasic/agentic compaction + overflow recovery, sidecarContext Sources + epochs + prefix caching + pruningstructured compaction, lossless session tree
Providers~50 + ~170 generated (models.dev), Vercel AI SDKmodels.dev + on-demand npm installpi-ai, 30+, tool-capable only, mid-chat switch
Extensibilityplugins/hooks/rules/skills/workflows/MCP/connectors/cronplugins/custom tools/agents/skills/MCP/LSP/commandsone-file TS extensions (~78 examples), pi packages
LicenseApache-2.0MITMIT

What All Three Have in Common#

Despite opposite philosophies, all three converge on the same underlying patterns — worth understanding if you build for the AI era:

  1. The agent loop is universal — Send conversation → model asks for tools → run tools → feed results back → repeat. Understand one and you understand all three.
  2. Provider-agnostic by design — None locks you to a vendor; all support BYO-key across many providers, so you optimize for cost, quality, and privacy.
  3. The context window is the enemy, and compaction is the answer — Every one summarizes old history to keep long tasks alive, and every one keeps the full original recoverable. Compaction is lossy for the model, lossless on disk.
  4. Instruction files are the standard — All three read AGENTS.md / CLAUDE.md-style project instructions — a genuine cross-tool convention now.
  5. Skills = load-on-demand expertise — All three implement SKILL.md-style progressive disclosure: the model sees only names + descriptions until a task matches, then loads the body.
  6. Tool output must be bounded — All three cap tool output (truncate / spill-to-file / 50 KB) so one noisy command can't blow the context window.
  7. They run on your machine with your permissions — None is a hosted, indexed cloud service, and none is a true sandbox. The safety differences are about defaults and gates, not magic isolation.

Honest Limitations#

Before you install one, here's what each won't do.

Shared by all three: they need a model (cost, latency, credentials) and can be wrong; none is a sandbox (auto-approve/yolo/skip-permissions modes remove the human gate); compaction is lossy in-context; and prompt injection — a malicious instruction hidden in a repo — is a real, largely unpreventable risk.

ToolTool-specific caveats
ClineFeature availability is uneven across surfaces — teams, plugins, and scheduling are CLI/SDK/Kanban-only, chat connectors are CLI-only, the VS Code extension is mid-migration onto the SDK, and the JetBrains plugin isn't open-sourced. The Hub adds moving parts (cline doctor exists for a reason). Checkpoints can be heavy on very large repos. The plan-mode guard is a blacklist, not a shell interpreter.
OpenCodeTwo overlapping runtimes (mature v1 + in-progress V2) coexist during migration. No clustering / crash-recovery of in-flight work yet, event streams don't auto-reconnect, and the public client API is beta/unstable. Depends on external services at runtime (models.dev, on-demand npm install) — awkward for air-gapped setups (machines deliberately kept off any network).
PiNo built-in permission system or sandbox — safe only if you isolate it (project trust is a loading gate, not a boundary). Bare-bones out of the box — subagents, plan mode, MCP, to-dos all need extensions. Lockstep versioning means a breaking change can land in a minor release — pin versions. Extensions run arbitrary code — review third-party ones.

Which One Is Right for You?#

Cline. Approval + Plan/Act + checkpoints on day one, VS Code/JetBrains/CLI/Kanban surfaces, and when you outgrow one agent, persistent agent teams and connectors are right there.

npm install -g cline
cline auth
cline "Explain what this project does"

"I want to build tooling on top of a coding agent — a web UI, an editor plugin, a bot — all against one clean API"#

OpenCode. It's literally designed as a server with generated SDK clients and a documented HTTP contract; the permission engine and 38 LSPs make it a serious foundation.

curl -fsSL https://opencode.ai/install | bash
opencode          # interactive TUI
opencode serve    # headless server for clients to attach to

"I want a sharp, minimal, provider-flexible terminal agent I can mold to my exact workflow without forking anything"#

Pi. Four tools, ~78 example extensions, no-build-step TypeScript, mid-chat model switching, and a branchable session tree. You add only what you need.

npm install -g --ignore-scripts @earendil-works/pi-coding-agent
export ANTHROPIC_API_KEY=sk-ant-...
pi

"Safety and control matter most"#

OpenCode for a configurable policy (allow/ask/deny per agent), or Cline for the most guard-rails-by-default (approval + shadow-git undo). Pi only if you run it in a container/VM — it has no built-in gate.

"License matters for commercial work"#

All three are permissive: OpenCode and Pi are MIT, Cline is Apache-2.0 — plus Cline offers usage-billing and a subscription if you'd rather not manage keys.

Decision Flowchart#

Rendering diagram...

Final Verdict#

There's no universal winner — the right choice is about which bet fits how you work.

Pick Cline if you want the most batteries-included experience: approvals and undo out of the box, your IDE and terminal and a Kanban board all covered, and room to grow into agent teams and scheduled automations. It feels like a complete product on day one.

Pick OpenCode if you think like an engineer building on a platform: one clean HTTP engine that a TUI, a web app, and your editor all attach to, a real permission policy, 38 language servers, and a genuinely clever crash-durable, cache-friendly context design.

Pick Pi if you want a scalpel, not a Swiss Army knife: a tiny, fast, provider-flexible terminal agent you reshape with a few lines of TypeScript, with the best model-switching and the cleanest session model. Just remember — you are the sandbox, so run it in a container for anything risky.

The beautiful part? They're all open source and all model-agnostic. The wrong choice isn't "which of these" — it's not trying any of them while you keep copy-pasting from a chat window.