@nice-code/devtools-cli
v0.112.0
Published
Standalone nice-code devtools window, relay-session manager, and local dashboard.
Readme
@nice-code/devtools-cli
Standalone nice-code devtools: open the full devtools window without booting an app server, manage deployed relay sessions, and produce the URL a staging producer can join.
$env:RELAY_ADMIN_SECRET = "<secret>"
bunx @nice-code/devtools-cli `
--topology pixel-plaza `
--relay staging=https://staging.devtools-relay.example.com `
--producer-url staging=https://staging.example.com/The package is Node-compatible ESM (node >=22) and is also smoke-tested under Bun. The browser
window, React, ReactDOM, and all panel code are pre-built into the package; Vite is not installed or
run on the operator's machine.
Configure after launch
CLI arguments are startup shortcuts, not the only configuration path. The dashboard remains
available at / and every workspace has a Workspaces & settings link back to it. From there you
can add, rename, duplicate, or remove local topologies; add deployed relays and create/import their
sessions; set producer URLs; and add direct backends without restarting nice-devtools.
An argument-free first launch intentionally starts with no workspace and presents those three add
flows; later launches restore only the workspaces that were selected previously.
The Settings section exposes every CLI setting. Workspace, relay, session, backend, mint-default,
and local-relay settings apply live. Dashboard host/port, fallback-port, and browser auto-open values
are saved for the next launch and are labelled restart required; the page always shows both the
effective value and its source (CLI, environment, saved, or default). A later explicit CLI
argument overrides the saved UI preference again.
Machine-oriented flags have native UI equivalents: Copy configuration JSON for --json, explicit
reveal/reprint for --show-credentials, confirmation dialogs for --yes, and Help/About for
--help/--version.
Workspaces
Each opened window has one provenance boundary:
--topology <id>observes one local topology through the local relay;--relay <name>=<url>selects one deployed relay session;--backend <name>=<ws-url>dials one token-gated backend directly.
Repeat an option to create several labelled windows. They are never flattened into one transport.
With fresh state and no workspace option, the CLI selects the default topology; this observes only
producers configured with topologyId: "default". The dashboard defaults to
http://127.0.0.1:5200; if that default is occupied it tries a small following range. An explicit
--port fails on conflict unless --fallback-port is passed. --no-open suppresses browser launch.
Sessions
nice-devtools session create --relay staging=https://relay.example --ttl 8h
nice-devtools session list
nice-devtools session show staging <id> --show-credentials
nice-devtools session close staging <id>
nice-devtools session forget staging <id>list means sessions known to this nice-devtools installation, not a live relay-wide listing.
forget removes local state only. close calls the relay and can then forget the local copy.
session create --json deliberately includes the new token; list and show --json redact unless
--show-credentials is explicit. JSON is the only stdout output in JSON mode; diagnostics use
stderr and non-interactive invocations never prompt.
Relay-session windows report connecting, connected, retrying, expired, and proven terminal-close states. An initial WebSocket refusal remains intentionally broad because a browser cannot distinguish an invalid/expired token, capacity, origin policy, and a relay outage at that stage.
Admin-secret precedence is explicit --secret, named --secret-env, single-relay
RELAY_ADMIN_SECRET, remembered matching profile, then a hidden TTY prompt. Prefer env mappings over
--secret, whose value can enter shell history.
Plaintext OS state
This development-first release deliberately stores remembered credentials unencrypted in a per-user
state.json:
- Windows:
%LOCALAPPDATA%\nice-devtools\state.json - macOS:
~/Library/Application Support/nice-devtools/state.json - Linux:
$XDG_STATE_HOME/nice-devtools/state.json, or~/.local/state/nice-devtools/state.json
NICE_DEVTOOLS_DATA_DIR overrides the directory. nice-devtools data path prints the resolved path.
Session tokens minted/imported by the CLI are remembered automatically. Admin/backend credentials are
remembered only after the disclosed prompt/UI choice or --remember-credentials. The dashboard and
credentials forget/data clear remove them. On loopback, the dashboard accepts a replacement
credential through a one-way field that is immediately cleared: values are never prefilled, echoed,
cached, or stored in browser storage. Environment-variable names may be saved without copying their
values; copying a resolved environment value to plaintext requires a separate confirmation. Admin
secrets otherwise stay in the CLI process and state file.
A remembered admin secret has broader and longer-lived authority than a session token: it can mint
and close sessions for that relay until it is rotated or forgotten locally. Treat state.json
accordingly.
Owner-only permissions are applied best-effort, writes are atomic, and read-modify-write operations
are locked across processes. A corrupt file is preserved as state.broken-<timestamp>.json before a
fresh state is written. Treat the directory as plaintext: clear it on a shared or less-trusted
machine.
LAN mode
The HTTP dashboard is loopback-only whenever a relay session or backend token is present. A local, credential-free topology may be exposed deliberately:
nice-devtools --topology pixel --host 0.0.0.0 --relay-host 0.0.0.0This is not a low-risk mode: the local relay is unauthenticated, so anyone on the reachable network can observe application state/actions. Credential and data controls are omitted from the LAN-served dashboard. A producer page opened on another device must use matching Vite configuration:
niceDevtools({ host: "0.0.0.0", port: 5199 });Producer refresh continuity
The producer URL carries an advisory expiry alongside its id/token. The producer immediately clears
all recognised devtools params from the address bar, remembers the credential in that tab's
sessionStorage, reconnects after refresh/sleep, and clears it after expiry (with clock-skew grace),
an explicit detach, or a proven terminal relay close. Closing the tab ends browser persistence.
