Skip to content

Architecture

Nori CLI is a harness: it never implements an agent. Every agent is an external subprocess speaking the Agent Client Protocol, and the workspace is organized so that rule is structural, not aspirational.

┌ layer 2 · frontends ────────────────────────────┐
│ nori-cli (the binary) nori-tui (terminal) │
└───────────────────┬─────────────────────────────┘
┌ layer 1 · runtime ▼─────────────────────────────┐
│ nori-harness (sessions, transcripts, undo, │
│ hooks) nori-config (~/.nori/cli) │
└───────────────────┬─────────────────────────────┘
┌ layer 0 · leaves ▼─────────────────────────────┐
│ nori-acp-host nori-protocol │
│ mock-acp-agent (conformance testing) │
└─────────────────────────────────────────────────┘

Rules that hold the shape: dependencies point strictly downward; the TUI never talks to nori-acp-host directly (everything flows through harness events); nothing below layer 2 knows a terminal exists; no cargo feature may move a responsibility between crates.

Layer 0 is being groomed for crates.io:

  • nori-acp-host — the host side of ACP as a standalone library: agent registry, subprocess spawning, JSON-RPC connection, permission plumbing.
  • nori-protocol — the event vocabulary on top of the ACP schema.
  • mock-acp-agent — a scriptable agent for conformance-testing hosts and agents.

The session transcript format is a stable, documented contract for third-party tools (JSONL, one file per session under ~/.nori/cli/transcripts/).

The workspace began as a fork of OpenAI Codex. Crates prefixed codex-* are inherited (sandboxing, login, protocol vocabulary, utilities) and get renamed to nori-* as they’re adopted; upstream syncing has ended, so inherited crates shrink or disappear over time.

this page as markdown: /cli/develop/architecture.md· index for agents: /llms.txt