Table of Contents
🌏 中文版
For the past six months I've been writing my own coding agent called rivumi. I got stuck far more often than expected: how should the agent loop terminate, how fine-grained should approvals be, how do you resume a session after a crash, how do you stop a small model from emitting garbage diffs? Every time I designed something from scratch, two weeks later I'd discover some open-source project had already stepped on the same landmine.
So I inverted the process: read five mature codebases first, then decide how rivumi does it. The findings piled up faster than I could use them, so they became a series. This post is the overview — three things it needs to answer: what problem rivumi solves, who the five reference projects are, and how to read this series.
Why write your own coding agent
There are already plenty of coding CLIs on the market. There is only one reason to write another: nobody sells the combination of capabilities you want.
What I want is a Python-first agent that works as an interactive daily CLI, and switches to a bounded, auditable headless mode for CI and, eventually, Cloudflare execution. It sounds simple, but that sentence hides a pile of design decisions — how tightly should the workspace be isolated, who signs off before a patch lands, does a failed verification count as failure, and how much code changes when you swap model APIs.
rivumi deliberately splits into two parallel runtime paths:
- The native harness: we own the loop, approvals, sessions, tools, verification gate, and model API adapters.
- External CLI runtimes: explicitly selected external coding CLIs (Claude Code, Codex CLI, OpenCode, Pi, and OMP) act as backends. They run their own loops but share rivumi's conversation UI, workspace safety, patch audit, and verification boundary.
The key discipline: one path is never disguised as the other. An external CLI is an external CLI; we never pretend it's our native implementation. That discipline itself is something I learned only after reading other people's source code.
Rivumi is no longer just the early Python harness. Beyond its provider-neutral ModelProvider contract, state-first event journal, rivumi resume, runtime-first TUI, local model gateway, and bounded Worker plus Cloudflare Sandbox slice, the native loop now has allowlisted MCP, explicit JSONL memory, automatic context-pressure compaction, model fallback, static-table cost estimates, ripgrep-backed search, and bounded tool programs. These are runnable, tested baselines. They do not prove cross-runtime parity, complete provider pricing, hostile-code production hardening, or behavior under real production traffic.
Who the five reference projects are
All five exist as shallow clones on my machine. The descriptions below were written after actually looking at their top-level structure — not copied from landing pages.
pi (badlogic/pi-mono)
A TypeScript monorepo that takes a minimalist approach. packages/ splits into agent (the loop), ai (the provider layer), coding-agent, tui, protocol, server, session-backends, telemetry, and evals. Its value is its smallness: the entire loop is one exported function at pi-mono/packages/agent/src/agent-loop.ts#agentLoop — the perfect textbook for reading a "minimum viable agent". rivumi's provider table derives from the definitions in packages/ai.
omp (can1357/oh-my-pi)
A fork of pi, then loaded with extras. The TS packages/ tree gains things pi doesn't have: snapcompact (context compaction), mnemopi (cross-session memory), hashline (hash-anchored line editing), catalog (model database), metaharness (experiment infrastructure), and collab-web (multiplayer collaboration). Hot paths get Rust crates underneath: pi-shell, pi-walker, pi-ast. For any given question, look at pi's minimal answer first, then see what omp added and why — the two-generation evolution is itself a design document.
opencode (sst/opencode)
TypeScript, at a completely different scale. The engine lives in packages/core (session, config, provider, credential), wrapped by thirty-plus packages: cli, tui, desktop, server, sdk, plugin, codemode (tool calls compiled into batched program execution), containers, and more. If you want to see what an agent project looks like after it grows into a platform, look here.
codex (openai/codex)
OpenAI's official CLI, with its core in codex-rs/ — a Rust workspace with over a hundred crates: core, tui, apply-patch, rollout (session recording), mcp-server, code-mode-*, plus a full safety stack: sandboxing (landlock.rs, bwrap.rs, and friends), linux-sandbox, windows-sandbox-rs, execpolicy, shell-escalation, and network-proxy. For OS-level sandboxing and dangerous-command interception, it's the most complete public implementation out there.
claude-code (decompiled source)
Honesty first: the official anthropics/claude-code repo only ships minified bundles; what I have locally is a community-decompiled/reconstructed v2.1.88 source tree. Under src/, the structure is startlingly legible: query.ts, tools/, services/, context/, memdir/, skills/, hooks/. Symbol names may differ from the original, and I'll flag that when citing. It's the only material where you can see the internal organs of a production-grade agent.
How to read this series
Two parts, 38 posts total, all bilingual (Chinese and English).
Part 1, "Implemented comparisons" (24 posts): topics rivumi has already shipped — the shape of the agent loop, workspace isolation, approval grading, verification gates, the ModelProvider abstraction, retry policies, subscription OAuth, external CLIs as backends, edit-tool trade-offs, sandboxing and remote execution, CLI ergonomics, and more. Each post is a head-to-head comparison of "how five projects do it vs how I did it", including where I got it wrong.
Part 2, "Improvement roadmaps and implementation tracking" (13 posts): these posts began as gap analyses, but Rivumi has since shipped baselines for context compaction, explicit memory, native MCP, hooks/skills/plugins, subagents, replay/fork, usage/OTel/cost estimates, static model-role routing, IDE/LSP snapshots, bounded code-mode tool programs, and a Cloudflare control plane. They now record both what landed and what remains. Dangerous-command rule policy, comprehensive egress controls, cross-runtime consistency, and production validation are still not complete.
Every post follows the same five-part structure:
- The design question: what is this really asking, and why is it hard.
- How five projects do it: each reference project's solution, with source-level evidence.
- rivumi's choice: what I chose and why it differs (or why I copied).
- Academic grounding: what papers and technical reports like ReAct, SWE-agent, or Reflexion say, with inline links on first mention.
- Improvement roadmap: can it be better? Concrete enough to start building.
The evidence standard
Every claim in this series requires a file#symbol citation, in the form codex-rs/sandboxing/src/landlock.rs#create_linux_sandbox_command_args_for_permission_profile — file plus function or type name, never line numbers (clones update; line numbers drift). If I can't find it, I'll say so; fabrication is off-limits. Before writing any Part 2 topic, I'll grep all five codebases to confirm every citation location. And if a project simply doesn't implement something, that's a fact worth recording too.
One aside: this "research first, write second, evidence on disk" workflow is itself the series' methodology — I took the research-note process I use while developing rivumi and repurposed it as a writing process.
If you're building your own agent, or just want to know what Claude Code and Codex look like under the hood, this series is for you. The first substantive post starts with the agent loop — the foundation of everything else.
References
- Rivumi README at fixed commit
2ed5efb— current capabilities, runtime split, and safety boundary - badlogic/pi-mono — pi source code, TypeScript monorepo
- can1357/oh-my-pi — omp source code, a fork of pi
- sst/opencode — opencode source code
- openai/codex — Codex CLI source code, Rust workspace
- anthropics/claude-code — official Claude Code repo (ships minified bundles)
- ReAct: Synergizing Reasoning and Acting in Language Models — the foundational paradigm for interleaving reasoning and acting
- SWE-agent: Agent-Computer Interfaces Enable Automated Software Engineering — how agent–computer interface design shapes performance
- Reflexion: Language Agents with Verbal Reinforcement Learning — self-reflection via verbal feedback as agent memory
Loading...