Client-Agnostic Cores
Client-Agnostic Cores
Synthesis. The architecture pattern that runs through Mxr, Lazydap, LSP, DAP, MCP, ACP, headless CMSes, kubectl, the AWS API surface, and a long lineage of "headless" systems. The collective term doesn't exist canonically; "client-agnostic core," "headless core," "protocol-oriented architecture" all describe the same shape.
This note pulls together the cluster: API-First Design, Headless Architecture, The Bezos API Mandate, LSP and the X-Protocol Family, Agent-Native Interfaces — and connects them to the more specific patterns (Headless Core + Multiple Clients, The Local Daemon Pattern).
The pattern in one sentence
A core service exposes its capability through a stable wire protocol; multiple thin clients (CLI, TUI, web app, mobile, agent skill, third-party plugins) all consume the same protocol equally; no client gets privileged access; the protocol IS the product.
That's it. Everything else in this cluster is a refinement of that one idea.
Why this is hard to name
Multiple traditions converge:
- Unix daemons + clients (1970s) — the original local-IPC pattern.
- X11 (1984) — the first widespread "core + many clients" GUI architecture.
- The Bezos API mandate (2002) — the org-scale forcing function. See The Bezos API Mandate.
- Headless CMSes (2013–) — the term "headless" entering product vocabulary. See Headless Architecture.
- API-first companies (Stripe, Twilio) — the methodology side. See API-First Design.
- The X-Protocol family (LSP 2016, DAP, BSP, MCP 2024, ACP 2025) — the dev-tools restatement. See LSP and the X-Protocol Family.
- Agent-native design (2024–) — the AI-era refresh. See Agent-Native Interfaces.
Each tradition has its own vocabulary. None is universally adopted. The pattern is real and recognisable across all of them; the names aren't.
If you want a single term I'd reach for in writing: "protocol-oriented headless core" or "daemon-with-many-clients." If you want literature backing: "API-first headless architecture." If you want a clever quip: "LSP-style architecture for [whatever the domain is]."
The three properties that define it
- The core has no built-in UI. It exposes capability via API/protocol; clients consume.
- Clients are interchangeable peers. No client is privileged. Adding a client is a small project; replacing a client is invisible to the core.
- The protocol is stable, designed, and documented. Breaking changes are deliberate; clients can rely on contracts.
Everything else (transport choice, language, deployment model) is implementation detail. These three properties are what make it the pattern.
Why it works
The M × N → M + N collapse. Multiple clients × multiple consumers turns into clients + consumers. Each new client doesn't have to know about each backend; each new backend doesn't have to know about each client. They share the protocol. See LSP and the X-Protocol Family for the canonical example.
The second-client tax. Once you've designed for multiple clients, building the second one is cheap. Without the discipline, the second client requires refactoring the first.
The agent-friendliness side effect. Tools that already have stable JSON output and clean APIs are agent-ready by accident. See Agent-Native Interfaces.
Where it sits in the lineage
Unix daemons (1970s)
│
▼
X11 server + clients (1984)
│
▼
The Bezos API mandate (2002, organisation scale)
│
▼
Headless CMSes (2013–, product scale)
│
▼
API-first companies (Stripe 2010s, "API as product")
│
▼
LSP (2016) — the X-Protocol family begins
DAP (2018), BSP (2018)
│
▼
MCP (2024), ACP (2025) — the agent era
│
▼
Mxr (2025+), Lazydap (2026+) — the personal-scale instances
The pattern keeps being rediscovered because the underlying problem (one core, many consumers) keeps appearing in new domains. Every decade or so a new ecosystem hits the wall and reinvents protocol-oriented architecture from scratch.
When to use this pattern
Use it when:
- You have, or expect, multiple consumers. The CLI, the TUI, the web frontend, the agent skill, the third-party integration — even two of these is enough.
- The interface should outlive any one consumer. UIs change; protocols designed for stability can survive UI rewrites.
- You want third parties to extend the system. Without a stable protocol, third-party extensions require code-level access that's brittle and hostile.
- AI agents are a real consumer. Agents drive APIs; they don't drive UIs (well).
Skip it when:
- One client, no second one in sight. A monolithic CLI / GUI is fine.
- The interface really is one-shot. A throwaway tool doesn't need an evolved protocol.
- Real-time bidirectional UX (video calls, live drawing) where request/response shapes don't fit. Different problem.
How to implement it
The mechanical recipe (works at any scale):
- Define the protocol first. Message types, schemas, error model, versioning. Document before code. See API-First Design.
- Build a fake / mock implementation. Exercise the protocol without committing to backend choices. Validates the design.
- Build the core service against the protocol contract. Internal types stay internal; protocol types are the seam.
- Build the first client. It's just a protocol consumer; nothing special.
- Build the second client. This is the test — if the second client requires rework on the core, the abstractions are wrong.
- Document the protocol publicly. External clients are now possible.
Bonus: enforce the boundaries structurally. In Rust, the Cargo dependency graph. In Java/.NET, module visibility. In TypeScript, package boundaries with explicit exports. Don't rely on developer discipline alone; let the build catch violations.
How Mxr and Lazydap embody this
Both implement the pattern at single-machine, single-developer scale:
- Daemon owns capability. Email sync (mxr) or DAP adapter (lazydap).
- JSON IPC over Unix socket is the wire. Stable schemas, length-prefixed framing.
- Multiple clients. CLI subcommands, TUI, agent skill, future bridges.
- CLI is canonical. Bare CLI gives full capability; TUI is one consumer; agent skill is another.
- Cargo dependency graph enforces. TUI cannot depend on daemon internals.
- Bucketed protocol. Four categories of messages; new requests must classify; new buckets require deliberate design.
Same architecture, different domains. Once you've internalised the pattern, applying it to a new domain is mostly mechanical.
See also (the cluster)
- API-First Design — the methodology
- Headless Architecture — the architectural form
- The Bezos API Mandate — the org-scale precedent
- LSP and the X-Protocol Family — the dev-tools lineage
- Agent-Native Interfaces — the AI-era restatement
- Headless Core + Multiple Clients — the local-tool variant
- The Local Daemon Pattern — the auto-spawn variant
- Plumbing and Porcelain — the adjacent metaphor
- Mxr · Lazydap — concrete instances
Other syntheses (sibling MOCs in the vault)
The other "How X actually works" synthesis notes — each is the entry point to its own cluster. This synthesis describes the architectural shape; the others describe the layers that fill it:
- How Debuggers Actually Work — DAP / adapters / ptrace / DWARF (lazydap is one client-agnostic core for this stack)
- How Email Actually Works — SMTP / IMAP / MIME / threading / OAuth (mxr is one client-agnostic core for this stack)
- How Daemons Work — daemon lifecycle (auto-spawning daemons embody this architecture locally)
- How Processes Talk to Each Other — IPC stack (the wire underneath any local client-agnostic core)
- The Elm Architecture (TEA) — what individual clients typically use to manage their own state
Punch list — if you only read 5 things
- The Bezos API Mandate, retold by Steve Yegge — the org-scale "why."
- LSP Protocol History + the LSP spec — the canonical technical pattern.
- Anthropic — Introducing the Model Context Protocol + Writing tools for agents — the agent-era restatement.
- Command Line Interface Guidelines (clig.dev) + InfoQ: Patterns for AI Agent Driven CLIs — the modern-Unix CLI bible + agentic update.
- Worse is Better — Richard Gabriel — the philosophical bedrock for "ship the simple wire format."
Honourable runners-up: Stripe's payment API design retrospective; Ink & Switch's Local-first essay; Simon Willison's Designing agentic loops; the BSP launch post and ACP overview.
What this teaches
This pattern is older than software, predates the internet, predates Unix. It keeps being rediscovered because it keeps being right. The 2026 frontier — agent-native CLIs, MCP, capability discovery — is just the latest restatement.
When you arrive at this pattern on your own, you're in good company. Bezos arrived at it in 2002. Microsoft arrived at it for editors in 2016. Anthropic arrived at it for AI tools in 2024. You arrived at it for email and debuggers in 2025. The instinct that "this should be a stable protocol with many clients" is one of the most reliable instincts in software design. Trust it.