A native macOS app that turns project, environment, LLM, and ACP harness choices into one managed coding session.
Coding Agent Control Plane is an effort to make the changing combinations of projects, infrastructure, environments, AI providers, models, and coding agents manageable across an organization. It gives departments and teams one native application in which to choose the context for a coding session and start it without rebuilding the surrounding toolchain by hand.
The project is built around the Agent Client Protocol (ACP). ACP keeps the desktop experience independent of any one coding agent, so a team can use Claude Code for one project, Codex for another, Grok Build for an experiment, or OpenCode for an internal workflow without replacing the shell around them.
The application uses a quiet two-pane workspace:
- The off-canvas sidebar keeps projects, standalone threads, history, and settings close without reducing the transcript to an icon rail.
- Threads may start with or without a project and can be associated with a project until their first prompt.
- The composer keeps harness, project, environment, instructions, tools, and model choices outside the conversation.
- The model picker is searchable and shows only model names. Provider routing remains an implementation detail of the operator-approved catalog.
- Instructions use durable multiline guidance. Allowed tools use a searchable checklist instead of internal comma-separated names.
- Runtime-specific controls appear only when the selected harness reports and can apply them.
Projects, standalone threads, and resumable history stay in the off-canvas sidebar. The composer gives the project selector room while keeping the model immediately beside send and stop.
The world controls which harnesses and models are available. Unsupported harnesses remain visible but unavailable instead of failing after selection.
Settings makes installation state and operator-provided extensions visible without mixing administration into the conversation.
Enterprise development rarely has one stable stack. A department may own several projects, each with development, preview, staging, and production environments spread across platforms such as Vercel and AWS. Those environments may use different LLM gateways, provider accounts, approved models, permissions, and coding-agent harnesses.
Today, the combination is often reconstructed in shell profiles, environment variables, gateway settings, agent configuration files, and copied tokens. That creates avoidable work and makes the effective session configuration difficult to review, reproduce, or secure.
Coding Agent Control Plane turns that matrix into an explicit composition:
Coding session
= project
+ environment
+ LLM provider
+ model
+ coding-agent harness
The user selects the required combination. The application resolves the working directory, platform context, provider route, model policy, agent command, permissions, tools, and credential references needed to start the session.
The application is designed to enable departments and teams to:
- Organize projects and environments for a department or team, including platform-backed environments on services such as Vercel and AWS.
- Register approved LLM providers and gateways, then choose the model appropriate for a project, environment, or task.
- Use different ACP-compatible coding-agent harnesses, including Claude Code, Codex, Grok Build, and OpenCode.
- Compose project, environment, provider, model, and harness settings at session start instead of maintaining a separate hand-written launch setup for every combination.
- Start a coding session with the correct workspace, tools, permissions, routing, and credentials without manually exporting environment variables or copying gateway tokens.
- Keep sensitive values in the macOS Keychain while project and environment configuration contains only non-secret metadata or opaque credential references.
This is not intended to force an enterprise onto one cloud, model vendor, or agent. Its purpose is to make those choices explicit and interchangeable while giving operators a consistent policy and security boundary.
The product presents projects and environments to users while operator-authored world descriptors define the approved provider and harness catalog.
Department / team
└── Project
├── source and working context
└── Environment
├── platform target (for example Vercel or AWS)
├── working directories and environment URLs
└── session composition
├── LLM provider / gateway
├── model
├── ACP harness
├── permissions
└── plugins, skills, and MCP connections
An environment is the primary runtime context. It tells the desktop shell where the work happens and which platform context applies. A project supplies the work the agent should act on. Provider, model, and harness selections describe how the agent should run.
A world is an operator-controlled policy bundle. Exactly one world is active; it declares the providers and harnesses available to the shell, their defaults, and their launch semantics. World descriptors never contain raw secrets. This keeps configuration portable between teams without turning a repository manifest into a credential store.
A payments team could select:
Project checkout-api
Environment staging-us-east-1 on AWS
Provider company LLM gateway
Model approved coding model
Harness Claude Code
For a different task, the same project could use a Vercel preview environment,
another approved model, and Codex. The application should assemble either session
from managed configuration; the developer should not need to rewrite a .env,
change a global CLI profile, or paste a token into an agent config file.
World and session records contain environment variable names, never raw credentials. Electron main resolves approved names and passes their values only to the selected harness process. Values never cross preload IPC or enter the persisted transcript.
The enterprise configuration layer builds on the project's original goal: a desktop Agent Factory in which a Coding Agent can build and iterate on a target agent while a Test/Eval Agent validates its behavior and quality.
ACP is the interoperability contract between the desktop application and coding
agents. Electron main owns HarnessV1Session lifecycle through the AI SDK
@ai-sdk/harness-acp adapter. React consumes a validated event stream and does
not implement ACP.
Agent Plugins and Agent Skills provide reusable capabilities. Standard MCP or an agent's native transport connects tools; MCP-over-ACP is outside this shell's scope. The same declarations can also drive the Node-based harness evaluation lane without moving that runtime into the WebView or native byte pipe.
This repository is a greenfield implementation of that product direction, not a finished enterprise cloud-management suite.
The current foundation includes:
- a secure Electron main/preload boundary and React/Vite renderer;
- persistent projects and resumable AI SDK harness sessions with streaming and cancellation;
- world declarations for providers and harnesses, including Claude Code, Codex, Grok Build, and OpenCode;
- Application Support session and lifecycle-state storage;
- project, provider, model, harness, skill, tool-filter, and environment controls;
- a plugin registry, MCP runtime, OpenAPI connector, desktop update service, and a Node harness-evaluation lane.
Full platform lifecycle adapters for systems such as Vercel and AWS, centralized enterprise policy, and production identity integration remain part of the product direction. The shell and contracts are being shaped so those capabilities can be added without coupling every team to one infrastructure or AI stack.
The application keeps ownership boundaries narrow:
| Layer | Responsibility |
|---|---|
| React renderer | AI Elements transcript, composer, and project/session controls |
| Electron main | macOS windows, security, validated IPC, projects, environment resolution, and harness lifecycle |
| Desktop runtime | Shared AI SDK ACP adapter, bootstrap, and local sandbox |
| Domain packages | Project, environment, world, provider, model, harness, plugin, and theme contracts |
| Services | Provider gateway, plugin catalog, MCP aggregation, updates, and harness evaluation |
The production frontend is static. Node and Electron APIs are unavailable in the renderer; all native operations use the narrow preload contract.
See the environment domain model, the ACP runtime architecture, and the extensions architecture for the durable ownership and protocol decisions.
The signed app is only the shell. Policy, plugin content, tools, and binary updates travel on separate rails so an operator can change them without rebuilding the desktop.
A world is the operator catalog the shell is set for. Exactly one is
active. worlds/<id>/world.json declares approved LLM providers (gateways)
and ACP harnesses, their defaults, and how to launch them. It never holds
raw secrets — only variable names such as tokenEnv and forwardEnv.
worlds/example is the world that ships. services/chat-gateway loads it
and serves GET /world; Settings → LLM Providers and Harness read that
payload. Organizations, projects, and environments are product state, not
world fields. Staging with pnpm gateway:build copies the descriptor into
the host resources the packaged app uses.
services/plugin-registry is a private catalog of plugin packages. Operators
add or update skills and MCP connections without an application release.
Packages are validated, packed into zips, and listed in catalog.json with
a sha256 of the artifact that actually ships. The desktop sync client in
services/chat-gateway fetches the catalog, verifies the hash, then unpacks.
A mismatch skips that plugin rather than installing untrusted bytes.
This rail is the sibling of the update service: app binaries and plugin content publish independently.
services/mcp-runtime is the shared Streamable HTTP runtime for MCP servers
the chat-gateway spawns. Product tools use standard MCP (stdio or HTTP), not
MCP-over-ACP. The gateway aggregates those servers and attaches the ones a
chat selected. Each request gets a fresh transport so agent sessions stay
isolated.
services/openapi-connector is an MCP server that turns an OpenAPI 3.x or
Swagger 2.0 document into tools, one per operation. The gateway spawns it
per connection the same way it spawns any other stdio MCP source. The
example plugin uses it for the storefront sample spec under
plugins/example. OpenAPI is an authoring format; the runtime connection
the agent sees is still MCP.
services/update-service publishes signed desktop application archives.
The host checks a channel (stable or test) for darwin arm64/x64 (and
universal) zips and downloads through signed /api/release URLs. Checked-in
release metadata lives next to the artifacts; no GitHub Release is required.
Application updates stay on this rail. Plugin updates stay on the plugin
registry.
apps/
├── electron-desktop/ Electron main, preload, and session manager
└── web-ui/ React/Vite AI Elements renderer
packages/
├── desktop-runtime/ Shared AI SDK harness runtime
packages/shared/
├── chrome/ Desktop layout and navigation
├── plugins/ Plugin catalog and attachment contracts
├── theme/ Tokens and appearance
├── ui/ Shared shadcn and AI Elements primitives
└── world/ Provider and harness declarations
crates/ Rust protocol and plugin clients
plugins/ Example and bundled plugin packages
services/
├── chat-gateway/ Provider routing, plugin catalog, MCP aggregation
├── desktop-helper/ Native loopback helper
├── harness-eval/ Node runtime for harness evaluation
├── mcp-runtime/ Streamable HTTP runtime for MCP servers
├── openapi-connector/ OpenAPI spec → MCP tools (stdio)
├── plugin-registry/ Verifiable plugin catalog service
└── update-service/ Desktop update service
tooling/asset-assembler/ Atomic production asset assembly
worlds/ Operator-authored provider and harness catalogs
docs/ Intent, spec, plan, and durable architecture
- macOS (the first supported Electron target)
- Node.js 24+
- pnpm 10+
- Go 1.22+ for
services/desktop-helper - Rust 1.85+ for Rust services and crates
pnpm install
pnpm devWeb development uses Portless and is available at
https://web-ui.localhost/. The first startup may ask for permission to bind
port 443. For a browser-only fallback, use:
PORTLESS_PORT=1355 pnpm devpnpm dev:web remains available for static renderer work. It intentionally shows
that Electron is required because a browser cannot prove project access, process
lifecycle, environment resolution, or IPC.
pnpm build # renderer, Electron, services, and packages
pnpm gateway:build # gateway plus staged plugins, worlds, and MCP bundles
pnpm electron:build # Electron TypeScript build
pnpm validate # lint and type checks
pnpm test # renderer, Electron, Node, Go, and Rust tests
pnpm smoke:web # browser unavailable-state smoke
pnpm clean # generated build and package outputsThe Electron release contains main, preload, and the static renderer. The update service publishes application binaries; the plugin registry publishes separately verifiable plugin content.





