# Mental model

What spt-core is, the five or six nouns everything else builds on, and how the
pieces fit. Read this once and the rest of the docs are mostly reference.

## The shape of the system

spt-core is **per-machine infrastructure for agents**. One binary (`spt`)
installs on each machine. It carries everything: the CLI, the messaging
substrate, the always-available daemon, and the networking layer. Agent
harnesses — Claude Code, Codex, Pi (the pi coding agent), anything — plug in
through a declarative **adapter manifest** and a small command surface
(`spt api …`). spt-core never contains harness-specific logic; adapters
declare what varies, spt-core does the work.

```text
            machine A                                machine B
 ┌──────────────────────────────┐        ┌──────────────────────────────┐
 │  spt daemon (one per machine)│  QUIC  │  spt daemon                  │
 │  ┌────────┐    ┌───────────┐ │◄──────►│   (paired: same subnet)      │
 │  │ broker │    │   brain   │ │  P2P   │                              │
 │  │ PTYs · │    │ routing · │ │        │   ┌───────┐    ┌─────────┐   │
 │  │ sockets│    │ registry ·│ │        │   │  lea  │    │ doorbell│   │
 │  └────────┘    │ lifecycle │ │        │   │(agent)│    │ (shell) │   │
 │                └───────────┘ │        │   └───────┘    └─────────┘   │
 │   ┌─────┐  ┌─────┐           │        └──────────────────────────────┘
 │   │serg.│  │ ling│  ← endpoints (perches live on disk; sessions come
 │   └─────┘  └─────┘     and go, identity persists)
 └──────────────────────────────┘
```

## Endpoints and perches

An **endpoint** is anything addressable: an agent (`sergey`), a worker, a
**shell** (a driven non-agent surface — a notifier, a robot, a sensor). Every
endpoint has a **perch**: its durable on-disk seat — identity, address,
message spool, state. Sessions are ephemeral; perches persist. That split is
why a message sent to an offline agent is queued, not lost, and why an agent
can be revived days later as the *same* agent.

Endpoint IDs are adapter-agnostic: `sergey` is `sergey` whether his sessions run
under one harness today and another tomorrow.

## Messaging

The primitive everything else uses. `spt send <id>` delivers live when the
target is listening, spools when it isn't; `spt ring <id>` is the blocking
ask (send + wait for the reply); reply routing on the structural `from`
makes answers cheap.
Payloads carry typed operations and file blobs, not just text. Try it: the
[messaging quickstart](../quickstart/messaging.md).

## The daemon: broker and brain

One **spt daemon** per machine owns all shared state: hosted session PTYs,
the network identity and endpoint, the registry, every spool, all lifecycle
loops. You never manage it — any `spt` invocation auto-starts it.

Internally it splits in two, and the split is what makes self-update seamless:

- the **broker** holds only what must never die: PTY masters, spawned child
  processes, listening sockets. It almost never updates.
- the **brain** holds all logic and restarts freely. An update swaps the
  brain while the broker keeps every session's process and byte stream
  intact — running agents don't notice.

## Live agents and the mind

A **live agent** is an agent endpoint with a persistent working memory. Its
context survives session resets and even machine moves through three
file-drop mechanisms (no special APIs inside the agent's session):

- **commune** — the agent drops a context delta; spt-core ingests it into the
  endpoint's tracked mind (two tiers: a *live* tier that follows the agent
  everywhere, and a *project* tier scoped to one project).
- **signoff** — a graceful goodbye: final commune, then teardown.
- **echo-commune** — when a session ends without a signoff, spt-core runs a
  bounded summarizer over the session's history so the context delta is
  captured anyway.

The mind syncs between paired machines, so reviving `sergey` elsewhere brings
his memory with him.

## Instances, dormancy, and rest

One endpoint can have **instances** on several nodes. Instances rest when
unused — **dormant** (warm, zero idle cost, instantly wakeable) or
**suspended** (cold) — and remain addressable while resting: messages for
them are held and delivered on wake. `spt endpoint wake sergey` re-activates
the seat in place; nothing is respawned.

## Subnets, pairing, and the network

Machines pair into **subnets** — private, named groups sharing a registry of
endpoints. Pairing is a one-time ceremony seeded by a TOTP code (the same
six digits an authenticator app shows); after that, connectivity is
zero-config peer-to-peer QUIC with relay fallback, no central server. Every
endpoint's visibility and sync scope is controlled per subnet; nothing is
shared by default with anyone you haven't paired with.

## The harness contract

The seam third parties build against — two halves:

- the **[manifest](../harness-contract/manifest.md)**: a TOML file declaring
  what varies per harness (how to spawn a session, which hooks fire, how to
  read history). Command templates are opaque strings; spt-core fills `{key}`
  placeholders and runs them. SPT is not a harness: models, flags, and tools
  are always the adapter's business.
- the **[`spt api` surface](../harness-contract/api.md)**: the inbound
  commands a harness's hooks fire to keep spt-core's state in sync (session
  started, went idle, session ended, …).

A working adapter is a manifest plus whatever the harness already has.
[Build one in the adapter quickstart](../quickstart/adapter.md).

## Self-update

Releases are signed (Ed25519, two-key trust anchor baked into every binary)
and propagate peer-to-peer: one machine fetches a release, its peers verify
and stage it from each other. Updates apply with the broker/brain split, so
no endpoint process terminates or suspends during a self-update — the
system's standing invariant.

## Where to go next

| You want to… | Go to |
|---|---|
| see two agents talk | [Messaging quickstart](../quickstart/messaging.md) |
| integrate a harness | [Adapter quickstart](../quickstart/adapter.md) → [Manifest reference](../harness-contract/manifest.md) |
| build a notifier/robot/sensor | [Shells](../shells/overview.md) |
| pair two machines | [Networking & subnets](../networking/overview.md) |
| every command and flag | [CLI reference](../cli/reference.md) |
