Machine credentials
A machine records sessions where no person can sign in — CI runners, ephemeral agent sandboxes, anywhere a browser login is impossible. It records like a user but is never an administrator and never a member of a project. Instead of kcap login, the runner carries a machine credential: two environment variables that kcap exchanges for a short-lived access token by itself. No profile, no token files, nothing to refresh.
This is the right tool whenever recording has to survive a fresh environment. The interactive flows (kcap login, kcap login --device) both need a person at least once and leave a personal token behind; a machine credential is owned by the organization, works from the runner’s first boot, and can be revoked without touching anyone’s login.
1. Create the machine
Section titled “1. Create the machine”Creating a machine requires being signed in (kcap login), the owner or admin role in your organization, and Capacitor administrator rights.
kcap machine create ci-runnerThis provisions the credential and registers the machine with your Capacitor server. It prints the client ID (client_01…, public — safe to commit) and the secret, which is the only thing written to stdout; everything else goes to stderr.
Because the secret is alone on stdout, you can pipe it straight into a secret store without it ever touching disk — the client id and instructions still print to your terminal:
kcap machine create ci-runner | gh secret set KCAP_CLIENT_SECRET # only the secret enters the storegh secret set KCAP_CLIENT_ID --body client_01ABC... # the client id, from the output aboveMissed the client id? kcap machine list shows it any time — only the secret is unrecoverable.
create also accepts --visibility <private|org_public|public> — it doesn’t configure anything by itself; it selects the value the printed setup instructions tell you to set on the runner in step 3. Machines get the member role; a machine is never an administrator.
2. Configure the runner
Section titled “2. Configure the runner”The runner needs the CLI, hooks for whichever coding agent it runs, and the two credential variables in its environment:
| Variable | What it is |
|---|---|
KCAP_CLIENT_ID | The client id from step 1. Public. |
KCAP_CLIENT_SECRET | The secret from step 1. Keep it in your CI’s secret store. |
npm install -g @kurrent/kcapkcap setup --server-url https://acme.kcap.ai --default-visibility org_public --no-promptWith both variables set, every kcap invocation — hooks, watchers, imports — mints its own token (valid for about an hour) and holds it in memory. There is nothing to log in, nothing to refresh, and nothing written to disk.
- Pre-baked images — if your runner image already has hooks installed, you can skip
kcap setupand point kcap at the server withKCAP_URL=https://acme.kcap.aiinstead.KCAP_URLoutranks any profile the image might carry (see the resolution order), and a machine needs no profile at all. - Egress — the token exchange calls WorkOS directly, so a runner behind an egress policy needs
signin.kcap.aireachable in addition to your Capacitor server.
3. Choose what its sessions are visible to
Section titled “3. Choose what its sessions are visible to”A machine’s sessions follow the same visibility system as a person’s: they record with the default_visibility of the profile the machine runs under, and with no profile at all they record org_public. The valid values are private, org_public, and public — not project, which is member-only, and a machine is never a project member.
org_public is almost always what you want for CI: anyone in the org can open the runner’s sessions in the dashboard. For a machine this holds regardless of which repository the session ran in — unlike a person’s org_public sessions, a machine’s never fall back to private in personal or unrecognised repos. Set it in the kcap setup line above, or directly:
kcap config set default_visibility org_publicRun that on the machine itself — visibility lives in the profile the machine records with, exactly as it does for a person; nothing is stored on the credential. Avoid private unless you mean it: a private machine session is browsable by nobody in the dashboard, because the machine is not a person who can sign in and look.
4. Verify
Section titled “4. Verify”On the runner:
kcap statusWith the credential in place, the auth line reads:
Auth: machine credential (KCAP_CLIENT_ID and KCAP_CLIENT_SECRET set) — kcap records as the machine, not as your login.Then run your coding agent as you normally would. The session appears in the dashboard owned by the machine, visible per step 3.
Rotating and revoking
Section titled “Rotating and revoking”kcap machine list # find the service idkcap machine revoke service:9e96baf8f4f55363bc23d9a3a79939b3Revoking stops the machine authenticating from its next request. A token it already holds stays valid until it expires (up to an hour) but is no longer honoured; to cut it off at the source as well, delete the application in the WorkOS dashboard. Revocation cannot be undone — restoring access means creating a new machine. That is also the rotation story: secrets are never re-shown, so rotate by creating a replacement machine and revoking the old one.
Admins can review and revoke machines in the console too, under Settings → Machines — creation stays in the CLI, because the secret travels from WorkOS to your terminal without ever passing through the Capacitor server.
Keep machine credentials off your laptop
Section titled “Keep machine credentials off your laptop”Troubleshooting
Section titled “Troubleshooting”| Symptom | Cause and fix |
|---|---|
You need the owner or admin role in this organization to create a machine. | Your organization role is member. Ask an org owner or admin to run the create. |
You need to be a Capacitor administrator to register a machine. | The credential was issued but registration needs Capacitor admin rights on the server. Ask an admin. |
kcap machine create reports machine credentials aren’t enabled | The feature isn’t switched on for your tenant. Contact Kurrent. |
KCAP_CLIENT_ID is set but KCAP_CLIENT_SECRET is not — a machine needs both. | Half-configured runner. Set the missing variable (and check it’s stored as a secret, not a variable). |
the machine credential was rejected by … (HTTP …) | Wrong or revoked values. Check the runner’s secret store; if in doubt, revoke the machine and create a fresh one. |
| Sessions record but nobody can see them | The runner’s default_visibility is private. Set org_public (step 3). |
| The runner can’t reach the token endpoint | Allow egress to signin.kcap.ai as well as your Capacitor server. |
Related
Section titled “Related”- Commands — the full
kcap machinecommand surface - Configuration & profiles — visibility values, environment overrides, resolution order
- Visibility & sharing — how session visibility works across the product
- Setup CLI — the interactive setup for people