How do I manage the gateway system?
http://localhost:3001 These endpoints manage the gateway process itself: liveness checks, device pairing, daemon lifecycle, cost reporting, filesystem browsing, and UTCP tool discovery for external agents. Most require a bearer token; /health and POST /pair are unauthenticated.
How do I check if the gateway is running?
Liveness check. No authentication required.
{ “status”: “ok”, “uptime”: 3724.5 }
uptime is the number of seconds the gateway process has been running.
How does device pairing work?
Daemion uses a two-step OTP exchange to pair a new device. The mobile app (or any client) scans a QR code that encodes the gateway URL and a short-lived OTP. Presenting that OTP to POST /pair returns the long-lived bearer token used for all subsequent requests.
Step 1 — Generate a new OTP
Generate a fresh one-time pairing code. Requires an existing bearer token (i.e. called from an already-paired device).
curl “http://localhost:3001/pair/refresh”
-H “Authorization: Bearer $DAEMION_TOKEN”
{ “code”: “847291”, “expiresAt”: “2026-03-31T08:05:00.000Z” }
Step 2 — Exchange OTP for bearer token
Exchange a one-time pairing code for the gateway bearer token. No authentication required — this is how a new device gets its token.
| Parameter | Type | Description |
|---|---|---|
otp REQUIRED | string | The 6-digit one-time code from /pair/refresh or the QR code. |
curl -X POST http://localhost:3001/pair
-H “Content-Type: application/json”
-d ’{ “otp”: “847291” }’
{ “token”: “eyJ…” }
Store this token as $DAEMION_TOKEN and include it as Authorization: Bearer $DAEMION_TOKEN on all subsequent requests.
The bearer token is a device pairing credential, not a user login. It connects a browser or phone to your local gateway. There is no user account or password — authentication is handled by the Claude CLI session on the gateway host.
How do I stop or restart the daemon?
Gracefully shut down the gateway process. Returns 200 immediately; the process exits ~200ms later.
curl -X POST http://localhost:3001/daemon/stop
-H “Authorization: Bearer $DAEMION_TOKEN”
{ “status”: “stopping” }
Exit the gateway process so the process manager (launchd on macOS, systemd on Linux) can restart it. Returns 200 immediately; the process exits ~500ms later.
curl -X POST http://localhost:3001/daemon/restart
-H “Authorization: Bearer $DAEMION_TOKEN”
{ “status”: “restarting” }
Both endpoints rely on an external process manager to handle the restart. On macOS, launchd automatically relaunches the service. On Linux, systemd does the same. If no process manager is running, restart is equivalent to stop.
How do I resync built-in extensions without restarting?
Re-sync built-in extensions from disk and refresh the global skill context. Does not restart the gateway process.
curl -X POST http://localhost:3001/reseed
-H “Authorization: Bearer $DAEMION_TOKEN”
{ “status”: “reseeded” }
Use this after adding or editing agents or skills on disk (e.g. in ~/.daemion/agents/). The gateway picks up the changes immediately without a restart.
How do I check usage costs?
Return aggregated cost totals and breakdowns by agent and model.
| Parameter | Type | Description |
|---|---|---|
period | string | Time window: today (default), week (last 7 days), or month (last 30 days). |
curl “http://localhost:3001/costs?period=week”
-H “Authorization: Bearer $DAEMION_TOKEN”
{ “today”: 0.042, “week”: 1.18, “month”: 4.75, “by_agent”: [ { “agent_id”: “opus”, “name”: “opus”, “cost”: 0.91 }, { “agent_id”: “sonnet”, “name”: “sonnet”, “cost”: 0.27 } ], “by_model”: [ { “model”: “claude-opus-4-5”, “cost”: 0.91 }, { “model”: “claude-sonnet-4-5”, “cost”: 0.27 } ] }
All cost values are in USD. The period query parameter filters by_agent and by_model breakdowns; the today, week, and month totals are always returned regardless of the period filter.
How do I browse the filesystem?
Both filesystem endpoints default to os.homedir() when no path is provided. Any bearer-token holder can list and search your home directory. Scope the path parameter explicitly, and restrict who holds the gateway token.
List subdirectories at a path. Only returns directories (not files), and hides dotfiles. Path must be within the gateway host's home directory.
| Parameter | Type | Description |
|---|---|---|
path | string | Absolute path to list. Defaults to os.homedir(). Must be within the home directory — paths outside return 403. |
curl “http://localhost:3001/filesystem/ls?path=/home/user/projects”
-H “Authorization: Bearer $DAEMION_TOKEN”
{ “path”: “/home/user/projects”, “entries”: [ { “name”: “daemion”, “path”: “/home/user/projects/daemion”, “isDirectory”: true }, { “name”: “agent-desktop”, “path”: “/home/user/projects/agent-desktop”, “isDirectory”: true } ] }
Search for files and directories by name under a root path. Searches up to 3 levels deep, returns up to 15 results. Path must be within the home directory.
| Parameter | Type | Description |
|---|---|---|
q REQUIRED | string | Search query. Minimum 2 characters. Matched case-insensitively against entry names. |
path | string | Root path to search under. Defaults to os.homedir(). Must be within the home directory. |
curl “http://localhost:3001/filesystem/search?q=claude&path=/home/user”
-H “Authorization: Bearer $DAEMION_TOKEN”
{ “query”: “claude”, “root”: “/home/user”, “results”: [ { “name”: “daemion”, “path”: “/home/user/projects/daemion”, “isDirectory”: true }, { “name”: “.claude”, “path”: “/home/user/.claude”, “isDirectory”: true } ] }
Both endpoints resolve the path and reject any .. traversal attempts. Dotfiles and node_modules are excluded from search results.
How do external agents discover available tools?
Return a UTCP (Universal Tool Calling Protocol) manifest listing all tools the gateway exposes. Used by external agents (Pi, BeadBoard, etc.) to discover what operations are available.
curl “http://localhost:3001/utcp”
-H “Authorization: Bearer $DAEMION_TOKEN”
The manifest follows the UTCP schema: a list of tool definitions with name, description, input schema, and endpoint binding. External agents can import this manifest to call Daemion tools programmatically without hardcoding endpoint paths.
How do I list available agent modes?
List the built-in execution modes (plan, act, quick, complex, etc.). Requires authentication.
curl http://localhost:3001/modes
-H “Authorization: Bearer $DAEMION_TOKEN”
GET /health and POST /pair are the only unauthenticated endpoints. Everything else, including GET /modes, requires a bearer token.POST /reseed re-syncs disk agents, skills, and built-in extensions in place — the gateway process keeps running. This is the right way to pick up changes to ~/.daemion/agents/ without downtime./filesystem/ls and /filesystem/search resolve paths and reject anything outside os.homedir() with a 403. This is enforced server-side regardless of what path parameter is supplied.by_agent and by_model breakdowns. The three top-level totals (today, week, month) are always included in the response.What can go wrong
401 {"error": "unauthorized"} — Bearer token missing or invalid. Re-pair the device via POST /pair with a fresh OTP from GET /pair/refresh.
401 {"error": "Invalid or expired code"} — The OTP passed to POST /pair is wrong or has expired. OTPs are short-lived — generate a new one with GET /pair/refresh and retry immediately.
429 {"error": "Too many attempts. Wait a minute and try again."} — Too many failed OTP attempts. The rate limiter will reset after 60 seconds.
501 {"error": "Pairing not available — gateway started without token"} — The gateway was started without a token configured. Restart it with a token set in ~/.daemion/.gateway-token.
403 {"error": "path outside home directory"} — The path param on /filesystem/ls or /filesystem/search resolved to a location outside os.homedir(). Use an absolute path within your home directory.
403 {"error": "permission denied"} — The gateway process does not have read access to the requested path. Check filesystem permissions.
400 {"error": "query too short (min 2 chars)"} — The q param on /filesystem/search must be at least 2 characters.
What’s next?
- Apps API — start and manage Vite dev servers
- Projects API — workspace management
- Extensions API — manage the 12 extension types
- Conversations API — threads and turns