Local API
April 22, 2026 · View on GitHub
This page is the canonical contract for standalone HTTP/WebSocket/SSE routes. Use Setup for first-run flags and Configuration for password/network settings behavior.
The standalone server exposes local HTTP, WebSocket, and SSE endpoints at http://localhost:3847.
The canonical runtime contract is GET /api/v1/status and its sessions[] array. Treat older per-surface projections as convenience shapes, not the main contract.
HTTP Endpoints
Status
GET /api/v1/status
Returns the current standalone snapshot, including machine metadata, runtime sessions, and available providers.
Example shape (trimmed):
{
"id": "standalone_mach_123",
"type": "standalone",
"hostname": "studio-mac",
"machine": {
"hostname": "studio-mac",
"platform": "darwin"
},
"sessions": [
{
"id": "session_abc",
"providerType": "claude",
"transport": "pty",
"status": "idle",
"title": "Claude Code"
}
],
"availableProviders": [
{
"type": "claude",
"installed": true
}
]
}
Standalone Auth Status
GET /auth/session
Returns the current local auth posture for the standalone dashboard and API, including whether auth is required, whether the current request is authenticated, whether token auth is configured, whether dashboard password auth is configured, and whether the current bind mode is exposing a public-host warning.
Example response:
{
"required": true,
"authenticated": false,
"hasTokenAuth": false,
"hasPasswordAuth": true,
"publicHostWarning": false,
"boundHost": "127.0.0.1"
}
Dashboard Login
POST /auth/login
Content-Type: application/json
{
"password": "correct horse battery staple"
}
Successful response:
{
"required": true,
"authenticated": true,
"hasTokenAuth": false,
"hasPasswordAuth": true,
"publicHostWarning": false,
"boundHost": "127.0.0.1"
}
Command Router
POST /api/v1/command
Content-Type: application/json
{
"type": "send_chat",
"payload": {
"targetSessionId": "7d9fca29-a5d3-46ab-b16b-272f0187a8d5",
"message": "Fix the login bug"
}
}
Use raw targetSessionId from sessions[] whenever possible. Synthetic route ids are transport helpers, not the canonical runtime identity.
Runtime Snapshot
GET /api/v1/runtime/{sessionId}/snapshot
Returns the latest session-host text snapshot for CLI runtimes, including seq, text, truncated, cols, and rows.
Runtime Events
GET /api/v1/runtime/{sessionId}/events
Server-Sent Events stream for a hosted CLI runtime. The stream sends:
runtime_snapshotimmediately when available- session-host events such as
session_output,session_exit,write_owner_changed
Standalone Preferences
GET /api/v1/standalone/preferences
POST /api/v1/standalone/preferences
Reads or updates standalone-local preferences such as:
- saved default bind host (
127.0.0.1vs0.0.0.0) - standalone font preferences for chat/code/terminal surfaces
- whether token auth is configured
- whether dashboard password auth is configured
- whether the saved/current host mode should surface a LAN/public warning
Example response:
{
"standaloneBindHost": "0.0.0.0",
"currentBindHost": "127.0.0.1",
"standaloneFontPreferences": {
"chat": { "preset": "pretendard" },
"code": { "preset": "jetbrains-mono" },
"terminal": { "preset": "berkeley-mono" }
},
"hasPasswordAuth": true,
"hasTokenAuth": false,
"publicHostWarning": false
}
Example update request:
POST /api/v1/standalone/preferences
Content-Type: application/json
{
"standaloneBindHost": "0.0.0.0",
"standaloneFontPreferences": {
"chat": { "preset": "system-ui" },
"code": { "preset": "fira-code" },
"terminal": { "preset": "custom", "customFamily": "\"Berkeley Mono\", \"SF Mono\", monospace" }
}
}
These preferences persist to the standalone-local preference file and are reflected by the Settings → Network Access and Settings → Appearance → Fonts sections in the standalone dashboard.
Workspace Mux State
GET /api/v1/mux/{workspaceName}/state
GET /api/v1/mux/{workspaceName}/socket-info
POST /api/v1/mux/{workspaceName}/control
GET /api/v1/mux/{workspaceName}/events
These routes expose the local terminal mux workspace state and control/event channels for standalone/local workflows.
For the user-facing explanation of adhmux, workspace files, and mux control sockets, see Terminal Mux.
WebSocket
Connect to ws://localhost:3847/ws for real-time standalone updates.
const ws = new WebSocket('ws://localhost:3847/ws');
ws.onmessage = (event) => {
const message = JSON.parse(event.data);
console.log(message);
};
The standalone WebSocket currently carries:
- initial status payloads
- command results
- shared transport topic subscriptions
Like the HTTP API, the WebSocket requires either:
- a valid local dashboard session cookie, or
- token auth on the upgrade request (for example
?token=..., or an authorization bearer header when your client supports custom headers)
Supported shared subscription topics:
session.chat_tailmachine.runtimesession_host.diagnosticssession.modaldaemon.metadata
Capability-Driven Clients
If you are building against the local API, rely on runtime metadata instead of hardcoded provider assumptions.
sessions[].capabilitiestells you which commands are validsessions[].providerControlsdescribes provider-declared controls such as model/mode selectorssessions[].controlValuescarries the provider's current selected control values when availablesessions[].summaryMetadatacarries compact always-visible provider metadata when availableavailableProviders[]tells you which built-in providers are present and installed on this machine
Common Command Types
Available commands depend on the target session. Read sessions[].capabilities before assuming a command is valid.
Common command types:
| Command | Description |
|---|---|
send_chat | Send a message to the target session |
read_chat | Read current chat state |
new_chat | Start a new chat when supported |
list_chats | List available chats when supported |
switch_chat | Switch to another chat/session when supported |
resolve_action | Approve or reject a pending action |
change_model | Change model when exposed by the provider |
set_mode | Change mode when exposed by the provider |
set_thought_level | Change ACP thought-level style controls |
launch_cli | Launch a CLI or ACP session |
stop_cli | Stop a CLI or ACP session |
Session-host operator actions are also routed through the same command surface:
session_host_get_diagnosticssession_host_resume_sessionsession_host_restart_sessionsession_host_stop_sessionsession_host_prune_duplicate_sessionssession_host_force_detach_clientsession_host_acquire_writesession_host_release_write
For recovery workflows and diagnostics meaning, see Session Host.
Authentication
By default the local API follows the standalone auth state.
- if no token and no dashboard password are configured, the local API is open
- if token auth is enabled, API calls can use bearer auth or a
?token=query parameter - if dashboard password auth is enabled, browser sessions use a local cookie-backed login flow
- unauthenticated
/api/*requests return401 Unauthorized. Provide dashboard session cookie or token auth.
Relevant auth routes:
GET /auth/session
POST /auth/login
POST /auth/logout
POST /auth/password
Password management examples:
Set or rotate the dashboard password:
POST /auth/password
Content-Type: application/json
{
"currentPassword": "old-secret",
"newPassword": "new-secret"
}
Clear the dashboard password:
POST /auth/password
Content-Type: application/json
{
"currentPassword": "current-secret",
"clear": true
}
Successful password mutation response shape:
{
"success": true,
"required": true,
"authenticated": true,
"hasTokenAuth": false,
"hasPasswordAuth": true,
"publicHostWarning": false,
"boundHost": "127.0.0.1"
}
For operator/API access, token auth is still the main direct mechanism:
adhdev standalone --token mysecret
Then send either a bearer token or query token:
curl -H "Authorization: Bearer mysecret" \
http://localhost:3847/api/v1/status
curl "http://localhost:3847/api/v1/status?token=mysecret"
Standalone also allows a same-origin bootstrap path for the initial dashboard password/network-preference mutation when no auth exists yet. Once token auth or password auth is configured, those mutations require an authenticated request.
Practical examples:
- use
/auth/sessionto decide whether the local dashboard should show a password prompt - use
/auth/passwordto set, rotate, or clear the local dashboard password - use
/api/v1/standalone/preferencesto read or change the saved default bind host and standalone font preferences
Practical Rules
sessions[]is canonical- raw
sessionIdis the canonical runtime identity - chat/screenshot/terminal live state should be treated as transport-specific live data, not something mirrored into every status payload
- inventory presence is not the same as verified support; use the compatibility pages to set expectations