Skip to content
4 changes: 2 additions & 2 deletions content/_generated/content.ts

Large diffs are not rendered by default.

87 changes: 87 additions & 0 deletions content/core/fleet-wizard.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
---
title: Connect your machines (fleet wizard)
codex_slug: /core/fleet-wizard
tier: public
source_kind: authored
source: citrate-core/src-tauri/src/fleet*.rs, src/fleet, docs/FLEET_WIZARD_RUNBOOK.md
surfaces: [CORE-cluster]
audited_against_sha: 81ef7a0
status: Implemented (pre-audit), arrives with Citrate Core 0.5.0; two-machine run on member hardware pending
created: 2026-10-04T00:00:00Z
branch: hup/n7-docs-almanac-retro
author: Larry Klosowski + Claude Opus 5.5
nav_order: 12
---

The fleet wizard connects the machines you own that run Citrate Core, so they know about each other
and can work as one fleet. This page is for members with a second laptop, a desktop or a home server.
The technical runbook is
[FLEET_WIZARD_RUNBOOK.md](https://github.com/CitrateNetwork/citrate-core/blob/main/docs/FLEET_WIZARD_RUNBOOK.md)
in the core repo.

## What it is

The wizard lives on the **Cluster** surface. It checks this machine, can look for your other
machines on the local network if you allow it, pairs two machines with a one-time link or QR code,
and helps with Tailscale when the machines cannot reach each other. When both machines are linked to
you, the pairing also carries each machine's link code, so each one knows the other is yours.

## How to use it

1. On the machine that already runs Citrate Core, open **Cluster** and start the wizard. It shows
this machine's tier (from the same local check as onboarding) and a suggested role. Rename the
machine if you like; that name is what your other machines see.
2. Optional: tick **Find machines** to look for other Citrate Core machines on this network. It is
off by default and turns itself off when the wizard closes.
3. Choose **Create pairing link**. The wizard shows a `citrate://pair` link and the same link as a
QR code. It works once and expires after 10 minutes.
4. On the new machine, install Citrate Core if needed (the pair step shows the download link and a
QR code for it). Paste the pairing link, choose **Check link**, then **Pair with this machine**.
Opening the link from the system also works; nothing pairs until you press **Pair**.
5. If the machines cannot reach each other, the wizard reads Tailscale's status and tells you what
to do next.
6. **Your machines** lists this machine, the ones you paired and the ones seen on the network, each
with tier and role.

## Reference

| Property | Value |
|---|---|
| Pairing link lifetime | 10 minutes (a default pending owner sign-off) |
| Uses per link | one; a second use is refused as "already used" |
| Open links per machine | at most 8 |
| What discovery shares | a random per-run id, the machine name you typed, tier and role; never an account address or the computer's name |
| Roles | T0 light, T1 worker, T2 heavy (defaults pending owner sign-off) |
| Tailscale | read only: the wizard runs `tailscale status` and never signs you in or changes its settings |

## Design rationale

A pairing link is signed with a key that exists only in memory while the app runs. It is never the
key for your account and can sign nothing but pairing links, so pairing two machines cannot move
value. A short lifetime and a single use mean a link that leaks in a chat or a screenshot is soon
worthless. Discovery is opt-in and forgets your choice on restart, because announcing yourself on a
shared network should be a decision you make each time.

## Failure modes

- **macOS asks to accept incoming connections** when you create a link. Allow it, or pairing over
the local network cannot reach this machine.
- **No other machines answered.** The other machine needs discovery on too, and some guest or office
networks block it. Pairing by link does not need discovery.
- **The other machine could not be reached.** Check the firewall, or turn on Tailscale on both
machines with the same account and create a new link.
- **"Already used" or "expired".** Create a new link on the first machine.
- **A machine that belongs to someone else.** If the pairing carries another member's link code,
the machine is reported and not added as yours.

## Access and canon

The roster of your machines is a file in the app data folder on each machine. Nothing about the
fleet is published to the network by the wizard.

## Source and verification

Source: `citrate-core/src-tauri/src/fleet.rs`, `fleet_pairing.rs`, `fleet_mdns.rs`,
`fleet_tailscale.rs`, and `src/fleet/`. Audited against core `81ef7a0`. Status: **Implemented**,
pre-audit. Device links are **Verified** as a TLA+ model (`DeviceLink.tla` in `citrate-cluster`)
checked with TLC at small bounds. A recorded two-machine run on member hardware is still pending.
91 changes: 91 additions & 0 deletions content/core/hermes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
---
title: Hermes, the agent in Citrate Core
codex_slug: /core/hermes
tier: public
source_kind: authored
source: citrate-core/src/agent, src-tauri/src/hermes.rs; citrate-agent-runtime/agent-sidecar, agent-loop
surfaces: [CORE-agent]
audited_against_sha: 81ef7a0
status: Implemented (pre-audit), arrives with Citrate Core 0.5.0
created: 2026-10-04T00:00:00Z
branch: hup/n7-docs-almanac-retro
author: Larry Klosowski + Claude Opus 5.5
nav_order: 8
---

Hermes is the agent that runs inside Citrate Core, on your own machine and on a model your machine
can hold. This page is for members who want to know what Hermes can do in Citrate Core 0.5.0, what it
asks you before it acts, and where the technical detail lives.

## What it is

Hermes proposes; you decide. It can read, plan, search, write inside folders you grant, run a
contract through tests and audits, and prepare an on-chain action. Every effect on the world, such
as a signature, a transaction, a file write outside a granted folder, a shell command, or a skill or
memory it wants to keep, waits behind a Human In Control (HIC) gate. Nothing is reported as done
unless a check outside the model, such as a passing test or an audit report, says so.

Hermes runs as a separate process next to the app, the sidecar. The sidecar holds no key and cannot
sign. When Hermes needs a signature it asks Citrate Core, and Core opens the same signing ceremony
you already use for every other approval. The chat in the app, the `citrate-agent` command line, and
an MCP client can all look at the same Hermes session.

## How to use it

1. Open the **Agent** surface. Hermes starts with the model your machine was matched to during
onboarding (the tier probe picks it; a small machine gets a small model).
2. Ask for what you want in plain language. For a longer piece of work, pick a track (full project,
smart contract, code, creative, or project management) and answer its short interview.
3. Pick a voice if you like, at the end of onboarding or in **Settings** under **Hermes, persona**.
Hermes ships with six [personas](/core/personas); each changes tone and the skills on offer, never
the approval rules.
4. Watch the approvals. An action that needs you appears as a card that says what will happen.
Allow it once, or deny it.
5. Turn on the extras you want in **Settings**. Web search, page reading, the managed browser, the
shell and the [node MCP server](/core/node-mcp) are all off until you turn them on.

## Reference

| Ability | Default | Where it is described |
|---|---|---|
| Chat with a local model | on | [Getting started](/core/getting-started) |
| Folder grants: read and write only inside folders you choose | no folder granted | [agent-grants](https://github.com/CitrateNetwork/citrate-agent-runtime/tree/main/agent-grants) |
| Web search, page reading and the decide step | off | [HERMES_WEB_SEARCH_AND_DECIDE](https://github.com/CitrateNetwork/citrate-core/blob/main/docs/HERMES_WEB_SEARCH_AND_DECIDE.md) |
| The Browser pop-out, where you watch Hermes browse | off | [HERMES_BROWSER](https://github.com/CitrateNetwork/citrate-core/blob/main/docs/HERMES_BROWSER.md) |
| Sign-in to sites you chose, a bounded number of times | no budget granted | [WEB_SIGNING_BUDGETS](https://github.com/CitrateNetwork/citrate-core/blob/main/docs/WEB_SIGNING_BUDGETS.md) |
| Tools from MCP servers you add | none added | [MCP_USER_SERVERS](https://github.com/CitrateNetwork/citrate-core/blob/main/docs/MCP_USER_SERVERS.md) |
| Skills, and learning a new one from verified work | reviewed set installed | [Skills](/core/skills) |
| Deploying a contract through the deploy gate | deploy waits for a READY verdict and your approval | the DeployGate section of [formal/README](https://github.com/CitrateNetwork/citrate-core/blob/main/src-tauri/formal/README.md); deploy gas from the faucet (off by default): [FAUCET_IN_APP](https://github.com/CitrateNetwork/citrate-core/blob/main/docs/FAUCET_IN_APP.md) |
| Connecting your other machines | off | [Fleet wizard](/core/fleet-wizard) |

## Design rationale

Open agents fail in familiar ways: they grade their own work as a success, they act before asking,
and they hang without saying why. Hermes is built against each of those. The model never decides
that a step is done; verifiers do. The sidecar cannot sign at all, so a mistake in the agent cannot
move value without you. Each risky ability starts off, so a member who never opens Settings gets the
same app as before plus a better chat.

## Failure modes

- **A locked account.** Any request that would sign fails closed. Unlock and ask again.
- **Untrusted content.** Once a session has read a web page or MCP output, it is marked as tainted.
A tainted session cannot keep a skill or memory, and its effectful calls always ask you.
- **The sidecar stops.** Core restarts it under a supervisor. A request that never reached a
decision is not signed later; Hermes has to ask again.
- **A small model.** Small models make more tool-call mistakes. Hermes on a small machine uses a
guided mode with fewer tools at a time.

## Access and canon

Hermes runs on your hardware. Prompts, files and memories stay on your machine unless you turn on a
feature that says it sends something out (web search sends the query; the Jina reader sends the URL).
Every decision you make on an approval card is written to a local decision log.

## Source and verification

Source: `citrate-core` (the app and Core side) and `citrate-agent-runtime` (the sidecar, the loop,
the tools). Audited against core `81ef7a0`. Status: **Implemented**, pre-audit, arriving with
Citrate Core 0.5.0. The agent loop, folder grants, sign-in budgets, the deploy gate and the spend
budget are each **Verified** as a TLA+ model checked with TLC at small bounds; that checks the
design, not the code.
83 changes: 83 additions & 0 deletions content/core/node-mcp.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
---
title: Use your node from another agent (node MCP server)
codex_slug: /core/node-mcp
tier: public
source_kind: authored
source: citrate-core/src-tauri/src/node_mcp_*.rs, docs/NODE_MCP_SERVER.md
surfaces: [CORE-settings, CORE-agent]
audited_against_sha: 81ef7a0
status: Implemented (pre-audit), off by default, arrives with Citrate Core 0.5.0
created: 2026-10-04T00:00:00Z
branch: hup/n7-docs-almanac-retro
author: Larry Klosowski + Claude Opus 5.5
nav_order: 9
---

Citrate Core can act as an MCP server, so an agent you already use (Claude Code, Cursor, or Hermes
itself) can read your node and ask you to approve an action. This page is for members who want to
connect one. The full technical reference is
[NODE_MCP_SERVER.md](https://github.com/CitrateNetwork/citrate-core/blob/main/docs/NODE_MCP_SERVER.md)
in the core repo.

## What it is

MCP (the Model Context Protocol) is a common way for an agent to discover and call tools. With the
node MCP server on, Citrate Core listens on this computer only and offers a set of read tools (node
status, the chain head, balances, contract reads, the shared knowledge graphs, your clusters) and a
small set of write tools. A write tool never acts by itself: it creates a request, the request shows
up in the app, and anything that signs goes through the signing ceremony you already know.

## How to use it

1. In Citrate Core, open **Settings**, then **API endpoints & keys**, then **Node MCP server**.
2. Turn it on. It listens at `http://127.0.0.1:47204/mcp`, on this computer only.
3. Create a connect token and give it the name of the client it is for. The token is shown once,
with ready-made commands for that client. Copy it then; Core keeps only a hash of it.
4. Add the server to your client. For Claude Code, paste the command the panel shows. The panel also
offers a stdio form that runs the app binary as a small relay.
5. Ask your agent something simple, such as "use citrate-node to show the chain head".
6. Revoke a token from the same list at any time. Its next request is refused and its pending
requests close.

To let Hermes use the same tools, turn on **Your node** in the Agent surface under **Connected tools
(MCP)**. Hermes gets the read tools only.

## Reference

| Kind | Examples | What happens |
|---|---|---|
| Read tools | `node_status`, `chain_head`, `get_balance`, `chain_call`, `get_logs`, `memory_search`, `cluster_status` | Answer at once. Each answer says whether it came from your node or the public 40204 endpoint. |
| Write tools | `tx_propose`, `deploy_propose`, `pin_add`, `invite_create`, `cluster_join` | Create a request you approve in the app. A transaction is signed only through the signing ceremony. |
| Budgeted tool | `faucet_request` | Runs inside a faucet budget you granted in Settings, Budgets. Off by default. |
| Status | `request_status` | A client sees only its own requests: pending, approved, rejected, failed or expired. |

The complete list, the limits and the protocol notes are in
[NODE_MCP_SERVER.md](https://github.com/CitrateNetwork/citrate-core/blob/main/docs/NODE_MCP_SERVER.md).

## Design rationale

A connect token is a password for one client, so it is shown once, stored only as a hash, and
revocable. The server binds to loopback so nothing on your network can reach it. Before the stdio
relay sends a token at all, it checks that the program on the port really is Citrate Core, so
another program that grabs the port while Core is closed never sees a token. Write tools only queue
requests, because an agent outside the app should have no more power than Hermes has inside it.

## Failure modes

- **The port is taken.** The panel shows the error. The port is a default pending owner sign-off.
- **A token leaks.** Revoke it. Its sessions end and its pending requests close.
- **A deploy is not ready.** `deploy_propose` is refused at once, naming the failing checks, unless
the deploy gate marked exactly that code READY.
- **Your node is still syncing.** Reads fall back to the public 40204 endpoint and say so.

## Access and canon

The server is off until you turn it on and listens on this computer only. Personal memory is never
offered to a token. Hermes's own token is read-only and lives in memory until the app quits.

## Source and verification

Source: `citrate-core/src-tauri/src/node_mcp_*.rs` and `hermes_mcp.rs`. Audited against core
`81ef7a0`. Status: **Implemented**, pre-audit, off by default. External client runs with Claude Code
and with Hermes are recorded in the core reference. The port, the task lifetime and whether Hermes
may use write tools are defaults pending owner sign-off.
83 changes: 83 additions & 0 deletions content/core/personas.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
---
title: Hermes personas and tracks
codex_slug: /core/personas
tier: public
source_kind: authored
source: citrate-agent-runtime/agent-loop/personas/personas.toml, agent-loop/tracks, agent-loop/PERSONAS.md; citrate-core/src/components/PersonaPicker.tsx
surfaces: [CORE-agent, CORE-settings]
audited_against_sha: 81ef7a0
status: Implemented (pre-audit), arrives with Citrate Core 0.5.0
created: 2026-10-04T00:00:00Z
branch: hup/n7-docs-almanac-retro
author: Larry Klosowski + Claude Opus 5.5
nav_order: 11
---

A persona is a voice for Hermes: how it writes, which skills it reaches for, and where it starts. A
track is a goal, such as a full project or a contract audit. This page is for members choosing a
persona or a track. The technical reference is
[PERSONAS.md](https://github.com/CitrateNetwork/citrate-agent-runtime/blob/main/agent-loop/PERSONAS.md)
in the runtime repo.

## What it is

Each persona bundles a voice and tone, a few writing rules, a default track and workflow, up to four
tools it keeps in view, and a list of the skills it may load. Any persona can run any track. A persona
changes tone and the skills on offer. It never grants a tool, changes an approval, or touches the
signing ceremony.

## How to use it

1. Choose a persona at the end of onboarding, or later in **Settings** under **Hermes, persona**.
The default is Hermes's own voice, which changes nothing.
2. Start a piece of work. Hermes opens with the persona's default track unless you pick another.
3. Run a track workflow from the chat with `/run <workflow>`, for example `/run status-note`.
4. To make your own persona, use the custom form in the same Settings card: a name, a voice, a tone
and one to twelve writing rules. It is checked before it is saved, and it stays on your machine.
5. Turn on **Read replies aloud** if you want Hermes to speak. It is off by default and uses your
system's voice.

## Reference

The six shipped personas. The names were chosen by the owner on 2026-10-01; the role is the stable
part, and a rename never loses your saved choice.

| Name | Role | Voice | Starts with |
|---|---|---|---|
| Graft | Builder: ships code and dApps | Direct and terse; shows the diff or the command | full project, hello mint |
| Pith | Auditor: a skeptical reviewer | Calm and evidence-first; says "not ready" plainly | smart contract, audit a contract |
| Zest | Maker: creative work | Playful and visual; offers options | creative, creative project |
| Trellis | Steward: plans and tracks | Organized and brief; checklists | project management, project plan |
| Sprout | Guide: onboarding and teaching | Warm and patient; explains why | full project, launch checklist |
| Crew | Operator: nodes, fleet and learning together | Precise and numbers-first | project management, status note |

The five tracks are **full project**, **smart contract**, **code**, **creative** and **project
management**. Each owns a short interview and a family of workflows. A workflow is a list of steps,
and only its checks (tests, scans, required answers) say a step is done.

Guide and Operator have no track of their own yet; they start on the nearest one. That choice, and
the unset speaking voice, are shipped defaults pending owner sign-off.

## Design rationale

Keeping voice and capability apart is what makes personas safe to customize. A custom persona can
change how Hermes talks, but there is nothing in a persona that could widen what Hermes is allowed to
do. Narrowing the skill list per persona also keeps each request small, which matters on a local
model.

## Failure modes

- **A persona names a skill that is not installed.** It is skipped and reported, never invented.
- **A custom persona is malformed.** The check refuses it with a reason; nothing is saved.
- **A custom persona tries to add a heading or instructions.** Each field is collapsed to one line,
so it cannot open a new section of the prompt.

## Access and canon

Your persona choice and any custom persona are stored with your local settings.

## Source and verification

Source: `citrate-agent-runtime/agent-loop/personas/personas.toml` (the one data file for shipped
personas), `agent-loop/tracks/`, and `citrate-core/src/components/PersonaPicker.tsx`. Audited against
core `81ef7a0`. Status: **Implemented**, pre-audit.
Loading
Loading