owlette docs
cli

owlette cli — overview

owlette is the command-line client for the owlette.app api. It runs on macOS, linux, and windows and lets you authenticate, push roosts, manage sites and machines, mint api keys, and inspect audit logs from your terminal or ci pipeline.

This page is the 15-minute onboarding: install → log in → push your first roost. For per-command reference, start with auth, roost, machine, listen, or trigger. For route/stub/deferred status across the whole CLI, see the readiness matrix.


installation

npm release target

npm install -g @owlette/cli@rc
owlette --version

The cli is prepared for the @owlette/cli@1.0.0-rc.0 release channel, but it is not externally complete until the SDK and CLI distribution gate is verified. Install from source until the npm rc tag is published.

local dev (from the monorepo)

git clone https://github.com/owlette-app/owlette.git
cd owlette/cli
npm install
npm run build
npm link            # makes `owlette` available on your PATH
owlette --version

The bin/owlette launcher prefers the compiled dist/ output but falls back to running the typescript source via ts-node so node bin/owlette … works without npm run build.


first 15 minutes

1. log in (device-code flow)

owlette auth login

Opens your browser to owlette.app/cli with a 3-word pairing phrase pre-filled. Approve the request in the dashboard and the cli stores the issued api key for the default profile using the OS keychain when available, or ~/.config/owlette/credentials.json as a 0600 token-file fallback.

If you can't open a browser on the cli host (ssh, headless ci, etc):

owlette auth login --no-browser
# copy the pairing phrase + url from stderr, open them on a different machine

2. confirm who you are

owlette whoami
# user id     u_abc...
# email       you@example.com
# scopes      site:*=read|write|deploy
# environment live
# apiUrl      https://owlette.app
# profile     default
# configPath  /home/you/.config/owlette/config.toml

owlette auth status is an alias of whoami and prints byte-identical output.

3. push your first roost

A "roost" is a content-addressed bundle of files (a touchdesigner project, a media payload, an npm build artifact — anything). Pushing it dedupes chunks against the server and publishes a new immutable version.

owlette roost push ./my-project --to rst_my_project_id --site site-1

The cli walks the directory, computes content-addressed chunks, asks the server which chunks it doesn't have yet, uploads the missing ones via signed urls, then publishes a new version on the named roost. On subsequent pushes only changed chunks upload.

4. trigger a deploy

owlette roost deploy rst_my_project_id --site site-1 --dry-run
# inspect the canary / fleet split + extract path

owlette roost deploy rst_my_project_id --site site-1
# real deploy — auto idempotency-keyed so a network blip can be retried safely

That's the loop. owlette roost diff <roostId> --against <versionRef> shows what changed between any two versions; top-level owlette rollback <roostId> reverts to the previous version.


config precedence

Config resolution is first-wins, but the credential store and the config profile swap positions depending on the field:

token (auth):
1. cli flag / env var  (OWLETTE_TOKEN)
2. credential store    (OS keychain, then ~/.config/owlette/credentials.json)
3. profile in config   (legacy token in ~/.config/owlette/config.toml)
4. built-in default    (none)

api_url / environment:
1. cli flag / env var  (--api-url, OWLETTE_API_URL, OWLETTE_PROFILE, OWLETTE_ENVIRONMENT)
2. profile in config   (~/.config/owlette/config.toml — selected by --profile or OWLETTE_PROFILE)
3. credential store    (OS keychain, then ~/.config/owlette/credentials.json)
4. built-in default    (api_url=https://owlette.app)

config file schema

# top-level defaults — used when the active profile doesn't override
api_url = "https://owlette.app"
environment = "live"

[profiles.default]
api_url = "https://owlette.app"

[profiles.dev]
api_url = "https://dev.owlette.app"
environment = "test"

Legacy token = "owk_*" fields are still read for migration, but owlette auth login now writes secrets to the credential store and uses config.toml for non-secret profile metadata. Switch profiles with --profile dev or OWLETTE_PROFILE=dev.


global flags

Flags inherited by every command:

flagenv vardefaultpurpose
--profile <name>OWLETTE_PROFILEdefaultnamed profile from config.toml
--jsonfalseemit structured json instead of ascii tables on stdout
--api-url <url>OWLETTE_API_URLhttps://owlette.apptarget api host
-h, --helpshow help for the current command
-V, --versionprint cli version

--json mode is scriptable, but the output shape is command-specific: newer commands use { ok, data } or { ok: false, error } wrappers, while legacy commands may return raw payloads or compatibility objects. Check the per-command page before scripting against a field.


noun matrix

Every command lives under one of these top-level groups. [ready] verbs hit a public api today. [stub] verbs reserve the namespace and exit 3 with a pointer to a future plan.

top-level verbs

commandtierdescription
owlette auth loginreadydevice-code login; stores token in active profile
owlette auth statusreadyalias of owlette whoami
owlette auth logoutreadyclear token from active profile
owlette whoamireadyprint server-resolved identity + scopes
owlette versionreadyprint cli version, server version, and the supported API date catalog

operator nouns (site-scoped)

nountierverbswhat it does
roostreadypush list get diff versions deploycontent-addressed project distribution
machinereadylist get deployments reboot shutdown screenshotmanage windows machines
machine live-viewstubstreaming desktop feed; deferred as live-view-webrtc outside the MVP
audit-logreadylist getsite audit log + hash-chain verification
quotareadyshow historysite storage + bandwidth usage
chatreadynew list send delete renamecortex ai chat
webhookplannedcreate list get update delete rotate-secret deliveries delivery get retry probepublic routes exist; CLI noun group remains deferred
deployreadycreate list get retry cancel uninstall deleteclassic agent-installer deploys (NOT roost deploy)
processreadylist get create update delete kill start stop scheduleprocess lifecycle on machines

user nouns

nountierverbswhat it does
sitereadylist getsites you have access to
keyreadycreate list rotate revokeyour api keys

superadmin nouns

nountierverbswhat it does
userreadylist get promote demote assign-sites remove-sites deleteplatform user management
installerreadylist latest upload set-latest deleteagent installer binary management

legacy top-level verbs (kept for muscle memory)

commanddescription
owlette rollback <roostId>top-level rollback helper for roost versions
owlette listenopen the scoped SSE liveness stream and forward received events to a local url
owlette trigger <event>fire a synthetic webhook for local testing

disambiguation: owlette deploy … is the classic installer deploy group (silent exe pushes). owlette roost deploy <roostId> is the content-addressed deploy that ships per-version diffs to a fleet. Same word, different surfaces — the help text disambiguates.


exit codes

scripts can branch on these — they're stable and meaningful:

codemeaningexample trigger
0successowlette roost push ./dist --to rst_abc
1generic error — network failure, api 5xx, unexpected stateserver unreachable; invalid response shape; transient 429
2usage error — missing required flag, bad arg, unknown commandowlette roost push with no path
3stub — noun exists but has no public api yetowlette machine live-view m-1 --site site-1

Exit code 3 is intentionally distinct from 1 so ci can tell "the api will never accept this until the backend ships" apart from "transient failure, retry."


json output shapes

Commands that accept --json write one JSON document to stdout. Newer commands generally use the wrapper shapes below; legacy commands can return raw server payloads or command-specific objects, so the per-command reference is authoritative.

wrapped success

{ "ok": true, "data": { /* command-specific payload */ } }

Examples in source include roost list, key list, site list, machine list, whoami, and trigger, which print raw payloads or command-specific objects rather than a universal { ok, data } envelope.

wrapped failure

{ "ok": false, "error": { "code": "<stable_string>", "message": "human-readable", "detail": { /* optional */ } } }

When a command surfaces API problem+json details, stable code values match the API's codes (scope_insufficient, token_expired, idempotency_key_mismatch, manifest_stale, rate_limited, unsupported_version).

stub (exit 3 only)

{ "ok": false, "stub": true, "noun": "machine", "reason": "live-view streaming is being reframed as a webrtc-native feature; resume when prioritized", "dashboard_url": "https://owlette.app/dashboard", "future_plan": "public-api deferred: live-view-webrtc" }

next steps

on this page