Daemion docs

How do I pair a device?

~1 minute
Prerequisites: Running gateway

The gateway token is device pairing — it connects your browser or phone to YOUR gateway running on your machine. It is not user authentication. You authenticate via the Claude CLI (claude /login), not through Daemion.

QR code pairing

When the gateway starts, it prints a QR code directly in the terminal:

text

Daemion gateway running on http://localhost:3001

Pair your phone: ┌─────────────────────────────┐ │ │ │ ▄▄▄▄▄ ▄ ▄▄▄ ▄▄▄▄▄ │ │ █ █ ██ █ █ █ █ │ │ █▄▄▄█ █▄▄█ █ █▄▄▄█ │ │ │ └─────────────────────────────┘

OTP: 847291 (expires in 10 minutes)

Point your phone’s camera at the QR code. The app opens automatically and completes pairing — no typing required. The QR encodes both your gateway URL and the one-time pairing code.

6-digit code pairing

If scanning isn’t an option, use the 6-digit OTP shown in the terminal. Enter it on the pairing screen in the browser app, or POST it directly to the gateway:

POST /pair

Exchange a one-time pairing code for a bearer token. The token is valid until the gateway is reset or a new token is issued.

Parameter Type Description
otp REQUIRED string The 6-digit code printed in the terminal on gateway startup.
bash

curl -X POST http://localhost:3001/pair
-H “Content-Type: application/json”
-d ’{“otp”: “847291”}‘

Response:

{“token”: “dae_tok_a1b2c3d4e5f6…”}

Store that token — every subsequent API request needs it as a bearer header.

Using the bearer token directly

The token is saved to ~/.daemion/.gateway-token on the gateway machine. All API endpoints except /health and /pair require it:

bash

DAEMION_TOKEN=$(cat ~/.daemion/.gateway-token)

curl http://localhost:3001/agents
-H “Authorization: Bearer $DAEMION_TOKEN”

The browser and phone store the token in localStorage after pairing — you won’t need to handle it manually in normal use.

Refreshing the pairing code

The OTP expires after 10 minutes. If you need a fresh one without restarting the gateway:

GET /pair/refresh Auth required

Generate a new OTP and print a fresh QR code. The previous OTP is immediately invalidated. Requires an existing bearer token.

bash

curl http://localhost:3001/pair/refresh
-H “Authorization: Bearer $DAEMION_TOKEN”

The terminal will print a new QR code and 6-digit code. Previously issued bearer tokens remain valid — only the OTP changes.


Common questions

Q What if my code expired?
Run GET /pair/refresh to get a new one, or restart the gateway with daemion start. Already-paired devices are not affected — only the OTP changes.
Q Can I pair multiple devices?
Yes. Each device goes through the same OTP flow and receives its own bearer token. Run GET /pair/refresh between pairings to generate a fresh code for the next device.
Q Where is the token stored?
On the gateway machine it lives in ~/.daemion/.gateway-token. The paired browser or phone stores its copy in localStorage. Neither location is synced — if you clear localStorage you'll need to re-pair that device.
Q Is this secure?
The OTP is rate-limited and expires after 10 minutes. The bearer token is validated with a timing-safe comparison (no timing attacks). For remote access over the internet, run Daemion behind Tailscale — it adds end-to-end encryption on top of the bearer token.

What can go wrong

Pairing errors

429 “Too many attempts” — The OTP endpoint is rate-limited. Wait 60 seconds, then try again. Don’t retry in a loop — each failed attempt resets the window.

401 “Invalid or expired code” — The OTP expired (10-minute window) or was mistyped. Run GET /pair/refresh or restart the gateway to get a fresh code.

501 “Pairing not available” — The gateway started without finding a token file at ~/.daemion/.gateway-token. Make sure the ~/.daemion/ directory exists and is writable, then restart.


What’s next?