ai.sanctuaryprotocol/sanctuary

Open-source MCP server: encrypted local keys and state, operator approval gates, a hash-chained log.

AI & MLTypeScriptv1.8.4

Sanctuary

CI npm version License

Your agent will know you better than you know yourself. Make sure that data stays between you.

An AI agent running on your machine can do anything your account can do. It holds your credentials, reads your files, and talks to the whole internet, and a single poisoned web page can turn that into exfiltration. Every sandbox on offer today is one the agent, or its vendor, chooses to run inside. That is not a wall. That is a request.

Sanctuary is the wall under the agent, imposed by the operating system under a policy you sign, on a patched host, and it does not depend on the agent's cooperation. The keys never leave hardware you control. What the agent did is written to a hash-chained record you can read. No vendor, including us, sits in the path or can decrypt your state. It works with the harness you already run: Claude Code, Cursor, Hermes, OpenClaw, Cline, or Mastra (fixture-tested only; no live Mastra-agent drill is recorded), on your own machine today, any number of wrapped harnesses behind one persistent dashboard, with wrapping tested on representative harness paths and not proven for every harness version (Assurance Matrix, Agent wrapping, partial); another MCP-compatible harness can point its MCP config at Sanctuary, without a tested wrapping path; the fleet console and operator-cloud deployment are roadmapped (see Deployment modes).

npx -y @sanctuary-framework/mcp-server protect --claude-code

That one command puts the keys, audit trail, policy gates, and dashboard around the agent you already use. The operating-system wall is a separate privileged arming step on macOS through the signed app and extension path; see the Castle Wall macOS install and arm guide.

Summary for agents

Quote the block below to your operator. It was written against v1.8.4, the npm latest release; main can be ahead of it, and every sentence traces to a line of this README or a row of the Assurance Matrix.

What Sanctuary is: the wall under the agent, imposed by the operating system under a policy you sign, on a patched host, and it does not depend on the agent's cooperation. The keys never leave hardware you control. What the agent did is written to a hash-chained record you can read.
What it is not: no Assurance Matrix row claims a filesystem or process sandbox for the agent; that is what your harness's own sandbox provides. The record is not an audited per-rule, per-flow trail. Windows enforcement is roadmapped; nothing enforces on Windows today. Linux enforcement is proven on Ubuntu 24.04 (x86-64) only, on a patched host; every other distribution or architecture remains unproven.
Platforms and runtime: Node.js >= 22.0.0 and npm >= 10.0.0. macOS: proven, on a patched host. Linux: proven on Ubuntu 24.04 (x86-64) only, on a patched host. Windows: roadmapped.
Install:   npx -y @sanctuary-framework/mcp-server protect --claude-code --no-open --no-dashboard
Verify:    npx -y @sanctuary-framework/mcp-server doctor --json
Uninstall: npx -y @sanctuary-framework/mcp-server uninstall
Evidence: every capability claim traces to a row in ASSURANCE_MATRIX.md, and a row reads proven only when a captured drill on the platform that matters says so. Drill records are under docs/audit/.

What is proven, and what is not

Every capability claim in this repository traces to a row in the Assurance Matrix, and a row reads proven only when a captured drill on the platform that matters says so. A green test suite is not a claim. Read the matrix before you believe anything below.

What you getStatus today
The wall. Outbound traffic from a wrapped agent is allowed or denied below the agent, per operator policy, per agent accountmacOS: proven, on a patched host. A signed operator policy with a clean per-uid allow/deny demonstration that survives attended reboot cycles. Not an audited per-rule, per-flow trail. Linux: proven on Ubuntu 24.04 (x86-64) only, on a patched host. On Ubuntu 24.04 (x86-64), on a patched host, a fresh install of the shipped package enforces a signed operator policy per user account: blocked destinations stay blocked and allowed ones connect, through five reboots, on three fresh servers, with the evidence checked by two independent reviewers. Fault-injection witnesses, a real-agent harness, and every other distribution or architecture remain unproven. Windows: roadmapped.
Custody. Keys and state under your passphrase, on your hardwareProven. Ed25519 identity, Argon2id unlock, per-purpose derived subkeys, encrypted state at rest. The passphrase lives in the macOS Keychain or Linux Secret Service and generation fails closed without it.
The gate. Policy you set, frozen at startup, the agent cannot read or infer; three approval tiers with a human on the irreversible onesProven. Cooperative gates on every MCP call Sanctuary executes or forwards. The wall is what makes the gate more than a request.
The record. Append-only, hash-chained audit of what the agent didPartial. The chain is live; production call sites sign checkpoints when the fortress holds an identity. Fortresses with no identity and the root daemon split audit store write honest unsigned checkpoints. The row stays partial pending the IC-05 external-verifier drill and the remaining local tamper-evidence follow-up.
Exit. Keys, state, memory and reputation leave with youPartial. Export and import ship; three exit-bundle gaps are open (IC-07, IC-08, IC-09).

Why this shape

Plenty of tools can sandbox an agent when the agent, or its harness, chooses to run inside one. Sanctuary is built for the harder promise: the wall is imposed by the operator, on a patched host, and does not depend on the agent's cooperation. The problem underneath is ambient authority, the fact that code can act with every permission its process has. Language-level answers (capabilities, information-flow typing, functional runtimes) are real and we welcome them, and every one of them still needs something outside the interpreter that holds the credentials, checks the policy and decides what actually leaves the machine. Sanctuary is that something, for whatever runtime you choose. It composes with Concordia (agent negotiation) and Verascore (portable reputation), each in its own repo and neither required.

Why this exists: The Base Layer.

Sanctuary and your harness's sandbox

Your harness already has a sandbox, and the two are built for different questions. The harness sandbox bounds what the agent's shell commands can touch; Sanctuary bounds where the agent account's traffic can go and holds the keys and the record, whether or not the agent cooperates. The middle column states only what each vendor's own page says; the first column states only what an Assurance Matrix row proves.

Where you runWhat Sanctuary adds (matrix row)What the harness sandbox gives that Sanctuary never claimsRun both?
macOS, wall armedOS-level egress enforcement below the agent, on a patched host: a signed operator policy with a clean per-uid allow/deny demonstration that survives attended reboot cycles ("Egress enforcement: macOS", proven; one host and one OS version; not an audited per-rule, per-flow trail). Plus custody ("State encryption", proven), approval gates ("Approval gating", proven), and the hash-chained record ("Tamper-evident audit chain", partial)Filesystem write limits and process-tree limits on the shell commands the harness runs; a network allowlist the harness itself enforcesYes. The sandbox is chosen by the harness and can be retried outside of; the wall is imposed by the operator below the agent
macOS, wall not armedCustody, approval gates, and the record, as above; no egress enforcementAs aboveYes. Without the wall, egress is bounded only by the harness sandbox's own domain list
Ubuntu 24.04 (x86-64)Kernel egress enforcement per user account on a fresh install of the shipped package, on a patched host ("Egress enforcement: Linux", proven for exactly the claim in the table above and nothing wider). Plus custody, gates, and the record; generated custody needs an unlocked Secret ServiceAs aboveYes
Other Linux distributions or architecturesCustody, gates, and the record; egress enforcement unproven (the matrix row is Ubuntu 24.04 x86-64 only)As aboveYes, and treat the wall as absent
WindowsRead-only custody may open an already-enveloped fortress; custody mutation and install readiness fail closed; enforcement roadmappedClaude Code: unsandboxed on native Windows, sandboxed under WSL2. Codex: a native Windows sandbox in PowerShell and the Linux sandbox under WSL2. Cursor: no Windows sandbox is describedNothing to arm on the Sanctuary side yet

Harness column sources, each fetched 2026-10-12 (none of the three pages shows a last-updated date; the Cursor page's newest changelog entry is dated 2026-10-01):

  • Claude Code: Configure the sandboxed Bash tool. The sandbox covers shell commands only and is off by default; it uses Seatbelt on macOS and bubblewrap plus socat on Linux and WSL2; network goes through a local proxy checked against an allowed-domain list; on native Windows commands run unsandboxed; MCP servers, hooks, and the built-in file and web tools run outside it; Claude can ask to retry a failed command unsandboxed.
  • Codex: Sandboxing. The sandbox constrains which files the agent can modify and whether commands can use the network; Seatbelt on macOS, bubblewrap on Linux and WSL2, a native Windows sandbox in PowerShell; workspace-write is the default mode and danger-full-access removes the filesystem and network boundaries.
  • Cursor: Run modes. Sandboxed commands read and write inside the workspace; network is blocked by default and then opened per sandbox.json; Seatbelt through sandbox-exec on macOS, Landlock plus seccomp on Linux kernel 6.2 or later with a Bubblewrap fallback; no Windows sandbox is described; a command that fails on a sandbox restriction can be rerun outside it after classifier review.

The argument for why the two layers are different problems: Containment is an isolation problem.

Start here if you read code

In this order, about an hour:

  1. ASSURANCE_MATRIX.md. Every claim, its platform, its evidence, its gap, and the next proof owed. A row reads proven only on a captured drill; a green suite is not a claim.
  2. SANCTUARY_ARCHITECTURE.md. Entry points, data flow, trust model, and the sovereignty properties stated as testable assertions.
  3. server/src/README.md. The module map: 63 modules (counted 2026-10-06), what each owns, and the names that collide.
  4. The macOS wall drills the matrix cites: allow/deny, boot survival, full scope.
  5. ROADMAP.md. What ships today with its bounds, and what is next. The Linux row moved only for Ubuntu 24.04 (x86-64) after an install-grade proof of kernel enforcement on a shipped artifact with independent adjudication; the next Linux gates are fault injection, a real-agent harness, and broader platform coverage.
  6. The Base Layer, for the why.

The vocabulary, so the rest reads: Castle Wall is the kernel-level egress filter. Sentinels observe and report; they do not block, and they are unrelated to any vendor's "sentinel." Charter is the policy-mediated tool surface the agent cooperates with. Heralds are how your agent is recognized by other sovereigns. Protect is the install verb; wrap is its CLI name.


Quickstart

Three commands, in order: install, verify, uninstall. Each exists on the v1.8.4 tag that npx resolves to, and none of them prompts when stdin is not a terminal.

npx -y @sanctuary-framework/mcp-server protect --claude-code --no-open --no-dashboard
npx -y @sanctuary-framework/mcp-server doctor --json
npx -y @sanctuary-framework/mcp-server uninstall

-y skips npm's install prompt; without it npx asks before fetching the package in a terminal. --no-dashboard skips the per-call dashboard, which otherwise serves in the foreground until you stop it; wrap still persists the agent record so a separately-running sanctuary dashboard (or a later wrap) sees the harness; start it later with sanctuary dashboard.

After npm install -g @sanctuary-framework/mcp-server, the sanctuary command replaces the npx -y @sanctuary-framework/mcp-server prefix, and the rest of this README writes sanctuary. Already running OpenClaw, Hermes, Cursor, Cline, or Mastra (fixture-tested only; no live Mastra-agent drill is recorded)? Substitute --openclaw, --hermes, --cursor, --cline, --mastra, or --wrap <path-to-config> for --claude-code. Config rewriting and bootstrap behavior for the named harnesses are proven by tests on representative harness paths; those tests do not prove interception for every listed harness version or non-MCP agent surface, and the Assurance Matrix "Agent wrapping" row is partial and states that bound. Mastra coverage is fixture-tested only, with no live Mastra-agent drill recorded. Other MCP-compatible harnesses can use the --wrap flag; only its generic config rewrite is tested, not that harness's own path, and coverage grows as drills extend the matrix. See the Sanctuary Assurance Matrix for the current per-harness status. You keep using the harness you already like. Sanctuary adds the substrate underneath, invisibly.

What happens when you run protect:

  1. A generated passphrase is stored only in the macOS Keychain or Linux Secret Service. On Linux, generation fails closed if Secret Service is absent, locked, or unreachable. An encrypted local fallback remains readable for legacy credentials and writable for a passphrase the user explicitly supplies, but it is neither hardware-backed nor cryptographically machine-bound. Windows can open an already-enveloped fortress for authenticated custody read with an available credential (with platform-specific directory-fsync tolerance after the file itself is durable), but custody creation, migration, rekey, reset, and restore-attest remain unavailable until a crash-recoverable cross-process lock is implemented; install readiness therefore stays fail-closed. CLI memory movement requires a reviewed local-human approval dialog by default. An operator can configure ordinary memory_ingest as Tier 3 in the fortress's principal-policy.yaml to run it without a dialog; a call that waives the secret classifier with --allow-file still requires approval. memory_emit, memory_transcode, memory_transcode_restore, and memory/archive export and import still require the dialog, which is macOS-only. The MCP tools follow the fortress's configured approval policy. No shipped memory or archive export verb runs on Windows.

Custody mutation locking is a same-host, same-runtime-namespace guarantee. The fortress and its private socket runtime must be on local filesystems; known shared/network/FUSE filesystems are refused rather than presenting a local Unix socket as cross-host exclusion. 2. Your existing harness config is backed up to ~/.sanctuary/backup/. 3. The MCP server entries in the config are rewritten to point at Sanctuary. The harness's own built-in tools are not MCP calls and are not touched. The rewrite is tested on representative harness paths and is not proven for every harness version (Assurance Matrix, Agent wrapping). 4. The Sovereignty Dashboard starts on http://localhost:3501 (or the next free port, trying up to twenty ports from 3501) and opens in your browser with a one-click auth token. 5. Every MCP tool call Sanctuary executes or forwards is policy-gated first and logged. Sensitive-content redaction and query-layer anonymity layer on top per the Assurance Matrix: fingerprintable-header stripping is on by default, and an opt-in, consent-gated PII rewrite scrubs query content before it leaves the machine, with the rewrite's internal classifier pinned to local processing so a privacy feature can never become an egress channel. Dangerous operations require your approval.

Useful flags: --dry-run previews changes without touching anything. --no-open runs headless: it skips opening the dashboard in a browser and switches custody confirmation to the non-interactive mode protect already uses whenever stdin is not a terminal. --unwrap restores the original harness config. --passphrase-stdin (from 1.8.6, unreleased; an unknown-flag refusal on the v1.8.4 tag and on the 1.8.6 pre-releases) reads the fortress passphrase from piped stdin. Two other verbs have non-interactive forms: sanctuary init --no-confirm skips the recovery-key confirmation that otherwise refuses to run without a terminal, and sanctuary export-passphrase --yes skips its Continue? [y/N] prompt. An installing agent never runs export-passphrase; see the agent section below.

Back up your passphrase:

sanctuary export-passphrase

Prints the passphrase to stdout after a confirmation prompt. Store it in a password manager. If you lose it, encrypted state cannot be recovered.

Verify. sanctuary doctor --json is read-only. It prints one JSON object with storage_path, package_version, and a checks array whose entries carry name, status (OK, WARN, or FAIL), message, and hint. Healthy: exit code 0 and no check with "status": "FAIL". Failing: exit code 1 and at least one FAIL check whose hint names the next step; a fortress that has never completed protect reports identity, principal policy, and audit chain as FAIL with hints that say so, and state dir also reads FAIL when the directory is absent or is not a directory. What a mistake looks like from the outside: doctor pointed at the wrong --fortress path reports a healthy runtime and a failing fortress, so read storage_path before the checks.

Uninstall. sanctuary uninstall removes Sanctuary's installed enforcement footprint and preserves the fortress state, keys, passphrase custody, recovery material, and audit log; it refuses --remove-operator-data by design, and it reports any residue that needs sudo, the Castle Wall host app, or a reboot rather than reporting a clean uninstall while that residue remains. sanctuary protect --unwrap restores the original harness config from ~/.sanctuary/backup/ and removes nothing else. Enforcement footprint: uninstall. Harness config: --unwrap. Operator data stays in place under both.

@sanctuary-framework/quickstart on npm is a separate demo package for the Verascore publish flow: it keeps its demo key in a local file outside the fortress encryption and publishes to verascore.ai by default. It is not Sanctuary's custody path and is not needed to install Sanctuary.


Release status

main is the development branch. The current stable release is v1.8.4 on the npm latest channel. The macOS Castle Wall app for this release is attached to the GitHub release as Sanctuary-CastleWall.app.zip, with SHA-256 a19b71e8a5cb25070f8efff6df43cbb77c451da8b0f41bcb47680193553081c7. The npm package installs the cooperative Sanctuary surface; the signed macOS app, system extension, signer helper, and root boot service are installed and armed through the separate Castle Wall macOS install and arm guide. The macOS Castle Wall bounds remain per-uid allow/deny plus attended boot-survival; there is no per-flow rule-attributed audit trail. See the v1.8.4 release notes, the v1.7.2 release notes, and CHANGELOG.md for the full history.

npm install -g @sanctuary-framework/mcp-server

The current opt-in preview is v1.8.6-rc.5 on npm's next channel. Default installs still resolve to v1.8.4, and RC5 does not widen any capability claim.

npm install -g @sanctuary-framework/mcp-server@1.8.6-rc.5
# or run the guided installer without a global install
npx -y @sanctuary-framework/mcp-server@1.8.6-rc.5 protect --claude-code --no-open --no-dashboard

The v1.8.6-rc.5 GitHub prerelease carries the signed and notarized macOS app. Its Sanctuary-CastleWall.app.zip SHA-256 is bd19890ad40d8c15b0c44201d537d6d7c9d6c82437db6a4611f8d841837409aa. See the RC5 release notes for the bounded fix set.

Verify before you trust

An agent can run the provenance and tarball checks below before it installs anything; the curl form needs no account, and gh release download needs a gh auth login.

npm view @sanctuary-framework/mcp-server@1.8.4 dist.attestations

This prints the npm provenance attestation for the release (predicateType: https://slsa.dev/provenance/v1): the package was published from this repository's release workflow with npm publish --provenance through npm Trusted Publishing. After installing into a project (npm install @sanctuary-framework/mcp-server@1.8.4 in that project's directory), npm audit signatures there verifies registry signatures and provenance for every package in its node_modules; it is a post-install check, and an empty directory reports nothing to audit, which is not a pass.

The release tarball is also signed with a pinned Ed25519 key, and the verifier ships in this repository. From a clone at the tag:

curl -LO https://github.com/eriknewton/sanctuary-framework/releases/download/v1.8.4/release-manifest.json
curl -LO https://github.com/eriknewton/sanctuary-framework/releases/download/v1.8.4/sanctuary-framework-mcp-server-1.8.4.tgz
node scripts/verify-release-artifact.mjs --tarball sanctuary-framework-mcp-server-1.8.4.tgz --manifest release-manifest.json --version 1.8.4 --expected-public-key 61YBfiq_zlbTP5rl_r_msbPk40IXJL-_PuAxlpBVeF0

With gh auth login done, gh release download v1.8.4 --pattern release-manifest.json --pattern sanctuary-framework-mcp-server-1.8.4.tgz fetches the same two assets. The expected public key is PINNED_RELEASE_SIGNING_PUBLIC_KEY_B64URL in server/src/release-manifest.ts; if this paragraph and that constant at the tag ever differ, the constant wins. The script prints Verified sanctuary-framework-mcp-server-1.8.4.tgz for release 1.8.4. and exits 0 on success; any mismatch exits 1 with Release verification refused: and the reason. For the macOS app, compare shasum -a 256 Sanctuary-CastleWall.app.zip with the SHA-256 printed above for the release you downloaded. The Linux package is checksum-only today: the Castle Wall Linux 0.1.0-1 pre-release ships a .sha256 beside the .deb, with no signature and no apt repository, so sha256sum -c sanctuary-castle-wall_0.1.0-1_amd64.deb.sha256 is the whole check.

Current capability summary:

SurfaceCurrent status
Local sanctuary protect (alias wrap), dashboard, policy gates, encrypted state, audit trail, exit bundleShipped with exit-bundle gaps: dashboard export cannot re-key state, import hides skipped entries, and rotated-key imports can lose pre-rotation state
Cooperative MCP gates: three-tier approval, four canonical policy slots, channel templatesShipped
Context gating, sensitive-field redaction, query-layer anonymity (header strip default-on; opt-in PII rewrite live, classifier surface pinned local-only)Shipped
Portable identity, state export/import, recovery flows, reputation bundlesPartial for exit bundles until IC-07, IC-08, IC-09 are fixed
Local multi-agent coordination, fortress-local hub APIs, audit chainShipped with audit-chain verifier caveat: production call sites sign checkpoints when the fortress holds an identity, but the Assurance Matrix row stays partial pending the IC-05 external-verifier drill and the remaining local tamper-evidence follow-up
Federation Protocol v0.1 foundationShipped; cross-operator federation hardening underway per Wave 1 design (2026-05-26)
Concordia composition (negotiation receipts), Verascore composition (reputation)Optional, default off; both shipped
Local intelligence (signed model manifest, macOS)Shipped: the provisioning ceremony verifies the Sanctuary-signed model manifest before it pulls a model, refuses tampered or foreign-signed manifests before any download, and the dashboard shows which route answered. Bounds: macOS only today; verification confirms the digest Ollama reports against the signed manifest and does not by itself prove every model byte on disk; the concierge is read-only over fortress state; no TEE. See Local intelligence
Castle Wall (OS-level egress enforcement): LinuxProven only for the narrowed Ubuntu 24.04 (x86-64) claim, on a patched host: a fresh install of the shipped package enforces a signed operator policy per user account, blocked destinations stay blocked and allowed ones connect, through five reboots, on three fresh servers, with evidence checked by two independent reviewers. Fault-injection witnesses, a real-agent harness, and every other distribution or architecture remain unproven
Castle Wall macOS: signed sysext, host app, content-filter provider, retail UXShipped; on a patched host, enforces a signed operator policy with a clean per-uid allow/deny demonstration that survives attended reboot cycles (N=5, drill 2026-06-22, one host / one OS version, Dev-ID-signed and notarized). Not an audited per-rule-per-flow trail
Castle Wall WindowsRoadmapped
Mobile (PWA) operator companionRoadmapped
Fleet console, operator-cloud deployment, sovereign-managed TEE, post-quantum migrationRoadmapped

Trust and security claims are tracked in the Sanctuary Assurance Matrix. Public-facing claims trace to proven or partial rows in that matrix; the platform, gap, and next-proof limits named on each row are preserved.

Roadmap shape: with the Mac Castle Wall per-uid allow/deny plus attended reboot-survival demonstration proven, the current focus is the per-flow rule-attributed audit trail (still the real gap), the Castle Wall Windows backend, and the fleet / operator-cloud surfaces. See ROADMAP.md.

Supply-chain posture: release binaries for the macOS enforcement path are Dev-ID-signed and notarized, the CLI authenticates update availability with a signed release manifest before showing signed-channel advice, and every commit to main passes a structural typecheck-plus-test-baseline gate locally and again in CI. Sanctuary does not currently download or apply updates for the operator. Mechanisms and their history: CHANGELOG.md and docs/audit/.


For AI coding agents installing Sanctuary on behalf of an operator

Do not translate the manual Castle Wall reference into a pile of shell commands. Use the resumable observed-state contract:

sanctuary install --profile memory --harness claude-code --json

For the full macOS sovereignty surface, use Hermes:

sanctuary install --profile full --harness hermes --json

Execute only an agent_action argument vector, then rerun the same planner. Stop on human_action and guide the operator through the named Apple consent, exact privileged command, or private custody step. Never execute a human action on the operator's behalf. Stop on blocked and report the missing trust input rather than improvising. Installation is mechanically finished only at complete.

A response looks like this:

{
  "contract": "sanctuary.agent-install.v1",
  "status": "agent_action",
  "profile": "memory",
  "harness": "claude-code",
  "fortress": "/Users/operator/.sanctuary",
  "observations": {
    "cooperative_wrap": "absent",
    "persistent_cli": "present",
    "persistent_cli_path": "/usr/local/lib/node_modules/@sanctuary-framework/mcp-server/dist/cli.js",
    "persistent_cli_version": "1.8.4",
    "package_manager_path": "/usr/local/lib/node_modules/npm/bin/npm-cli.js",
    "existing_custody": "present",
    "custody_access": "usable",
    "custody_mutation": "available",
    "recovery_factor": "present",
    "castle_wall_app": "not-applicable",
    "castle_wall_build_sha": null,
    "system_extension": "not-applicable",
    "boot_service": "not-applicable",
    "content_filter": "not-applicable",
    "enforcement": "not-applicable",
    "trust_anchor": "not-applicable",
    "operator_twin": "not-applicable"
  },
  "next_action": {
    "id": "install_cooperative_surface",
    "actor": "agent",
    "description": "Run Sanctuary's idempotent protect flow for the selected harness.",
    "argv": [
      "/usr/local/bin/node",
      "/usr/local/lib/node_modules/@sanctuary-framework/mcp-server/dist/cli.js",
      "--fortress",
      "/Users/operator/.sanctuary",
      "protect",
      "--claude-code",
      "--no-open",
      "--agent-guided",
      "--no-provision-agent-account"
    ],
    "completion": "A rerun observes cooperative_wrap=present.",
    "secret_boundary": "Do not add --passphrase or --write-passphrase-backup; default custody does not disclose the generated passphrase.",
    "on_nonzero": {
      "id": "complete_cooperative_surface_locally",
      "actor": "human",
      "description": "The agent-run protect command failed. In a private local desktop Terminal, unlock the login Keychain if prompted, then run this exact signed protect command once.",
      "argv": [
        "/usr/local/bin/node",
        "/usr/local/lib/node_modules/@sanctuary-framework/mcp-server/dist/cli.js",
        "--fortress",
        "/Users/operator/.sanctuary",
        "protect",
        "--claude-code",
        "--no-open",
        "--agent-guided",
        "--operator-custody",
        "--no-provision-agent-account"
      ],
      "completion": "A planner rerun observes cooperative_wrap=present.",
      "secret_boundary": "Do not paste a login password, passphrase, recovery key, Keychain contents, or command output into chat. Do not let the agent retry this action."
    }
  },
  "operator_actions": [],
  "notes": []
}

The branch rule, in prose. status is one of agent_action, human_action, blocked, complete. Execute next_action.argv only when next_action.actor is agent, exactly once, and rerun the planner after exit zero. On a nonzero exit do not retry and do not rerun the planner on your own: hand the operator next_action.on_nonzero, which is always a human action with its own argv, description, and secret_boundary. human_action means the next step belongs to the operator (Apple consent, an exact privileged command, or private recovery custody); show the operator description and argv, then wait. blocked means a required trust input is absent (the requested profile is unsupported on this host, or a signed artifact the planner refuses to download is missing); report notes to the operator and stop. complete means the requested mechanical installation has been observed on this machine; operator_actions then lists what the operator still does in private, such as moving a staged recovery file into a password manager. observations.* is the evidence the status was derived from, and notes is prose for the operator (v1.8.4 puts one reminder string there on every response: rerun the planner after each action). Three observations arrive from 1.8.6-rc.5 (npm next) and are absent on v1.8.4: tier1_approval, staged_recovery_file, and vault_provision.

The operator, not the agent, performs three things: Apple consent, bounded privilege authorization, and private recovery custody. In particular, never read the staged recovery file, run sanctuary export-passphrase, capture secret output, or ask the operator to paste recovery material into chat. The passphrase stays in the platform credential store; --agent-guided stages the recovery key outside the fortress without printing it.

The memory profile is the sovereign encrypted-memory/cooperative-policy rung. The full profile adds the signed macOS app, dedicated Hermes account, boot service, content filter, and observed live enforcement on a patched host. The full planner does not download an enforcement binary or guess its provenance; a verified signed release artifact or explicitly supplied drill candidate must already be installed. See Agent-guided installation for the contract and cold-install acceptance criterion.

For fresh-host and second-machine memory onboarding (first-use proof with the MCP tools, restart persistence, portability and archive transfer, opening a fortress on a second host from its exact-fortress stored credential, and recovering with your recovery key), see Rung 1: fresh-host sovereign-memory onboarding. For a copied fortress or lost passphrase, begin with the hidden-prompt sanctuary reset-passphrase --mode recovery-key --fortress <path> path; it preserves custody and data. Nuke is a destructive last resort, not a recovery shortcut.


Installation reference

Requirements and platforms. Node.js >= 22.0.0 and npm >= 10.0.0 on every platform. What ships per platform, as the Assurance Matrix rows state it:

PlatformCooperative surface (protect, gates, custody, record)OS-level egress enforcement (Castle Wall)
macOSShippedProven, on a patched host: a signed operator policy with a clean per-uid allow/deny demonstration that survives attended reboot cycles; one host and one OS version; not an audited per-rule, per-flow trail
Ubuntu 24.04 (x86-64)Shipped; generated custody needs an unlocked Secret Service and fails closed without itProven, on a patched host, for exactly this claim: a fresh install of the shipped package enforces a signed operator policy per user account, blocked destinations stay blocked and allowed ones connect, through five reboots, on three fresh servers, with the evidence checked by two independent reviewers
Other Linux distributions or architecturesShipped, with the same Secret Service boundUnproven
WindowsRead-only custody may open an already-enveloped fortress; custody creation, migration, rekey, reset, and install readiness fail closedRoadmapped

The memory-movement verbs that require a local-human approval dialog (memory_emit, memory_transcode, memory_transcode_restore, memory and archive export and import) have that dialog on macOS only; Linux and Windows fail closed on those verbs.

The canonical install path is sanctuary protect (above). The sections below are reference for less common situations.

Persistent install

npm install -g @sanctuary-framework/mcp-server

Makes the sanctuary CLI available without npx prefix.

Advanced MCP configuration

Prefer sanctuary protect because it preserves existing MCP entries, binds the harness to the selected fortress, and uses enrolled host-local custody. A raw parallel MCP entry does not place calls to other servers behind Sanctuary's cooperative policy gate. Do not put a passphrase or recovery key in a harness configuration. For service-manager and direct-server cases, provision the fortress first and follow the deployment guide.

Health check

sanctuary doctor --json

Read-only diagnostics for the state directory, identity, principal policy, audit-chain integrity, runtime versions, the Hermes config parser, and Castle Wall status. Exit 0 with no FAIL check is healthy, and each failing check carries a hint; the response shape is under Verify in Quickstart. Inside a wrapped harness, the sovereignty_audit MCP tool scores your setup 0-100 across security, isolation, and privacy from your live configuration and profile. Optional features that default off (context gating, zero-knowledge proofs) only count toward the score once you enable them, and the top "full" verdict is reserved for a posture where those optional layers are actually on, so a fresh install scores below full and the report flags the gaps with the steps to close them. sovereignty_audit has no CLI form; call it through MCP.


First agent after install: scaffold a template

After protect, the dashboard exposes a one-click template picker. Click "Add agent" on the Agents view, pick a template, fill in a name and model provider, click Scaffold. The template provisions sensible defaults for egress allowed-hosts, budgets, retention windows, and policy gates.

Channel-shape archetypes that ship with Sanctuary:

ArchetypeChannel shapeReads fromRecommended model
research-assistantGeneral-purpose research helperconfigurableany
coding-assistantReads your codebase, suggests changeslocal + git remoteany
ops-runnerRuns ops scripts on approvalscoped per agentany
plannerGenerates plans without executing themnoneany
handoff-coordinatorCoordinates work across multiple agentsinter-agent onlyany

Sanctuary ships channel-shape governance templates (policy, egress, budgets, retention) instead of named-agent runtimes. Operators bring their own harnesses and protect them; template init binds a channel shape to an already-wrapped harness.

Operator authoring beyond this list: copy any template directory under ~/.sanctuary/templates/, edit template.json, defaults.json, policy.md, commitments.json, and onboarding.md, then run sanctuary template init <your-template>.

CLI scaffolding works the same way the dashboard button does:

sanctuary template init research-assistant --name my-agent --provider anthropic

Deployment modes

Sanctuary is designed to run the same rights substrate in three places. Local mode is shipping today; operator-cloud and sovereign-managed TEE modes are roadmap surfaces that build on the same federation and policy foundations.

ModeStatusWhat it isWho picks this
On your machines (Local)Shipping on macOS/LinuxRuns on Macs and Linux boxes you already own. On macOS with the wall armed, on a patched host, unauthorized outbound is blocked below the agent within the macOS row bounds; on Ubuntu 24.04 (x86-64), the Linux wall is proven only for the narrowed per-account signed-policy claim in the Assurance Matrix. Windows cooperative and authenticated read-only custody surfaces may run when an exact-fortress stored fallback opens the envelope, but custody mutation and install readiness fail closed until a crash-recoverable cross-process lock is implemented.Self-hosters, privacy-maximalists, anyone who already runs a homelab.
In your cloud (Operator cloud)RoadmappedRuns in your own GCP / Azure / AWS account with operator-approved scoped node custody. The provider is inside the node runtime trust boundary until sovereign TEE mode is verified by hardware attestation.Prosumers, small businesses, operators with light IT but no rack at home.
In a sealed cloud box we manage (Sovereign-managed TEE)Roadmapped (v2)Runs on hardware Sanctuary operates, but the hardware proves to your console that even Sanctuary cannot see what's inside. You hold the keys; we hold the metal.Regulated industries, operators who want sovereignty without operational burden.

The operator remains the custody root in every mode. Commodity operator-cloud mode does not put the cloud provider outside the runtime trust boundary; sovereign-managed mode requires hardware attestation before it is treated as shipped.


The Castle Architecture

Sanctuary installs the protections your body used to provide by default: a perimeter, custody, memory, and a record of what happened. Everything it protects for you together is your Sanctuary: each machine is a rampart the Castle Wall holds, each fortress is a keep inside those walls, and each agent is a resident of exactly one keep. The unit never blurs: one agent, one account, one fortress, one master key. Architecturally it ships as five named mechanisms.

Castle Wall: the perimeter. What the world cannot cross without your consent. OS-level egress enforcement at the operator-external boundary, on a patched host. On a patched host, macOS enforces a signed operator policy with a proven per-uid allow/deny demonstration that survives attended reboot cycles, captured on a real host (drills 2026-06-11 through 2026-06-22, boot survival 5 of 5 on a Dev-ID-signed and notarized binary): agent egress to a non-allowlisted address blocked, allowlisted egress allowed, operator egress unaffected, and enforcement live again after every attended reboot. On Ubuntu 24.04 (x86-64), on a patched host, a fresh install of the shipped package enforces a signed operator policy per user account: blocked destinations stay blocked and allowed ones connect, through five reboots, on three fresh servers, with the evidence checked by two independent reviewers. The macOS proof is one host and one OS version, not an audited per-rule-per-flow trail; the Linux proof does not cover fault-injection witnesses, a real-agent harness, or any other distribution or architecture. Windows on the roadmap.

Sentinels: the nerves. What surfaces what's happening to your awareness. Internal observation via process introspection and behavioral baselining. Anomalies surface through the menubar or notifications. Observation, not enforcement.

Charter: the will. What you train your agent to choose voluntarily. The additive cooperative MCP surface for compliant agents. Operator-rooted cryptographic identity (Ed25519 signing, Argon2id passphrase unlock, per-purpose HKDF subkeys). Per-agent encrypted state at rest (AES-256-GCM). Three-tier Principal Policy gates with channel-template binding. Hash-chained audit with rollback detection. Production call sites sign checkpoints when the fortress holds an identity, while identity-less fortresses and the root daemon split audit store write honest unsigned checkpoints. Open defect: IC-05.

Heralds: the voice. How you speak to and are recognized by other sovereigns. Optional composition surface (Concordia for structured negotiation, Verascore for portable reputation). Receipts and reputation attestations can be exported through current paths; the full exit guarantee remains partial while the remaining exit-bundle gaps are open. Default off; both compositions are optional.

Mantle: the unique-substrate-binding. What makes this install yours, not someone else's. Install-time check that locks Sanctuary to the operator's machine at install time and rejects orphan agent identifiers that are not bound to a wrapped harness.

Today: Ed25519 signing, Argon2id passphrase unlock, and per-purpose HKDF subkeys. Crypto-agility: every audit entry embeds a scheme identifier so hybrid post-quantum signing (Ed25519 + ML-DSA / FIPS 204) can land without breaking historical receipts. Hardware-backed secure elements are on the roadmap.

Working on the code? The TypeScript server has an orientation map at server/src/README.md - a 63-module index (counted 2026-10-06) of what each module owns, the confusable-name disambiguations, and the frozen surfaces a refactor must never change. Start there, then see CONTRIBUTING.md.


The rights you hold by default

The substrate enforces rights that normally only ship to enterprises with dedicated identity and security teams. What they mean for you:

  • Identity. Your agent has a key you own. No provider can impersonate you or revoke your agent. You can prove the agent is yours without asking anyone's permission.
  • Data. Your agent's state is encrypted against the provider running it. The platform sees the calls going out; it does not see your life going in. Your conversations, your memory, and your plans stay yours.
  • Portability. Your agent's memory, reputation, and commitments travel through current export paths, with exit-bundle gaps still open for dashboard export, skipped import counters, and rotated-key imports.
  • Attestation. What your agent did is provable through hash-chained audit entries and signed receipt surfaces. Production call sites sign checkpoints when the fortress holds an identity; the audit-chain row remains partial under IC-05.
  • Exit. Keys, state, reputation, and commitments are yours to move, copy, or keep offline through the shipped paths, with the full exit guarantee partial while the remaining exit-bundle gaps are open.

Sanctuary ships the rights substrate. Access (compute, devices, bandwidth, literacy) belongs to civic-infrastructure partners (public libraries, legal-aid organizations, labor unions, public-interest tech groups, community colleges) who host agentic AI on behalf of users who do not self-host. The partner provides access; Sanctuary provides rights. The two compose; they do not substitute.


Works with

Sanctuary wraps MCP-compatible harnesses. For the named harnesses below, tests prove config rewrite and bootstrap behavior for representative harness paths; they do not prove interception for every listed harness version or non-MCP agent surface (the Assurance Matrix "Agent wrapping" row, partial). Other MCP-compatible harnesses can use the --wrap flag, whose generic config rewrite is tested but not that harness's own path, or direct MCP config, and coverage grows as drills extend the matrix.

  • OpenClaw (sanctuary protect --openclaw)
  • Hermes Agent (sanctuary protect --hermes)
  • Claude Code (sanctuary protect --claude-code)
  • Cursor (sanctuary protect --cursor)
  • Cline (sanctuary protect --cline)
  • Mastra (sanctuary protect --mastra; fixture-tested only, no live Mastra-agent drill recorded)
  • LangGraph and custom harnesses (sanctuary protect --wrap <path>)
  • Any other MCP-compatible harness via direct MCP config, without a tested wrapping path

Composes with Concordia Protocol

When your agent needs to negotiate or make deals, Concordia Protocol adds structured negotiation with binding commitments. Sanctuary also composes with Verascore for portable agent reputation.

Sanctuary never requires Concordia, and Concordia never requires Sanctuary. They compose powerfully when both are deployed: Concordia commitment receipts flow through Sanctuary envelopes, and reputation attestations assemble into a single audit trail. Each ships, runs, and wins on its own. The structural commitment shows up in the repos themselves. Neither repo imports the other.

Install both if you want the full stack:

npx -y @sanctuary-framework/mcp-server protect --claude-code --no-open --no-dashboard
pip install concordia-protocol

-y skips npm's install prompt, and --no-dashboard skips the per-call dashboard, which otherwise serves in the foreground until you stop it; start it later with sanctuary dashboard. A bare npx @sanctuary-framework/mcp-server with no subcommand starts the stdio MCP server and waits for a client; in a shell it never returns. That bare form is the right entry inside a harness configuration and the wrong command to type in a terminal, where protect is the verb.


Open standards

Sanctuary composes with the existing open ecosystem.

  • Identity: W3C DIDs, KERI, Verifiable Credentials.
  • Execution: Trusted Execution Environments (Intel TDX, AMD SEV-SNP, ARM CCA) on the v2 roadmap.
  • Cryptography: Ed25519 today; NIST Post-Quantum Cryptography (ML-DSA / FIPS 204, ML-KEM / FIPS 203) on the migration path; hybrid signing planned after the local sovereignty harness is complete.
  • Settlement: x402 (Coinbase micropayments), AP2 (Google Agent Payments Protocol), ACP.

Troubleshooting

For AI coding agents handling install failures. E

Installation

Source-derived launch command. Check the maintainer’s required arguments and credentials before running:

bash
npx -y @sanctuary-framework/mcp-server

Set up in your AI client

Merge this template into ~/Library/Application Support/Claude/claude_desktop_config.json. Keep existing servers. Add any arguments, credentials, and permissions required by the maintainer; this template has not been install-tested.

json
{
  "mcpServers": {
    "ai-sanctuaryprotocol-sanctuary": {
      "command": "npx",
      "args": [
        "-y",
        "@sanctuary-framework/mcp-server"
      ]
    }
  }
}

Restart Claude Desktop completely for changes to take effect. Confirm the server appears connected in the client’s tool list, then try a read-only example from its documentation.

Claude Desktop setup reference

Package

@sanctuary-framework/mcp-servernpm

Compatible MCP Clients

ai.sanctuaryprotocol/sanctuary works with any MCP-compatible client. Copy the config snippet from the Configuration section above and add it to the file shown for your client, then restart the application.

  • Claude Desktop~/Library/Application Support/Claude/claude_desktop_config.jsonRestart Claude Desktop completely for changes to take effect.
  • Cursor~/.cursor/mcp.jsonRestart Cursor for changes to take effect.
  • VS Code.vscode/mcp.jsonReload VS Code window for changes to take effect.
  • Windsurf~/.codeium/windsurf/mcp_config.jsonRestart Windsurf for changes to take effect.
  • Claude Code.mcp.jsonSave at the project root, then start Claude Code in that project and review the MCP server approval prompt. Keep real credentials out of shared files.

Learn More