Skip to content

How it works ​

This page explains snowpea's local daemon, client connections, protocol flow, and storage locations.

On this page

  • Overall flow
  • Daemon-owned state
  • Client connection
  • Client choices
  • Storage locations

Overall flow ​

The daemon, also called snowpea core, is a local process written in Python that owns all stateful data. The terminal UI (TUI), desktop app, and custom clients are clients attached to the daemon. Clients communicate with the daemon over the documented WebSocket JSON-RPC protocol.

text
        ┌──────────────┐   ┌──────────────────┐   ┌────────────────┐
        │ terminal UI  │   │   desktop app    │   │  your own app  │
        └──────┬───────┘   └────────┬─────────┘   └───────┬────────┘
               │                    │                     │
               └──────── ws://127.0.0.1:<port>/ws ────────┘
                                    │
                          ┌─────────┴──────────┐
                          │  snowpea daemon    │
                          │ sessions · tools   │
                          │ permissions ·      │
                          │ memory · schedules │
                          └─────────┬──────────┘
                                    │
                    LLM vendors · files · shell · web

Daemon-owned state ​

The daemon stores the canonical state for sessions, tools, permissions, memory, schedules, and messenger bindings. Clients do not store that state separately.

StateDescription
Sessionsconversations and every event inside them
Toolsreading and editing files, the shell, web search, the browser, and the other work the agent performs
Permissionswhich tools run without asking and which tools request approval before they run
Memorydata that persists across sessions. A named agent gets its own namespace
Schedulesjobs like "every day at 9am", run inside the daemon rather than a separate cron daemon
Messenger bindingsTelegram, Discord, and Slack connections

Because the daemon owns schedules, closing the terminal does not stop a scheduled job. Because the terminal UI and desktop app display the same session, the same conversation can continue in either place.

The daemon starts when the first client attaches. It shuts down when there are no open sessions, enabled jobs, messenger bindings, or named agents.

  1. To check daemon status, run this command.

    bash
    snowpea daemon status

    The output shows the sessions, jobs, bindings, or agents currently keeping the daemon alive.

Client connection ​

On startup, the daemon chooses a loopback-only port. It writes {port, pid, token, startedAt, protocolVersion} to $SNOWPEA_HOME/daemon.json. A client reads this file first.

SurfaceEndpointFor
WebSocketws://127.0.0.1:<port>/wsJSON-RPC 2.0, bidirectional
HTTP GET/healthis it alive
HTTP GET/protocol.jsonthe schema, as JSON
HTTP GET/versionserver and protocol versions

The daemon is loopback-only and is not exposed to the network. To work on code on another host, use a backend (docker, ssh) instead of opening a port.

A connected client immediately calls system.hello. The parameters are the token from $SNOWPEA_HOME/token, the client version, and the protocol version the client was built against. Any other method before that fails with unauthorized, and a major-version mismatch is refused with protocol_incompatible.

After system.hello, communication is bidirectional. The client calls methods such as session.*, turn.*, approval.*, schedule.*, and memory.*. The daemon sends events such as message.delta, tool.call, diff, and turn.done.

The exact schema is the protocol reference. The protocol overview explains how the reference and TypeScript bindings are generated together from the core source. CI fails the build when they drift apart.

Client choices ​

ClientUsage
Terminal UI (TUI)Run snowpea to start the daemon when needed and attach the UI
Desktop app (snowpea desktop)A separate window attached to the same daemon. Installing it does not move sessions; it displays the same sessions
Headless CLIsnowpea -c "..." runs one turn with no UI and exits with a code. Add --json to output events as JSON Lines
Custom clientThe TypeScript SDK uses the same protocol
  1. To inspect events from the headless CLI as JSON Lines, run this command.

    bash
    snowpea -c "summarise README.md" --json

    One turn runs and protocol events are written as JSON Lines.

Storage locations ​

snowpea data is stored on the local machine.

PathWhat
$SNOWPEA_HOME (default ~/.snowpea)everything global
$SNOWPEA_HOME/settings.jsonproviders, search and browser choice, tool categories, timeouts
$SNOWPEA_HOME/credentials.jsonbot tokens and secrets, mode 0600
$SNOWPEA_HOME/daemon.jsonport, pid, token, start time, protocol version
$SNOWPEA_HOME/state.dbsessions, events, memory, jobs, team tasks, named agents
$SNOWPEA_HOME/logs/daemon.log, approvals.jsonl
$SNOWPEA_HOME/plugins/, skills/, agents/, commands/installed and hand-written extensions
<project>/.snowpea/settings.jsondefault mode, allowlist and backend for this repository
<project>/.snowpea/{skills,agents,commands}/project-local extensions
<project>/.claude/{skills,agents,commands}/read for Claude Code compatibility

SNOWPEA_HOME is honoured everywhere.

  1. To use a second, fully isolated installation, run this command.

    bash
    SNOWPEA_HOME=/tmp/snowpea-scratch snowpea daemon status

    The daemon status is shown for the separate state under /tmp/snowpea-scratch.

Only the prompt sent to the LLM vendor you chose leaves the machine. The only first-party service snowpea contacts on its own is registry.snowpea.ai, and only when you search for or install a skill. If you use a model running locally, the prompt also stays on the machine.

Next steps

MIT licensed. The manual is generated from the product repositories — see the banner on each page.