Every agentdeck command, plus how a session is started and stopped.
For the one-command install see README → Start here.
agentdeck daemon install
claude # or: codex · opencodeThe 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, andagentdeck monitorare a long-term compatibility path; no removal is planned (#273). The daemon-first default isagentdeck daemon installfollowed by a normal agent launch, withagentdeck runfor custom launch arguments,agentdeck orderfor deck ordering and the experimentalagentdeck relayfor 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.0for LAN access (multi-surface monitoring). Local connections bypass authentication. Remote connections require the auth token from the AgentDeck data directory (~/.agentdeck/auth-tokenon Node CLI builds,~/Library/Containers/bound.serendipity.agent.deck/Data/Library/Application Support/AgentDeck/auth-tokenon Mac App Store).
The CLI command is agentdeck.
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).
| 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 startanddaemon restarton a checkout rebuild stale workspace packages first, then re-execute so one process cannot mix an oldcli.jswith a newdaemon-server.js. The rebuild only happens with a terminal attached (never on the autostart path, where a failed build would loop againstKeepAlive) and only re-executes when the build digest actually changed — a rebase or atouchthat moves an mtime without changing a byte compiles to nothing.--no-buildskips it;--buildforces it without a terminal.daemon startagainst a daemon of yours whosebuilddiffers 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-upgradeleaves it alone.daemon statussays 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 theagentdeckcommand itself (the arg-parser layer). Applied only when the command (argv[2]) isclaude/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-crather 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-controlOverriding 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).
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 onNegative 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.
--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 listLifecycle: 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.
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.
| 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.
| Command | Description |
|---|---|
agentdeck status |
All sessions + daemon status |
agentdeck stop |
Stop a session (-a for all, -p for specific port) |
| 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>) |
| 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 showAn 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.
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 shelfAn 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.76See 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.
| 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.
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. |
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.
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.
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.