Viewport daemon, relay, and hosted runtime are available in alpha. Surfaces may change.
VIEWPORT
Concepts

Sessions

One agent run on one machine. The daemon owns the live transcript; the platform persists only metadata and receipts.

A session is one agent run. The daemon owns the live transcript. The platform persists session metadata and governance state — status, participants, routing decisions, receipts — for review and audit, but it does not persist the transcript plaintext. There is no server-side transcript table where prompts, tool calls, or agent messages could leak from.

When you load Sessions in the app, the page connects to paired daemons over the relay and asks each daemon for the sessions it owns. Live runs update immediately. Recent rows come from the daemon's local session history, not from a server-side transcript table. If a daemon is offline, Viewport can show last-known machine metadata, but it cannot reconstruct or replay that machine's transcript from the platform database.

What the Sessions page shows

The Sessions page is a runtime workspace, not just a chat log.

  • Native Claude Code and Codex titles when the agent stores one.
  • First meaningful prompt as a fallback, excluding injected environment metadata.
  • Model, reasoning effort, approval policy, and sandbox mode when the provider records them.
  • Per-session capability flags, so the UI can tell whether this run supports transcript reads, live tailing, resume, model override, interrupt, or permission responses.
  • A timeline with messages, reasoning, commands, file changes, subagent/task lifecycle events, token usage, errors, and permission requests.
  • Allow, deny, and always-allow actions for permission requests that are still waiting on the owning daemon.
  • Resume controls for resumable sessions, including slash snippets and an optional model override.

Provider details are normalized by the daemon before they reach the UI. Unknown provider events are still surfaced as muted debug rows instead of being silently dropped.

Claude Code also writes local command wrappers into its transcript for slash commands, model changes, and local command output. The daemon treats those as provider control events. It hides caveat boilerplate, strips terminal color codes, and renders slash commands or local stdout as quiet timeline events instead of showing raw <local-command-*> text as user messages.

What's on the wire

The protocol between daemon and client lives in the open-source daemon at packages/daemon/src/server/ws-protocol.ts. Three frame types announce a session:

// daemon → client when an agent starts
{ "type": "session-started", "sessionId": "ses_…", "directoryId": "dir_…" }

// daemon → client on every update
{
  "type": "session-update",
  "sessionId": "ses_…",
  "seq": 142,
  "update": {
    "updateType": "tool-call",  // or agent-message, step-committed, …
    /* per-updateType payload */
  }
}

// daemon → client when the agent exits
{ "type": "session-ended", "sessionId": "ses_…", "reason": "completed" }

update.updateType values currently emitted:

agent-message, agent-message-chunk, agent-thought-chunk, user-message, tool-call, tool-call-update, permission-request, permission-resolved, state-change, step-committed, token-usage, system-status, attention, streaming-state.

For already-created Claude Code and Codex sessions, the daemon also reads provider history files on the owning machine and maps them into rich timeline rows. Examples include Claude Bash/Edit/Agent/Task* tool uses and Codex app-server exec_command_*, exec_approval_request, turn_diff, turn_failed, and thread_name_updated events.

Provider transcript cleanup happens in the daemon, before the browser sees the row. That means old Claude transcripts with local command wrappers are cleaned up when they are re-read; the app does not need to special-case that markup in the UI.

What's not on the wire

There is no flat session.start / session.tool_call / session.end event stream. There is no server-side persistence of session transcript content (the plaintext). Tool-call payloads, prompts, and agent transcripts only leave the machine on demand. The browser explicitly subscribes (subscribe, watch-discovered-session, or read-session-messages) and the daemon streams from its local store under ~/.viewport/ or the provider's own session files.

Privacy load-bearing

This is the load-bearing piece of the privacy claim. The daemon is open source so you can read every line that handles session content; the platform has no transcript table to leak from. (Session metadata and governance receipts are persisted — see Trust & privacy for the per-data-class breakdown.)

Lifecycle

StateWhen
activeAgent is producing work. Update frames are flowing.
awaitingAgent is paused on a permission request or approval gate.
idleAgent is alive with nothing to do.
endedAgent exited. Updates stop.

If the daemon crashes or the machine goes offline, the session enters a disconnected substate. The platform shows its last-known status from persisted metadata; it cannot replay the transcript from the platform database.

Starting a session

Two ways:

Programmatic (over the local WS):

// client → daemon
{
  "type": "launch",
  "directoryId": "dir_…",
  "prompt": "fix the failing auth tests",
  "model": "claude-3-5-sonnet",   // optional
  "configOverrides": {            // optional
    "agent": "claude",
    "costCapUsd": 5
  },
  "requestId": "req_…"
}

That's what vpd run sends.

Out-of-band: start claude or codex directly in a registered directory. The daemon picks up the session via its hook bridge and announces it to subscribers.

Resolution: what context the session sees

At session start, the daemon resolves the resource manifest for the working directory. Resolution is deterministic and driven by the repo-local .viewport/config.yaml (validated against the schema in the daemon repo). The resolved manifest names:

  • contexts to attach
  • workflows applicable in this scope
  • plans templates available
  • agentProfiles that apply

Inspect the resolution from the CLI:

vpd config resolve
vpd session manifest --session SID

Multi-repo sessions

If the agent runs above two repos (a meta-monorepo, a worktree), the daemon resolves both configs and merges them. Conflicts surface as conflicts in the resolved manifest. Nothing is silently chosen.

What's not a session

  • A workflow run is a coordinated set of one or more sessions and is persisted server-side. See Workflows.
  • A pairing is the trust relationship between a machine and a workspace. Sessions don't exist without one.
  • A plan is an artifact a session might produce. See Plans.

On this page