Skip to content

Latest commit

 

History

History
481 lines (391 loc) · 34.2 KB

cli.md

File metadata and controls

481 lines (391 loc) · 34.2 KB

CLI Reference

Every agentdeck command, plus how a session is started and stopped. For the one-command install see README → Start here.

Usage

Start

agentdeck daemon install
claude             # or: codex · opencode

The daemon installs or refreshes the lifecycle integrations and observes agents started through their normal commands. The daemon (port 9120, 0.0.0.0 by default) aggregates all sessions for external clients.

npx @agentdeck/setup installs this CLI. It accepts --yes, --enterprise, --statusline and --surface=ulanzi|streamdeck. If npm's global prefix is not writable, it installs into ~/.agentdeck/npm instead. Both are described in install.md § What npx @agentdeck/setup does.

Compatibility notice: agentdeck claude, agentdeck codex, agentdeck opencode, and agentdeck monitor are a long-term compatibility path; no removal is planned (#273). The daemon-first default is agentdeck daemon install followed by a normal agent launch, with agentdeck run for custom launch arguments, agentdeck order for deck ordering and the experimental agentdeck relay for sessions on another machine. Keep using the managed path when you need immediate terminal steering (Ctrl-C, Shift+Tab, cursor), typing into the terminal on Windows, or terminal-only telemetry. Those have no daemon-first equivalent.

Lifecycle compatibility: Claude Code >=2.1.50 and Codex CLI >=0.141.0 are the supported hook baselines. All same-major AgentDeck clients remain wire-compatible; older agent CLIs can still run in the managed terminal, but their lifecycle monitoring is not guaranteed.

Security: The daemon binds to 0.0.0.0 for LAN access (multi-surface monitoring). Local connections bypass authentication. Remote connections require the auth token from the AgentDeck data directory (~/.agentdeck/auth-token on Node CLI builds, ~/Library/Containers/bound.serendipity.agent.deck/Data/Library/Application Support/AgentDeck/auth-token on Mac App Store).

CLI Reference

The CLI command is agentdeck.

Observed launch without a PTY

agentdeck run claude, agentdeck run codex, or agentdeck run opencode launches in the current terminal without a managed bridge or PTY. Install the daemon and hooks first with the ordinary setup flow. Hooks/transcripts own observation, just as when running the agent directly. The launcher does not auto-start a daemon, rewrite hook settings or capture terminal output.

agentdeck run claude -c 'claude --resume my-session'
agentdeck run codex --no-env-args

-c and the agent-specific AGENTDECK_*_ARGS append retain their shell grammar: POSIX uses the configured login shell (SHELL, default /bin/bash); Windows uses COMSPEC (default cmd.exe) with /d /s /c. AGENTDECK_COMMANDER_ARGS is inserted after run, before typed options; typed -c wins. --no-env-args disables both layers. Exit status and terminal streams are inherited. Commands remain user-authored shell text, including pipes and redirects.

Managed-only flags such as --remote-daemon, --weight, wake word and terminal controls are rejected by run, including when supplied through environment defaults. Use the existing managed command for those workflows, or agentdeck order for observed ordering. Launching inside an existing managed session is rejected to avoid routing hooks to its AGENTDECK_PORT. This is an additive local launcher. Managed terminal controls have no daemon-first parity, which is why the managed commands stay, with no removal planned (#273).

Sessions

Command Description
agentdeck claude Legacy compatibility: start Claude Code in the managed PTY session bridge
agentdeck codex Legacy compatibility: start Codex in the managed PTY session bridge
agentdeck opencode Legacy compatibility: start OpenCode in the managed PTY/SSE session bridge
agentdeck monitor Legacy compatibility: start the managed hook-only per-session bridge
agentdeck order set <id> <n> Pin an observed session's deck/tab sort slot (daemon-persisted; 0 clears)
agentdeck order clear <id> Remove an observed session order pin
agentdeck order list List stored order pins

The following flags document the managed compatibility path. New ordinary local sessions should use the normal agent commands; keep this path when one of these capabilities is required.

Flags: -p <port>, -c <command>, -d (debug), --no-update-check, --weight <n> Remote attach flags: --remote-daemon, --daemon-host <host[:port]>, --daemon-token <token> (pairing token of the remote hub — from ~/.agentdeck/auth-token there, or agentdeck token show; env AGENTDECK_DAEMON_TOKEN). Required for a current hub: since issue #145 daemons no longer hand their token to unauthenticated LAN peers. Module flags: --local (all device modules off — derived from the module registry, so it covers every module including ones added later), --no-adb (skip ADB reverse). Hardware modules (mDNS/serial/Pixoo/Timebox/iDotMatrix) are daemon-only — session bridges never activate them, so there are no per-session --no-mdns/--no-serial/--no-pixoo flags.

Port window (--port-window <lo-hi> / AGENTDECK_PORT_WINDOW). The daemon's singleton guard sweeps the documented 9120–9139 window and concedes to any live daemon it finds, which is why an isolated daemon could not be started beside the real one — neither a separate AGENTDECK_DATA_DIR nor an explicit -p moved the sweep. Override the window to run a throwaway daemon for testing (daemon start -p 9200 --port-window 9200-9209 --loopback --local). A daemon outside the default window is invisible to clients that scan it, so daemon start prints the window whenever it is not the default, and an unparseable value falls back to the default rather than disabling the guard.

Running the current build (--no-build, --no-upgrade). /health carries a build field: a digest of the JavaScript the answering daemon started with. It exists because on a source checkout agentdeck is a shim onto bridge/dist/cli.js, which is overwritten in place — a daemon started before a rebuild reports the same pid, port and version as one started after it, so "already running" used to be indistinguishable from "still running the code you replaced".

  • daemon start and daemon restart on a checkout rebuild stale workspace packages first, then re-execute so one process cannot mix an old cli.js with a new daemon-server.js. The rebuild only happens with a terminal attached (never on the autostart path, where a failed build would loop against KeepAlive) and only re-executes when the build digest actually changed — a rebase or a touch that moves an mtime without changing a byte compiles to nothing. --no-build skips it; --build forces it without a terminal.
  • daemon start against a daemon of yours whose build differs from the one on disk stops it and takes the port, rather than exiting "already running". Both digests must be known to differ: a daemon predating the field reports none, and evicting on no information would make every start a restart. --no-upgrade leaves it alone.
  • daemon status says which build is serving and which is on disk when they differ.

Preferred daemon port (agentdeck daemon port). The daemon resolves the port it intends to serve from -p/--port › AGENTDECK_DAEMON_PORT › settings.json daemonPort › 9120, and records where it actually landed in daemon.json. Only the user writes the persisted value (agentdeck daemon port 9200, --clear to forget it); nothing in the startup path does, because persisting the outcome would turn a 14-second kernel hold on 9120 into a permanent move to 9121. When the preferred port is held but nothing answers /health there, the daemon waits up to 20s for it rather than conceding — see docs/daemon.md § Preferred port vs actual port.

On the managed compatibility path, the -c flag sets the full command AgentDeck spawns inside the session PTY, so any arguments you add are forwarded straight to the underlying agent. For example, to resume an earlier Claude Code session (the interactive picker appears when no id is given):

agentdeck claude -c "claude --resume"

The same pattern passes through any other flag the agent accepts — for instance -c "claude --remote-control".

Environment-variable defaults. To avoid retyping the same flags, set them once in your shell profile:

  • AGENTDECK_COMMANDER_ARGS — extra arguments for the agentdeck command itself (the arg-parser layer). Applied only when the command (argv[2]) is claude/codex/opencode/monitor; every other command ignores it, even when a positional value happens to equal a session word (agentdeck speak board1 claude).
  • AGENTDECK_CLAUDE_ARGS / AGENTDECK_CODEX_ARGS / AGENTDECK_OPENCODE_ARGS — extra arguments appended to the spawned agent command for that agent. These weave into an existing -c rather than replacing it.
export AGENTDECK_COMMANDER_ARGS="--no-postit"
export AGENTDECK_CLAUDE_ARGS="--remote-control"

agentdeck claude
# ≡ agentdeck claude --no-postit -c "claude --remote-control"

agentdeck claude -c "claude --resume 0000-0000-0000-0000"
# spawns: claude --resume 0000-0000-0000-0000 --remote-control

Overriding a default for one invocation. Env tokens are inserted before the flags you type, which gives scalar options last-write override semantics — retype --weight 2 or --daemon-host other.lan and the typed value wins. Boolean flags (--local, --no-postit, --no-adb, --remote-daemon, hook-skip flags) have no inverse spelling, so retyping cannot undo them; pass --no-env-args to ignore both env layers for that invocation:

export AGENTDECK_COMMANDER_ARGS="--local"

agentdeck claude               # device modules off (env default applies)
agentdeck claude --no-env-args # device modules on (both env layers ignored)

--no-env-args covers only the two *_ARGS layers. Remote attach is a separate opt-in that lives outside it: AGENTDECK_REMOTE_DAEMON=1 is the only switch that turns it on (there is no --no-remote-daemon inverse) — unset it to disable remote attach. AGENTDECK_DAEMON_HOST is not an opt-in; it only names the endpoint and is inert unless AGENTDECK_REMOTE_DAEMON=1 (or --remote-daemon) is also set. Unsetting a *_ARGS variable remains the permanent opt-out.

Works identically on Linux, macOS, and Windows: the commander-layer var is parsed in-process (no shell), and the per-agent append rides the same shell path AgentDeck already uses for -c. One Windows caveat: the spawned command is re-parsed by cmd.exe, which does not treat single quotes as quoting — use double quotes for grouped values in AGENTDECK_<AGENT>_ARGS (see windows.md).

Pinning session order with --weight

By default sessions sort by agent type → project name → start time, which keeps positions stable but not necessarily aligned with your terminal tabs. Pass --weight <n> (integer between -9999 and 9999, default 0) to pin a session's slot: sessions sort by weight ascending first (negatives, then unweighted/0, then positives), and only fall back to the default ordering within the same weight. Nothing changes when no session sets a weight.

So if you run five tabs on one project in Windows Terminal (or iTerm), give each tab a weight matching its tab number and the Stream Deck — plus every other surface (macOS/iOS/Android dashboards and the TUI) — mirrors that tab order:

agentdeck claude --weight 1   # tab 1 → deck slot 1
agentdeck claude --weight 2   # tab 2 → deck slot 2
agentdeck claude --weight 3   # …and so on

Negative weights sort ahead of unweighted sessions (e.g. --weight -5 to always float a session to the top). The value is a pure sort key — it never changes how a session behaves.

Pinning observed session order with agentdeck order

--weight is a launch-time flag of the managed PTY commands. A normally launched observed session (run claude/codex/opencode directly with the daemon installed) has no launch line to hang a flag on, so ordering it is daemon-first instead: agentdeck order pins the weight on the daemon, and the daemon applies it every time it builds sessions_list — same comparator, same surfaces, and independent session identities. Same-project Codex tabs remain separate at every weight; pins only change their order.

agentdeck order set observed:claude:1a2b… 1   # pin (id, unique prefix, or bare uuid)
agentdeck order set observed:claude:1a2b… 0   # weight 0 clears the pin
agentdeck order clear observed:claude:1a2b…
agentdeck order list

Lifecycle: pins live in ~/.agentdeck/session-order.json, survive daemon restarts, and re-apply automatically when the same session id reappears (claude --resume <uuid> keeps its pin). A pin whose session has been absent from the roster for 30 days is garbage-collected; at most 256 pins are kept (least-recently-seen evicted first). Precedence: the store pins observed rows only — a managed session's launch-time --weight (and a remote-attached session's pushed weight) always wins.

Both daemons implement it: the Node daemon and the in-process Swift daemon read and write the same pin file and serve the same agentdeck order routes with identical behaviour, so pins survive a daemon handover in either direction. Only a daemon build older than the feature answers 404 — update and restart it.

Relaying observed sessions to another machine with agentdeck relay

Experimental and additive to --remote-daemon (#273). Run on the worker machine — the one where you run agents — to publish its observed sessions to a hub daemon whose Stream Deck you use:

agentdeck relay set mainnode.lan --token <hub token>   # token: ~/.agentdeck/auth-token on the hub
agentdeck relay set 127.0.0.1:19120                     # through ssh -L 19120:127.0.0.1:9120 — no token
agentdeck daemon restart                                # relay.json is read at daemon start
agentdeck relay status                                  # configured hub + what the daemon reports
agentdeck relay clear                                   # stop (then restart the daemon)

The hub must run a current Node CLI daemon. Relayed sessions accept the observed controls (approve/deny, AskUserQuestion answers, a queued prompt, a stop at the next tool, terminal injection where the worker has a rung); details in daemon.md § Daemon relay.

Daemon

Command Description
agentdeck daemon start Start monitoring daemon (--local, --loopback, --port-window, --no-build, --no-upgrade — see below)
agentdeck daemon stop Stop daemon
agentdeck daemon restart Restart daemon — reads posture from the port it is actually on, restarts on its preferred port
agentdeck daemon status Show daemon status (says so when it is serving a fallback port)
agentdeck daemon port [n] Show or persist the preferred daemon port (--clear to forget it)
agentdeck daemon install Register auto-start (macOS LaunchAgent / Windows Scheduled Task / systemd unit); --enterprise bakes the loopback posture into it; --statusline also installs the Claude status-line relay when no status line is configured (a status line you already have is wrapped by default, and a configured status line hides Claude Code's footer hints); --no-statusline removes the relay again and restores your own status line; --codex-approvals adds the Codex device-approval hold (a connected device can answer a Codex approval for up to 25 s before Codex shows its own prompt; Codex asks you to review the new hook once) and --no-codex-approvals removes it — without either flag, or AGENTDECK_CODEX_APPROVALS=1/0, a refresh keeps whatever is installed
agentdeck daemon uninstall Remove auto-start (LaunchAgent / Scheduled Task)

Network posture on a shared or corporate network. --local turns every device module off (the daemon still binds all interfaces, so a paired companion app keeps working). --loopback — equivalently AGENTDECK_LOOPBACK_ONLY=1 — binds 127.0.0.1 and emits nothing onto the LAN: no mDNS advertisement, no UDP discovery beacon, no Pixoo subnet sweep, no BLE scans. The USB channels survive --loopback — serial, because a board on a cable is not a network peer, and ADB reverse, because the tunnel rides the USB cable into the host's own loopback. Use agentdeck daemon install --enterprise (or npx @agentdeck/setup --enterprise) so the posture lands in the autostart unit rather than only applying when the flag is typed by hand. Full table: docs/daemon.md § Enterprise and shared-network posture.

Session Management

Command Description
agentdeck status All sessions + daemon status
agentdeck stop Stop a session (-a for all, -p for specific port)

Monitoring

Command Description
agentdeck dashboard TUI monitoring dashboard (alias: dash): sessions with state, model/effort/permission, CI waits and subagents; per-provider usage; aquarium; activity feed. Keys: ↑↓ select, tab switch focus (narrow: next panel), ⏎ detail, f follow the selected session, 1-9 switch managed session, ? help
agentdeck devices Connected devices (WS, ESP32, Pixoo, Timebox, ADB)
agentdeck qr Pairing QR code + URL
agentdeck pair Pair a device with a one-time code — no camera, no cable (-t <seconds>, -n <devices>)
agentdeck token [show|rotate] Print the local profile token, or rotate the confirmed active daemon and re-pair its clients; no restart required. Offline/older daemons remain unconfirmed; see rotation scope
agentdeck diag Daemon diagnostic dump (-a for AI analysis)
agentdeck diag agents [--json] Privacy-safe version, compatibility and registration-file evidence for normal Claude/Codex/OpenCode launches; activation and event reception are explicitly unverified; no daemon or paid probe required
agentdeck hermes-observer [--home <profile>] [--port <port> | --registry] Install/update the opt-in observer, select a loopback receiver if needed, and print setup readiness; Hermes enablement/restart remain explicit
agentdeck hermes-observer [--home <profile>] --check [--json] Read-only Hermes installation, enablement, discovery and receiver-capability check; see Hermes setup
agentdeck diag connection [--json] [-p <port>] Read-only registry, PID, HTTP health and WebSocket ping/pong checks; allowlisted report excludes tokens, paths and session content
agentdeck diag kiro [--json] Privacy-safe Kiro passive-observation diagnostic; no daemon required
agentdeck diag native [--json] Open an in-memory APME database under the current Node executable and report its version, ABI, native-binding status, and recovery; no daemon required
agentdeck inject-test Exercise observed-answer injection against one host, for tuning (--tty <ttysNNN> --pid <agent-pid> or --app <Name>; --label <text>, -i <n>, --text <text>)

Weather context

Command Description
agentdeck weather set --lat <n> --lon <n> [--place <label>] [--timezone <iana>] Save an explicit coarse forecast location for Dashboard and portable-reader Glance
agentdeck weather show Show the saved location, time zone, and portable provider without printing a custom API key
agentdeck weather clear Remove the location and persisted Node forecast cache

The default portable provider is the keyless MET Norway Locationforecast service; there is no account screen, API key, or IP-location lookup. Coordinates are rounded to two decimals before they are written (roughly a 1 km privacy boundary), and the host time zone is used when --timezone is omitted. The daemon reads the setting on the next feed pull, so none of these commands require a restart.

agentdeck weather set --lat 37.5665 --lon 126.9780 --place Seoul --timezone Asia/Seoul
agentdeck weather show

An intermittently connected portable-reader/v1 client receives a provider-attributed outlook of up to seven days plus bounded absolute-time display/notification cues. It persists those with the Card Feed and must stop using them after validUntil; the daemon never asks the reader to fetch a weather service directly.

agentdeck diag kiro is designed to be attached to an issue. It reports whether native Kiro CLI/IDE processes, conversation stores, schema markers, and process-to-session correlation are visible. It never includes prompt or response text, tool inputs, command lines, session titles, model names, or TTY names; cwd paths and session IDs become report-scoped salted keys. Use --json when a machine-readable attachment is more useful.

Kiro CLI v2 is observed from its native process and read-only conversation store. Kiro v3 additionally supports AgentDeck's global lifecycle hook, so a normal kiro-cli --v3 launch reports exact prompt/tool/stop boundaries without an agentdeck kiro wrapper.

Pairing a device with no camera and no cable

agentdeck qr assumes a camera and wifi_provision assumes USB serial. An e-ink reader has neither, which left adb reverse as its only path — a developer tunnel that dies on reboot. agentdeck pair opens a short window and prints a six-digit code to type on the device (Settings → Connection → Pair with code):

agentdeck pair              # 120s, one device
agentdeck pair -n 3         # pair three readers from one window
agentdeck pair -t 300       # a longer walk to the shelf

An ESP32 has no keyboard, so it cannot type a code. Name its address instead — copy it from the daemon's Rejected <ip> (esp32) line — and the credential is pushed down the socket the board opens next, no cable involved:

agentdeck pair --adopt 192.168.68.54 192.168.68.76

See daemon.md § Re-arming an ESP32 without a cable for the authorization model and the firmware floor this needs.

The command then watches the window and reports each device as it pairs — and each wrong code as it arrives, which is the point of a short window somebody is standing in front of. The window closes on success, on expiry, or after five wrong codes. See daemon.md § Pairing codes for why this does not widen the LAN boundary.

inject-test reproduces what the daemon does when a device answers an observed session's prompt: it drives the host's own UI rather than the bridge. Terminal hosts are addressed by controlling tty and agent PID (find both with ps -eo pid=,tty=,command= | grep -E ' claude| codex'): pass --tty <ttysNNN> --pid <agent-pid>. The PID identifies the cmux surface or, for iTerm2 and Terminal.app, the owning app through process ancestry. Without a verified host, AppleScript is skipped; tmux can still match by tty alone. GUI hosts are addressed by app name, where --label presses the button carrying that text before falling back to key events. --text types and submits a line instead of picking an option, which is the path dictation uses. Node daemon only — the App Store app spawns no subprocesses.

Evaluation (APME)

Command Description
agentdeck apme runs List recent runs (filter by --agent, --model, --limit)
agentdeck apme run <id> Detailed run view — steps, turns, per-turn evals, vibe
agentdeck apme judge Evaluate pending runs manually (no daemon required)
agentdeck apme scorecard Model scorecard by category and overall
agentdeck apme stop-health Stop-hook delivery rate — how turns actually closed (--since 7d, --agent)
agentdeck apme judge-health Judge coverage — whether closed work actually got a verdict (--since 14d, --json)
agentdeck apme coverage Per-agent coverage — reply and model capture on finished turns, and judge coverage per agent (--since 30d, --json)
agentdeck apme prune Reclaim apme.sqlite disk space by clearing old tool payloads (--older-than 30, --apply, --vacuum)
agentdeck apme reference-judge Re-score tasks the local judge already scored with a stronger model through your Codex CLI login (dry run by default; --run, --limit 10, --since 30d, --until, --expect, --retry-parked, --model, --effort high, --category, --local-band, --project)
agentdeck apme agreement How closely the local judge agrees with the reference judge: MAE, bias, outcome bands, largest disagreements per judge and sampling design (--judge, --sample, --since, --top, --json)
agentdeck apme vibe <runId> <verdict> Label a run (approve/reject/neutral)
agentdeck apme tag <runId> <category> Manually set task category
agentdeck apme reclassify Re-run classifier on unclassified runs
agentdeck apme rubric Inspect current rubrics
agentdeck apme export Export dataset to JSON

apme prune addresses #302: steps.payload and tool-kind sample_events.payload were measured at 71% of a 2.33 GB apme.sqlite on one desk (~7.7 KB/row), with no retention. Default is a dry run — it reports how many rows and MB per table would be reclaimed and changes nothing; pass --older-than <days> (default 30, the same window the judge backlog drain uses) to change the age cutoff. --apply performs the prune inside one transaction: the row is kept (never deleted — every reader that counts or keys off row existence keeps working) and only its payload is replaced with a small JSON marker ({"pruned":true,"prunedAt":…,"bytes":…}) so the row still shows up and says why it has no content. runs/tasks/turns/evals are never touched, a row whose age is unknown (ts=0) is never a candidate, and sample_events is pruned only where kind='tool' — every other kind (user/assistant messages, model usage, subagent lifecycle, state/info/relation) is left alone since those are the small, semantically load-bearing rows. --vacuum reclaims the freed bytes on disk (SQLite does not shrink the file on UPDATE alone) but only runs after --apply, and only when free disk space on the DB's volume is at least 1.1x the file's current size — otherwise it explains why it skipped and leaves the file as --apply left it. There is no automatic or background pruning; run this by hand (or from your own cron/launchd) when you want the space back.

apme reference-judge measures the local judge instead of trusting it. It rebuilds the prompt a task's local verdict came from, with the same builder (the only difference is the redaction below), sends it through codex exec to a stronger model on your own Codex login (no API key), and stores that second verdict in its own reference_evals table, so nothing the product scores or sorts on changes. Default is a dry run listing the tasks, prompt sizes, redaction counts and an input-token estimate; --run sends them. Each call sends that task's prompts, replies and tool trajectory to the model behind your Codex login. Redaction is best effort: this machine's pairing tokens, private keys and credentials with a recognizable shape (known prefixes such as sk-, ghp_ or hf_, JWTs, Authorization headers, URL passwords, KEY=value where the name says secret) are replaced, each field before it is clipped so a key the clip cuts is still caught; a credential with none of these shapes is sent as it is. The reference model gets no tools (no shell, file or image reads, web search, connectors or subagents), like the local judge it is compared with, and a verdict whose run shows a tool call is discarded. The sample is uniform over the locally judged tasks in --since, in a stable hash order, so a rerun continues with new tasks. The dry run reads the pool as it stood at one time and prints the --run command that sends that list: it carries --until (the dry run's time) and --expect (a digest of the list), and sends nothing if the list no longer matches. A --run typed without them picks from the pool as it is when you type it. A task whose call failed twice in the same sample is parked (--retry-parked sends it again), a run stops after three failed calls in a row, and Ctrl-C stops the call in flight along with every process Codex started and records nothing for it. --local-band fail instead asks how many of the local judge's failures the reference confirms. --project AgentDeck,other is an allow-list: only those projects' tasks are picked, so a client project's text never leaves the machine. The dry run lists each task's project. The model defaults to the model in ~/.codex/config.toml, effort to high. apme agreement reports every reference verdict so far per judge (model@effort). CLI only, Node daemon install: the App Store app spawns no subprocess, and no daemon path calls it. Detail and the first measurement: apme.md § Reference judge.

Device Setup

Pixoo auto-discovery is off by default — the daemon no longer sweeps the LAN or calls the Divoom cloud on its own. Run agentdeck pixoo scan once, or set "pixooAutoDiscover": true in ~/.agentdeck/settings.json to opt back in. In the macOS app (which has no CLI) the equivalent is Settings → Pixoo → Scan LAN. A configured panel that changes IP is still recovered automatically — that path is not gated on the discovery setting, because re-locating a device you added is not the same act as finding one you never asked for.

Command Description
agentdeck pixoo scan Discover Pixoo devices on LAN (--no-cloud skips the Divoom cloud lookup and sweeps the local subnet only)
agentdeck pixoo add <ip> Add a Pixoo device
agentdeck pixoo list List configured devices
agentdeck pixoo remove <ip> Remove a device
agentdeck pixoo test [ip] Send test pattern
agentdeck timebox scan Discover BLE TimeBox-mini-light peripherals
agentdeck timebox add <address> Add a Timebox Mini by BLE address
agentdeck timebox list List configured Timebox devices
agentdeck timebox remove <address> Remove a Timebox device
agentdeck timebox test [target] Send one frame (BLE)
agentdeck timebox sync [target] Run foreground Timebox frame sync (BLE)
agentdeck wifi-setup Save ESP32 WiFi credentials (--ssid, --password; SSID from the WiFi interface and password from the Keychain when omitted). With a daemon running, it hands them to that daemon (POST /esp32/wifi), which sends them to the boards on USB at once; --port names the daemon, otherwise the one this user's registry names, and then only while that port's /health reports the registered pid. It never probes ports for a daemon, since the request carries the password. With no daemon it only writes wifi-config.json in the data dir (~/.agentdeck, or AGENTDECK_DATA_DIR when set), which a Node daemon reads when a board connects; the macOS app's daemon keeps its own copy (Settings → ESP32 & Pixoo → ESP32 boards). See esp32.md § Setting the credentials.
agentdeck esp32 orientation <target> <auto|portrait|landscape> Persist a T-Display-S3-Pro layout (portrait Pocket ↔ landscape Focus Strip); the board restarts when the layout changes. auto = portrait with a camera shield, else landscape. Node daemon only.
agentdeck esp32-ota <target> Push ESP32 firmware over WiFi OTA (--build or --firmware <path>). Pull staging uses --stage; X3/X4 additionally require --manifest <agentdeck-surface.json> or both --product-id and --update-channel.

Local connection diagnostics

For a Stream Deck OFFLINE report, run agentdeck diag connection --json from the same account as Stream Deck, alongside agentdeck --version, agentdeck diag native --json, and the installed plugin version. The report checks the registry without pruning it, distinguishes a dead PID from an inconclusive permission check, then probes HTTP health and a WebSocket pong with a three-second deadline. It never sends an agent command or uses a token. Only selected identity/status fields are emitted; remote errors and close reasons, full health frames, file paths and session content are omitted.

Without -p, the target comes from the CLI's ordered registry candidates; it does not silently scan ports or assume 9120. An explicit -p probes that loopback port for both HTTP and WebSocket, independently of stale registry entries. A registry PID mismatch is reported even if both protocols answer. The command exits 0 when both protocols work without a known PID mismatch, and 1 otherwise. A CLI success does not prove the plugin's account, elevation, environment or macOS sandbox discovery path is identical, nor does it say an agent session is active.

Dot direct HTTPS host

The optional direct host runs inside the Node daemon after explicit private configuration. See configuration and security boundaries. agentdeck dot status shows pending approvals, grants and results; approve <id> --code <browser-code> or deny <id> resolves a local connection request. request <grantId> --context-file <absolute-path> --profile desk explicitly shares a briefing, and disconnect <grantId> revokes access and deletes its local content. These commands use a separate authenticated loopback operator endpoint; they never expose LAN pairing credentials through MCP.

Dot character: agentdeck dot character import <file> selects a local static PNG/WebP/JPEG for this Node host; agentdeck dot character reset restores the original orb. It does not configure HTTPS, connect an account, fetch ChatGPT artwork or create a session.

Pixoo settings ownership

agentdeck pixoo --port <port> add|list|remove edits the active local daemon. With no daemon, offline edits stay in the Node profile; an unknown or unsupported live owner never triggers an inactive-file fallback. add --no-test skips the optional device connectivity probe.