Developers
Agent runtime
Sessions, the system prompt, permission gating, and the Mock and ACP adapters.
The agent runtime lives in the desktop main process. It manages sessions, transcripts, configuration, streaming output, permission prompts, and adapter execution while keeping all app actions behind the shared tool registry.
The runtime keeps provider-specific code out of the core app. AgentService owns sessions and gating; adapters know how to talk to a specific backend or protocol.
Session model
A session contains an id, title, cwd, optional space id, optional model, adapter id, status, timestamps, and messages. AgentStore persists session metadata and messages. On startup, AgentService.hydrate() loads stored sessions and resets any crash-left running sessions back to idle. The renderer shows sessions in AgentView: a resizable session list, transcript, composer, stop button, and pending permission cards.
Configuration
Agent config is stored by AgentConfigStore and edited in Settings:
adapter:mockoracpacpPreset:claude,codex, orcustomcommandandargsfor a custom ACP executablemodel(optional) andautoAccept
The default adapter is mock, so the UI works without external setup.
System prompt
buildSystemPrompt() composes the prompt from a static base, the live tool catalog from registry.describe(), the current session context (cwd, space name, open browser tabs), and safety text reflecting whether auto-accept is enabled. The tool list is never hardcoded — if a tool is registered, the agent prompt can include it. If a tool is removed or renamed, the prompt changes with the registry.
Tool calls and permissions
Agents are just another registry caller, but not a trusted one. AgentService.gatedCall() applies this policy:
- tools with no privileged capabilities run directly,
- privileged tools prompt the user unless auto-accept is on or the decision was remembered,
- denied calls return
PERMISSION_DENIED, - approved calls write a one-use grant into
PermissionService, - the final call goes through
ToolRegistry.call()withcaller: "agent"and the real session id.
writes-files, controls-browser, starts-process, and destructive. accesses-network is still declared and audited.The ACP adapter
AcpAdapter runs an external Agent Client Protocol subprocess over stdio:
- Resolve the configured preset or custom command.
- Spawn the subprocess in the session cwd.
- Initialize ACP with
protocolVersion: 1. - Start the per-session MCP bridge and register the session, receiving a localhost URL and bearer token.
- Send
session/newwith that MCP server, thensession/promptwith the composed prompt. - Map ACP
session/updatenotifications into meith stream chunks.
ACP permission requests are allowed at the ACP layer because meith independently gates actual tool execution through AgentService and PermissionService.
MCP bridge
McpBridgeService is a dependency-light local HTTP JSON-RPC server bound to 127.0.0.1 on an ephemeral port. Each session gets a unique bearer token mapping to a binding, and tools/callmaps the external request back into the session's gated tool call function — preserving the same permission, audit, and browser-ownership model as in-process calls.
// supported MCP-style methods
initialize
notifications/initialized
notifications/cancelled
ping
tools/list
tools/call