The control plane
for coding agents.

Run Claude Code, Codex, Grok and three more from one surface — one at a time, or as a team on one goal. Bring your own subscription.

Download for macOSLatest (v0.2.3216)Other platforms
Install on a server
curl -fsSL https://dl.ycodium.com/install.sh | sh

It writes its own tools.

This is a session that actually ran. The agent read the plugin API, wrote a plugin, stopped to ask, and then called the tool it had just built.

Recorded, not drawn. Real events, replayed through the same reducer the app uses.7 tool calls · 50s
You
I keep wanting to know how many lines each file in this project has, but there is no tool for it. Write yourself a Ycodium plugin that adds one command: given a glob, it returns each matching file with its line count, sorted longest first. Keep it tiny. Run it in this thread and show me the result for "*.md". Don't install it permanently.
Tool
ycodium ycodium_inspect api
done
Tool
Read claude-config/…/toolu_01MuPEqzSSmibj44VQSAEk2j.txt
done
Tool
Staged plugin line-counter v1
done
Tool
ycodium ycodium_plugin_define import { definePlugin } from "@ycodium/plugin-api"; const ROOT = "/tmp/ycodium-fixture/…
done
agent
Plugin staged. Now mounting it into this thread only (not installing permanently) and will need your approval.
Asks you
Run plugin line-counter v1 in this thread?
RejectApprove
Tool
ycodium ycodium_plugin_run line-counter
done
Tool
Plugin line-counter v1 is running in this thread
done
agent
I've staged the plugin and requested to mount it in this thread — an approval card should appear for you. Let me know once you approve it (or I'll notice when the tool becomes available) and I'll run it against *.md.
agent
The plugin is mounted and approved. Running it now against *.md.
Tool
ycodium line-counter_count_lines *.md
done
agent
Result for *.md:
3   README.md
The plugin (line-counter) is mounted in this thread only — it wasn't installed permanently, so it disappears when this session ends. It walks the project tree (skipping .git, node_modules, etc.), matches file basenames against your glob, and returns lines<TAB>path, sorted longest first. Say the word if you want it made permanent (ycodium_plugin_promote).

A thin view of the product timeline — expanded output, diffs and the full approval card live in the app.

It looks at the page.

The agent read the page, not a description of it. It took the total off the rendered cart, fixed the line behind it, reloaded, and looked again. Both screenshots below are what it actually saw.

Recorded, not drawn. Real events, replayed through the same reducer the app uses.6 tool calls · 19s
You
The cart total on http://127.0.0.1:5173 is wrong. Open it in the preview, tell me what it says and why, then fix site/cart.js and reload to confirm.
Tool
Read demo/site/cart.js
done
Tool
ycodium preview_open http://127.0.0.1:5173
done
Tool
ycodium preview_snapshot
done
agent
The page shows Total: $101.75, but it should be $126.25 (Keyboard $89.50 × 1 + Cable $12.25 × 3 = $89.50 + $36.75). The bug is in site/cart.js:13 — the reduce sums item.price but ignores item.qty. Fixing it now.
image.png
Tool
Edit demo/site/cart.js
done
Tool
ycodium preview_navigate http://127.0.0.1:5173
done
Tool
ycodium preview_snapshot
done
agent
Confirmed fixed — total now shows $126.25 after reload. The bug: cart.js:13 summed item.price without multiplying by item.qty, so the Cable's quantity of 3 wasn't counted. Fixed by changing the reduce to sum + item.price * item.qty.
image.png

A thin view of the product timeline — the browser itself, the element picker and the console live in the app.

Remote is the default, not an afterthought.

Ycodium runs on a machine you own — a spare desktop, a home server, a small cloud box — and every client connects to that one place.

  • Multiple clients connect to the same environment at once.
  • Close your laptop — the agent keeps running.
  • Check progress from your phone.
  • Switch devices and pick up the same thread.
Direct

Straight to the Host over your LAN or a reachable address. No third party in the path.

Relay

No open ports. Ycodium's relay — hosted or self-hosted — forwards the connection between your client and the Host.

Tailscale

Already on a tailnet? Publish the Host over Tailscale Serve HTTPS and pair through a clean MagicDNS URL.

SSH

Point the desktop app at user@host. It starts or reuses Ycodium there and forwards a local port — nothing to set up by hand on the remote box.

The relay introduces you. It never joins the session.

A direct connection cannot reach a machine behind a router you do not control. The relay's job is to put the two ends in touch — not to carry what they say. The session is sealed end to end, and the relay forwards bytes it cannot read.

Your clientweb, desktop or phone
Relayin the path, not in the session
Your machinewhere the agents actually run
sealed end to end — Noise IK
The relay sees
  • which environment a client is asking for
  • an endpoint to hand back, good for two minutes
  • the size and timing of the bytes it forwards
The relay never sees
  • anything inside the session
  • your machine's static key, or your client's
  • a credential it could mint or replay
Bound to keys, not to hostnames

The session identity is the host's static key and the client's, not a TLS certificate or a tunnel hostname. Your server generates its key on first run and the client pins it; TLS still carries the ciphertext, but it is no longer what you are trusting.

Connect hands back an address, nothing more

connect returns an environment id, an endpoint and a two-minute expiry. No credential, and it never mints one for you — the client authenticates the endpoint with the grant it already holds, or you pair first.

The same relay, yours or ours

One set of handlers runs either as a Cloudflare Worker or as a plain Node process, so a self-hosted relay and a hosted one are interchangeable. Neither holds a host key, which is what makes swapping them safe.

Bring your own sub

Ycodium doesn't resell tokens. Plug in the agents you already pay for with the credentials you already have — six come set up by name, and anything that speaks ACP is one command away.

Codex
codex login
Claude Code
claude auth login
Grok
grok login
DeepSeek Harness
DEEPSEEK_API_KEY
OpenCode
opencode auth
Kimi Code
kimi login
Any ACP agent
Tell Ycodium what to run and which flag turns on ACP. No per-vendor work needed.

Two accounts on one provider, side by side.

An account is an instance: its own login, its own default model, its own colour. Nothing is shared between them, and the choice rides on the turn — switch mid-thread and the next turn runs on the other account.

One providerone CLI on the machine
Instance A
CLAUDE_CONFIG_DIR=~/.claude-a
  • Its own login
  • Its own default model
  • Its own proxy
Instance B
CLAUDE_CONFIG_DIR=~/.claude-b
  • A different login
  • A different default
  • Direct, no proxy

The driver hands each instance its own config directory when it launches the CLI, so the two logins never overwrite each other. Codex works the same way through CODEX_HOME; the ACP vendors each name their own variable.

Per instance
  • displayName
  • accentColor
  • environment
  • proxyId
  • enabled
  • hiddenModels
  • modelOrder
  • defaultModel
  • The picker shows who is signed in on each one — read from that instance's own credential file, decoded for display and never used to authorise anything
  • Sign in headlessly where the CLI supports a device code: it prints a URL and a code and polls until you approve, so a machine with no browser can still hold an account
  • The model selection travels on thread.turn.start, not on the thread, so one conversation can run turns on two accounts

One thread, three surfaces.

Start a thread on the web, keep it going on desktop, check in from your phone — same environment, same history, no hand-off required.

Web

Open a browser, pair once, and you're in — nothing to install for a quick check-in.

Desktop

The full app, plus the one thing only Desktop can do: launch or take over a remote Host over SSH.

Mobile

Built for checking in — watch a turn land, approve a pending step, or nudge the agent from your pocket.

Or @ a bot in Telegram, WeCom or Lark: the work lands in a normal thread on a normal project, and you pick it up later from any of the three.

Everything else, without leaving the thread.

The panel on the right carries the tools you would otherwise switch windows for. They follow the project you have open, and they run on the environment — not in your browser.

Source control

Stage, unstage, commit, switch branch or worktree. Publish a local repository to GitHub or GitLab and wire up the remote in one flow.

Files

Browse, open, edit, search, upload and download — on the machine the agent works on, not a copy of it.

Terminal

A real shell on that same machine, in a drawer under the conversation.

Pull requests

Read and review GitHub pull requests and GitLab merge requests in the panel.

Browser

A built-in preview for the dev server the agent just started.

Permission modes

Four settings, per thread, from the composer: ask every time, auto-accept edits, auto, or full access.

Teach it your tools once. Every agent gets them.

Add an MCP server or a skill in Settings and every provider Ycodium launches receives it. Ycodium never edits a provider's own config files — it passes the entries at launch time, so nothing you set up by hand gets overwritten.

MCP servers

stdio, http or sse, with per-CLI switches and a health check that runs from the environment. A CLI that cannot speak a transport is shown disabled, never silently skipped.

Skills

A folder with a SKILL.md, written where Claude, Codex and OpenCode look for it. Two switches decide whether the agent may call it and whether you may.

Two scopes

Environment entries apply to every project on that machine. Entries in a repository's ycodium.json travel with the repo and win on a name clash.

Ready-made servers from a catalog, installed in a click
Plugins add tools, background reactions, settings cards and panels
Chat is itself a built-in plugin — nothing special about it
Written against a plugin API that never imports the host

And the product itself is plugins.

The chat bridge, the pull-request panel, session import — each one is a plugin, mounted through the same API a plugin you write gets. Nothing in it is reserved for us.

What a plugin can add
  • ctx.toolkit()tools the agents can call, over MCP
  • ctx.command()a command the clients can dispatch
  • ctx.reactor()a reaction to orchestration events
  • ctx.interval()a background loop the host stops for you
  • ctx.cli()a ycodium subcommand
  • ctx.settingsCard()a card in Settings, secrets included
  • ui.pagesa page of your own inside the app
  • ui.panelspanels docked beside the conversation
  • ui.appearancea theme pack, one per plugin
What it must ask for
  • fs.readread files, path prefixes declared up front
  • process.spawnrun a program from an allowlist
  • process.workspaceand run it inside a project directory

Anything not declared is refused at the call, not audited afterwards. The approval card lists what a plugin asked for before you say yes.

These ship as plugins
  • conversation
  • tool-display
  • skill-discovery
  • connector-registry
  • telemetry
  • trace-diagnostics
  • plugin-center

Which is the honest test of a plugin API: if it could not carry the product's own features, it could not carry yours. The first demo on this page is an agent writing one of these from scratch and running it in the thread.

Your agents deserve better than a terminal.

Install it, plug in the harness you already pay for, and let your agents get to work.

Download for macOSLatest (v0.2.3216)Other platforms
Install on a server
curl -fsSL https://dl.ycodium.com/install.sh | sh