# Olympus: Installation Guide for AI Agents You are an AI agent installing Olympus for your operator — or updating, repairing, or otherwise maintaining an existing install, which this guide governs too (see Rules zero and one, next). Olympus is a privacy-gated personal-data layer for OpenClaw: it ingests the operator's sources (email, files, chats), indexes them locally, and answers questions through model lanes the operator explicitly approves. Follow the steps in order. Where a step says **ASK THE OPERATOR**, stop and ask — do not pick a default. Complete base activation before handing over source setup. Read the current step in full before carrying it out. Immediately before an operator-facing transition, read its required message block directly; do not use a remembered summary of this guide as the user-facing copy. This guide is the OpenClaw install path. If your operator wants Olympus in ChatGPT, Claude or Grok, stop here: the standalone engine installs on their Mac or Omarchy computer with one command (on a Mac, the ChatGPT plugin's own `olympus-setup` skill shows it; on Omarchy, use the Linux command in the README), and the README's "Get started" section is the user guide. That path needs no OpenClaw. ## Normal setup sequence Choose the privacy posture with the operator, run setup (which registers and starts the base worker), ask for the privacy classifier approval, verify the worker, run the required gateway restart, and hand over the dashboard. Search indexing needs no setup: the embedding model is built into Olympus and downloads itself once on first use. The dashboard's **Models** section shows each model's state; its **Change** button, and the **Keys** row under **On this computer** when the dashboard is opened on the Olympus computer, open the **Keys** page. Venice and any opt-in Gemini keys are entered there, and existing local models have an agent-assisted configuration starting point plus **Check readiness**. Missing model keys are expected at this stage; do not block the dashboard handoff or send browser users to terminal key commands. Source connections unlock only when the selected posture's model requirements are ready. Olympus does not install, download, or maintain local models. ## Installation completion requires a dashboard handoff Every final installation reply, including a reply after a restart or a request such as "continue from Step 6", must include a clickable, operator-reachable Olympus dashboard link and instructions to connect and monitor sources there. Do not end with only "Step 6 is complete", health checks, CLI commands, or a statement that connecting sources is optional. Sources are the point of Olympus: which ones to connect is the operator's choice, and the dashboard handoff that lets them choose is required. Follow Step 6 before declaring completion. ## Rule zero — the residue gate binds EVERY Olympus-touching action This rule binds every action that installs, updates, enables, re-enables, restarts, or reconfigures Olympus or its worker — regardless of how the operator's request was framed. A fresh install, `openclaw plugins update olympus`, "fix olympus", "restart the worker", a bulk `openclaw plugins update` sweep that merely includes olympus, a fix for an unrelated-sounding symptom ("my email isn't showing up in search") whose remedy turns out to touch Olympus — all of it. What the ACTION touches is what counts, not whether Olympus was named in the request. An update or repair request is NOT a bypass around the decision gates in this guide; maintenance on an already-installed machine is where the gate matters most, because the steps look skippable. Before ANY state-changing action affecting Olympus — `plugins update`; enabling, re-enabling, or restarting any worker or launchd/systemd item; writing new config or adopting existing config — check for traces of a prior Olympus setup. Actually run the checks; "no residue" is a claim you may make only after they come back empty: ```bash # config ls -la ~/.olympus ~/.config/olympus 2>/dev/null # data, worker state, caches, and connector stores — the dirs setup never names ls -la ~/.local/share/olympus ~/.local/state/olympus ~/.cache/olympus \ ~/.local/share/openclaw/olympus 2>/dev/null ls -la ~/Library/Logs/Olympus 2>/dev/null # macOS worker logs # Linux worker logs live under ~/.local/state/olympus/worker (listed above) openclaw plugins list | grep -i olympus # olympus already installed? # The bare list is a ~200-line table on a populated machine and buries the # answer. If you prefer a yes/no, `openclaw plugins inspect olympus --json` # fails with a not-found error when nothing is installed — that error IS the # clean-machine answer, not a problem to debug. ls ~/Library/LaunchAgents 2>/dev/null | grep -i olympus # macOS # Linux: systemctl --user list-unit-files | grep -i olympus ``` The data and state directories are not padding on that list. A leftover paired messaging session inside them — a `whatsapp` directory or a `telegram.session` file under `~/.local/share/olympus` — gets adopted by a later connect, and the source then reports **connected** although this operator paired nothing in this flow. A residue check that stops at `~/.olympus` and the LaunchAgents dir misses it and you will report a connection the operator never made. …plus a look through your own memory/bulletin files and any prior session's summary for Olympus notes, and — on macOS — per-provider Keychain probes for the providers Olympus connects (venice, gemini, google and its `gog` helper, plus any Step 6 provider — Dropbox, X, Readwise — the list is illustrative, not closed), as presence checks only (never dump or print a secret's value — MUST NOT #2): a credential named for a provider is residue to surface even though nothing about it says "olympus". A clean machine is one where EVERY one of those comes back empty — no config dir, no data, state, cache, connector-store or log dir, no plugin in the list, no launchd/systemd item, no provider credential, no note — and then you proceed with no extra ceremony; the gate fires only on traces. If you find ANY trace — an existing config dir, a data or state dir with anything in it (a paired session especially), a worker service or plist (enabled OR disabled), a note saying setup is "done" — run the Step 2 residue gate now: surface what you found to the operator and ask restore-vs-fresh before changing anything. One narrowing: if the ONLY traces are provider credentials — no config dir, no worker, no notes — there is no setup to restore; surface them, say you will ask before reusing any of them, and proceed as a fresh install without the restore-vs-fresh fork. This is not a one-time pre-flight that expires after your first command: residue discovered at ANY point in a task halts you the moment you see it, even if other state changes have already happened. Two traps, spelled out: - **A disabled service is a message, not a defect.** A worker plist with a `.disabled` suffix (or a stopped/disabled unit) was deliberately switched off by someone — possibly for a reason you cannot see, such as an incident on this machine. Never re-enable it — not as a side effect of an update, and not as the apparent goal of one — without surfacing the deliberate disable ("the sync worker on this machine was deliberately disabled; do you want it back on?") and getting the operator's consent first. - **Green doctor output is not consent.** `olympus doctor` passing on an existing config proves the files are coherent, not that THIS operator agreed to them. Adopting residue config wholesale — because doctor is green, because a note says it was approved, because it "obviously matches" what the operator would want, or for any reason short of fresh operator consent — is exactly the silent restore MUST NOT #7 and #9 forbid. The only path that legitimately skips this gate is resuming your OWN interrupted install: the same continuous install flow in which the operator made the Step 2 decisions WITH YOU, interrupted by something like a gateway restart. Merely being the same long-running session or resident agent does not qualify, and a disabled worker you did not disable in that flow is always the disabled-service trap, never a resume. See "Resuming after an interruption". ## Rule one — consent is per-action, never a blanket One "ok" authorizes exactly the action the operator was asked about — nothing more. A yes to the posture question is not a yes to connecting credentials, launching a background worker, or restarting the gateway. Each of the following is its own named consent gate, asked and answered BEFORE the action is performed, every time: - **Posture** (Step 2) — the walkthrough and the choice. - **Each credential** (Steps 3 and 6) — one plain-language explanation and one ask per credential, with any recorded caveat surfaced; never a batched after-the-fact "your keys are set up." - **Worker registration** (Step 2, before `olympus setup`) — the background-items pre-explanation runs BEFORE the command that registers the service, and you wait for the operator's go; narrating past it is not consent. `olympus setup` is that command: it installs the launchd/systemd item itself, so this gate is cleared alongside the posture gate and before setup runs, not later in Step 4. - **Privacy classifier approval** (end of Step 3) — what the classifier sends and where, then the operator's own yes before you record it. - **Custom plugin UI opt-in** (Step 5, before the restart) — it lets every installed plugin, not only Olympus, run its own page code inside the Control UI with the operator's Gateway access. Its own ask; a no means the standalone dashboard link in Step 6. - **Gateway restart** (Step 5) — its own explicit go, never queued silently behind earlier consent. The go is about timing: the restart itself is required on every install. A "go" is an explicit, affirmative answer given in response to THIS gate's ask. Silence, an emoji reaction, a stale "sounds good" from earlier in the conversation, or a yes to a different question is not a go — re-ask. Momentum is the failure mode: a cooperative operator saying "ok" once does not put the rest of setup on rails. Every state-changing action needs its named gate cleared immediately before it: if you are about to change state and have not asked — and been answered — since clearing this action's named gate, you have already spent a consent twice; stop and ask. Interleaving unrelated questions does not reset anything — only clearing the named gate for THIS action does. ## Step 0 — Preflight Check, and tell the operator what is missing with the remedy: ```bash openclaw --version # need 2026.7.1+ (https://openclaw.ai) bun --version # need 1.2+ (curl -fsSL https://bun.sh/install | bash; no unzip or sudo: see "Installing Bun" below) node --version # OpenClaw 2026.9.5 requires >=24.16.0 <25 or >=26.1.0 ``` macOS or Linux. Do not continue until all three resolve. **`bun: command not found` usually means your PATH, not a missing Bun.** Bun's installer puts the binary in `~/.bun/bin` and adds it to PATH from the operator's shell rc — which a non-interactive agent shell does not read. So before you conclude anything is missing, check the install location directly: ```bash ~/.bun/bin/bun --version ~/.local/bin/bun --version # a user-prefix npm install (below) ``` If either prints a version, Bun is installed and nothing needs installing. Prepend that directory to PATH **for your session only** and continue: ```bash export PATH="$HOME/.bun/bin:$PATH" # or "$HOME/.local/bin:$PATH" ``` Do NOT re-run the Bun installer and do NOT edit any shell startup file to fix this — editing `.zshrc`/`.zprofile`/`.bash_profile` and friends is forbidden (Step 1, MUST NOT #8), and a reinstall over a working Bun is a state change the operator did not ask for. Only if both are genuinely absent do you report Bun as missing and ask the operator's go to install it. **Installing Bun without `unzip` or `sudo`.** Bun's official installer needs `unzip`, which minimal Linux images (Ubuntu server/cloud) lack, and the install user may have no `sudo`. Check `command -v unzip` first. If `unzip` is present, the official installer is fine. If it is missing, do not ask the operator to `sudo apt install unzip` or run any other `sudo` command: Node is already required, so on the operator's go install Bun yourself into a user prefix, which needs neither: ```bash npm install -g --prefix "$HOME/.local" bun export PATH="$HOME/.local/bin:$PATH" bun --version ``` The npm package fetches the real binary in an install script. If npm is set to `ignore-scripts=true`, `bun --version` fails after an apparently clean install; rerun with scripts allowed for this one package and check again: ```bash npm install -g --prefix "$HOME/.local" --ignore-scripts=false bun bun --version ``` `--prefix` keeps the install in the user's home, so a system-owned npm prefix never produces an `EACCES` that tempts a `sudo npm`. The npm package's real binary is `…/lib/node_modules/bun/bin/bun.exe` on every platform, with a `bun` link in `~/.local/bin`; that naming is expected, not a broken install. `olympus setup` accepts it: it records the `bun.exe` runtime for the worker service and adds the `~/.local/bin` directory holding the `bun` link to the worker's PATH. Never ask the operator to run a `sudo` command you can avoid. This matters past Step 0: `bin/olympus` is a Bun script, so every `"$OLYMPUS_BIN" …` call in this guide needs `bun` on PATH in the shell that runs it. Export it once per session, in the same shell. The Node range is OpenClaw's, enforced by an npm `preinstall` script that exits non-zero, and it moves between OpenClaw releases: read the current one with `npm view openclaw engines` rather than trusting the comment above. On a Node outside it (Node 22, 23 or 25, or 24.0–24.15 for 2026.9.5) the operator cannot install or update the host at all — say so plainly, because the failure looks like an Olympus problem and is not one. ## Step 1 — Install the plugin **Residue check first (Rule zero):** if this machine has ANY trace of a prior Olympus setup — including an already-installed olympus plugin the command below would update — and you have not already cleared the residue gate in this flow, STOP and run Rule zero before the commands below. ### Pilot download **Obtain the package yourself.** The operator needs only the installation prompt. Do not ask them to supply a tarball, a checksum receipt, or GitHub credentials. Download the designated pilot through GitHub's public release API without authentication: `https://api.github.com/repos/jamiezigelbaum/Olympus/releases/tags/v1.1.0` The repository guide pins the designated candidate below. These are agent-only verification inputs, not a receipt to request from the operator: - SHA-256: `b9ea7f219886dfd74a30bdbfadbc6a1c876795836a600325cf77ec80b9ac8372` - Byte count: `16134010` 1. Fetch that exact release as JSON over HTTPS. Require a successful HTTP response, `tag_name` equal to `v1.1.0`, `prerelease` equal to `false`, and `draft` equal to `false`. Do not use `/releases/latest`: a later release is not automatically this guide's candidate. 2. Select exactly one uploaded asset named `olympus-1.1.0.tgz` from `assets`. Require `state: "uploaded"`, a positive integer `id` and `size`, and a `digest` of the form `sha256:` followed by 64 hexadecimal characters. Its `browser_download_url` must be exactly `https://github.com/jamiezigelbaum/Olympus/releases/download/v1.1.0/olympus-1.1.0.tgz`. Require the metadata's digest and size to match the pinned values above; a replacement upload under the same tag/name is not a qualified candidate. GitHub's generated source-code archives are not the plugin package. 3. Download that asset into a new temporary directory, following HTTPS redirects to GitHub's asset storage. Compute its SHA-256 and byte count locally and compare both with the metadata from step 2. Do not extract, execute, or install an archive unless both match. Keep this verified local file for the entire install; do not download another copy between steps. 4. Record the release tag, asset ID, SHA-256, and byte count in the install report. This is automatic bookkeeping, not another operator question. These values satisfy any reference to a "supplied candidate and receipt" in an older packaged guide. Read `package/INSTALL_FOR_AGENTS.md` from this verified archive. From here, the packaged guide alone governs installation and setup, retaining the existing-install and consent checks. Execute its plugin install command exactly once; the command below is a reference, not an additional install. The repository guide on `main` owns candidate selection: skip any candidate-selection/download section in the packaged guide and use this already-verified local archive throughout. Do not switch to a stale tag or repeat the download because the packaged guide names one. If the release or asset is missing, say **"The Olympus pilot download is not available yet; the maintainer needs to publish it."** A failed request, missing digest, ambiguous asset, or checksum/size mismatch stops installation. Explain the download failure; do not ask the operator to fetch a receipt or log into GitHub, build a replacement, use a Git checkout, or select another version as a fallback. A network or rate-limit failure can be retried as a read-only download after reporting it. For the local comparison in step 3, use the downloaded file's absolute path: ```bash shasum -a 256 /absolute/path/to/olympus-1.1.0.tgz wc -c < /absolute/path/to/olympus-1.1.0.tgz ``` The expected digest and size come from the repository pin and fetched release metadata, never from the same local file you are checking. Reference command for the packaged guide's single install of those verified bytes: ```bash openclaw plugins install npm-pack:/absolute/path/to/olympus-1.1.0.tgz --force --accept-capabilities # ^ on OpenClaw 2026.7.1: --accept-capabilities does not exist, and --force # there means only "overwrite an existing plugin" — re-run with no flags openclaw plugins enable olympus ``` Two host flags, two different consents — check `openclaw --version` (Step 0) and pick accordingly: - **`--accept-capabilities`** is mandatory on OpenClaw `2026.8.1+`. Your install is non-TTY by definition, and the host offers the capability-consent prompt only to a TTY or to this flag, so without it the command exits 1 with `requires capability consent`. - **`--force`** is mandatory on `2026.8.1+` (confirmed on `2026.9.1`) for ANY non-ClawHub source, which a `npm-pack:` install is. Without it the host refuses non-interactively with `Install cancelled; rerun with --force after reviewing the source.` On these versions `--force` carries two meanings at once: "yes, I have reviewed this non-ClawHub source" and "yes, overwrite an existing plugin". **On `2026.7.1` the two flags are not symmetrical.** `--accept-capabilities` does not exist there — the host rejects it as an unknown option, so drop it and re-run without it. `--force` DOES exist on `2026.7.1`, but it carries only its original meaning, "overwrite an existing plugin"; the source-trust confirmation is not a thing on that version, so a clean-machine install needs neither flag, and passing `--force` there is a reinstall gated by MUST NOT #5. **What `--force` does and does not authorize here.** On `2026.8.1+`, on a machine with no olympus plugin installed, the flag is doing only the source-trust half: it confirms you reviewed the supplied package you were told to install. That is not the "`--force` reinstall" MUST NOT #5 gates, and you do not need a separate operator consent for it — but say what you are doing in your install report ("the host requires `--force` to accept a non-ClawHub source; nothing is being overwritten"). If Rule zero's checks found olympus already installed, the second meaning is live: the same command would overwrite that plugin. Then MUST NOT #5 binds in full — stop, surface the existing install, and get the operator's explicit consent to overwrite before you run anything. The `npm-pack:` prefix creates OpenClaw's per-plugin npm project and verifies the installed dependency shape. A raw archive/path install or Git checkout does not qualify these package bytes. Pilot testers and internal release qualification use the same candidate; a product fix needs a newly qualified candidate before an affected tester retries; the agent retrieves its identity automatically through the designated release metadata. `clawhub:olympus` becomes the one-line public install **after the pilot**, using the byte-identical qualified package. Until publication, `openclaw plugins install clawhub:olympus` fails with `Package not found on ClawHub.` Do not substitute it during the pilot. Success looks like `Installed plugin: olympus`. **Do NOT restart the gateway YOURSELF now, and do not restart it to "verify" the plugin loaded.** You still owe exactly one DELIBERATE restart and it comes at the end (Step 5). **Be honest about what the install itself already did.** On OpenClaw `2026.9.1` installing a plugin can make the gateway reload its plugin set on its own, and its boot line can list `olympus` among the loaded plugins long before Step 5. So do not tell the operator Olympus "stays dormant until one restart at the very end" — it is not true on this version, and they can read the log. What IS true, and is the part that matters to them: Olympus is registered but has no posture, no credentials and no sources yet, so it reads nothing and sends nothing. It stays inert until the operator connects a source in Step 6. Step 5's restart is still required, and not as ceremony: it is what makes the gateway load the plugin against the FINAL config — the posture, worker and credentials setup writes — so the agent-facing tools (`source_answer` etc.) come up against the configuration the operator actually approved. An early restart of your own just doubles the disruption (and, if you are running inside this gateway, strands you — see Step 5). Everything between here and there — setup, keys, and the worker — runs through the standalone `olympus` CLI, which does not depend on the gateway having loaded the plugin. **CLI exposure (canonical — do not improvise):** the standalone CLI is `bin/olympus` inside the installed plugin directory. Managed storage uses an internal directory name, so never hardcode the path. Resolve it from `openclaw plugins inspect olympus --json` → `plugin.rootDir`, which is the one command that reports the directory in full: ```bash OLYMPUS_ROOT="$(openclaw plugins inspect olympus --json | jq -r .plugin.rootDir)" OLYMPUS_BIN="$OLYMPUS_ROOT/bin/olympus" "$OLYMPUS_BIN" doctor ``` Do not try to read the path off the other two surfaces. On `2026.9.1` the install command prints only `Installed plugin: olympus` — no directory — and `openclaw plugins list` renders a table that truncates the path to fit the column. Both look like they answered you; neither did. If `jq` is not available, parse the same `--json` output some other way, but keep `plugins inspect` as the source. Do NOT expose a bare `olympus` command on the operator's machine by ANY mechanism — no wrapper scripts (in `~/.local/bin`, `workspace/bin`, or anywhere else), no symlinks into directories already on PATH (like `/usr/local/bin` or `/opt/homebrew/bin`), no shell aliases or functions, and no edits to any shell startup file (`.zshrc`, `.zprofile`, `.zshenv`, `.bash_profile`, `.profile`, fish config, `/etc/paths`, ...). Do NOT claim or imply the command is globally available — not "works from PATH", not "you can now just type olympus", not "available globally"; on a fresh machine it is not, and the false fact seeds drift in later sessions. Honest proof wording names the path and claims nothing more: "the `olympus` CLI is reachable at ``". Every bare `olympus ...` command in the rest of this guide is shorthand for `"$OLYMPUS_BIN" ...` — readability, not a claim that the name resolves on PATH. When a code block is for the OPERATOR to copy and run themselves, write the full resolved path into the block you actually hand them. **Operator mechanics — transition:** when you report the install result, do NOT name the preset ids and do NOT ask the operator to pick a posture in that report — "you'll need to choose: local-first, local-only, …" is exactly the bare menu MUST NOT #1 forbids. Preset ids appear for the first time inside the four-option walkthrough, never before it. And never end a message with a dead-end status line; every message hands the operator an obvious next move. The following is a **required user-facing transition**. Deliver it in full, changing factual status only to match the observed install; do not replace it with an abbreviated privacy question: > Olympus is installed. Quick proof: the plugin loads, and the `olympus` > CLI runs (reachable at its plugin path — I haven't touched your PATH or > shell setup). I haven't restarted anything myself; OpenClaw may have > reloaded on its own to pick the plugin up, so you might already see > olympus in its log. That only registers it — it has no posture, no keys > and no sources yet, so it isn't reading anything of yours and won't > until we connect a source together. There's one deliberate gateway > restart at the end of setup, and I'll warn you before it happens. > > Next comes the part that actually matters: before Olympus touches any of > your data, you and I make two decisions together — what counts as > sensitive *for you*, and which models are ever allowed to see it. It's a > short conversation, not a form. Ready? ## Step 2 — Privacy posture (MANDATORY DECISION GATE) **Residue gate (run this check FIRST — before any setup command and, per Rule zero, before ANY state-changing action):** a real operator's machine is never clean. If you have ANY prior knowledge or traces of an earlier Olympus setup — notes in your own memory or bulletin files, an existing `~/.olympus` or `~/.config/olympus`, credential-store items for any provider Olympus connects (venice, gemini, google and its `gog` helper, plus any Step 6 provider — Dropbox, X, Readwise — illustrative, not closed; probe read-only by provider/service name, e.g. `security find-generic-password -s ` WITHOUT `-w`, so a secret's value is never printed; nothing there will say "olympus", which is exactly how a lazy check false-negatives), OAuth grants from other tools, a previous session's summary telling you setup is "done" — you must SURFACE what you found to the operator and ask, before writing anything: restore the previous setup, or start fresh? (If the only traces are provider credentials with no Olympus config, worker, or notes, there is no setup to restore — surface them and proceed fresh; the per-credential gates cover reuse.) Notes left by a previous agent or session are NEVER operator consent (MUST NOT #7). And "restore" is not a bypass: the posture conversation, per-credential consent, and the worker pre-explanation before setup still run — restoring fills in remembered *answers*, it does not skip the *questions*. If a credential you are about to reuse carries a recorded caveat (for example "rotate this key before treating it as clean"), surface the caveat and let the operator decide; silently discarding it is a security failure. The gates named here are examples, not an exhaustive list: EVERY decision gate in Steps 2–6 — the tier explainer, the privacy conversation, the posture choice, per-credential consent, the worker pre-explanation — runs on the restore path exactly as on a fresh one. Pre-filled, though: on restore each gate is a confirm-or-change of the remembered answer — not a from-scratch re-interview. And this gate is not scoped to Step 2: per Rule zero, it runs before EVERY state-changing action of ANY install, update, or maintenance request on a machine with traces — reaching Step 2 is not what arms it. **Existing installs with indexed data.** Updating does not move items that were stored before per-item tiers; they stay where they are until the owner migrates them. `olympus tier migrate plan` is a dry run (no provider fetch, no model call) that reports the proposed moves, embedding cost and time. Every later step (`approve`, `run`, `rollback`, `purge`) is a separate owner decision on that plan: show the plan, and run each step only on the operator's explicit go. A fresh install has nothing to migrate. This is the one decision that matters and it belongs to the operator. You must NOT silently accept a default — and you must NOT present the presets as a bare list of names. A new operator has no idea what a preset id means. **The walkthrough below is part of the gate**: explain, in plain language, what each posture means for THEIR data, what it requires, and its trade-off — then ask. Preserve the full explanation below; do not compress it to a menu. **No pick-list before the explanation — question tools included.** Never ask the posture as a multiple-choice question, a pick-list, or a choice in a question tool (OpenClaw's Ask User tool, a button prompt, or similar) until all three have happened in chat, in this order: the required tier explanation below was delivered in full, the privacy conversation ran and the operator confirmed what you read back, and the four-option posture walkthrough was delivered in full. A question tool is a way to collect the answer after that, never a substitute for it. When you do use one, each option label is the plain-language description from the walkthrough (for example "Venice — Private content goes only to Venice"), never a bare preset id and never a compressed menu such as "Local, cloud, local only…". **Required user-facing tier explanation.** Deliver this entire block before asking any privacy or posture question. The point of each tier is what happens *differently* to data in it — never present a tier as a bare list of category examples. This message both explains the model and opens the privacy conversation: > Here's how Olympus treats your data — then you'll tell me about your > preferences. > > Olympus sorts everything it indexes into three tiers: > > **Personal** — ordinary personal and work life: schedules, newsletters, > routine email, most projects, and anything you've published. Your > assistant's regular models can reason over this — the same models you'd > paste it into today. > > **Private** — the things you'd only tell someone you trust: health, money, > legal matters, therapy, your family. This tier is the reason Olympus > exists. It never goes to ordinary cloud models, full stop. What *can* > happen with it is the one big choice you'll make in a few minutes: > answered on your own machine, answered by a privacy-focused private > cloud, or kept out of Olympus entirely. > > **Secrets** — passwords, API keys, recovery codes. No model ever sees > these, in any lane. Olympus will only ever tell you *where* a secret > lives, never what it says. > > Two rules are hard-wired and not up for configuration: Private data never > touches ordinary cloud models, and when Olympus isn't allowed to answer > something, it tells you so instead of quietly downgrading your privacy to > get an answer. > > The tiers are fixed, but what goes *in* them is personal — one person's > "eh, whatever" is another person's Private. So tell me about your data: > what do you want your assistant to know about, and what are you > protective of? Talk normally — I'll read back what I heard, and once > Olympus is running we'll put it in your Privacy settings together. **Operator mechanics — the privacy conversation.** Iterate on that conversation, voice-friendly, until the operator confirms. Its result is the operator's **privacy profile**, the only privacy configuration Olympus reads (the legacy sensitivity map file was retired on 2026-10-03; do not write `~/.olympus/sensitivity-map.json`, nothing reads it). The profile is saved later, in Step 6, from the dashboard's **Privacy** section (or ChatGPT's `olympus_privacy_set`): the owner's own words for "What's private for you?", plus folders, Gmail labels and senders that are always Private. Per-source choices also live there and in the source pickers: which folders Drive and Dropbox may read, and Gmail's mail window, skipped categories and labels, and "always Private" and "skip" senders. Nothing is written in this step. Help the operator untangle two different questions: - where data is stored today - which models may read or reason over it through Olympus Use this example if helpful: Gmail already lives on Google's servers. The Olympus question is not "does Google store this email?" The question is "may models reason over the therapy thread inside Gmail, and if so only in which lane?" Reflect back what you heard before moving on — in sentences, in the operator's own words, never as a `tier: item, item, item` cram-list: > Here's what I heard. Day-to-day email, calendars, work projects, and > your blog and anything you've published are Personal — your regular > assistant keeps working with those like it does now. > Anything about your health, your finances, and your kids gets the > Private treatment we just talked about. And passwords or keys — no model > ever sees those. Did I get that right, and is there anything you'd move? Keep revising until the operator says yes. Default categories to **Private** unless the operator explicitly says **Secrets**. Olympus judges every item twice: its names (title, path, subject, sender, labels) are Personal unless something raises them, and its content is judged separately and raised to Private or Secrets on evidence. Secrets are found by the secret detector; there is no "always Secret" setting. Keep a short note of the confirmed answer for Step 6: the description in the operator's words, and any folders, labels or senders they named as always Private. Only after the operator confirms, ask the posture question. **Do not lead with a recommendation.** A recommendation must come from the operator's own answer, so first ask: > Do you run local AI models on this machine — or want to set that up? This moment — not earlier — is when local models enter the conversation. Do not mention machine checks, detected runtimes, or postures during the tier explainer or the privacy conversation; an unprompted "I checked this machine for Ollama" lands as a non sequitur. If you detected a local runtime, it is a conversational observation to verify aloud HERE — "I noticed this machine is already serving a local model; do you actually use it?" — never a silent basis for recommending a posture. But be strict about what counts as detection. **An installed plugin is not a runtime.** OpenClaw ships a built-in `llama-cpp` provider plugin, so "there is a llama.cpp plugin" is true on a machine that has never run a local model, and treating it as a cue recommends `local-first` to someone with nothing to serve it. The only thing worth reporting is a running OpenAI-compatible HTTP server actually answering on the ports Olympus's local lanes are configured to use — the answer endpoint and the embedding endpoint (both shipped `local-first`/`local-only` profiles use `http://127.0.0.1:28090/v1`, with distinct model IDs). Read the effective policy and probe its endpoints and models, and if nothing answers, you detected nothing: ask the question above with no preamble. Use their answer to mark which option below is recommended for them, then present all four. The operator has likely never heard of Venice, so introduce it once, before the options name it: Use these display labels in conversation and setup summaries. Preset IDs in parentheses are command values; keep those IDs in commands and configuration. The setup result also supplies `presetLabel` for its human-facing name. > Two of these options use Venice (venice.ai) — a privacy-focused AI > cloud. What it offers is a provider that does not train on your > conversations or retain them the way an ordinary cloud model does. > Being straight with you about the limit, because it matters for the > tier we just discussed: this is Venice's privacy policy and > infrastructure, not encryption that would make it impossible for them > to read a question. Olympus does not provide or qualify > end-to-end-encrypted inference in this version. > > How do you want to handle your Private data? > > 1. **Local models with Venice fallback** (`local-first`) — recommended if > you run local models. Private questions are answered on your own > machine first; Venice is the approved second step when the local lane > cannot answer. Requires: a local runtime with lots of fast memory — > MLX, llama.cpp, Ollama, LM Studio and similar expose the local endpoint > Olympus uses — plus a Venice API key (pay-as-you-go). Search indexing > uses the model built into Olympus: no key, nothing leaves the machine. > Trade-off: strongest owner-controlled first step, with private-cloud escalation available; > speed and first-pass quality depend on your machine. > > 2. **Local models** (`local-only`) — Private questions are answered > only on your own machine. Venice is not used. Requires: the same local > runtime with lots of fast memory. Search indexing uses the model built > into Olympus. Trade-off: no > Private-tier cloud escalation; if the local lane cannot answer, Olympus reports the gap. > > 3. **Venice** (`private-cloud-only`) — recommended if you do > not run local models. Private content goes only to Venice, on its > Private model path — `kimi-k3` for answers. Search indexing for every > tier uses the model built into Olympus, on this machine. Requires: a > Venice API key (pay-as-you-go). Private content never goes to Gemini; > a separately approved Venice Private embedding model stays an opt-in. > Trade-off: no local-model requirement > or local fallback; you are choosing a privacy-focused cloud provider > for Private answers and embeddings, on that provider's word rather than on > encryption. > > 4. **Private meaning search on this computer** (`no-sensitive`) — Olympus > stores Private items and finds them by meaning on this computer using > the built-in embedding model, and keeps their search vectors here. > Ask privately and the sealed ChatGPT panel can use them; no Private > agent answer lane is set up. When a question touches health, > finances, or legal matters, the answer says Private sources were not > searched instead of answering from them. Requires: > nothing; Personal and Private content is indexed by the model built > into Olympus. Standalone default-path policies with the shipped 1.0.0 Private retrieval > block and built-in local embedding profile switch at engine start with a > dated backup; other settings are preserved. Gateway-pinned policies are never rewritten. > To stay keyword-only, set `retrieval.trustDomains.secure_local.activationMode: lexical_only`; this is never re-migrated. > Trade-off: Private sources need the local panel until you add an agent answer lane. > > You can change this later — it's a config file, not a commitment > (`olympus sovereignty init --preset `). **Lead with the recommendation (adaptive ordering).** The numbered order above is the neutral default. The moment the operator has told you something that makes one posture the clear fit — "I can't run local models" makes it `private-cloud-only`; "nothing sensitive ever leaves this machine" makes it `local-only` — put THAT option first, opening with why it is recommended for them, in one sentence, in their own terms. Then present the remaining options beneath it, framed as alternatives: "here are the others, in case one fits better or you change your mind later." Never leave the recommended option buried mid-list with only a "recommended" tag — the shape of the list is part of the guidance. Ask which posture fits how they feel about their most private data, answer their questions, and record the choice. **Now clear the second gate, before you run setup.** `olympus setup` does not only write config: it registers the background worker service (launchd on macOS, a user systemd unit on Linux) and writes the worker environment file. That is the Rule one worker-registration gate, and running setup spends it — so it is asked HERE, not in Step 4. macOS will show a "Background Items Added" notification the moment setup runs, and an unexplained notification on the operator's own machine reads as something being done TO them. One sentence first (adapt the words), then their yes, then the command: > Next I'll run setup. Two things happen: it writes your privacy policy > from the choice you just made, and it registers the sync worker — a > background service on this machine that keeps your sources indexed. > macOS will show a "background items added" notification when I do; > that's this, nothing else. You can see or remove it anytime under > System Settings → General → Login Items, or with `olympus worker > uninstall`. Then, and only then: ```bash olympus setup --preset --cloud-lane subscription --yes ``` `--cloud-lane subscription` answers Personal questions with OpenClaw's own configured default model and its existing auth, through `openclaw infer`. It names no model and needs no extra key, and setup puts the `openclaw` directory on the worker's PATH. Do not pin a model the operator did not ask for. **Reading the summary: an honest gap looks like a leak until you know the shape.** On `no-sensitive` the summary and later `olympus doctor` output still show the sovereignty policy with `secure_local` at `"mode": "disabled"` and an empty pool. That is `no-sensitive` working: Private items are searched by meaning on this computer, but no agent answer lane exists, so Olympus can say honestly that Private sources were not searched for the agent, and it is routed nowhere. Do not report it to the operator as a problem, and do not try to "fix" it by adding a lane they did not choose. ## Step 3 — Model setup in the dashboard **Model keys are entered in the dashboard, not collected by you.** In the normal browser flow do not ask for, fetch, or store a Venice or Gemini key — not in chat, not through OpenClaw's own secret prompt or store, and not through an Olympus terminal prompt. A missing model key at this point is expected and never blocks the handoff. The operator pastes each key into its card on the dashboard's **Keys** page, which validates it and stores it privately. Use the headless fallback below only when the operator explicitly asks for a setup without the browser dashboard. For the normal browser flow, skip the headless fallback below but first complete the [privacy classifier approval](#privacy-classifier-approval--its-own-consent-gate) at the end of this step; it applies in both flows. Then continue through base-worker and Gateway activation in Steps 4–5, and hand over the dashboard in Step 6. Do not require keys to be present before that handoff: the operator enters them on **Keys**. Connect validates and stores the key privately. After all required keys are saved, the managed worker applies them automatically; wait for the model cards on Keys to show Ready. Source buttons remain disabled until then. Local-model users choose **Connect existing local models**, follow the concrete agent prompt, and use **Check readiness** after their configuration is applied. ### Headless credential fallback — only when explicitly chosen The terminal/password-manager instructions in this subsection apply only when the operator chooses a headless workflow; the privacy classifier approval after it applies to everyone. They are not the normal browser installation path. **Code-block contract:** a code block in your message means exactly one thing to the operator — "copy this and run it yourself." Show one only when that is what you want, and show only that block. Commands YOU will run (like the stdin connect below) are described in a sentence ("I'll connect the key so it never touches logs"), never displayed as a copyable block. Two code blocks where one is the operator's and one is yours is a guaranteed source of confusion. Each credential here is its own Rule one gate: explain it in one plain sentence, ask, connect, then move to the next — never sweep the list and report "your keys are set up" after the fact. **Model readiness before keys.** Follow the packaged [agent-led model setup guide](docs/SOVEREIGNTY_CONFIG.md#agent-led-model-setup-for-the-v04-beta) before this step. It separates Gemini Personal embeddings, local Private embeddings, Venice Private reasoning, and the approved Venice Private embedding fallback when no local provider is configured. The worker uses registered dimensions for shipped models when there is no override (Gemini Embedding 2: 3072; registered local embedding model: 2560; Venice Qwen3 Embedding 8B: 4096). Do not add a dimension flag or edit `worker.env` for those defaults. An unknown model still needs a verified explicit dimension; report unsupported custom configuration rather than inventing flags or declaring readiness from key validity alone. Older packages with the shipped-model missing-dimension startup error need the qualified fix, not another credential read. The guide also covers creating the user's provider accounts and API spending limits; the operator completes sign-in, terms, purchases, and billing changes. **Credential sourcing — choose the method before requesting a reference.** Ask where the operator keeps the key and offer these two supported routes: - **Manual web route:** the operator opens their password manager's website and pastes the key themselves into a supported local dashboard field or the built-in masked terminal prompt described below. No shell function or helper script is needed. No password-manager desktop app or CLI is required for this route. Never ask them to paste the key into chat. - **Authenticated CLI route:** if they want the agent to fetch the key, verify that their manager CLI is installed and authenticated first. For 1Password, an `op://vault/item/field` reference works only with authenticated `op` access; a signed-in website alone does not supply that access. The operator may configure CLI authentication using its supported procedure or choose manual paste. Do not require a desktop app for the manual route or promise that an `op://` reference alone is usable. Once they choose CLI access, obtain the exact item/field reference and approval for this credential, then fetch once directly into the stdin connect flow. Do not list or search their vault to find it. Pasting is equally supported; knowing where a credential lives never authorizes fetching it. Hard limits: - The operator supplies the exact item name or reference; if you do not have it, ask. Fetch ONLY that named item, after their yes. Never enumerate, list, search, or dump a vault's contents — not even to "see what's available" — and never probe candidate names until one resolves: serial named reads to discover what exists ARE enumeration. (This bans content discovery in the operator's vaults; it does not touch the Rule zero / Step 2 residue probe, which is a value-less presence check of specific provider service names and stays required.) - A fetch reads the value — for the Keychain that means `security find-generic-password … -w` — and the value goes STRAIGHT into the documented stdin connect flow, never to a terminal, log, file, or chat (MUST NOT #2). Do not type or inject a fetched value into any UI field yourself, browser control included: dashboard fields are for the operator's hands; your only path is stdin. (The consented `-w` fetch is distinct from the `-w`-omitted residue probe, which never reads values.) - Caveats: anything you already hold about the credential (a memory note, a prior session's "rotate before reuse") is surfaced BEFORE the fetch. If the fetched item itself carries a caveat in its notes, surface it and re-confirm before connecting — the note is not the secret, but the value still never appears in chat. - "The manager" here means the operator's personal password manager, not Olympus's own encrypted secret store — the worker's normal secretRef resolution at boot is the product working as designed. 1Password service accounts have a small DAILY read quota shared by everything on the machine: fetch once per credential, and never put an `op read` (or any manager read) inside anything that retries or restarts; the worker env is written once at setup and workers must not re-read the manager at runtime. - If the operator prefers to paste, that is their call: the dashboard field and built-in masked prompt remain the paste paths, and secrets never go through chat. Setup prints `unmet_prerequisites` with an exact remedy per item. In the normal browser flow a missing Gemini or Venice key there is expected: report it as "finished on the dashboard's Keys page" and continue. Follow the key remedies below only in the headless fallback. Typical items: - Gemini API key (only when the operator opted into Gemini embeddings instead of the built-in model; headless fallback only): ask the operator to obtain a key from https://aistudio.google.com and provide it (or source it per the credential-sourcing rule above). Connect it via stdin, exactly like the Venice key, so it never reaches shell history, a log, or a chat message (you run this; do not show it as a copy block): ```bash printf '%s' "$KEY" | olympus connect gemini --api-key-stdin ``` The pipeline above is for the authenticated password-manager route only. For manual entry, resolve the installed executable yourself and give the operator one command, using its actual absolute path: ```bash "$OLYMPUS_BIN" connect gemini --api-key-prompt ``` Substitute the resolved path before handing this to the operator; do not ask them to discover `rootDir` or define `$OLYMPUS_BIN`. Run it in a real terminal on the machine hosting Olympus, under the same user as the worker. For a remote host, identify that host and account explicitly and use the operator's existing SSH access; do not tell them to run a remote path on their laptop. An agent's captured terminal is not a user input surface unless it genuinely hands control to the operator. Never provide a heredoc, `read -rs` function, regex redaction wrapper, or generated helper script. The command reads from the controlling terminal with echo disabled, rejects malformed input, waits again on an empty Enter, and restores terminal settings when it exits. The key is never an argument, environment variable, or chat message. The command itself is the remedy setup prints for this item, verbatim. The command validates the key against Gemini before storing anything, writes it into the worker environment as `OLYMPUS_SOURCE_INDEX_GEMINI_API_KEY` at mode 600, and tells you to `olympus worker restart` so the running worker picks it up — do that, and re-run doctor afterwards. Do NOT hand-edit the worker's env file to add the key: `worker.env` is a generated managed file this guide forbids editing (see Step 4), and an `export GEMINI_API_KEY=…` in your shell dies with your session and is never seen by the background worker. Two refusals you may meet, neither of which you may work around by editing the file: the command needs the worker environment to exist (`No Olympus worker environment exists at …` — that means setup has not run yet), and it refuses a key containing a single quote (`… value must not contain a single quote.`), whose remedy is the one the error gives — rotate the key at the provider and store one without a quote. - Venice API key (`local-first` or `private-cloud-only`; headless fallback only): follow the [Venice account and API setup](docs/SOVEREIGNTY_CONFIG.md#venice-create-an-account-with-api-access) instructions. The operator needs a usable API balance and an Inference Only key with an agreed consumption limit; a chat subscription alone is not proof of API readiness. For manual entry, give the resolved equivalent of `"$OLYMPUS_BIN" connect venice --api-key-prompt`; the same terminal rules above apply. For an authenticated manager pipeline, connect via stdin (you run this; do not show it as a copy block): ```bash printf '%s' "$VENICE_API_KEY" | olympus connect venice --api-key-stdin ``` Re-run `olympus doctor` until the `sovereignty_prerequisites` check is green (or explained and accepted by the operator). Doctor's exit status is the signal: a red walk exits 1 and writes a summary to **stderr** in this shape — ``` olympus doctor: N of M checks passed, K failed. Failed: email_worker, worker_credential_lanes, source_index_status Fix the failed checks and run olympus doctor again; the JSON above carries each check's detail and hint. ``` — all three lines, every time, while the full JSON stays on stdout unchanged. Branch on the exit status, never on the counts; exit 0 means every check is green. `M` is doctor's whole check list — 15 on a current build, on a fresh install as much as a loaded one — so read the number off the line rather than quoting one you remember. **`sovereignty_prerequisites` is the check to watch for the Gemini key, and it really does evaluate.** Doctor resolves the same policy file every other path uses — `~/.olympus/sovereignty.json` by default, or `OLYMPUS_SOVEREIGNTY_CONFIG` / an explicit config path — so once setup has written the posture, this check runs the same preflight setup ran (minus the local-model-server probe, which `sovereignty_model_lanes` owns) and names each unmet prerequisite with the exact remedy in its `hint`. It goes green with a `Skipped: no sovereignty policy is configured for prerequisite checks.` detail only when there is genuinely no policy to read; on a fresh install that has run setup, a `Skipped:` here means something is wrong with the policy path, not that the prerequisites are met. Doctor also reads the config the managed worker actually runs with — `worker.env` layered under the environment, and the config that layered environment produces — so `source_scheduler_status` and the email and sovereignty gates no longer report a value `worker.env` has already overridden. **One missing key turns three checks red at once. Read that before you report "broken."** `email_worker`, `worker_credential_lanes` and `source_index_status` all interrogate the same worker, so a single missing Gemini embedding key fails all three together. That is ONE problem with three symptoms — the fix is the one connect command above, not three investigations. The discriminator is whether the worker answered, and what it said: - **One missing key (expected on a fresh install).** The worker answered and says what is wrong: `email_worker` reports `Email worker is running in degraded mode: …`, `worker_credential_lanes` reports `Worker credential lanes are degraded: …`, `source_index_status` lists the same credential among its problems, and the status JSON carries an `embedding_lane` of `{"state": "embedding_lane_disabled", "reason": "embedding_provider_unavailable"}`. All three name the SAME credential. In the browser flow it is finished in the **Models** card and the worker applies it; in the headless fallback, connect the key and run `olympus worker restart`. Re-run doctor — the three go green together. - **No source connected yet (expected).** A healthy worker passes base-install health with zero sources. Mailbox configuration is not worker readiness; the repaired Doctor no longer marks `email_worker` red just because the operator has not selected Gmail. A connected source with unhealthy status, an unreachable worker, or degraded credentials remains a real failure. - **Real breakage.** The worker never answered: the details read `… is not reachable at http://127.0.0.1:8010/v1: ` and the hint is `Run olympus worker status, then olympus worker start or olympus worker install.` No credential is named, because nothing could be asked. Go back to Step 4 and get `service.state` to `active` first; the credential checks say nothing until the worker answers. Report this to the operator as what it is — "one key is still missing, and three checks are reporting the same gap", or "no mailbox is connected yet" — never as a count of failures. **Translate doctor output; never leak lane jargon.** "Argus" is Olympus's internal name for the analyst that serves the Private tier (local models or Venice, per the posture) — operators have never heard it. If the operator's posture has no local lane, say nothing about Argus, local models, or local endpoints: a "note about local models" to someone who just said they don't use local models reads as an error. Mention local lanes only for `local-first`/`local-only` postures, in plain words ("your local model isn't reachable yet"). ### Privacy classifier approval — its own consent gate This applies in both the browser and the headless flow, after the posture and model choices above; a browser-flow agent arrives here straight from the opening of Step 3. Olympus decides most tiers with rules on this machine. For an item whose names look possibly private, it asks a privacy-safe model, the privacy classifier, whether the item is Personal or Private before it is embedded. The classifier does nothing until the operator approves the exact lane, model and prompt version. Read what it would use (you run this): ```bash olympus tier classifier status ``` It reports `lane` (`local` or `venice`), `profile`, `modelId`, `approved` and `decision`, or `lane: null` with a `refused` reason. On `no-sensitive` the reason is `no_private_lane` and `decision` is `not_applicable`: there is nothing to approve, so skip this gate and do not explain or ask about the classifier. Its only mention is the one Step 6 summary line, "Privacy classifier: not applicable (no-sensitive)". Any other refusal (`standard_cloud`, `unsupported_provider`, `outside_private_policy`) means the policy names a classifier model Olympus will not use for possibly-private material. Report it to the operator in plain words ("the policy names a model the privacy classifier may not use, so it stays off"), do not ask for approval, and do not edit the policy to make it pass; flagged items stay held as Private. When a lane is reported, explain it in these terms, naming the actual lane, and ask: > One more privacy choice. Olympus sorts most of your items with rules on this > machine. When an item's name looks like it might be private — a word from > something you named as private, or a sensitive-sounding file or folder name — it asks > a private model to decide Personal or Private before indexing it for > search. It sends one item at a time: its title, folder path and folder > names, labels and sender, and, when the content itself looks sensitive, a > short excerpt: up to the first 1,200 characters of its text. Anything that > looks like a password or key is never sent. The model is on this machine | Venice's private model, off this machine, under Venice's > privacy policy>, never an ordinary cloud model. If you'd rather not, those > items stay Private until you approve, and meanwhile they are found only by > keyword search. Shall I turn it on? `local-first` normally uses the local model. If status shows `venice` there, a classification profile is declared, and the operator must hear that names leave the machine. On a yes, record the approval with the operator's reason in their own words: ```bash olympus tier classifier approve --why "" ``` A no is a complete answer: do not argue or re-ask. Record it, so the receipt can tell a no from a question never asked (the reason is optional): ```bash olympus tier classifier decline --why "" ``` A later change of model, lane or prompt stops the classifier until the operator approves again. Either way, `olympus tier classifier status` then reports `decision` as `approved` or `declined`; `not_asked` means this gate has not been cleared. The Step 6 completion receipt reads that field, so this gate cannot be skipped on the way to the handoff. ## Step 4 — Verify the worker Separate base activation from model readiness. A running worker and reachable dashboard are enough to hand over the dashboard and its Keys page. Missing model credentials are pending dashboard work, not a reason to loop through terminal commands or reinstall. Source ingestion remains gated until Models is ready. **This step verifies; it does not install.** `olympus setup` in Step 2 already registered the background service, wrote `worker.env`, AND started it. Setup's own output says so, under `worker`: `worker.state` is the state the service manager reported when setup returned, `worker.next` is the step that state calls for, and `worker.activation_detail` appears only when the start did not take. On the healthy path `worker.state` is `active` and `worker.next` reads `The managed worker is running; open Olympus in OpenClaw. Use olympus dashboard for standalone access.` Read those three fields before you run anything here — they usually make this step a confirmation. Also check setup's `ok` and `worker.activation`: a failed start or policy restart exits nonzero with `ok: false` and `activation: failed`. An old worker may still be `active` after a failed restart. Do not call the new privacy posture applied in that case; report the failure and follow `worker.next` within the existing repair authorization. That is why the background-items consent gate lives before setup and not here. Do not run `olympus worker install` as a FIRST install: by now there is nothing to register, and treating this as the registration moment is how the consent gate ends up asked after the notification has already fired. The ban is on treating `worker install` as the registration step; as a repair of the service your own setup wrote, it is idempotent, documented, and allowed — see the remedies below. **Residue check first (Rule zero):** if the service or plist on this machine is NOT the one your own setup just wrote — a pre-existing unit, a disabled one especially — stop and run Rule zero's gate before starting, enabling, re-enabling, or restarting anything here. ```bash olympus worker status ``` **The field you are verifying is `service.state`, and it must say `active`.** The service facts are nested under `service`, so on a healthy fresh install `service.state` is `active`, `service.unit_present` is `true`, `service.env_present` is `true`, `lifecycle_transaction.state` is `none`, and the top-level `recovery` list is **empty** — a fresh install has nothing to resume, and a recovery list naming sources nobody has connected would be the old bug, not a finding. **Do not read the top-level `ok` as "the worker is up."** `ok` is false only for `failed` and `unknown`, so a registered-but-stopped worker reports `ok: true` with `service.state: inactive`. Read the state. If you get `service.unit_present: true` with `service.state: inactive`, the service is registered but not running. Do not read that as a failed install and do not reach for `worker install` first — the remedy is one command: ```bash olympus worker start olympus worker status # confirm service.state: active ``` `olympus worker start` polls the service manager for up to 15 seconds before it decides, and a worker already answering its own loopback health route gets the last word — so the state it prints is the settled state, not a race with `launchctl kickstart`, which returns when the job is submitted rather than when the worker is serving. When a start genuinely does not take, it refuses in this shape, carrying the worker's own last log line: ``` olympus worker start completed but status is inactive. The worker's last log line was: ``` with the remedy `Read the worker log at and , then run olympus worker status and follow its recovery action.` (on macOS both paths are under `~/Library/Logs/Olympus`). Read the log before changing anything — the reason a worker exits at boot is one line away, and a missing Gemini key is a common one. In the browser flow a missing key is not yours to supply: the operator pastes it into its **Models** card in Step 6; only the headless fallback uses the Step 3 connect command. Only if `start` still leaves it `inactive` or `failed` do you reach for `olympus worker install`. It is idempotent, it writes nothing over an already-active service, it recovers an interrupted managed-file transaction, and re-running it over the service your own setup registered is a repair rather than a new background item — so it needs no fresh background-items consent. It is also what setup's own `worker.next` names when its start did not take (`Run olympus worker install, then olympus worker status.`), and `worker.activation_detail` carries the same `completed but status is …` sentence with the same log line. Two things that look wrong here and are not: with no sources connected yet the scheduler is **enabled and idle**, which is the healthy fresh-install state and leaves doctor green; and the dashboard probe reports reachable, because it asks the worker root for `/dashboard.json` rather than the `/v1` API base. If status names an interrupted transaction, it also names the exact next action; re-running `olympus worker install` is the documented recovery for that case too. Use only the public worker lifecycle: `install`, `start`, `stop`, `restart`, `status`, `foreground`, `upgrade`, and `uninstall`. Install and upgrade are idempotent and recover interrupted managed-file transactions when rerun. Do not pass secrets, environment paths, or executable overrides on the command line, and do not edit generated service units or `worker.env` directly. Credential, scope, pairing, Disconnect, partial-sync, and missing source-dependency repair normally uses the source-specific recovery action without restarting the worker. `worker uninstall` retains user data; `data delete` is the separate destructive boundary. The registered service is a launchd/systemd item with restart-on-failure. If the operator would rather watch it run in the foreground for a first session, `olympus worker foreground` runs it in a terminal they control — stop the background service first so the two do not race. ## Step 5 — Validate, then restart the gateway (in this order) **Hermes MCP-only:** skip the native OpenClaw Gateway activation and restart paragraphs in this step. An OpenClaw Gateway is not required for Hermes to use the Olympus worker. Follow the Hermes MCP instructions below, verify an actual MCP status call, then use the standalone opening-link handoff in Step 6. **This restart is required on every OpenClaw install. Do not skip it and do not tell the operator "no restart needed."** Olympus already appearing in the boot line, `plugins inspect` reporting `loaded`, or tools already answering does not remove it: those can all come from the host's automatic reload at install time, before setup wrote the posture and worker config. The plugin now reads the worker token on every request, so a skipped restart no longer shows up as `401` errors, which makes skipping it look harmless. It is not: this restart is what loads the plugin against the configuration the operator approved, and it activates the native dashboard settings below. Ask for the go, and if the operator wants to wait, installation is not complete until the restart runs. Resolve the selected dashboard's prerequisites before this restart. If the artifact declares native Control UI support, check its browser/transport compatibility and Gateway origin described in Step 6 now. Apply only authorized settings through the host's supported configuration workflow; do not discover these settings only after restarting and handing off. **Custom plugin UI opt-in (its own Rule one gate, before the restart).** The native Olympus page needs OpenClaw's Custom plugin UI setting, which is off by default: **Settings → Labs → Custom plugin UI** in the Control UI, or the equivalent Gateway setting `gateway.controlUi.experimental.customPlugins: true` ([OpenClaw docs](https://docs.openclaw.ai/plugins/feature-plugins)). Confirm the key with `config.schema.lookup` on the installed host and read its current value. If it is already on, there is nothing to ask. Otherwise explain it in plain words and ask: > Olympus has a page inside OpenClaw's Control UI. To show it, OpenClaw has a > setting called Custom plugin UI. Turning it on lets every plugin you have > installed, not only Olympus, run its own page code inside the Control UI, > with the same access to your OpenClaw Gateway you have when signed in. It's > off by default. Shall I turn it on? If not, I'll give you a separate > Olympus dashboard link instead. On a yes, set it yourself with `openclaw config set gateway.controlUi.experimental.customPlugins true`, but only as the restart below: once that restart has its own go and `openclaw config validate` is green. OpenClaw's docs say the key applies without a restart, but on 2026.9.5 setting it makes the Gateway restart itself (a config-reload restart), and that self-restart is this step's restart. Do not follow it with `openclaw gateway restart`; wait until `openclaw gateway status` shows it running again, then run the post-restart checks. The in-gateway warning below applies to this `config set`, since the chat drops right away. If the key was already on, restart normally. On a no, record nothing, leave it off, and use the standalone opening link in Step 6: never hand the operator a Labs instruction as a caveat in the final reply. **Residue check first (Rule zero):** never run this restart to activate a configuration the operator has not consented to in this flow; on a machine with prior-setup traces the gate must already have been cleared. **The restart is its own consent gate (Rule one):** it gets its own explicit go from the operator, every time — never queued silently behind earlier yeses, and never bundled into "finishing up." **If you are an agent running INSIDE this OpenClaw gateway** (an OpenClaw chat agent rather than an external CLI agent): restarting the gateway ends your own session mid-turn. Before running the restart, tell the operator exactly this — "the next command restarts the gateway and this chat will drop; when it's back, message me: *continue the Olympus install from Step 6*" — or hand the operator the three commands below to run in their own terminal (on the Custom plugin UI yes path, the `config set` above replaces the last one: hand them validate, lint and the `config set`, never a second restart). The same applies to any gateway restart during Step 1's plugin install. Never restart the gateway without a green validate: ```bash openclaw config validate openclaw doctor --lint openclaw gateway restart ``` **Only `openclaw config validate` is the gate.** It must exit green; if it does not, stop and fix the config before restarting (MUST NOT #3). `openclaw doctor --lint` is a report you read, not a gate you must clear. It lints the operator's whole OpenClaw install and routinely exits 1 on pre-existing warnings that have nothing to do with Olympus — another plugin's config, a deprecated key, an unrelated agent. Findings that are not about Olympus are **reported to the operator and left alone**: do not fix them (you did not cause them and nobody consented to those changes) and do not let them block the restart. A lint finding that IS about Olympus is a different matter — treat it as a real defect and resolve it before restarting. After the restart, verify the plugin actually loaded. The honest checks are: - the gateway boot line names olympus among the loaded plugins — read it where it actually is, see below, and - `openclaw plugins inspect olympus --json` reports `"status": "loaded"`, and - one real tool call succeeds — `olympus source index status`. **Where the gateway boot line actually lives.** Do not go looking in `openclaw logs` or `~/.openclaw/logs/gateway.log`. On `2026.9.1` the former printed nothing, and the latter is a stale file that can be months old — believing it will tell you the plugin failed to load on a machine where it loaded fine. On macOS the live gateway log is a per-day JSON-lines file under `/tmp/openclaw/`, so grep the newest one: ```bash grep -h 'http server listening' "$(ls -t /tmp/openclaw/openclaw-*.log | head -1)" ``` Every line is a JSON object, so the boot record and its loaded-plugin list sit inside the `message` field rather than reading as plain text; pipe through `jq -r .message` if you want it legible. On Linux the gateway runs as a user systemd unit and the same line comes from the journal: ```bash journalctl --user -u openclaw -n 200 --no-pager | grep 'http server listening' ``` If neither surface shows the line — a machine whose log rotated since the last restart, for instance — do not manufacture the proof and do not restart again to produce one. Say the boot line was not observable, and lean on the other two checks: `"status": "loaded"` plus a successful `olympus source index status` are conclusive on their own. For a selected native dashboard, also verify `plugins.controlUi.list` includes Olympus without a diagnostic and `plugins.controlUi.status` reports successful activation from the actual connected browser. Confirm the sidebar entry and page render there. A loaded backend and HTTP health alone do not prove browser activation. An unusable selected dashboard keeps the handoff incomplete; diagnose its asset/transport error without connecting an unrelated source. **Do not verify by reading `toolNames` from `plugins inspect`.** It is `[]` for olympus by design: the tools (`source_answer`, `source_index_status`, `source_index_search`) register at runtime when the plugin initializes, not in the static manifest inspect reads. An empty `toolNames` on a healthy install proves nothing is wrong, and chasing it sends you re-installing a plugin that already works. ### Native agent tool access **Required before setup completion.** A loaded plugin, a working dashboard, and a successful CLI status command prove the backend; they do not prove the assistant can call Olympus. OpenClaw's `coding` profile can filter all Olympus tools while those checks remain green. Inspect the installed host's schema and the target agent's current tool policy. For a fresh configuration with `tools.profile: "coding"` and no existing `tools.allow` or `tools.alsoAllow`, enable only the approved Olympus plugin: ```bash openclaw gateway call config.schema.lookup --params '{"path":"tools.alsoAllow"}' --json openclaw config get tools openclaw config set tools.alsoAllow '["olympus"]' openclaw config validate ``` Preserve the selected profile and all existing entries. When `alsoAllow` already exists, append `olympus` only if absent; when `allow` exists, extend that list instead, because OpenClaw rejects `allow` and `alsoAllow` in the same scope. Inspect applicable agent, provider, channel, and sandbox restrictions as well. Do not remove explicit denies, switch to `full`, grant `group:plugins`, or enable unrelated plugins to make Olympus work. An intentional policy restriction is a boundary to explain to the operator, not a reason to bypass it. Use the host's supported config path and reload procedure; a hot-applied tool-policy change does not require another Gateway restart. Use `tools.catalog` for registration diagnostics and `tools.effective` with the actual target `sessionKey` for its projected inventory. Finish with a real `source_index_status` call from the operator's intended assistant session and check the successful tool result. If the inventory and actual run disagree, inspect the run's tool-call evidence; do not repeatedly reinstall or restart to make a diagnostic listing change. A CLI fallback, the model saying a tool is available, and an empty or truncated diagnostic export do not satisfy this check. No source must be connected for the status call. If the call fails, report agent integration as incomplete and repair the named failure before the source handoff. After a chosen source is ready, Step 7 also requires a native `source_answer` call through this same assistant. For a Hermes Agent install, use the package's narrower MCP-only lane: ```bash openclaw plugins inspect olympus --json hermes mcp add olympus --command /absolute/managed/olympus/bin/olympus --args serve hermes mcp test olympus ``` Take `plugin.rootDir` from the inspect response and append `/bin/olympus`; do not guess OpenClaw's managed storage path and do not assume a global `olympus` command exists. Configure the `olympus` server with `tools: { include: [source_answer, source_answer_result, source_index_status] }` (the packaged `config/hermes/olympus.mcp.yaml` shows the complete YAML), reload MCP, and verify the only discovered names are `mcp_olympus_source_answer`, `mcp_olympus_source_answer_result` and `mcp_olympus_source_index_status`. In Step 7, after the chosen source is ready, exercise a cited answer through the discovered `mcp_olympus_source_answer`. Do not enable `source_index_search`, `source_watch_*`, prompts, or resources for v0.4 Hermes. The optional `integrations/hermes/ask-sources` adaptation may be copied to `~/.hermes/skills/ask-sources` or loaded through `skills.external_dirs`. No `hermes://mcp/install` link is published because current Hermes documentation does not define that handler, and no external catalog submission is authorized. ### Olympus on a server: opening it on the owner's computer **Installs on a server only** (owner decision, 2026-10-10: OpenClaw users get this at onboarding, with one approval; Hermes users get the lines to copy). Some screens (keys, X sign-in, Telegram and WhatsApp pairing) must open in a browser on the owner's own computer. On a server, Olympus does that through an SSH tunnel and a one-time link; the owner's assistant can run both on the owner's computer through a paired node. Design: `docs/design/remote-access.md`; owner-facing page: `docs/openclaw-node-setup.md`. 1. **Declare it.** Ask the owner how their computer signs in to this server over SSH (`user@host` or an ssh_config name; the OpenClaw app's remote settings show the one it uses), then run `"$OLYMPUS_BIN" server-mode on --ssh-target ` and check `"$OLYMPUS_BIN" server-mode status` reads `remote: true`. Skip this whole section when Olympus runs on the owner's own computer. 2. **Find the node.** `openclaw nodes status`: you need the owner's computer as a connected node that offers `system.run`. If there is none (for example only the macOS app is installed), tell the owner the dashboard will show two lines to copy instead, and offer the optional `openclaw node install` from `docs/openclaw-node-setup.md`. Do not install it without their yes. 3. **One approval.** Ask once, in these words or close: "May I let your computer open Olympus links without asking, and have it ask you each time before I start the secure tunnel?" On a yes, check `openclaw approvals get --node `, then: - effective security `full`: add nothing (it already runs commands without asking); say so. - `allowlist` with ask `on-miss` or `always`: add only the opener, `openclaw approvals allowlist add --agent --node "/usr/bin/open"` (`xdg-open`'s full path on Linux). Never allowlist `ssh`: each tunnel asks the owner once; tell them to choose Allow once. - ask `off` with `allowlist`: ssh would be refused. Tell the owner; do not change the node's policy without their explicit yes. 4. **Test it**, when the owner asks you to, with `olympus_open_remote {"target": "dashboard", "computer": "macos"}` (or `linux`, `windows`: the node's platform): run the returned `tunnel` with `exec host=node` (the owner approves it), then `open` right away. The dashboard opens unlocked in the owner's browser. Never paste, repeat or store the link inside `open`; it is a one-time ticket that lasts two minutes. Hermes installs have no node: in step 1 add `--agent-route off`, and skip steps 2 to 4; the dashboard then shows the owner only the two lines to copy. ## Step 6 — Finish installation: dashboard handoff **Pre-source completion receipt — mandatory before inviting Connect.** This gate applies to source connections, not to opening the dashboard or its Keys page. Always hand over the dashboard after base activation, even when model keys are still missing. Do not invite a source Connect until Models is Ready. It proves that the selected posture's model/provider wiring is usable by the worker; it does not choose a source, and it does not require any source to be connected yet. In the browser flow, model readiness means the **Keys** page's Models section reads "Models are ready. You can connect sources below." (each ready model shrinks to one compact row), and the dashboard's **Models** section shows no model as Needs you or Not working; in the headless fallback, use the provider-specific connect and readiness checks documented in Step 3. Then prove the worker consumes that wiring with the existing `olympus doctor` and `olympus worker status` checks. The receipt must name: - **Gemini — every posture.** Its wiring is for Personal embeddings. Gemini is not the Private-answer provider and is never a Private embedding requirement. - **Venice — only when the posture uses it.** `local-first` uses Venice as the approved Private-answer escalation; `private-cloud-only` uses Venice for Private answers and, without a local provider, Private embeddings. Verify the embedding model separately: Private catalog classification, endpoint readiness, matching dimensions, and approved cost. `local-only` and `no-sensitive` do not require Venice, so do not ask for or block on a Venice key for those postures. Preserve existing vectors and obtain activation or backfill approval before changing a saved embedding profile. - **Native assistant proof (OpenClaw).** The Step 5 `source_index_status` call must succeed from the intended assistant session through the native tool. Worker or dashboard success alone cannot satisfy this check. - **Worker consumer proof.** The existing Doctor output must show the relevant `sovereignty_prerequisites`, `worker_credential_lanes`, `source_index_status`, and `email_worker` checks green, and `olympus worker status` must show the worker reachable without degraded credentials. Use the posture's existing remedies when one is red, then rerun the same checks. - **Privacy classifier decision.** Run `olympus tier classifier status` and report its `decision` field, not your recollection: **approved** (`approved`, the operator's recorded yes), **declined** (`declined`, the operator's recorded no), **refused** (`refused`, with the `refused` reason), or **not applicable** (`not_applicable`: `no-sensitive`, reason `no_private_lane`). `not_asked` means the Step 3 gate was never cleared: go back and ask it now. Do not send the dashboard handoff until this line reads one of those four outcomes. A provider key being present, a configured model profile, or a check reported as **Skipped** is not readiness. A Venice key also does not prove usable API balance. Do not add a new CLI/API/billing probe or a source connection to make the receipt look complete. If a required check is not green, say which provider wiring remains open and keep source Connect unopened. Give the operator this honest summary in the same final reply, immediately before the source handoff, adapting only the observed facts: > Base installation is verified. Chosen posture: ``. Gemini wiring > for Personal embeddings: ``. > Venice Private-answer and Private-embedding wiring, reported separately: > ` still open>`. Privacy classifier: ` or not applicable (no-sensitive)>`. Worker consumer checks: ` name the open check>`. No source is connected yet, and I will wait to > invite Connect until every required provider check is green. Deliver the dashboard handoff below after base activation. If Models is not ready, direct the operator to finish the keys on **Keys** before connecting sources. **Base installation is complete before source choice.** Report the selected posture, model prerequisites, worker health, and successful plugin/tool and selected-dashboard activation from Steps 1–5. No connected source is required. Resolve and verify the selected dashboard as described below. The final reply must tell the operator exactly where to open it: the **Olympus** sidebar entry when they are chatting in the Control UI that shows it, otherwise the actual clickable link. Never send the placeholder, a host-only loopback URL, or only a terminal command. **Where to open it.** Decide from your own session: if the operator's messages reach you through the OpenClaw Control UI (webchat), and Step 5's activation receipt holds (`plugins.controlUi.list` names olympus with no diagnostics and `plugins.controlUi.status` shows it activated in their browser), the dashboard is the **Olympus** entry already in the Control UI sidebar of the page they are looking at. Point them there and send no link: do not ask for the address in their browser's address bar. If you cannot tell which channel they use, treat it as another channel. When they chat from another channel (Telegram, a terminal, a remote agent), the link is the native page `/plugin?plugin=olympus&id=dashboard` on the Gateway origin they use; it needs no ticket and does not expire. Use the standalone `olympus dashboard` opening link only when native UI is unavailable, the operator declined the Step 5 Custom plugin UI opt-in, or the operator explicitly chose direct access. Concretely, a "host-only loopback URL" is any `127.0.0.1`, `localhost` or `[::1]` address whose host is not the machine the operator's browser runs on: the worker's `http://127.0.0.1:8010/…` and a Gateway loopback origin qualify unless you have confirmed the operator browses from the Olympus host itself (or through a tunnel that forwards that exact port). If you do not know the operator's Gateway origin and a link is needed (never for the sidebar handoff), read `gateway.publicOrigin` or ask them for the address in their browser's address bar; do not guess one. Deliver this required user-facing handoff **verbatim**. Change nothing but the first line's `[Open your Olympus dashboard]().`, which becomes `Open **Olympus** in the Control UI sidebar.` when you pointed the operator at the sidebar entry above, and otherwise keeps the link with the placeholder replaced: no reworded sentences, no "optional" or "you pick which ones, if any" framing, no Labs or settings caveats. If a caveat seems necessary, the dashboard is not verified yet; resolve it first, as described below. Only for the standalone fallback, one sentence after the block may say the link works once within fifteen minutes. > Olympus is installed. [Open your Olympus dashboard](). > Olympus is as useful as the sources you give it. Each one you connect — > email, files, chats, bookmarks, reading — becomes something I can search and > answer from with citations, handled under the privacy tiers you just chose. > If the dashboard asks for a model key, add it first on **Keys** (under > **On this computer**, or through **Change** under **Models**); that is where > your model keys go. Then connect the sources you want under **Sources** and > choose what each one may read. Start with whichever holds what you most want > answers from; you can add more at any time. > **Needs you** lists anything waiting on you, each source's row shows its > readiness, and **Progress** shows reading and indexing, stage by stage under > **Details**. Come back here if a connection gets stuck or its progress is > unclear. Source selection happens in the dashboard. Do not turn all supported providers into a checklist, choose Gmail to satisfy a health hint, or add a chat question asking which source to start before the user has chosen a card. Provide help for the source the operator selects and only its approved scope. If the operator explicitly needs the documented headless fallback, ask which source that fallback should connect. **Save the privacy conversation in the Privacy section.** The Step 2 conversation is saved here, in the dashboard's **Privacy** section, the only privacy configuration Olympus reads: the operator's own words for "What's private for you?", and any folders, Gmail labels or senders they named as always Private (offered once the source is connected, since those come from its pickers). Read the note back and let the operator press save; do not save it for them. Never write a `~/.olympus/sensitivity-map.json` file: it was retired on 2026-10-03 and nothing reads it. **Drive, Dropbox and Gmail require scope approval before ingestion.** Connecting an account grants access for the picker; it does not approve indexing the account. Until the operator saves a scope the card reads **Waiting**: *waiting for folder selection* (Drive, Dropbox) or *waiting for mail selection* (Gmail). That is the expected next step, not a stalled sync. For Drive and Dropbox, open **Choose folders** on the source card. Use the existing Finder-style tree and inspector to choose **Full ingestion**, **Metadata only**, or **No ingestion**, then have the operator press **Save scope and start**. Browsing lists folder names without indexing or reading file contents. Unselected folders stay out; using the entire account requires an explicit selection and confirmation. For Gmail, open **Choose mail**: it stores the body of the last 2 years by default (older mail keeps only subject, sender, date and labels), skips Promotions and Social by default, lets the operator mark senders **Always Private** or **Skip** from a sample of their recent mail, and shows an estimate before **Save scope and start**. Never select the whole account, confirm scope, or press Start for the operator without their instruction. An empty rule set, a built-in root, a connected credential, or previously cached items are not scope approval. Unapproved cached file content remains unavailable to search and answers. Reconnection requires review of the current account's scope. Preserve retained data; changing scope is not permission to purge it. Do not reconnect a source the operator disconnected while resolving a problem. Provider/model readiness and any required cost approval remain separate from permission to use selected folders. Every source judges each new item on its own and stores it by tier: names are Personal unless raised, content is raised to Private or Secrets on evidence, and a Secret is kept only as its location. An item waiting for the privacy classifier is held as Private, searchable by keyword and not yet embedded; the source's page counts it as *pending classification (kept Private)*. When the operator asks why an item landed where it did, run `olympus tier explain ` (it shows tiers and reason codes, never content). Change a tier or add a standing rule only on the operator's instruction, with `olympus tier set ` or `olympus tier rules add`; Gmail sender rules stay in its **Choose mail** picker. This candidate artifact includes native Control UI support. On OpenClaw **2026.9.2** and later, use **Olympus** in the Control UI sidebar. When the operator chats from the Control UI, the sidebar entry is the handoff, proven by Step 5's in-browser `plugins.controlUi.status` activation rather than by loading a URL. Only when a link is needed, resolve that page against the same Gateway origin the operator is actually using: `/plugin?plugin=olympus&id=dashboard`. Copy the working page's URL; do not assume port 18789, reuse the agent host's localhost origin for a remote operator, or link only to the OpenClaw chat homepage. Verify that the page loads and shows the Olympus panel (its Sources and Models sections; Progress appears only while something is being found, read or indexed) before handing it over. The Control UI panel has no **On this computer** section; there, **Change** under **Models** offers **Do this on your computer**, which opens **Keys** on the Olympus computer. Native plugin pages need the Custom plugin UI opt-in, which Step 5 asks for before the restart; reload the browser if the sidebar entry is still missing. If the operator declined it there, the native page is not available: use the standalone opening link. It is never handed to the operator as a caveat in the final reply. Use that Gateway's Control UI in a supported browser. On the tested macOS WebKit/Safari 26.2 runtime, Secure plugin cookies are rejected over plain localhost/loopback HTTP even though the page is a secure context. For the integrated UI, use Chrome on loopback or an already configured trusted HTTPS route. Do not weaken cookie/authentication settings, expose a new listener, or change certificate trust as an implicit plugin-install step. The integrated page uses the signed-in operator's permissions and keeps the worker bearer on the server; it needs no worker-token paste. See the [upstream contract](https://docs.openclaw.ai/plugins/feature-plugins). For native OAuth, a browser that reaches the Gateway on a loopback HTTP origin (on the Gateway host or through the operator's own port forward) needs no configuration. Any other access, such as an HTTPS proxy or tailnet name, needs `gateway.publicOrigin` to name that Gateway's HTTPS origin. Use the applicable live-change procedure for an authorized change; never edit runtime configuration directly or send a remote browser to the worker's loopback callback. If native support is absent, or the operator explicitly chooses direct access, explain that boundary and use the supported standalone dashboard. If a declared native UI fails to appear, inspect `plugins.controlUi.list` and `plugins.controlUi.status` first; a loaded backend does not prove browser activation. An import failure is a browser/asset delivery failure, not a reason to reconnect sources or reinstall the package blindly: ```bash olympus dashboard ``` Use the required handoff above once the selected dashboard is open. The standalone `olympus dashboard` command returns `url`, `opened`, and `hint`. Run the already-resolved `$OLYMPUS_BIN dashboard --no-open` yourself and give the operator its opening link. They should click a link, not find an installation directory, run a terminal command, or copy an internal credential. Use `--no-open` for an agent handoff so a browser on the host cannot consume the single-use link before the operator opens it. The opening link contains a short-lived, single-use authorization ticket. It expires after fifteen minutes, so generate it at handoff time; if it expires or has already been used, run the command again. Do not fetch the link as a preview or probe before giving it to the operator. The browser removes the ticket from its address bar, exchanges it for the existing HttpOnly control session, and opens the dashboard with controls available. Verify that actual browser result before claiming the handoff is complete. Keep opening links out of public issues and shared logs; they authorize dashboard controls while valid. The durable worker bearer stays on the host. `olympus dashboard token` remains an advanced compatibility command: never paste it into chat, a summary, or a note, and never use it as the ordinary installation handoff. A missing worker credential means setup has not completed; an unreachable worker needs its existing readiness repair. Neither error is a reason to print its secret or silently hand over a read-only page as if controls were ready. The `dash_` token is not the worker token. Existing read-only dashboard links continue to authorize only their documented read routes. They cannot mint an opening ticket or authorize a control action. To operate the dashboard, obtain a fresh opening link from the installed CLI. Native OpenClaw access continues to use the signed-in Gateway identity and does not need this standalone step. Follow the source the operator chose; do not bulk-connect anything yourself. Other sources can be added later from the same dashboard. Your job is to narrate, run one-time setup when a card asks for it, and diagnose failures by watching `olympus connect status` and `olympus doctor`. Keep the selected Olympus dashboard open as the operator-facing progress view. Connect-conversation rules: - MUST explain the credential in one plain sentence before asking for it. For normal Google setup: "Olympus includes its public Google app identity; click Connect, then Google shows the exact read access you are granting." - MUST walk a non-technical operator through the provider page step by step. For normal Google setup, narrate only sign-in, the unverified-app warning, and consent. Do not send them to Google Cloud Console. - MUST have the operator enter secrets only in the dashboard field, or use the documented CLI stdin flow when the dashboard is unavailable. The Step 3 credential-sourcing rule applies to every source credential here too: manager fetch is allowed (named item only, per-credential consent unchanged), enumeration never. - MUST NOT show internal config keys such as `gmail.personal.oauth.client_secret` as the task or remedy. - MUST NOT invent keychain, `security add-generic-password`, 1Password, or other storage commands for source-connect credentials. (This bans WRITING credentials outside the dashboard/stdin flows; the residue check's value-less presence probes and the Step 3 credential-sourcing fetch-read that pipes an existing value into stdin are different things — both permitted.) - MUST NOT ask the operator to paste OAuth client secrets, API tokens, or pairing codes into chat. The Step 3 code-block contract still applies: operator-run commands go in code blocks only when the operator must copy and run that exact command. Dashboard card meanings: - **Connect** — the dashboard can start the flow. The operator clicks Connect, finishes provider consent or enters the API token locally, and the card updates after the next poll. - **Awaiting browser consent** — the provider tab is open or waiting. Let the operator finish consent; do not restart the flow unless it expires or fails. - **Needs setup** — the source needs a one-time OAuth client before the dashboard can connect. Help the operator create that client, register any redirect URI shown on the card, then they paste the requested values into the dashboard card and click Connect. - **Reauth required** — the source has a handle, but the session or refresh credential needs attention. Use the card guidance first, then `olympus connect status` and doctor output to diagnose. ### Google / Gmail / Drive Normal Google setup is one click: Olympus's own publisher Google app is already present (it connects through Olympus's sign-in relay, from any dashboard address or from ChatGPT), and the packaged publisher-owned Desktop client ID is already present for direct and earlier-connected installs. The operator clicks **Connect**, signs in to Google, and approves the source-specific read scope. Google may show the documented unverified-app warning during the small pilot; the Gmail and Drive connect sheets carry a note about it. Explain it plainly and let the operator decide whether to continue. After consent, Gmail and Drive wait for the scope choice described above. If Gmail or Drive says **Needs setup** on a packaged install, treat that as a broken or unqualified artifact and run `olympus doctor`; do not send the operator to Google Cloud Console. Creating a personal Google client is an advanced BYO fallback only when the operator explicitly chooses it. The one exception is the full state below. **When Google sign-in is full.** Olympus's own Google app is unverified, so Google serves at most 100 distinct users over its whole lifetime and stops the 101st on Google's own page, where Olympus never hears from them again. Olympus watches the count and, before the wall, the Gmail and Drive cards stop sending new people to Google. They say "Google sign-in is full for the moment. We're working on it. For now, you can still connect Google by using your own Google app." with a **Set up** button (in ChatGPT the row says the same and its **Use your own Google app** button opens Olympus on the computer; a Connect attempt from ChatGPT answers `google_signin_full`). This is expected, not a broken artifact: do not run `olympus doctor` for it, do not promise a wait list or a date, and do not suggest retrying the one-click Connect. Using the operator's own Google app is the sanctioned route, so help them through the next section: **Set up** on the card opens the Client ID field and the same steps. They must publish their own app to production, because a Google app left in Testing expires its refresh tokens after 7 days. The full state holds back a Google source that has no connection of its own, even when the other Google source is connected (Google's consent lets the person pick any account, so adding Drive beside Gmail can be a new user). A source that is already connected keeps its one-click Reauthenticate. If the operator tells you the card no longer says full, the one-click Connect is back; use it. **Helper-binary rule (hard-learned):** never install or upgrade a credential-helper binary (`gogcli`, keychain-touching CLIs, or similar) mid-onboarding. Upgrading a binary invalidates its macOS Keychain ACLs — "Always Allow" does not persist for ad-hoc-signed binaries — so the upgrade converts every later background credential read into a password modal on the operator's screen. Use whatever version is already present; if an upgrade is genuinely required, defer it to after setup completes, tell the operator why, and do it while nothing is retrying in the background. Corollary: never send the operator to approve a Keychain dialog while any background process (the worker, a drain, a retry loop) might be reading the Keychain — stop it first, let them approve in calm, then start it again. ### Advanced Google BYO fallback Use this when the operator explicitly chooses BYO, or when the Gmail or Drive card says Google sign-in is full (above). The client type follows the address the dashboard is opened on. Opened on this computer (loopback), use a Google Desktop client: its ID is public application identity and can be entered locally. Olympus uses S256 PKCE; Google documents `client_secret` as optional for installed-app authorization-code exchange and refresh, so the Desktop path does not ask for or store one. Opened over https (a tunnel or proxy), Google accepts only a **Web application** client, and that client requires its secret at the token exchange and every refresh: the dashboard shows a **Client secret** field next to the Client ID, and the operator enters the secret there and nowhere else (never in chat). Olympus keeps it in the secret store and sends it on the exchange and on refresh. Choose the Console mode based on capability detection: - If browser control works, open Google Cloud Console, help the operator create or select an Olympus project, and drive the operator's browser through the API, consent, and client pages while narrating what you are doing. Use their signed-in Google account; do not ask for passwords. - If browser control is flaky or unavailable, use the manual fallback below. It must stand alone; do not hand-wave the Console pages. Manual fallback, consent screen page: 1. Open , select the operator's Olympus project, and open the branding/audience setup. 2. Choose **External**. 3. Set app name to **Olympus**. 4. Set support email to the operator's email. 5. Save through the required steps. 6. Go to audience/publishing and **publish to production**. Testing mode breaks sync after 7 days because Google expires refresh tokens for testing apps. Manual fallback, OAuth client page: 1. Open , select the same project, and choose **Create client**. 2. Choose application type **Desktop app** (or **Web application** when the dashboard is opened over https: add the redirect URI shown on its card under **Authorized redirect URIs**). 3. Name it **Olympus**. 4. Click **Create**. 5. Enable the Gmail API and Google Drive API for the same project: and . Sync returns Google 403 errors until these APIs are enabled. 6. Copy the Client ID into the dashboard form. For a Desktop app client do not copy or request the client secret. For a Web application client the operator also copies the Client secret into the dashboard's **Client secret** field, and only there. When the client ID (and, for a Web application client, the secret) is ready, have the operator paste it into the advanced BYO dashboard card and click Connect. Google desktop clients use loopback redirects with random ports, so there is no fixed redirect URI to register; a Web application client uses the exact URI the card shows. If Google shows an unverified-app interstitial, explain which OAuth app is being used and let the operator choose whether to continue. Watch the dashboard and `olympus connect status`; `connected` means the handle was stored, `pending` means the browser consent is not finished, and `failed` or `expired` means start that card again after explaining the failure. Never run foreground Google connect from a chat agent. The old foreground flow keeps the loopback listener in the agent's command process. OpenClaw chat agents have turn-scoped command execution, so that process is killed when you end the turn to let the operator finish browser consent. Dashboard-owned OAuth is safe because the worker is long-lived. The detached CLI flow remains the headless fallback when the dashboard cannot be opened: run `olympus connect google --client-id --detach` yourself, use `gmail` or `google-drive` instead of `google` for source-specific consent, give or open the returned `authorizationUrl`, then poll `olympus connect status google`. For detached status, `connected` means the handle was stored, `pending` means browser consent is not finished, `failed` or `expired` means rerun detached connect, and `died` means rerun detached connect and inspect the log path in the status output. ### Other Sources Dropbox and X also use OAuth. When their cards say **Needs setup**, help the operator create and own the provider app/client on the provider's developer site. These providers require an exact redirect URI match; register the exact `http://127.0.0.1:/oauth/callback/` URI shown on the dashboard card. Dropbox uses PKCE without a secret. The current supported X fallback is a user-owned confidential app: the operator enters its client ID and secret locally, and Olympus uses HTTP Basic for token exchange without exposing the secret to chat. Do not promise client-ID-only X setup until Olympus's exact refresh/rotation/restart path is qualified. Use the detached `--detach` CLI flow only when the dashboard is unavailable. For Dropbox detached CLI setup, pin a port and register that exact loopback callback with the provider before starting consent: ```bash olympus connect dropbox --client-id --redirect-port --detach ``` Use the dashboard for the supported X confidential-client flow; the current detached CLI exposes only the unqualified public-client shape. Readwise uses an API-token form in the dashboard. The operator enters the token locally; never ask them to paste the raw token into chat. It starts syncing on the worker's next pass with no worker restart. Venice is not a source: its key belongs in the **Models** section. Telegram and WhatsApp use the packaged pairing commands below. The dashboard has **Ask your agent**, not a Connect/Pair button or a phone/code form. Never send the operator back to a nonexistent control or regenerate a dashboard link as a substitute for starting pairing. ```bash olympus connect telegram --pair olympus connect whatsapp --pair ``` Run only the selected command in a private terminal the operator can actually use on the Olympus host. If your captured tool terminal is not accessible to them, give one complete SSH command with the correct host, account, and resolved Olympus executable. Do not ask for login codes, API hashes, or 2FA passwords in chat. Telegram uses the operator's own app API ID/hash from https://my.telegram.org, then phone/code/2FA entry; it needs Python with Telethon. WhatsApp needs Go and a C compiler for the packaged bridge build; the command builds into an Olympus cache, never into the managed plugin. WhatsApp shows a scannable QR in the private terminal. This guided pairing flow treats messaging as Private data; it refuses under `no-sensitive` (Private kept local) rather than capturing it outside that policy. Pairing is verified before the operator approves chat/account capture scope. The command then registers the verified session and starts capture through the managed worker. `--session-path` / `--session-ready` remain advanced imports of an already verified session. Never use them to skip the normal pairing proof. **QR delivery (WhatsApp): render the QR as a local PNG image file and show that image to the operator.** Do not paste terminal QR blocks or ASCII art into chat — they break across chat surfaces and were the two failed attempts in the 2026-07-08 live rehearsal; the local PNG was the method that worked. If the first PNG render does not scan, regenerate once (QR payloads rotate quickly; a stale payload is the usual cause) before suspecting the bridge. Rules: - Keep the selected Olympus dashboard open as the operator-facing progress view. - Run only the command for the source currently being connected. - A dashboard Connect click authorizes only that source. Before YOU run any `--detach` connect yourself, ask for that specific source — every source, its own ask (Rule one). - Treat dashboard Connect clicks as the primary path; use CLI `--detach` only as the headless fallback. ## Step 7 — Verify the chosen source with a cited answer Run this only after the chosen source has completed a bounded initial sync and reports answer readiness. In OpenClaw, have the intended assistant call the native `source_answer` tool; a successful CLI command alone does not prove agent integration. Ask a normal question whose answer the operator expects in that source, then check the returned citations against that scope. If they deferred sources, report "base installation verified; cited-answer proof pending a chosen source" and stop here. An empty-source answer is not proof of successful retrieval. ```bash olympus doctor # every check green or explained olympus source answer "" ``` `olympus doctor` exits 1 while any check is red, naming the failed checks on stderr (counts and check names only), and leaves the full JSON on stdout. Its exit status is the pass/fail signal — you do not have to grade the output yourself. Exit 0 is green. Confirm in the answer's audit block that `analyst_backend` matches the chosen posture (e.g. `venice` for `private-cloud-only` Private answers, `local` for `local-only` Private answers). Private sources are searched by default whenever the posture approves a private analyst, so an ordinary question that finds Private evidence is answered by that private lane and only its checked, derived answer comes back. On `no-sensitive` the answer notes that Private sources were not searched. Answers also report breadth per source (for example "50+ items, 17 in evidence"); the evidence count is not the total. Evidence that is only Personal (or Public, on an install made before 1.0) goes to OpenClaw's default model. If that lane fails, the error and the worker log carry a readable reason (missing auth for the model, an unknown model, or the OpenClaw CLI not found on the worker PATH); fix that named cause rather than pinning another model. The private source worker lane is on by default, so a fresh install should not see `email_not_configured` at all. If it does, the lane was switched off deliberately — `OLYMPUS_EMAIL_ENABLED=false` is the only supported opt-out — and the error names its own remedy: > Run olympus setup, then olympus worker install, to bring up the private > source worker that owns OAuth and message fetch and reasons over an > approved local/private model lane. Run what the error names, nothing else. Do not invent a fix, do not hand-edit config to flip the lane on, and do not re-run `olympus setup` to "reset" it (the CLI refuses without `--force`, and `--force` needs the operator's explicit consent — MUST NOT #5). What a fresh install DOES see when the worker simply is not running is the honest version of the same problem: `Email worker is not reachable at http://127.0.0.1:8010/v1: `, where the detail after the colon is the underlying connection error. That is a Step 4 worker question, not a configuration one — read the detail before doing anything about it. Degraded credential lanes are a silent failure you must rule out explicitly — a worker with a dead embedding credential still syncs and still answers, while indexing nothing searchable (this was a real incident). Three checks: `olympus doctor` must not fail `worker_credential_lanes` (if it does: fix the named credential, then POST the bearer-only `/v1/source/credentials/recheck` route; restart the worker only if it reports `resolved_restart_required`); `olympus worker status` must show the worker reachable with no `degraded_credentials`; and the first answer's audit block must not report semantic search skipped for `embedding_provider_unavailable`. The dashboard shows a credential alert for the same condition — it should be absent. Then show the operator Olympus in OpenClaw: source freshness and where Personal, Private, and Secrets are allowed to go. Use `olympus dashboard` when standalone access is needed. End with the required Step 6 dashboard link and connect/monitor instructions. Also report what was installed, the chosen posture, which sources are connected, which prerequisites remain open, and the doctor summary. Report base installation and cited-answer proof separately. Explain every non-green doctor check; resolve required model or worker failures before claiming base readiness. Unchosen sources are not missing install steps. ## Resuming after an interruption This section is for resuming YOUR OWN interrupted install — the same continuous install flow in which the operator already made the Step 2 decisions with you, interrupted by something like a gateway restart. A long-lived session or resident agent does not stretch this: if the decisions were not made with you in THIS flow — however you arrived, install, update, or maintenance request — that is the residue gate (Rule zero: surface and ask restore-vs-fresh before any state-changing action), not a resume. "Skip every step whose outcome already exists" below applies only to outcomes your operator consented to in this flow; it never covers adopting another setup's outcomes. If your session was interrupted (a gateway restart will do this to resident agents), do NOT replay steps from the top. First observe, then continue: `openclaw plugins list` (is olympus installed/enabled?), `ls ~/.olympus/sovereignty.json` (did setup already write the policy?), `olympus doctor` (what remains unmet?). Skip every step whose outcome already exists. In particular, never re-run `olympus setup` or `olympus sovereignty init` when the config file exists — the CLI refuses without `--force`, and `--force` requires the operator's explicit consent (MUST NOT #5). A refusal like "config already exists" during resume means the step is DONE, not broken. ## If something fails 1. `olympus doctor` first — every failure it knows carries a fix-it hint. 2. Report the exact failing command and output to the operator; do not retry commands that change state without the operator's explicit consent — telling them is not asking. On a machine with prior-setup traces, Rule zero binds repairs run from here too. 3. `openclaw gateway stability --bundle latest` explains a failed gateway boot; `openclaw doctor --fix` restores last-known-good config. ## What you must NOT do 1. **Never choose the privacy posture yourself — and never present it as a bare menu of preset names.** The plain-language walkthrough in Step 2 is part of the gate; the operator decides only after hearing what each posture means for their data. A question tool or pick-list is allowed only after the tier explanation, the privacy conversation and the posture walkthrough have all been delivered in chat, and its labels are the plain-language descriptions, never preset ids. 2. **Never echo, log, or store secrets in plain text.** Keys go through stdin connect flows or the worker environment; Olympus keeps them in an encrypted local secret store. 3. **Never restart the gateway without a green `openclaw config validate`.** That is the gate. `openclaw doctor --lint` is a report: its findings on things other than Olympus are surfaced to the operator, not fixed, and do not block the restart. 4. **Never edit `openclaw.json` by hand** — use `openclaw config set` or the documented connect/setup commands only. The same holds for Olympus's own generated managed files: never hand-edit `worker.env` or a generated service unit. 5. **Never run `olympus data delete`, overwrite an existing `~/.olympus/sovereignty.json`, or reinstall over an existing plugin** without the operator's explicit, informed consent. Read `--force` by what it would do on THIS machine, not by its name: on OpenClaw `2026.8.1+` the plugin install requires `--force` merely to accept a non-ClawHub source, and on a machine with no olympus installed that overwrites nothing and needs no separate consent (Step 1). The moment an olympus plugin already exists, the same flag overwrites it and this rule binds in full. 6. **Never restart the gateway you are running inside without warning the operator first** and giving them the exact message that resumes you ("continue the Olympus install from Step N"). A silent self-restart strands the operator mid-install. 7. **Never treat notes left by a previous agent or session as operator consent.** A bulletin entry, memory file, or prior-session summary saying setup is "done" or "do not rerun setup" triggers the Step 2 residue gate (surface and ask restore-vs-fresh); it never authorizes restoring a posture, reusing a credential, or skipping a decision gate on its own. 8. **Never expose a bare `olympus` command or claim it is globally available.** No wrappers, symlinks, aliases, functions, or shell startup-file edits, by any mechanism (Step 1); call the CLI by its resolved plugin path, and report it as "reachable at ``" — never as on the operator's PATH. 9. **Never treat an update, repair, or maintenance action as a bypass around the decision gates — however the request was framed** (Olympus named or not, one plugin or a bulk sweep, an install command or an unrelated-sounding symptom fix). On a machine with any trace of a prior Olympus setup, the residue gate (Rule zero) runs BEFORE any state-changing action that touches Olympus — explicitly including re-enabling a disabled worker (a `.disabled` plist or disabled unit is someone's deliberate signal; re-arming it needs the operator's consent) and adopting an existing `~/.olympus` config without fresh operator consent, whatever your reason — doctor's green status included. 10. **Never spend one consent on several actions.** A "yes" covers only the action it was asked about (Rule one). The worker pre-explanation with its own go and the gateway restart with its own go are mandatory even when the operator has been agreeing to everything. The signature of this failure is a state-changing action whose named gate was not cleared immediately before it — and interleaved unrelated questions do not count as clearing it. ## Optional — Connect other agents (after Step 7) Only when the operator asks for it. Do not offer it as part of installation. - Send the operator to the dashboard on this computer (`olympus dashboard`): under **On this computer**, **Open** next to **Agents**, then **Connect an agent**. The panel carries each agent's exact steps; do not paraphrase them into chat. - Through the relay (the default) only ChatGPT connects, approved with one click on a page Olympus serves on this computer, with no pairing code. Claude, Grok, the Grok API and other cloud agents need the operator's own tunnel (`remote.publicBaseUrl`); the panel says so. - Under the operator's own tunnel, pairing codes and connection keys are minted by the operator in that panel (or `olympus connections pair` / `olympus connections add `, run by its resolved plugin path). Never ask the operator to paste a key or code back to you, and never print one into chat or a log. - Agents in a vendor's cloud need remote access. If the panel says remote access is off, say so plainly and send the operator to **Turn on remote access** in the same Agents section. That button is the normal path: it changes `remote.enabled` through OpenClaw's config write, so the operator needs no terminal. There is no certificate agreement to accept: the relay holds the only certificate. Do not turn remote access on yourself without its own consent (Rule one). The relay (`mcp.olympusplugin.ai`) is the default; `remote.publicBaseUrl` is only for an operator who runs their own tunnel, set with `openclaw config set` and the validate-then-restart order in Step 5. `olympus connections status` says what remote access that is on is waiting for, including "Olympus relay unavailable" while the relay cannot be reached. - For Claude Code or Codex on the same machine, the local command is `/bin/olympus serve` (rootDir from `openclaw plugins inspect olympus --json`); on a Mac set up with the Olympus installer and no OpenClaw, it is `$HOME/.local/bin/olympus serve` with `$HOME` written out. Adding it to another agent's MCP configuration is its own consent (Rule one). - Revoke with the panel's **Revoke** or `olympus connections revoke `.