CLI
The vpd CLI reference, grouped by surface, with the flags the daemon actually accepts.
vpd ships with @viewportai/daemon (current local source: 0.2.1). The binary is wired at viewport/packages/daemon/bin/vpd.js; the source of truth for help text is cli/lifecycle-commands.ts:312-457.
npm i -g @viewportai/daemon
vpd --helpGroup-by-surface below. Every command listed here is implemented in code as of the audit.
Lifecycle
vpd start
Launches the daemon. Two-process supervisor + worker model.
| Flag | Default | What it does |
|---|---|---|
--foreground | (background) | Run in current shell instead of detaching |
--listen ADDR | 127.0.0.1:7070 | Listen address. Accepts host:port, just port, or a unix socket path. |
--profile NAME | local | One of local, lan, relay. |
--allowed-hosts LIST | none | Comma-separated Host header allow-list. |
--allowed-origins LIST | none | CORS origins for the local API. |
--auth | off | Require token auth on the local API. |
--home PATH | ~/.viewport | Daemon home directory. |
State files: ~/.viewport/runtime.json, plus pidfiles. Resolves VIEWPORT_HOME / VPD_HOME first.
vpd stop
Sends a graceful shutdown via the lifecycle channel. Optional --force to send SIGKILL to the process group. --timeout SECONDS controls how long to wait, --json for machine-readable output.
vpd restart
Stops, then re-launches with the previously persisted launch config.
vpd status
GET /health from the running daemon plus pidfile checks. Reports running / stopped / unresponsive. Pass --check-updates to also query npm for the latest CLI version. Output sections: Status, Runtime, Home, Listen, Owner PID, Worker PID, Profile, Server, Relay WS, Relay state, Node, npm, CLI, Latest CLI, Update, Sessions, Directories, Agents.
vpd doctor
Read-only environment check. Prints daemon identity (machineId, version, runtime kind, home, scope, profile), control-plane endpoints, relay state, config source path, and recovery hints.
vpd doctor does not repair anything. If something is wrong it tells you where to look.
vpd setup
First-run guided setup.
| Flag | What it does |
|---|---|
--yes | Accept recommended defaults |
--choose | Walk through each choice |
vpd install
Installs the local runtime files for vpd.
It does not silently install Claude/Codex hooks, skills, or MCP servers. Those are explicit opt-in setup steps for personal monitoring, not required for a self-hosted team worker.
vpd installvpd update [--yes]
Updates the daemon npm package. With --yes, also restarts the running daemon to pick up the new binary.
vpd service install|uninstall|status
Manages a launchd (macOS) or systemd (Linux) unit so the daemon auto-starts on login / boot.
Pairing
vpd pair [CODE] [--worker] [--transport polling|relay] [--server URL] [--app-url URL] [--auto-unlock] [--no-auto-unlock] [--auto-unlock-ttl SECONDS]
The entry point.
- No
CODE: mints a fresh 8-char code viaPOST /api/pairing-codes, prints it, opens your browser to{appUrl}/pair?code=…, polls/api/pairing-codes/{code}/statusuntil approval. - With
CODE: claims a web-initiated code by callingPOST /api/pairing-codes/{code}/claim. - With
--worker: pairs a team worker profile for claiming governed execution leases. Hosted Viewport is the default server; use--serverfor a self-hosted or customer-internal control plane. - With
--transport=polling: configures outbound polling, the recommended self-hosted worker default.
On approval the daemon receives relay_credentials, persists them to ~/.viewport/config.json, and auto-restarts.
--server and --app-url override the default Viewport URLs (useful for self-hosted relays pointed at your control plane).
Auto-unlock flags control whether the approved machine can satisfy short-lived web unlock sessions without you pasting a vpd unlock ... command every time:
--auto-unlockmarks this paired install as trusted for automatic unlock.--no-auto-unlockexplicitly opts out.--auto-unlock-ttl SECONDSsets the unlock session lifetime. Values are clamped between 300 and 3600 seconds. The default is 1800 seconds.
Web-generated pairing commands include --auto-unlock when the setup flow asks you to trust this device. Plain vpd pair stays manual unless you pass the flag.
vpd pair anchor
Prints the daemon's trust anchor fingerprint. Used when verifying a daemon's identity out-of-band.
vpd pair rotate-token
Rotates the on-disk daemon auth token via rotateAuthToken(). Restart the daemon to pick up the new token.
Note:
vpd unpairis not implemented as a CLI command today. To detach a daemon,DELETE /api/workspaces/{workspace}/installs/{install}from the web UI under Settings → Machines.
Directories
vpd add PATH
Registers a directory in the global config and POSTs to /api/directories on the running daemon so it picks up the change live.
vpd remove PATH
Unregisters via DELETE /api/directories/:id.
vpd list
Lists registered directories and active sessions.
Sessions
vpd run [DIR] --prompt TEXT
Connects to the daemon over WebSocket, auto-registers the directory if needed, sends a launch request, and (optionally) streams session-update events back.
| Flag | What it does |
|---|---|
--prompt TEXT | Initial prompt (required) |
--agent ID | Override agent (default: workspace policy) |
--model ID | Override model |
--wait | Block until the session ends |
--attach | Follow updates like vpd logs --follow |
--timeout SECONDS | Timeout for --wait |
--json | Machine-readable output |
vpd send SID --prompt TEXT
Sends a prompt message to an existing session.
vpd logs SID [--follow]
Subscribes via WS, replays messages from --last-seq N if provided, renders text updates (agent-message, tool-call, etc.) or --json.
--follow is the canonical streaming mode. Without it, the CLI does a short flush and exits. Fine for interactive snapshots; not lossless replay.
vpd wait SID [--timeout]
Subscribes and blocks until session-ended arrives.
vpd attach SID
Equivalent to vpd logs --follow.
vpd ls
Lists sessions. Flags: --scope ALL|ACTIVE|DISCOVERED, --directory ID, --agent ID, --json or --format FMT.
vpd session stop SID
Sends a kill request for the session.
vpd session manifest --session SID
Prints the provider, workflow, and approval manifest for the session: what context was attached, which workflows applied.
vpd permit ls|allow|deny
Manages pending permission requests (Claude Code tool-use gates surfaced over the daemon hook bridge).
vpd agent mode SID [detect|bypass]
Reads or sets operator control mode for an active session.
Worktree
vpd worktree ls|diffs|summary|rollback|retry|squash
Operator-side worktree primitives backing the safe-edit model:
ls: list worktreesdiffs: show pending diffs vs HEADsummary: short status overviewrollback: revert to a specific SHA (--to SHA)retry: branch-retry from a SHA (--from SHA)squash: squash-merge worktree into a target branch with a commit message
These map to the WS commands rollback, branch-retry, squash-merge (see API).
Workers
vpd worker
Starts or checks a customer-owned team worker from a paired profile. This is the preferred path for new self-hosted runners.
vpd pair PAIRING_CODE --worker --transport=polling --workdir "$HOME/.viewport/worktrees"
vpd worker doctor
vpd worker start --mode persistent --transport polling
vpd worker stopHosted Viewport is the default server. For a self-hosted compatible control plane, specify the server while pairing:
vpd pair PAIRING_CODE --worker --server https://viewport.customer.internal --transport=polling --workdir "$HOME/.viewport/worktrees"
vpd worker start --mode persistent --transport pollingWorker commands:
vpd worker start --mode persistent --transport polling|relay|inbound: keep heartbeating and claim multiple assignments over time.vpd worker run-once --lease <lease-token> --transport polling|relay|inbound: run one ephemeral lease, emit cleanup, and exit.vpd worker stop --json: sendSIGTERMto the persistent worker for the paired profile, or clear the stale local lock if the recorded PID is gone.vpd worker doctor --json: validate paired server, worker identity, workspace id, workspace root, transport, and detected capabilities without claiming work. The JSON includesvpdProfile(name,source,home, andbaseHome) so operators can catch accidental profile switches before a worker claims work. If multiple local profiles exist and no profile is selected, doctor prints a warning before pairing or worker start. It also understands managed-executor registration profiles and explicit managed-worker flags, so support can diagnose the current proof path without starting a worker.vpd worker reset --json: clear the local worker profile and identity before re-pairing.vpd diagnostic --json: print a sanitized support snapshot with runtime, config, path, and support-packet metadata. It redacts secret-looking config fields, but you should still review local paths and workspace names before sharing.
Defaults:
- hosted server: Viewport managed, unless
--serveror config overrides it; - transport: polling for self-hosted workers;
- workspace root:
~/.viewport/profiles/local/workspacefor the default local profile; - worker lifecycle: persistent for
start, ephemeral forrun-once.
--workdir is a pairing-time flag. Pass it to vpd pair --worker; vpd worker start reads the stored worker profile.
The runner credential only lets the worker claim scoped workflow leases and report evidence. It does not grant GitHub, Slack, Linear, model, repo, or context authority by itself.
If start says another worker is already running, use vpd worker stop for the
paired profile, then start again. Use run-once for proof runs that should not
hold the persistent worker lock.
For explicit managed-worker credentials, diagnose before starting:
vpd worker doctor --json \
--server https://api.getviewport.com \
--workspace WORKSPACE_ID \
--executor EXECUTOR_ID \
--credential-file ~/.viewport/profiles/local/runner/acme-runner-token \
--runner-pool default \
--workdir "$HOME/.viewport/worktrees"The doctor output reports credentialSource (file, profile, or inline)
but never prints the credential value. JSON output also includes a
supportPacket block with the support-packet docs URL and the secret classes
the command intentionally omits, so operators know what to review before
sharing evidence. It also includes processLock, which reports whether a
persistent worker lock is active, stale, or absent for the configured profile.
For paired self-hosted workers, workspaceId should match the workspace shown
in the app-generated pairing command, and vpdProfile.home should be the local
profile directory you intended to use.
Doctor options:
--registration-profile PATH: load managed executor registration JSON written from the app.--runner-pool NAME: advertise the runner pool for policy matching.
Agent capability checks are strict. If you pass --agents codex,claude, the
connected daemon must actually have those adapters loaded. The worker checks the
daemon before claiming work and exits before taking an assignment if an
advertised agent is unavailable.
For a deterministic or custom runner, start the daemon with a PTY-backed custom agent:
VIEWPORT_CUSTOM_AGENT_COMMAND=/usr/local/bin/my-agent \
VIEWPORT_CUSTOM_AGENT_ID=my-agent \
VIEWPORT_CUSTOM_AGENT_ARGS_JSON='["--json"]' \
vpd startThen advertise and use that same id in workflows:
vpd pair PAIRING_CODE --worker --transport=polling --workdir /path/to/repo
vpd worker start --mode persistent --transport pollingCustom command agents stream terminal output as session evidence. They do not provide SDK-level structured tool calls, token usage, or permission callbacks.
vpd team-resource sync
Writes a Team Resource export bundle into a Git checkout. Use this on a worker that has access to the team's configured repository. The API prepares the bundle; the worker performs the local filesystem write and Git commit.
vpd team-resource sync \
--bundle /path/to/export-bundle.json \
--repo /path/to/team-resource-repo \
--commit-message "Sync Viewport Team Resource" \
--jsonOr let a managed worker fetch the bundle and report the commit with its runner credential:
vpd team-resource sync \
--server https://api.getviewport.com \
--workspace WORKSPACE_ID \
--executor EXECUTOR_ID \
--credential VP_EXECUTOR_TOKEN \
--resource TEAM_RESOURCE_ID \
--repo /path/to/team-resource-repo \
--push \
--jsonThe command verifies every file's SHA-256 before writing, rejects any path
outside .viewport/, stages the exported files, and creates a commit using a
Viewport worker identity. When server credentials are supplied, it reports the
resulting commit SHA back to Viewport. Pass --push to push HEAD to origin
for the selected branch, or --no-commit when you only want to inspect the
materialized files.
Declarative GitOps
vpd check [PATH] [--json]
Validates committed .viewport/ policy and route files before you push them.
vpd check .
vpd check . --jsonIt checks:
.viewport/policy.yaml;.viewport/routes/*.yaml;.viewport/access.yamlstructure when present.
It also warns when .viewport/ appears in .gitignore. Declarative GitOps
requires policy and route files to be committed; ignored local config will never
sync to the control plane.
Config
vpd config resolve
Resolves repo-local .viewport/config.yaml (or .viewport/config.json) and prints the resolved resources.
vpd validate [--path FILE]
Validates a repo-local Viewport config against viewport-config-v1.schema.json.
vpd contract resolve [--path FILE]
Resolves the contract manifest for a path.
vpd guard check --path FILE
Runs the policy guard against a specific file. Useful in pre-commit hooks.
Team Context
The vpd context family manages encrypted team memory (see Team Context).
vpd context init
vpd context status
vpd context add
vpd context propose
vpd context use-github
vpd context resolve
vpd context sync-push
vpd context sync-pull
vpd context sync-all
vpd context epoch-publish
vpd context epoch-rotate
vpd context recovery-backup
vpd context recovery-restore
vpd context rotations-process
vpd context grants-process
vpd context revokes-process
vpd context decisions
vpd context candidate-preview
vpd context device-enroll-request
vpd context device-enroll-approve
vpd context device-enroll-accept
vpd context device-enrollments
vpd context team-grant-create
vpd context team-grants-accept
vpd context dev-reset-crypto --i-understandSome local-store commands accept --key-store file|macos-keychain.
The trusted-edge sync commands are the ones used for team sharing:
createandusecan carry descriptor guidance with--use-whenand--update-when. These fields are server-visible metadata, not encrypted body content. They tell agents when the vault is relevant and when a durable update is worth proposing.use-github --repo <owner/repo|url> --provider <id>attaches a GitHub markdown repo as a provider. The trusted edge clones or pulls it with local Git auth.context propose --provider <id>pushes a branch and opens a PR whenghis available.epoch-publishpublishes public user/team epoch material. Private key material stays local.epoch-rotatepublishes a signed user/team epoch rotation after a revoke or manual rotation.recovery-backupencrypts the active user epoch locally and uploads a ciphertext-only backup. Pass--recovery-key <key>or let the daemon print a new one once.recovery-restore --recovery-key <key>fetches the latest encrypted backup, decrypts it locally, restores the user epoch, then immediately rotates and stores a fresh backup.device-enroll-request,device-enroll-approve, anddevice-enroll-acceptadd a laptop, workstation, or VPS as decrypt-ready.device-enrollmentsshows pending, approved, accepted, and revoked device enrollment state.team-grant-createandteam-grants-acceptmaterialize team epoch access for team members.grants-processlets a trusted edge wrap pending vault grants for active user/team epochs.sync-pullimports encrypted events and reports grant materialization when this edge can unwrap a grant.candidate-previewdecrypts a candidate on the trusted edge and mints the proof required for approval.revokes-processemits revoke and rotated-key events after access is removed.dev-reset-crypto --i-understandclears local encrypted collaboration state for local/staging QA while preserving auth and daemon config.
Agent skills
vpd skills install [claude-code|cursor|all]
Writes per-agent contract markdown into a target path so the agent prompt-references vpd. Pass --force to overwrite. This is the magic that makes "Claude knows about vpd" work end-to-end.
Remote
vpd remote login|status|enable|disable|logout
Manages daemon-native relay transport options. Useful for switching between hosted relay, self-hosted relay, and disabled remote.
Hooks
vpd hook notify|plan|capabilities
Used by Claude Code hooks that vpd install writes into ~/.claude/settings.json. Not typically called by humans.
Internal
vpd __supervisor and vpd __worker are the daemon's two-process model. Don't invoke them directly.
What's persisted on disk
~/.viewport/
├── config.json # daemon config (mode 0600)
├── runtime.json # daemon runtime state (pid, listen address)
├── relay-identity.json # daemon device identity for relay handshakes
├── plugins.json # workflow plugins loaded at startup
├── replay/ # session replay event store
├── sessions/ # per-session message logs (driven by directory + session id)
├── crypto/epochs.json # local user/team epoch private material (mode 0600)
├── plans/trusted-edge-keys.json # local trusted-edge plan body keys (mode 0600)
├── pairing-* # in-progress pairing identity / file stores
└── ...Override the root path with VIEWPORT_HOME or VPD_HOME. Repo-scoped daemon overrides (separate from the repo's .viewport/config.yaml contract) can be opted into with VIEWPORT_RESOURCE_OVERRIDE_DIR.
Related
- Quickstart for the minimal flow end-to-end
- CLI setup reference for worker vs monitor pairing
- Sessions for what
vpd runproduces - Workflows for what
vpd workflowoperates on - API for the WebSocket protocol the CLI speaks to the daemon