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. A coding run’s state lives on the thread row.

arbe send <who…> "<msg>" → the thread you share with them, then the message
arbe thread create <parent> [-e <id>] → create a thread (the env gives its bots a sandbox to reach; no trigger yet)
arbe thread entries create <thread-ref> "<msg>" → 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 x -s <sandbox> -- <argv…> → one-off command on a sandbox (daytona provider id by default)
arbe x -e <environment> -- <argv…> → same, resolving the environment's live box for you

Authed threads are portable: when you arbe 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.