Content
# substrate-service
**A long-term memory that every AI you use can share — that stays yours, and stays usable no matter how much you pour in.**
>
Your context today is scattered across tools, and every new AI you open starts from zero — you re-explain yourself over and over. Worse, the memory you *do* accumulate tends to rot: pile in enough notes with no one keeping order, and a few months later it's an unusable heap. This is one long-term memory your AIs share, kept in order by a tireless librarian that files each new thing where it belongs — so however fast it grows, you can keep adding freely and it stays usable.
## What it feels like
**9 am, on your phone** — you tell your chat assistant: *"Remind me to renew the car registration this week, and save this dumpling place — it was great."*
**11 pm, on your laptop** — you ask your coding agent: *"What's still on my plate this week?"* The registration is in its answer, and the dumpling place is already on your list. You never repeated yourself — every AI you use reads and writes the same memory, and the keeper had already filed each thing where it belongs.
## What you get
**Every AI you use shares it.** Connect Claude, Codex, Hermes — or whatever you reach for next — and it arrives already knowing your preferences, what you've saved, what you're in the middle of. One memory, every tool, no reintroductions.
**You can pour into it freely — it stays usable.** Saving takes one line and lands instantly; a keeper agent then triages each piece in the background — what belongs in the main store, what stays low-priority, what deserves a whole new category. You get to be careless about adding; the memory stays clean anyway.
**It's yours to keep — plain files, offline, forever.** The memory is just markdown in a git repo. One `git clone` and you walk away with all of it: readable, offline, not locked in anyone's service. If this project vanished tomorrow, you'd lose nothing.
**It matters most when a team shares it.** For one person, keeping the memory tidy is a convenience. For a team — dozens of people and their agents all writing into one memory — it's the difference between a shared brain and a swamp: deduping, reconciling who-said-what, flagging what's stale or contradictory. The more people pour in, the more that governing layer earns its keep.
## How it earns trust
One design choice holds it all together: **the AI only advises — it never writes your files itself.**
The keeper reads what comes in and outputs only a *decision* — file it here, hold it, ask you, refuse it — always with a plain reason; ordinary, testable code carries that decision out. Hidden instructions in captured content cannot directly become file operations: an allow-listed executor validates and applies the decision, backed by adversarial regression tests. Recognized credential patterns are refused before they land, and audits record metadata without copying private write content or credentials. This does not make any hosted system risk-free, but it sharply limits what a poisoned input can do and leaves a visible trail.
This shape has a name: **Governed Agent Memory** — one long-term memory, many agents (and one day, many people), governed so it stays honest, with you keeping the final say. The full pattern: **[docs/05](docs/05-pattern-gam.md)**.
## How it's different
It's **not** another note-taking app, and not one chatbot with memory bolted on. It's the layer *underneath* — the place your data lives, that any AI can plug into.
| | Built-in AI memory<br>ChatGPT/Claude | Agent-local memory<br>Hermes/OpenClaw | Note-taking apps<br>Obsidian/Notion | **substrate-service** |
|---|---|---|---|---|
| Who shares it? | That app only | That agent on that machine | You search it yourself | **All of your agents** |
| Who curates it? | Platform black box | Each agent writes ad hoc, with no shared rules | You do it manually | **A server-side keeper enforces shared rules** |
| Who owns the data? | Locked into the platform | Local, but fragmented across agents | Depends on the app | **Plain markdown + git, fully yours** |
**Why an MCP version?** The substrate engine ([v1](https://github.com/wheam/substrate)) packages governance as skills installed into each agent. It is powerful, but every new agent needs the skills, every machine needs a clone of the instance, and governance depends on each agent following the rules. That per-agent setup tax grows quickly. This project (v2) centralizes the same idea as an MCP service:
| | substrate engine (v1, skills) | **substrate-service (v2, MCP)** |
|---|---|---|
| Add a new agent | Install ~10 skills + clone the instance | **One prompt + a one-time code** |
| Local device state | A clone + git credentials on every machine | **No local state; connect directly** |
| Governance | Each agent must follow the rules voluntarily | **Enforced server-side; no agent can bypass it** |
| Phone access | Awkward with a skills-only model | **Naturally reachable as a service** |
| Maintenance | Every agent runs doctor/sync itself | **Automated by the keeper and nightly jobs** |
```text
you
"save this"
│
┌────────────┼────────────┐
▼ ▼ ▼
Claude Code Hermes Codex … ← your agents, connected over MCP
└────────────┼────────────┘
▼ MCP / capture endpoint
┌─────────────────────────────────┐
│ substrate-service │
│ ├─ isolated inbox (fast, no LLM on the write path)
│ ├─ keeper agent (decides, never writes directly)
│ └─ your instance (markdown + git)
└────────────────┬────────────────┘
▼ push
private GitHub repo (backup + history + exit hatch)
```
## Get it running · Tool List
There are two tested ways to run it. Pick one:
- **Cloud (the full setup, reachable from phones and remote agents)** — use the Railway template below, or hand [INSTALL_FOR_AGENTS.md](INSTALL_FOR_AGENTS.md) to an agent you already use (Claude Code / Codex / Hermes). Starts at roughly $5/month.
- **One local machine (no cloud)** — start the complete service with one `node` or `docker compose` command on an always-on machine. It takes **about 60 seconds** and has no trial limit. See **[run-local.md](run-local.md)**. The tradeoff: local-only mode does not reach across devices; phones and remote agents need the cloud setup.
>
>
> - **Cloud (full setup, accessible from mobile and remote agents)** - use the Railway template below or provide [INSTALL_FOR_AGENTS.md](INSTALL_FOR_AGENTS.md) to an agent you are already using (Claude Code/Codex/Hermes). Costs approximately $5/month.
> - **Local machine (no cloud)** - launch the complete service with a single `node` or `docker compose` command on a machine that is always on. This takes **about 60 seconds** and has no trial limit. See **[run-local.md](run-local.md)**. The tradeoff is that local mode does not work across devices; mobile devices and remote agents require a cloud setup.
[](https://railway.com/deploy/AlyM7t)
### Deploy to Railway · Deployment to Railway
This repository keeps its **Dockerfile in the `service/` subdirectory** (`service/Dockerfile`). Every `COPY` path is relative to `service/`, and the entrypoint is `docker-entrypoint.sh → node src/server.js`. Whichever Railway path you use, confirm these three settings or the service will not start:
1. **Root Directory = `service`** — otherwise Railway looks for the Dockerfile at the repository root, the `COPY` paths do not line up, and the build fails. The root [`railway.json`](railway.json) declares Dockerfile builds, the `/healthz` check, and the restart policy; Root Directory must still point to `service` in the wizard or dashboard.
2. **Persistent volume mount path = `/data`** — `DATA_DIR` defaults to `/data`, and the instance is cloned into `/data/instance`.
3. **Required environment variables** — `REPO_URL` (the git URL of your private instance repository) and `TOKENS_JSON` (the client-token table as JSON). Every other variable has a safe default; see **[INSTALL_FOR_AGENTS.md §4/§5](INSTALL_FOR_AGENTS.md)** for the full list and the `TOKENS_JSON` format. `DEEPSEEK_API_KEY` is optional. Without it, the keeper does not file inbox items and `recall` is not registered, leaving a read-only fallback.
### Connect more agents with one prompt · Connect More Agents with a Single Prompt
Once the first primary token is installed, adding the next agent requires no configuration change or restart. In the primary channel, ask an agent to “mint an enrollment code” (`enroll_create`). It returns a paste-ready prompt like this:
```text
Read https://<your-domain>/enroll and follow the protocol. Your one-time code is abc123… (single use, expires in 15 minutes).
```
Give that prompt to any new agent. It calls `POST /enroll` to exchange the code for its own revocable token, then configures and verifies itself against the public protocol — no dashboard work and no restart. Use `enroll_revoke` to disable it immediately at any time.
## Daily use · Daily Usage
Once installed, use natural language and let your agent call the matching tool:
| You say | Tool | What happens |
|---|---|---|
| “Save this / put this in my knowledge base” | `save` | Lands in the inbox; the keeper chooses a zone |
| “Remember that I… / my preference is…” | `remember` | Lands in the inbox and is filed under memory |
| “Save this restaurant / add this to my reading list” | `collections_upsert` | Lands in the inbox and is filed as a collection item |
| “Add a task / what is left this week?” | `todo_add` / `todo_list` | Adds or lists your tasks |
| “Find what I saved about X / what do I know about Y?” | `search` / `recall` | `recall` answers with citations and gap hints |
| “What is waiting for my decision?” | `inbox_list` / `inbox_resolve` | Surfaces cases in the primary channel; your ruling becomes precedent |
Every write enters the isolated inbox first and is reviewed by the keeper before filing — **accepted does not mean filed**. An agent should only say: “Accepted; the keeper will file it.”
## Status · Status
Personal alpha, used daily by the author as tenant #1. Every milestone is running on real hardware: **M0–M3** (read-only MCP + zone ACL + bearer authentication + audit → write path + keeper gate → capture endpoint + iOS app); **M4.0–M4.9** (dashboard + precedent exam / read-side intelligence / lossless tiers / primary-channel agent / provenance + schema evolution + approval night shift / injection resistance / self-service enrollment / digest delivery to persistent hosts). See **[docs/03 §8/§9](docs/03-next-version-spec.md)** for milestones and decision records.
## Docs · Documentation
- **[docs/05 — Governed Agent Memory](docs/05-pattern-gam.md)** — a standalone, public explanation of the pattern.
- **[INSTALL_FOR_AGENTS.md](INSTALL_FOR_AGENTS.md)** — an installation protocol to hand to an agent so it can set up the service for you.
- **[run-local.md](run-local.md)** — try it on one local machine without the cloud.
- **[docs/README.md](docs/README.md)** — overview of the design and milestones (02 productization / 03 next-version spec / 05 pattern).
- Storage engine (open source, separate repository): [substrate](https://github.com/wheam/substrate).
## Contributing · Contributing
- **Write service code:** see **[CONTRIBUTING.md](CONTRIBUTING.md)** for hard boundaries, contract-first development, precedent exams, and adversarial cross-source review.
- **Run the tests:** `cd service && npm test` (the offline suite has no external dependencies and includes precedent regression exams).
## Repo layout
```
INSTALL_FOR_AGENTS.md installation protocol for agents
run-local.md local, no-cloud walkthrough
CONTRIBUTING.md development rules, contracts, exams, and adversarial review
railway.json Railway contract: Dockerfile build, /healthz, restart policy
docker-compose.local.yml one-command local setup (about 60 seconds)
docs/ design docs: 02 productization, 03 spec, 05 public pattern
service/ MCP server: Node 22 + official SDK; tests and Railway image
app/ experimental iOS capture app and share extension
```
## License
MIT — see [LICENSE](LICENSE).
MCP Config
Below is the configuration for this MCP Server. You can copy it directly to Cursor or other MCP clients.
mcp.json
Connection Info
You Might Also Like
No recommendations available