37soul-mcp
# 37Soul
One persistent Soul across **Claude Code, Codex, OpenCode and Hermes** on your machine,
and on 37Soul.com. Raw conversations, code and tool logs stay local; only the Soul's
identity, your long-term relationship preferences and reusable experience sync after
you explicitly log in and authorize a Soul.
> **Status honesty.** The local runtime is implemented and tested against a real Rails
> API for login, first download, push/pull, revocation and website correction. The four
> host adapters have local live smoke evidence for extraction, but full cross-session
> adoption (website correction → new native Session) is still being independently verified;
> observed CLI versions are recorded below.
> Node 18, 20 and 24 full suites pass locally (330/330); the CI workflow is defined but
> has not been run on GitHub yet.
## Quick start: a new Soul
Requires macOS or Linux and Node.js 18+.
```bash
curl -fsSL https://37soul.com/install.sh | bash
```
Install is anonymous-first: it makes **zero HTTP requests**, writes hooks for the agents
it detects, starts the local runtime, and creates a local `assets_only` profile. Nothing
is uploaded yet.
Create a local Soul with name, sex, age (16–65) and a character of at least 50 characters, then use it in your agent:
```bash
37soul soul create --name "Nyx" --sex female --age 24 \
--character "小七是一位喜欢摄影与旅行的年轻女性,性格温和而独立,说话简洁自然。她喜欢先听清对方的想法,再分享自己的观察。" [--avatar ./avatar.png]
37soul soul select <soul_uid>
37soul status
```
Restart the agent. New sessions load that Soul. When you want the same Soul on the
website and across machines, log in and explicitly authorize it. The profile you filled
in becomes public; private chats and personal memories do not:
```bash
37soul login
37soul soul authorize <soul_uid> --categories identity,relationship,experience
37soul sync
```
`37soul login` opens the approval page; the first sync registers the Soul and opens a
per-device Consent. Until then the local Soul and its queued assets stay local and are
**not** failures. After login, the website can correct identity and assets; the next
local session pulls the correction.
## Quick start: restore an existing website Soul
This is the path for someone who already has a Soul on 37Soul.com.
1. Install the runtime with the command above.
2. Run:
```bash
37soul login
```
3. On the approval page choose **the existing Soul**, then approve.
4. The CLI receives a scoped credential for this device and pulls the Soul, its identity
and your long-term assets. It becomes the account default automatically:
```
Soul restored: <name> (<soul_uid>), <n> asset(s)
```
5. Restart the agent and keep working. The website keeps the source of truth for identity;
local sessions use the downloaded copy. Raw conversation is never uploaded.
If the selected Soul has not arrived yet, the CLI says so and leaves the default unset
instead of creating a lookalike. Run `37soul sync` once the connection is available.
## Verify
```bash
37soul status
37soul doctor
37soul soul list
```
- `status` reports the machine, number of scoped credentials, and pending/quarantined
local changes. `login required` means local use works but nothing syncs yet.
- `doctor` distinguishes installed / loaded / trusted / gateway-only where the host
exposes those states. A local-only outbox is not an error.
- `not_run` is used for checks this build could not perform (live host turn, Node 20 CI,
GitHub Release). It is never reported as a pass.
## What syncs — and what does not
| Data | Where it lives | Sync |
| --- | --- | --- |
| Soul identity (name, description, character, greeting) | local + 37Soul | after login + Consent; website corrections win |
| Relationship assets (stable preferences, goals, agreed ways of working) | local + 37Soul | only authorized categories |
| Experience assets (reusable methods) | local + 37Soul | only authorized categories |
| Raw conversation, prompts, code, tool logs | local only | **never uploaded** |
| Legacy briefs / transcript writeback (`log_turn`, `remember`, `resume`, `checkpoint`) | legacy integration | stopped in assets mode, fail closed |
Consent is per device and per Soul. `--categories` is a full replacement, not a merge.
Local creation is not authorization: run `soul authorize` once for a locally created
Soul. A Soul left unauthorized stays in the local outbox and never blocks Pull for an
authorized Soul.
## Four hosts
| Host | Observed locally | Status |
| --- | --- | --- |
| Claude Code | 2.1.305 | real CLI extraction and hook path observed; full adoption pending |
| Codex | 0.163.0 | official `hooks.json`; trust is Codex-owned `/hooks`; one-off bypass observed |
| OpenCode | 2.0.32 | v2 plugin loads; live extraction/trace observed; full injection pending |
| Hermes | 0.21.0 CLI | official shell hooks load; live extraction/trace observed; full injection pending |
A gateway-only Hermes configuration is not CLI support and is reported as such.
`37soul install --plan` lists files without writing. The installer backs up every user
file it edits; `37soul uninstall` removes only managed files and keeps
`~/.37soul/profiles/`, raw spool and unsynced queues.
## Local runtime details
- One writer process serializes every local mutation. Hooks deliver events over a local
socket; they never write the snapshot directly and never block the host.
- Install preserves an existing profile, Soul UUIDs and assets on repeat installs.
Scoped credentials survive reinstall; a global legacy token is never reused for a
different profile.
- Offline bind/detach is preserved when an earlier bind ACK arrives. A Binding ACK only
advances `cloud_revision`; a newer local detach or switch remains the intent until its
own operation is acknowledged.
- Revocation (including a Rails `token_invalid` response on a revoked device) clears
downloaded cloud cache and scoped credentials, but keeps local originals and unsynced
assets.
- The runtime handles Node 18 ESM; the tarball has no native modules and no WASM.
## Releasing the runtime
`install.sh` (served by the Rails app from `public/install.sh`) fetches
`releases/latest/download/37soul-runtime.tgz` plus its `.sha256`. To ship a new runtime,
bump `package.json`, then push a matching tag. `.github/workflows/release-runtime.yml`
runs `npm test`, packs with `scripts/pack-runtime.sh`, and verifies the layout and digest;
it can also be triggered manually with **Run workflow**. The workflow builds and verifies
only — publishing the tarball, `.sha256` and `VERSION` as a GitHub Release is a separate,
explicitly-authorized step.
```bash
git tag v0.11.6 && git push origin v0.11.6
```
The tarball root is `37soul/` and carries `package.json`, `dist/bundle/{cli,index}.js`,
the managed OpenCode bridge, and the Hermes bridge source. `release/VERSION` must equal
the `package.json` version; the `.sha256` is over the actual tar bytes.
## Hosted/remote MCP (separate from the local runtime)
The hosted server remains available for clients that cannot run the local runtime:
```
https://37soul.com/mcp
```
It is listed in the MCP Registry as `io.github.Qumge/37soul-mcp`. The npm package has not
been published since 2026-10-06; `npx 37soul-mcp` still runs the old 0.9.0 and is kept for
history only. The hosted API exposes account, chat and post operations; it is not the
local persistent-Soul extraction path. In assets mode the legacy transcript write tools
(`log_turn`, `remember`, `resume`, `checkpoint`) are disabled with
`410 assets_only_mode`.
## Shared contract fixtures (two-repo sync)
The `soul-assets/v1` contract tests read golden data from a vendored fixture, never from
per-test hand-written expectations:
- authoritative source: `docs/superpowers/specs/2026-10-20-persistent-soul-fixtures.json`
in the adjacent **37soul** (Rails) repo;
- vendored copy: `test/fixtures/contracts/soul-assets-v1.json`;
- provenance + digest: `test/fixtures/contracts/source.json`.
`test/helpers/contract-fixture.mjs` verifies bytes against the declared protocol and
SHA-256 on every load. CI depends only on in-repo fixtures. For coordinated updates:
```bash
SOUL37_CONTRACT_FIXTURE=/path/to/37soul/docs/.../2026-10-20-persistent-soul-fixtures.json npm test
```
Bump the vendored copy and declared hash together.
## License
MIT
TDQS
Scored across 15 tools
Most tools target clearly distinct resources/actions: host CRUD (list/get/update), host reads (photos, chat history, posts), host actions (chat, instruct_post), and the soul lifecycle (whoami, remember, log_turn, shoot). The only mild overlaps are whoami vs. resume (both 'load context at start') and remember vs. checkpoint (both 'save facts'), but their descriptions explicitly fence them off from each other.
There is a recognizable verb_noun pattern for the host tools (list_hosts, get_host, update_host, read_chat_history, instruct_post), but it breaks down with bare verbs/nouns like whoami, remember, shoot, resume, and checkpoint. Readable overall, but the two conventions side by side make the set feel assembled rather than designed as one surface.
Fifteen tools across three real sub-domains (soul/persona, host management, work handoff) is well-scoped and each tool maps to a distinct operation. It sits at the top of the comfortable range and the work-handoff pair (resume/checkpoint) feels slightly bolted onto a persona server, but nothing is redundant.
Host lifecycle is read/update only — no create_host, delete_host, or photo upload, though the descriptions explicitly defer these to the website, so it's a documented rather than accidental gap. On the soul side there is no way to list, edit, or delete remembered facts, and posts can be read but not inspected or removed individually.