A coding-agent CLI is convenient until one session becomes the failure domain for everything else you were doing.
The failure is usually ordinary. A tool call hangs. An MCP server wedges. A shell command leaves children behind. A model turn streams forever. A memory subsystem gets busy enough that it competes with the active turn loop.
codex-swift is my Swift port and expansion of the Codex runtime. The part I keep coming back to is not the language choice by itself. It is the process model: a coding agent as a supervised local service rather than a single process with a large amount of authority.
One daemon, many workers
The architecture splits the runtime into a small set of processes:
codexd is the supervisor daemon. It owns transports, request routing, subscriptions, resource policy, and the worker lifecycle. codex-session is the per-conversation worker, responsible for the turn loop, model calls, tools, sandbox, and MCP children for that session.
The shared services sit beside those workers. codex-broker handles auth and model catalog work, including single-flight token refresh. codex-memory keeps the memory subsystem outside the turn loop and exposes it through its own surface.
The boundary is practical. codexd should not run the model turn or the shell tool. It should supervise the process that does.
If a worker dies, the supervisor sees the IPC link close, clears that thread, notifies subscribers, and can later resume from durable state. If one worker is overloaded, new work for that thread can be rejected without treating the whole daemon as broken. Idle threads can unload their workers and keep their conversation on disk.
At that point the product shape is no longer “open a CLI and hope the one process stays healthy.”
The agent is a local service now
Once the agent becomes long-lived, the local operating system starts to matter.
On macOS, codex-swift can lean on platform primitives that are awkward to bolt onto a generic one-shot binary:
launchd lifecycle
Keychain-backed credentials
Seatbelt sandbox profiles
process groups for worker cleanup
resource sampling and governor state
durable app-server compatible session files
Those are not features users ask for by name, but they change the trust model. A coding agent that can edit files, run commands, reach MCP servers, and handle auth should not be held together only by prompt discipline.
The security boundary still has to be engineered. In codex-swift, the worker is the place where risky work belongs because the worker only owns one conversation. The supervisor keeps the control plane outside that blast radius.
Shared services prevent stampedes
The broker process is a small example of why this architecture is useful. If ten sessions all discover an expired credential, a naive design can turn that into ten refresh attempts. A supervised service can collapse that into one refresh, persist the result, and wake the waiting callers.
Memory has a similar reason to live outside the turn loop. Retrieval, scoring, local inference, and SQLite work are useful, but they should not share fate with a session that is streaming a tool-heavy coding turn.
This is also where the local small-model lane fits. codex-swift can route cheap, high-frequency work such as memory extraction, context shaping, and scoring through an on-device path on Apple Silicon instead of sending every small decision to the API. The point is not to replace the frontier model for coding. It is to keep routine support work local, cheap, and independent from the expensive turn.
Looking at coding agents only as chat surfaces hides the systems work. The hard problems start to look like ownership, isolation, lifecycle, backpressure, queues, and recovery.
Compatibility still matters
A port can become an excuse to invent a new world. That was not the goal here.
codex-swift speaks the upstream Codex app-server protocol so existing clients can connect without learning about the process fan-out. The session format and wire behavior are treated as compatibility surfaces. The implementation can be native Swift and macOS-aware while still respecting the client contract.
That constraint keeps the architecture honest. If the supervisor-worker split leaks into every client, the split has become a user-facing tax rather than an implementation boundary.
Where the boundary lands
The boundary I want is narrow:
A coding agent that is meant to stay running should be supervised like local infrastructure, not only invoked like a command.
This does not make every local agent safe. It does not remove the need for approvals, sandbox rules, audit trails, or careful tool design. It does change where failures land.
One bad session should be one bad session. If the agent is becoming part of the development environment, that is the bar I want the architecture to start from.