Skip to content
View as .md

Control plane

How arbe orchestrates execution, organized around the thread. The CLI has no local database: thread state is read and written through the arbe HTTP API; Postgres owns current state, the thread’s durable stream owns history. Local pi sessions (arbe chat) live under .arbe/pi-sessions/<threadId>/ as pi’s scratch — the arbe stream is still the durable truth. Status lives on the thread.

arbe thread create <parent> [--env <env>] → create a thread (--env gives its bots a sandbox to reach; no trigger yet)
arbe thread entries create <ref> "<msg>" → thread/agent ref; POST fires dispatch
arbe thread entries read <id> → tail live; exits on a dispatch terminal (non-zero on failed)
arbe thread result <id> → the last assistant message
arbe thread diagnose <id> → classify the last-dispatch stage
arbe thread list → threads in the active house
arbe chat [msg] → local pi via the per-thread session-dir; re-enters on the same thread
arbe x -e <env> -- <argv…> → one-off command on the env's sandbox (not a thread)

Authed threads are portable: when you arbe auth login, every thread is inspectable from any device through the API. Unauthed = local-only; an unauthenticated CLI has no threads to list. Auth is the consent boundary. The API is the single point of authority — threads from CLI, web, DO alarm, or webhook all go through one creation path that writes the thread + stream before execution starts. No surface creates durable authenticated thread state independently.

Code: apps/cli/src/commands/thread.ts, packages/core/threads.ts.
See threads, system/dispatch, daytona runtime, system/tasks.