The @usine/server package provides usine. Run commands from the instance folder, where .usine/runtime.sqlite stores configuration and run history. Each command reads .env before resolving its environment. usine --help prints usage; usine --version prints the installed release.
usine up
Section titled “usine up”| Option | Type | Default | Description |
|---|---|---|---|
-p, --port | integer, 1–65535 | USINE_PORT, then 7331 | HTTP port on 127.0.0.1. |
--origin | HTTP or HTTPS origin | USINE_ORIGIN, then loopback | Canonical browser address without a path, query, or fragment. |
--log-level | trace, debug, info, warn, or error | USINE_LOG_LEVEL, then info | Minimum log level, without case sensitivity. |
--allow-volatile-instance | flag | off | Permit an instance folder under temporary storage. |
--detach | flag | off | Start a detached process with output in .usine/usine.log. |
usine upusine up --detach --origin https://usine.example.comStartup takes the instance lock, opens the listener, applies runtime database migrations, loads stored configuration, reads App and worker credentials, checks workers, and recovers attempts. Recovery visits every attempt that still has tracked leftovers on a configured worker and logs one summary per worker with the attempts visited, and how many of them had leftovers that recovery found and reconciled, or kept for their run (kept), failed to reconcile (failed), kept tracked with nothing left on the worker (empty), and discarded (discarded). Reconciling a finished attempt’s checkout removes it when its salvage is pushed or it has nothing to salvage. A checkout whose salvage is retained, partly pushed, or rejected stays on the worker, and each later start reconciles it again and counts it as kept. The next start discards an attempt once nothing of it is left. A finished attempt that has nothing left on its worker is discarded, so later starts skip it: its checkout is gone, and so is its machine when the worker creates one per attempt. On a worker with a long-lived machine, such as an SSH worker that runs attempts in containers, a missing checkout is enough. Open attempts and attempts whose recovery failed stay tracked. On SSH workers, the first preparation after a start logs one warning with the number of unrecognized paths under attempts/, excluding the checkouts of attempts being reattached; the paths are logged at debug level. Empty configuration tables accept a bootstrap import or initialize empty setup configuration. Import and export format describes bootstrap input. Later starts read the database.
The listener answers from the moment it accepts connections, in setup mode too. Until the instance has started, every request returns HTTP 503 with Retry-After: 1. The instance has started when migrations are applied, configuration is loaded, the admin token is written, and either setup mode serves its routes and has logged the sign-in line, or runtime startup begins its worker checks and attempt recovery. From then on, GET /api/version returns the running release. In runtime mode, every other request returns HTTP 503 with Retry-After: 1 until recovery finishes and the runtime routes are installed; GET /api/ready then returns HTTP 200. Startup responses close the connection. When setup completes, the listener keeps the port and returns the same responses until the runtime routes are installed.
Missing or invalid App credentials start setup mode. Polling and schedules stay idle until setup completes. Worker preflight failure stops runtime startup. The App secrets file, .usine/github-app.json, must be a regular file with mode 0600; environment values override corresponding file fields.
A second process cannot run the same instance folder. Temporary paths are refused by default because runtime state needs persistent storage. On macOS, startup warns if system sleep can interrupt remote sessions. Logs use ISO 8601 UTC timestamps.
Session usage and pool rate-limit projection updates, including pool reset scheduling decisions, log at Debug. Use usine up --log-level debug or USINE_LOG_LEVEL=debug to include these per-report diagnostics. Reaching a pool reset deadline logs at Info.
Background start
Section titled “Background start”A detached start retains the selected Node binary, options, entry point, and launch flags. It returns when the new process holds the instance lock and GET /api/version returns HTTP 200, so the instance has started as described above: the admin token exists, and setup mode answers requests. It doesn’t wait for attempt recovery; poll GET /api/ready for that. If the process exits first, the command fails and prints its exit and the log tail. After 120 seconds without a start or a new log line, the command reports a timeout while the process can still be starting. Logs have owner-only permissions and require operator-managed rotation.
Instance record
Section titled “Instance record”.usine/instance.json records PID, release, start time, launch settings, systemd unit or launchd service target when applicable, and drain start time. The lock determines whether a process owns the instance; stale process records are replaced on the next start. .usine/instance-id identifies attempt containers and must remain with the instance during moves and restores.
Instances that systemd runs
Section titled “Instances that systemd runs”Lifecycle commands verify that the recorded unit owns the process. They use systemctl stop --no-block and systemctl start to preserve service management. Service starts use the service environment and the instance .env. The service user needs authorization to manage the unit. See server deployment.
Instances that launchd runs
Section titled “Instances that launchd runs”Set USINE_LAUNCHD_SERVICE=gui/<uid>/<label> in the instance .env and install the matching ~/Library/LaunchAgents/<label>.plist. up records the target only when launchctl print reports its PID. stop uses bootout; restart uses bootout, bootstrap, and kickstart. up --detach starts the configured job, loading its plist if needed, and uses its configured arguments. Commands run as the owning user in the login session. status uses print to verify supervision and reports launchctl failures. A failed start unloads a job waiting to retry. See macOS deployment for both jobs, login requirements, and log paths.
usine login and usine logout
Section titled “usine login and usine logout”Connect Claude or ChatGPT while usine up runs, from the instance folder:
usine login claudeusine login chatgptusine login chatgpt --api-keyusine logout claudeusine logout chatgpt --target usine-gatewayBoth commands read connection status from the running instance and authenticate with its local .usine/admin-token. Run them as the user who started the instance. Subscription login polls until authorization completes; logout disconnects the selected provider immediately.
--target <SSH destination> selects one gateway when several are configured. With one gateway, usine selects it automatically. With none, it stores credentials where the local Claude Code and Codex harnesses read them, honoring CLAUDE_CONFIG_DIR and CODEX_HOME.
Local preflight and attempt children use the same credential directories. If one gateway is unavailable, Settings shows its error while other gateways remain usable. --target can select a healthy gateway independently.
Local preflight and children accept subscription credentials and API keys. Claude setup tokens count as subscription credentials. Children report API-key usage in the API keys pool and subscription usage in the matching plan pool.
Without a gateway, usine checks each provider separately using the PATH of the user running usine up. A missing claude or codex command makes its provider unavailable and displays an installation instruction in that provider’s row. usine login reports the same instruction before starting authorization. The other provider remains available when its harness is installed, so an instance can install only one harness, as the quickstart does. Local provider availability changes log once at Info; repeated polls with the same error produce no additional log entries.
Local Claude status uses claude auth status --json, including macOS Keychain logins. Disconnect runs claude auth logout, removes usine’s settings overrides and file credentials, and verifies that Claude reports signed out. It clears the native login for the configured Claude directory, including an older login that a replacement credential overrides.
Local Codex preflight and children use file credential storage, overriding cli_auth_credentials_store in Codex configuration. Connect replaces $CODEX_HOME/auth.json (~/.codex/auth.json by default), and disconnect removes it. Keyring credentials remain available to Codex commands run outside usine. To sign in directly for usine, run codex -c 'cli_auth_credentials_store="file"' login --device-auth.
Subscription sign-in uses the installed Claude Code setup-token command or Codex login --device-auth command in a private temporary directory. Claude requires script and a code from its authorization page. Codex displays a device code for authorization in another browser. --api-key reads a masked key from the terminal. Ctrl+C cancels subscription sign-in. Failed or cancelled authorization preserves the previous login.
Gateway transfers use its authenticated admin API over SSH and require curl on the gateway. Managed credentials persist in its state directory with mode 0600, take precedence over environment credentials, and apply without reloading the service. ChatGPT refreshes use the gateway’s existing token refresh and atomic auth-file replacement. Worker routing changes are configuration revisions. Logout disables the managed provider and removes its routing from workers.
Instance admins can use the same controls in setup and Configuration > Settings > Provider connections. Expiry and last refresh show the provider’s reported values as local dates and times; opaque Claude setup tokens report neither. Pi children, and the Pi parent of coordinator: session agents, authenticate with a separate Pi login.
usine status
Section titled “usine status”| Argument | Type | Default | Description |
|---|---|---|---|
| none | none | instance folder | Report the owning process, listener, version, uptime, open runs, and supervising service. |
usine statusThe command exits with 0 for an owned instance and 3 when stopped. It identifies stale process records and reports an active drain.
usine stop
Section titled “usine stop”| Option | Type | Default | Description |
|---|---|---|---|
--timeout | integer seconds > 0 | 120 | Wait for the process to exit before reporting a timeout. |
--force | flag | off | Stop without waiting for attempts and send SIGKILL if the process exceeds the timeout. |
usine stop --timeout 300The first stop request stops admission and drains running attempts. A command timeout leaves the drain active. Another ordinary stop waits without escalating; --force sends the second termination signal. A stopped instance returns success.
Shutdown
Section titled “Shutdown”Ctrl+C or SIGTERM starts a drain. Its deadline uses settings.max_attempt_minutes when set. A second signal stops immediately. Retained Pi parent tasks and checkouts can reattach on the next start. If a task cannot be confirmed stopped, its slot remains reserved and reconciliation retries rather than starting duplicate work.
usine restart
Section titled “usine restart”| Option | Type | Default | Description |
|---|---|---|---|
--timeout | integer seconds > 0 | 120 | Maximum wait for stop and restart lifecycle operations. |
--force | flag | off | Permit interruption and later reattachment of active attempts. |
usine restartRestart requires a running instance and retains its launch flags. It refuses active attempts unless forced and verifies required gateway credential variables before stopping. A detached restart appends to .usine/usine.log; systemd and launchd instances restart through their service manager. The new process reads the instance environment again. Restart returns when the new process has started, by the same rule as a background start, and fails if the new process exits or its service stops first.
usine upgrade
Section titled “usine upgrade”| Argument or option | Type | Default | Description |
|---|---|---|---|
<version> | registry version, range, or tag | configured channel for managed global installs, otherwise latest | Release to install. |
--channel | latest or next | configured channel | npm channel for managed global upgrades. |
--check | flag | off | Report versions without changing packages or process state. |
--timeout | integer seconds > 0 | 120 | Lifecycle wait for local pin upgrades. |
--force | flag | off | Restart immediately and reattach active attempts. |
usine upgrade --checkusine upgradeFor a global installation managed by systemd or launchd, the command requests the separate upgrade helper and exits after acceptance. The default waits for admitted attempts to finish. Settings and the helper’s journal or log report the final outcome. The helper backs up stores, installs, restarts, and checks version and readiness. Installation or readiness failure restores the prior package and databases.
For an instance-local registry pin, upgrade backs up stores in .usine/backups/, changes package pins, installs with the instance package manager, commits manifest and lockfile changes, and restarts if the instance was running. It refuses active attempts unless forced. Failed installation restores manifests and lockfiles and leaves the instance stopped. Startup failure prints recovery instructions. A stopped instance receives the package update without starting.
A checkout installation requires updating and building its checkout, then restarting. Upgrade an instance describes the procedure.
usine backup
Section titled “usine backup”| Argument | Type | Default | Description |
|---|---|---|---|
<path> | new file path | required | Destination for the runtime database backup. |
usine backup /backups/instance.sqliteThe command creates a compact runtime snapshot with VACUUM INTO while the instance runs and syncs the file and destination directory before reporting success. Durable storage uses SQLite’s backup API. It copies durable storage first and the runtime store second, with owner-only permissions, and refuses an existing destination. The directory must exist and support hard links. A runtime backup failure removes the durable copy. An instance without durable storage produces only the runtime copy and reports it.
The durable path inserts .durable before .sqlite or .db, or appends .durable.sqlite for another extension. Backups omit credentials and connection-record files. See Back up instance state.
usine export-run
Section titled “usine export-run”| Argument or option | Type | Default | Description |
|---|---|---|---|
<runId> | run ID | required | Run to read from the runtime store. |
-o, --output | new file path | URL-encoded run-<runId>.json | Destination for run evidence and transcript. |
usine export-run <run-id> --output /evidence/run.jsonThe command reads a snapshot without starting execution. JSON contains version, exportedAt, snapshot, and transcript, including event, approval, attempts, results, and effective definitions. The file has mode 0600; an existing path or unknown run is an error.
usine sign-in
Section titled “usine sign-in”| Argument | Type | Default | Description |
|---|---|---|---|
<origin> | instance origin | USINE_ORIGIN, then http://127.0.0.1:<port> | Instance that issues the device token after GitHub authorization. |
usine sign-in https://usine.example.comOpen the printed device page and enter the code. The token appears once. Store it securely and send it as a bearer token. Its permission ceiling is limited by current role bindings. See Create a device token.
usine sign-in-link
Section titled “usine sign-in-link”| Argument | Type | Default | Description |
|---|---|---|---|
| none | none | local running instance | Issue a private one-time browser sign-in URL using local admin access. |
usine sign-in-linkThe URL works once within ten minutes. Local lifecycle and link commands require a regular .usine/admin-token owned by the current user with mode 0600. Startup replaces that file. See Access.
usine mcp
Section titled “usine mcp”| Option | Type | Default | Description |
|---|---|---|---|
--origin <url> | instance origin | running instance of the current folder | Instance whose operator tools to serve. With --origin, the command sends USINE_TOKEN; without it, it uses .usine/admin-token. |
USINE_TOKEN=<token> usine mcp --origin https://usine.example.comThe command serves the operator API as MCP tools over standard input and output, for a client that starts it as a local command. At start, it reads the instance’s /api/openapi.json and the token’s session, and lists only the tools that the token permits. It refuses a start response over 8 MiB, one that takes over 30 seconds, or one that nests arrays and objects over 256 levels deep or holds over 200,000 of them, before decoding it. It inlines schema references until the input schemas of the whole document hold 500,000 characters of JSON, at most 32 references deep, and at most 64 levels of arrays and objects deep; past any of these limits, the schema accepts any value at that point and a warning is logged. It sends the token only to the origin: a tool call whose URL resolves to another host returns an error result. It writes its logs to standard error. See Connect an MCP client.
Configuration commands
Section titled “Configuration commands”usine config documents export, import, edit, and log. These commands access the local database directly and save configuration revisions.
Environment variables
Section titled “Environment variables”| Variable | Type | Default | Description |
|---|---|---|---|
USINE_LAUNCHD_SERVICE | gui/<uid>/<label> | none | LaunchAgent target for supervised detached starts and lifecycle commands. The matching plist is in ~/Library/LaunchAgents/. |
USINE_PORT | integer, 1–65535 | 7331 | Port used when --port is absent. |
USINE_ORIGIN | origin | loopback listener | Canonical origin used when --origin is absent. |
USINE_LOG_LEVEL | log level | info | Minimum log level used when the flag is absent. |
USINE_ALLOW_VOLATILE_INSTANCE | 1 | off | Equivalent to --allow-volatile-instance. |
USINE_TOKEN | secret string | none | Instance token that usine mcp --origin sends. |
TMPDIR | path | OS default | Additional path considered temporary by the volatile-instance check. |
USINE_GITHUB_APP_ID | positive integer | App secrets file | GitHub App ID. |
USINE_GITHUB_PRIVATE_KEY | PEM string | App secrets file | App RSA private key in RSA-specific or generic PEM encoding. |
USINE_GITHUB_CLIENT_ID | string | App secrets file | App client ID for member sign-in. |
USINE_GITHUB_CLIENT_SECRET | secret string | App secrets file | App client secret for member sign-in. |
USINE_GITHUB_WEBHOOK_SECRET | secret string | App secrets file | Signature secret for endpoint webhook hints. |
PI_CODING_AGENT_DIR | path | ~/.pi/agent | Configuration and credential directory of Pi children and of the Pi parent of coordinator: session agents. |
| Worker credential variable names | secret strings | required when configured | Provider tokens, API keys, gateway admin tokens, and Access credentials referenced by worker records. |
OTEL_RESOURCE_ATTRIBUTES | percent-encoded key=value list | empty | Additional span resource attributes when tracing is enabled. |
Restart retains recorded port, origin, and log-level flags. Set a different flag on the next explicit start to change them. Invalid process settings fail with a diagnostic. Invalid App credentials enter setup mode. Child processes receive a restricted environment rather than all orchestrator secrets.
Environment file
Section titled “Environment file”Every command reads .env in the instance folder. Shell environment values take precedence; empty values count as unset. A missing file is allowed; an unreadable file is an error. Each line is KEY=value, optionally prefixed by export. Quote values containing a hash character. Single, double, and backtick quotes are accepted; double-quoted \n becomes a newline. Variable and command substitutions stay literal.
USINE_ORIGIN=https://usine.example.comUSINE_PORT=7331Keep .env private, set mode 0600, and exclude it from git. Changes take effect when a command starts; the running orchestrator does not reread it on configuration changes.
Reload
Section titled “Reload”SIGHUP sent to the orchestrator process requests a reread of stored configuration. It does not import files or reread .env. Most revisions apply automatically. See revision application.
Exit status
Section titled “Exit status”| Status | Type | Default | Description |
|---|---|---|---|
0 | exit code | success | Command completed or help printed. |
1 | exit code | failure | Invalid usage, refused operation, timeout, or operational error on standard error. |
3 | exit code | status only | No process owns the instance. |
130 | exit code | signaled shutdown | Foreground orchestrator stopped after SIGINT or SIGTERM. |
usine-gateway
Section titled “usine-gateway”The @usine/gateway package provides a separate usine-gateway binary with no arguments. It logs one JSON object per line. Refused proxy requests include x-usine-gateway-refusal and a logged reason.
Environment files listed by USINE_GATEWAY_ENVIRONMENT_FILES override process values, with later files taking precedence. This differs from the instance .env. Missing required values, invalid settings, or an unreadable allowlist stop startup.
| Variable | Type | Default | Description |
|---|---|---|---|
USINE_GATEWAY_ENVIRONMENT_FILES | string | none | Environment files separated by :, each with one KEY=value per line. Quote a value that contains #. A variable in a later file overrides the same variable in an earlier file and in the process environment. Read from the process environment only. |
USINE_GATEWAY_DOMAIN | string | required | The private DNS domain. The same value as gateway.domain in the stored configuration. |
USINE_GATEWAY_ADMIN_TOKEN | string | required | Bearer token of the admin API, at least 32 characters. The orchestrator’s variable named by admin_token_env contains the same value. |
USINE_GATEWAY_CALLER_KEY | string | required | HMAC key that signs caller tokens, at least 32 characters. Only the gateway has it. |
USINE_GATEWAY_EGRESS_ALLOWLIST | string | /etc/usine-gateway/egress-allowlist | File of hosts that the forward proxy allows. One rule per line: host or *.domain, optionally with :port. A rule without a port allows 443 and 80. # starts a comment. |
ANTHROPIC_API_KEY | string | none | Anthropic API key that the gateway adds for Claude Code. |
USINE_GATEWAY_ANTHROPIC_SUBSCRIPTION_TOKEN | string | none | Alternative Anthropic credential: a Claude subscription token from claude setup-token, valid for one year. Setting both Anthropic variables is an error. |
OPENAI_API_KEY | string | none | OpenAI-compatible API key that the gateway adds for Codex. |
USINE_GATEWAY_CHATGPT_AUTH_FILE | string | none | Alternative OpenAI credential: the absolute path of a Codex auth.json with a ChatGPT login, which the gateway refreshes and rewrites, so the service needs write access to its directory. Setting both OpenAI variables is an error. If the file isn’t a ChatGPT login, the binary exits before it starts listening. |
USINE_GATEWAY_ANTHROPIC_UPSTREAM | string | https://api.anthropic.com | Base URL for Anthropic requests. |
USINE_GATEWAY_OPENAI_UPSTREAM | string | https://api.openai.com | Base URL for OpenAI requests with OPENAI_API_KEY. |
USINE_GATEWAY_CHATGPT_UPSTREAM | string | https://chatgpt.com/backend-api/codex | Base URL for OpenAI requests with USINE_GATEWAY_CHATGPT_AUTH_FILE. |
USINE_GATEWAY_PROXY_HOST, USINE_GATEWAY_PROXY_PORT | host string, integer port 0–65535 | 127.0.0.1, 80 | Listener of the reverse proxy that workers call for GitHub and LLM providers. |
USINE_GATEWAY_EGRESS_HOST, USINE_GATEWAY_EGRESS_PORT | host string, integer port 0–65535 | 127.0.0.1, 3128 | Listener of the forward proxy. |
USINE_GATEWAY_ADMIN_HOST, USINE_GATEWAY_ADMIN_PORT | host string, integer port 0–65535 | 127.0.0.1, 7070 | Listener of the admin API. admin_port in the stored configuration is the same port. The executor forwards a local port to it over SSH. |
A port of 0 lets the operating system assign an available port. Each listener logs its bound host and port when it starts listening.
For example, set USINE_GATEWAY_DOMAIN=gw.internal, private listener addresses, and the required secrets in the gateway environment files.
systemctl reload usine-gateway sends SIGHUP and rereads provider settings, ChatGPT auth, upstreams, and the egress allowlist. An invalid reload keeps the accepted settings and logs the reason. Attachments and open tunnels continue. Domain, listener, admin-token, and caller-key changes require restart. After a gateway restart loses attachments, the executor registers running attempts again within two minutes. Configure a gateway describes setup.