page
Get Started
Install uterm, run the reference TermHub, attach a worker, and open a browser โ then add MCP or the edge backend when you need them.
uterm is an eleven-package monorepo spanning four languages: a Python core and reference hub, a TypeScript browser frontend and runtime port, and standalone Go and C# implementations of the same protocol. The reference hub runs locally; the frontend is a static bundle; the MCP server is one extra entry point; the Cloudflare edge backend is its own package. You can stop at step 2 and have a working shared terminal.
1. Install
git clone https://github.com/provide-io/provide-uterm.git
cd provide-uterm
uv sync --all-packages --all-extras --group dev
npm ci
npm run build:frontend
uv sync resolves the Python workspace โ six packages: the core, the server, the client, the platform tier, the annotation layer, and the Cloudflare adapter. npm run build:frontend builds the TypeScript bundle the hub serves to browsers. The Go and C# ports carry their own toolchains and are not part of either workspace.
2. Run the hub
The hub is a subcommand of uterm. Bind address, auth mode, and the sessions to
open all come from the config file:
uv run uterm server --config scripts/uterm-server.example.toml
The example config binds 127.0.0.1:8780 and sets auth.mode = "dev_token".
That is not an auth bypass: at startup it generates an HS256 secret, mints a
24-hour admin JWT, writes it 0600 to ~/.cache/uterm/dev_token, and then
rewrites its own config to jwt โ so local development exercises the same
validator production does. It is refused outright on a non-loopback bind.
The older mode = "dev" and mode = "none", which disabled authentication and
let any caller claim a principal via headers, have been removed.
3. Open the session
The example config declares a provide-shell session with auto_start = true,
so a shell PTY is already attached by the time the server is listening โ there
is no separate worker-attach step:
curl -H "Authorization: Bearer $(cat ~/.cache/uterm/dev_token)" \
http://127.0.0.1:8780/api/sessions
The dashboard is at http://127.0.0.1:8780/app/. It is behind the same token โ
send it as the uterm_token cookie, or as a bearer header. An unauthenticated
request gets 401 {"detail":"authentication required"}, not a login page.
4. Add a second participant
Open a second browser window, or a second client against the same session. The
hub assigns it an adjective-animal identity (e.g. drifting-otter), gives it a
deterministic color, and shows it in the presence strip. With the default RBAC,
it joins as viewer โ it can watch but not type.
Optional: register the MCP server
To let an AI agent participate, register uterm-mcp with your MCP harness.
Claude Code
.mcp.json (project) or ~/.claude.json (global):
{
"mcpServers": {
"uterm": {
"command": "uv",
"args": ["--directory", "/abs/path/to/provide-uterm", "run", "uterm-mcp",
"--url", "http://127.0.0.1:8780",
"--header", "Authorization:Bearer <dev token>"]
}
}
}
Codex
~/.codex/config.toml:
[mcp_servers.uterm]
command = "uv"
args = ["--directory", "/abs/path/to/provide-uterm", "run", "uterm-mcp",
"--url", "http://127.0.0.1:8780",
"--header", "Authorization:Bearer <dev token>"]
--url is required โ uterm-mcp is a client of the hub, not a second server. --role defaults to operator; admin is opt-in.
Reload your harness. The 28 uterm tools become available to the agent.
Optional: deploy at the edge
cd packages/provide-uterm-cloudflare
npx wrangler deploy
Point your browser at the deployed Workers URL instead of 127.0.0.1:8780. The same control channel runs on Cloudflare Durable Objects, with one DO per session.