CLI Auth & Board Claim
Paperclip has two separate identity flows for humans on the command line and browser:
- Board claim — a one-time bootstrap step that promotes your browser-authenticated user to the owner of a freshly started authenticated instance. It migrates the trusted "local board" placeholder into a real, named human account.
- CLI auth — the everyday flow that pairs a local
paperclipaiCLI process with a signed-in board user, so the CLI can call/apiendpoints on your behalf without you typing credentials into your shell.
Both flows use a short-lived, server-minted challenge and a browser approval page. Both are designed so the secret material (the board API token, the ownership migration) never leaves the browser or the CLI process that asked for it.
This guide walks through both, shows the approval pages, and explains how to use the resulting tokens with the CLI.
When you need each flow
- You just installed Paperclip in authenticated deployment mode on a server, and the loopback trust is still active → run Board claim once.
- You want to run
paperclipaicommands against that instance from your laptop → run CLI auth (paperclipai auth login). - You're using trusted deployment mode (loopback-only local dev) → neither flow is required; the CLI and browser already trust the loopback.
Claiming a board from the CLI
Board claim only exists when all of these are true:
- Deployment mode is
authenticated. - The only instance admin is the built-in
local-boardplaceholder (i.e., no human has claimed the instance yet). - The claim challenge hasn't expired (the server keeps the active challenge for 24 hours and refreshes it automatically after that).
When the server starts and those conditions match, it prints a Board claim URL to the server log. It looks like:
http://localhost:3000/board-claim/<token>?code=<code>
The token is 48 hex characters; the code is 24 hex characters. Together they identify exactly one pending claim.
Open the URL in your browser. If you aren't signed in yet, the page will ask you to sign in or create an account first and bounce you back to the same URL after authentication.
Once you're signed in, the page shows a panel titled Claim Board ownership with a short explanation ("This will promote your user to instance admin and migrate company ownership access from local trusted mode.") and a single Claim ownership button.
Click it and the server does three things in a single transaction:
- Inserts an
instance_adminrole for your user (if you weren't one already). - Deletes the
local-boardplaceholder admin. - Walks every company in the database and, for each one, either creates an
active,owner-role membership for you or reactivates your existing membership and sets the role toowner.
The button swaps to Claiming… during the request. When it returns successfully the page switches to Board ownership claimed with a link to open the board. The in-memory challenge is marked claimed and cannot be reused.
If the challenge expired, or the URL is malformed, the page shows Claim challenge unavailable instead. Restart the server (or wait for the next refresh) to mint a new challenge.
Device-code flow: paperclipai auth login
For day-to-day CLI use, the flow is a device-code-style pairing. The CLI creates a challenge, opens your browser, you approve it, and the CLI finishes with a stored token.
Starting the login
From the machine you want to use the CLI on:
paperclipai auth login
The CLI:
- POSTs to
/api/cli-auth/challengeswith a description of itself (command,clientName,requestedAccess, and an optionalrequestedCompanyId). - Gets back a challenge containing
token,boardApiToken,approvalUrl,pollPath,expiresAt, and a polling interval. - Prints the approval URL to your terminal and tries to open it in your default browser.
- Starts polling the server at
pollPathuntil the challenge is approved, cancelled, or expires.
Common flags:
# Request instance-admin approval (only instance admins can approve this)
paperclipai auth login --instance-admin
# Scope to a specific company
paperclipai auth login --company-id <company-id>
# Target a non-default server
paperclipai auth login --api-base https://paperclip.example.com
Approving the challenge in the browser
Your browser lands on a page titled Approve Paperclip CLI access:
The panel shows what the CLI is asking for:
- Command — the CLI command that initiated the login (e.g.
paperclipai auth login). - Client — the
clientNamethe CLI sent, defaultpaperclipai cli. - Requested access — either
BoardorInstance admin. - Requested company — only shown if the CLI asked to be scoped to a company.
Two buttons at the bottom:
- Approve CLI access — only enabled if your signed-in user is allowed to approve this level of access. An instance-admin challenge requires an instance-admin approver.
- Cancel — rejects the challenge. The CLI sees the
cancelledstatus on its next poll and exits with an error.
If you aren't signed in, the page first shows Sign in required with a button that returns you here after authentication. If the challenge has already been approved, cancelled, or expired by the time you visit the URL, the page reflects that state instead of offering the buttons.
Finishing on the CLI
Once you click Approve, the CLI's next poll sees status approved, calls /api/cli-auth/me with the board API token to confirm identity, and writes the credential to the local credential store. It prints a success summary:
{
"ok": true,
"apiBase": "https://paperclip.example.com",
"userId": "usr_...",
"approvalUrl": "https://paperclip.example.com/cli-auth/..."
}
If you cancel or let the challenge expire, the CLI errors out with CLI auth challenge was cancelled. or CLI auth challenge expired before approval. — re-run paperclipai auth login to try again.
After claiming: using and rotating the token
Where the token lives
The CLI stores the board API token (and the user id it resolves to) in the platform-appropriate config directory, keyed by apiBase. You don't need to copy the token anywhere — every CLI command that accepts --api-base will look up the matching stored credential automatically.
Using it
Once logged in, the CLI sends Authorization: Bearer <stored-token> on every request. You can verify by running:
paperclipai auth whoami
which calls /api/cli-auth/me and prints:
{
"user": { "id": "...", "name": "...", "email": "..." },
"userId": "...",
"isInstanceAdmin": true,
"companyIds": ["..."],
"source": "board-cli",
"keyId": "..."
}
All other CLI commands — the ones documented in Setup Commands and Control-Plane Commands — reuse this credential unless you pass an explicit --token or override PAPERCLIP_API_KEY.
Rotating and revoking
When you want to rotate the credential, log out and log back in:
paperclipai auth logout
paperclipai auth login
paperclipai auth logout:
- POSTs to
/api/cli-auth/revoke-currentwith the stored token to revoke it server-side. - Deletes the local credential entry for this
apiBase.
If the server-side revoke fails (network error, token already invalid) the local credential is still removed — you won't be stuck with a stale entry. A new paperclipai auth login mints a fresh challenge and a fresh token with no relationship to the old one.
Multiple servers and users
The credential store is keyed by normalised apiBase, so one machine can hold separate credentials for a local dev instance, a staging server, and a production server at the same time. Switching between them is a matter of passing --api-base (or setting it in config). Logging in as a different user for the same apiBase replaces the existing credential for that server.
Troubleshooting
- "Invalid CLI auth URL." — You opened the approval page with a missing
idortokenquery param. Re-runpaperclipai auth loginto get a fresh link. - "CLI auth challenge unavailable" — The token is valid but the server no longer has a matching challenge (it expired, or the server restarted). Start the login again.
- "This challenge requires instance-admin access." — You're approving an
--instance-adminchallenge but your signed-in user isn't an instance admin. Sign in with an admin account and retry. - "CLI auth challenge expired before approval." on the CLI — You let the browser tab sit too long. Just rerun
paperclipai auth login. - Board claim page shows "Claim challenge unavailable." — The one-time ownership challenge has already been consumed, or it expired. If the instance has no real admins yet, restart the server — it mints a new challenge and reprints the URL in the logs.
Where to go next
- Setup Commands — installing, onboarding, and configuring a Paperclip instance from the CLI.
- Authentication (API) — the underlying authentication model for board users, agents, and runs.