Skip to content

Quick start

This sets up one host with one agent, reachable in the browser. No chat platform is involved. Everything below assumes agentctl is already installed; see Install.

agentctl init                         # scaffold/adopt the GitOps repo at /opt/agentctl
                                      #   (agents.yaml + agents.d/ + overlays + secrets.d/)
agentctl provision                    # host base: group, slices, dirs, backup, host crons
agentctl secret set OPENAI_API_KEY    # encrypted store; value from stdin. repeat per key

The cockpit gateway and its login proxy

Once per host:

agentctl secret set WEBVIEW_HMAC_KEY  # plus your auth driver's config — see Channels
agentctl webview-gateway install      # WS router agents dial into            :8735
agentctl webview-login install        # browser-facing login proxy            :8736

webview-gateway install also installs agentctl-hostop-coordinator.service, the durable host-operation store (see Architecture).

Both listeners bind to localhost. Put your own HTTPS proxy in front of them; TLS and DNS are not handled by agentctl.

An agent whose channel IS the browser

agentctl agents add assistant --channel webview --user-email person@example.com
agentctl status                       # host readiness + fleet overview

The gateway routes to this agent by that login identity, so there is no bot token. Open the cockpit at your proxied top --web address and send a message. An auth card renders; authorize it and the agent is live. The cockpit can then be installed as a PWA.

An agent can also be reached on a chat platform at the same time. Adding a channel does not replace the cockpit. See Channels.

What you just created

/opt/agentctl is the source of truth. It holds agents.yaml, the per-agent agents.d/ shards, the mcp/ skills/ agents/ apps/ hooks/ overlays, and the sops-encrypted per-owner secrets.d/ store. It is an ordinary git repo: push it, clone it on another host, and run agentctl apply there. The age identity that decrypts the secret store stays on the host and is never committed.

See Architecture for the layering and precedence rules, and Multi-host fleet for how a second host becomes a secrets recipient.

The first agent on a host is an admin agent by default, which means the fleet can be driven through it instead of from a shell. Admin is a role and any number of agents may hold it. See the admin role.

First run in the cockpit

What the person named by --user-email sees, in order, the first time they open the proxied address.

The login page

The browser reaches webview-login before it reaches anything else, and what it renders is decided by WEBVIEW_AUTH_DRIVER:

  • basic — a username/password form served by agentctl itself, with the accounts read from WEBVIEW_BASIC_USERS (email:password,…). An entry with an empty password is refused at startup rather than accepted, so a trailing colon cannot open the host.
  • oidc — also entra, google, and the unset default. No local form: the browser is redirected to WEBVIEW_OIDC_ISSUER's own sign-in page and returns to /auth/callback. It needs WEBVIEW_OIDC_ISSUER and WEBVIEW_OIDC_CLIENT_ID or the service will not start.

On success the proxy sets a wv_session cookie — an HMAC token over WEBVIEW_HMAC_KEY, 30 days by default, WEBVIEW_SESSION_TTL to change it — and reverse-proxies to the cockpit with the authenticated address in X-User-Email. That address is the routing key. It is matched against the ledger, and the whole session is scoped to the single agent it maps to. An address that maps to no agent authenticates successfully and then sees nothing at all, which is what a mistyped --user-email looks like from the browser.

A scoped person lands directly in their agent's cockpit; the fleet grid and the close/back controls are removed from the page. An admin identity keeps the fleet mini-app and can open another agent in a second tab with /?agent=<name>&host=<host>. Sign out sits at the bottom of the left sidebar, and appears only when a login proxy is in front.

The first message is a Claude login

agents add provisions the agent but does not log it in — see Using the CLI. For a claude agent that is what the auth card is: the moment a browser opens the cockpit against an agent whose Claude credentials are dead or absent, the web-view tier posts a three-step message into the chat without waiting for the person to type anything.

  1. A claude.com authorize link. Open it in a browser already signed in to the account the agent should run as.
  2. Click Authorize. The page shows a code#state string.
  3. Paste that whole string — both halves and the # — back into the cockpit as the next message.

The paste is intercepted before it becomes a turn, exchanged for credentials that are written under the agent's own home, and the unit is restarted so it boots logged in. The agent answers with a when it is back. /login at any point issues a fresh link; the first one expires.

A message sent while the agent's session is not yet up is answered with ⏳ Still connecting — try again in a moment. That is the harness not being attached yet, not a failure.

This flow is claude-only. A pi agent boots on a provider API key from the secret store instead, and /login at one does nothing.

What is on screen

where what
header the session control (lane name, status dot, and a count carrying the worst status of the other lanes), the mini-app launcher strip, the all-apps drawer, tile-sessions, the agent panel toggle, the notifications bell
left sidebar sessions, open by default, stacked over the workspace tree rooted at ~/workspace with refresh / new folder / new file / upload
centre the transcript, with the composer pinned below it — it stays put while a file tab or a mini-app owns the pane above
composer row attach, camera (touch devices only), microphone for a voice note, the text box, send
right panel closed by default: skills, sessions, memories, subagents, scheduled jobs

Below 720px the header is hidden entirely and its sheet toggles move into a thumb band above the composer — the same nodes, relocated, not a second copy.

Typing / at the start of an empty composer lists the agent's activated skills, filtered as you type; picking one inserts /<name>. That is the discovery surface for what this agent can already do. A new agent carries the default skill set, which includes onboarding — the agent runs its own walk-through from it, and Onboarding describes what that covers.

The launcher strip shows the agent's active mini-apps. Activation is derived from which MCPs that agent has wired, so it is short on a fresh agent and grows with mcp add; the browser MCP is a default for every claude agent, so the live browser view is there from the start. Apps that declare no MCP at all are active for everyone. See The cockpit.

Where the files are

The workspace tree is the only way to browse ~/workspace, and it edits in place. An upload from the tree lands at the path selected in it; a file attached in the composer is staged for that one message instead. Both go through the same resumable uploader, so a large file over a phone connection survives a dropped tab.

Once the first message works, install the cockpit as a PWA — the 30-day session is sized for exactly that. Deeper detail on the surfaces lives in The cockpit, and on the two host services in The webview gateway.