möbius
möbius is a small, frontend-neutral Rust framework for coding agents. Its shipped
runtime has one headless composition root: mobius-gateway. The terminal and
Apple apps are thin clients of that gateway; they do not own agent behavior.
Architecture
Terminal client ─┐
SwiftUI client ──┼── versioned gateway protocol ⇄ mobius-gateway ──> Agent
Other clients ───┘ │
├─ model router
├─ sandbox
├─ checkpoints
└─ middleware stack
Core and agent
The mobius crate is the embeddable core.
src/agent/ owns one durable session and its linear command,
model, approval, and tool loop. src/protocol/ defines the
frontend-neutral operations, events, and presentation records around that loop.
A library caller supplies an AgentConfig; the core does not select a frontend
or hide runtime dependencies behind global state.
Middleware
src/middleware/ contains optional capabilities. One
middleware owns its tools, state, prompt section, runtime hooks, commands,
widgets, references, event rendering, and tests. MiddlewareStack validates one
ordered list, and that declaration order is observable.
The core exposes one typed hook suite directly on Middleware:
| Hook | Purpose |
|---|---|
session_start (SessionStart) |
Start or resume a main agent or subagent; after compaction, re-establish hidden context. Startup failures unwind completed starts in reverse order. |
user_prompt_submit (UserPromptSubmit) |
Inspect, enrich, or reject a prompt before it enters durable context. |
pre_model (PreModel) |
Apply durable context changes before a primary model step. |
model_request (ModelRequest) |
Add request-only material after every pre_model hook has finished. |
pre_tool_use (PreToolUse) |
Inspect, enrich, rewrite, or deny each normalized tool call before it is persisted or authorized. |
permission_request (PermissionRequest) |
Allow, deny, or defer a sandbox request immediately before the user would be asked. |
post_tool_use (PostToolUse) |
Change feedback or add context after a real tool execution, without pretending to undo its side effects. |
pre_compact (PreCompact) |
Inspect the exact context and optionally stop the turn before compaction. |
post_compact (PostCompact) |
Inspect the committed compacted context and optionally stop before session_start(compact). |
stop (Stop) |
Finish normally or request one bounded continuation. The context identifies whether the agent is main or subagent. |
turn_end (TurnEnd) |
Clean up transient turn state after either completion or abort. |
session_end (SessionEnd) |
Release session resources in reverse declaration order. |
All hooks run in declaration order except session_end. pre_model and
model_request are two complete stack passes, so no request-only decoration can
precede a later durable rewrite. Policy decisions are typed outcomes; hook
errors remain infrastructure failures. Static prompt sections are composed once
when the agent is created, and changing its Bot profile recreates the prompt and
tool catalog without adding either to conversation history.
continue: false is a typed core decision at session-start and compaction
boundaries: it stops a recovered or compacting turn, while an idle startup has
no turn to stop. Every middleware can use that lifecycle control.
The Extensions middleware loads standalone Agent Skills and explicitly activated
OpenAI plugin snapshots. A plugin is one package rooted at
.codex-plugin/plugin.json; its declared skills are exposed as
plugin-name:skill-name, and its command hooks adapt the OpenAI event contract
onto the typed lifecycle above. Hooks run synchronously in this slice. MCP and
app contributions are not yet supported.
The gateway installs skills and plugins from credential-free HTTPS Git sources
as content-addressed, read-only snapshots. Installation is inactive. An extension
may be selected independently for the Bot-creation template or one Bot; its skills
load immediately, while executable hooks stay disabled until their complete
package digest is reviewed. Selections follow an installed extension across
updates, and changed executable code requires a new review. Selected extensions
must be removed from every Bot profile before they can be uninstalled.
User-level Agent/Codex skill roots and project-local .agents/skills and
.codex/skills remain discovered, read-only inputs outside the managed catalog.
Providers
src/backend/model/ owns the Model transport contract,
ModelRouter, and built-in ProviderDefinition manifests. A manifest supplies
generic setup metadata, authentication, model choices, and advertised
capabilities. Each adapter converts its private wire format into ModelEvent
and ModelOutput before the agent loop sees it, so setup screens and model
pickers do not branch on provider IDs.
Backends
src/backend/checkpoint/ defines CheckpointStore
and owns durable checkpoints, event journals, transcript pages, and the session
catalog. src/backend/sandbox/ defines
SandboxBackend; Sandbox wraps an injected backend with approval policy,
background-process ownership, and frontend contributions.
Protected local modes use Seatbelt on macOS and Bubblewrap on Linux and fail closed when the selected platform sandbox is unavailable. Filesystem confinement stays active under every approval policy except Full access. Full-access shell commands can reach anything available to the gateway account, including gateway state and credentials; file tools remain workspace-scoped.
Gateway
mobius-gateway is the only shipped
owner of an Agent. It explicitly assembles one agent per active conversation
from its owning Bot and owns authentication, paired clients, workspaces,
artifacts, Git, usage, Bot profiles and routines, manual Bot swarms, and the
extension catalog. Its versioned wire protocol translates authenticated client
requests into core operations and publishes core events plus capability
contributions. Bots and context
defines the conversation, Swarm, routine, subagent, scratchpad, and escalation
boundaries.
CLI
mobius-cli provides the mobius
Ratatui client and the mobius-gateway executable. The terminal frontend sends
gateway operations and renders gateway events and the capability catalog;
crates/mobius-cli/src/frontend/ owns only
terminal lifecycle, input, and presentation.
SwiftUI app
mobius-app/apple/ is one SwiftUI gateway client for iPhone
and iPad. It uses the same versioned protocol and capability contributions as the
CLI, keeps paired client credentials in Keychain, and owns Apple lifecycle,
storage, navigation, and rendering—not agent, provider, or middleware behavior.
Install
Download mobius-<version>-<target>.tar.gz and its checksum from
GitHub Releases. The archive
contains mobius, mobius-gateway, and cloudflared. Rust users can install the
two möbius commands with Rust 1.98 or newer:
Cargo does not install cloudflared; Quick Connect requires it beside
mobius-gateway or on PATH.
Users upgrading from the earlier split packages should run
cargo install --force --locked mobius-cli once so Cargo transfers both commands to the CLI
package.
Then run mobius from the workspace it should own:
On first use, the CLI initializes the machine-wide gateway with a loopback listener
and Cloudflare Quick Tunnel, provisions its local credential, starts the gateway in
the background, and opens /login when no provider is configured. The first
configured model becomes the Bot-creation template default. Each CLI invocation
selects an existing Bot and creates an independent conversation for its current
directory; other terminal and app frontends can connect to the same gateway and
open separate or shared conversations. The conversation owns its workspace and
transcript. Its Bot owns the model, reasoning, capabilities, approval policy,
extensions, and prompt. The core mobius crate is linked into the binaries and
is not a separate runtime prerequisite.
Plaintext remains limited to loopback. Run mobius-gateway connect to advertise
both that local TCP endpoint and the Quick Tunnel's public WSS endpoint with one
single-use pairing code; pairing through either exchanges it for a per-client
token used on later connections. A direct TLS listener remains available as an advanced
alternative. See the
gateway guide,
the CLI guide,
and the Apple guide
for manual and remote setup.
To run the Rust binaries from this checkout:
Embed the core
möbius requires Rust 1.98 or newer.
[]
= "0.11"
The caller owns composition:
use Path;
use Arc;
use Result;
use ;
use ;
use ;
use ;
use ;
use Tools;
async
Frontends submit
protocol::Op values and consume
events from Agent. Framework capabilities may also contribute frontend-neutral commands,
references, widgets, and rendered blocks. A frontend decides how those contributions look;
capability implementations do not depend on terminal code. Interrupts target a specific turn, and
events carry an optional submission ID so command-driven and unsolicited system events remain
distinct.
Contributing
Read AGENTS.md before changing the framework. It defines module ownership, capability extension points, required checks, and the no-compatibility rule while the public contract remains under active development.
Release tags are intentionally separate:
mobius-vX.Y.Zpublishes the framework crate and creates its GitHub Release.mobius-gateway-vX.Y.Zpublishes the gateway crate and attaches server binaries.mobius-cli-vX.Y.Zpublishes the CLI crate and attaches downloadable binaries to a GitHub Release.
Publish mobius, then mobius-gateway, then mobius-cli, waiting for each dependency to appear in
the crates.io index. Creating a tag is a release action; ordinary pushes and pull requests only
run CI. The release workflow expects a CARGO_REGISTRY_TOKEN repository secret for
crates.io publication.
License
Licensed under Apache-2.0. See NOTICE for third-party attributions.