Substrate v0.7.0 · pre-release
EN ES

Keep your development process out of the agent’s head.

Substrate is a local-first work tracker that lives in your repo and is driven by your coding agents over MCP. The process is defined once, as data — so every agent, this session or the next, reads the same durable state and hits the same gates at write time.

v0.7.0 is pre-release: not on npm yet, so install from source until it ships.

Why not a todo list, a CLAUDE.md, or GitHub Issues?

Two things those can’t do — which are the whole reason Substrate exists.

A session todo list evaporates

Todo lists native to the agent runtime are per-session. When the context resets, so does everything the agent knew about where the work stood.

A convention file drifts

A CLAUDE.md is durable but unstructured, and it’s advisory: as context fills, agents drift away from it — and nothing tells them at the moment they break it.

Issues live outside the repo

GitHub Issues is durable and structured, but it sits outside the working tree — a round trip the agent has to remember to make — and it doesn’t model your gates.

Substrate’s state lives in .substrate/, next to the code. A new session — or a second agent — reads exactly where work stands and which gates are unmet, without re-deriving it from git log.

How it works

One binary in your project. Two processes, one directory, everything local.

Substrate-as-code

.substrate/boards/*.json defines boards, groups, your own field_schema, and policies. They’re committed with your code and read fresh on every call — edit the JSON and the change takes effect immediately. No migration, no cascade.

Runtime state in SQLite

Tasks, comments and an append-only event log live in a local SQLite database (libsql, WAL mode — safe for concurrent agents). It’s gitignored: runtime state stays on your machine.

One read-only web UI

substrate serve hosts a localhost-only inspector: a live kanban that auto-refreshes, so a task an agent moves shows up within seconds. It only observes — it never writes, and there’s no drag-and-drop.

Everything Substrate adds to your project:
.substrate/
  config.json          # project id + name
  boards/*.json        # boards, groups, field_schema, policies, team  (committed)
  members/*.json       # optional team registry                        (committed)
  data.sqlite          # tasks, comments, event log                    (gitignored)
  attachments/         #                                               (gitignored)
  logs/substrate.log   # warnings + errors from mcp/serve              (gitignored)

The JSON is committed. The database and attachments are gitignored by default.

Gates that fire at write time

Two policy classes. That’s the whole model.

transition_guard — blocks

Blocks a move between groups when a required field isn’t set, and returns transition_blocked to the agent at the instant of the write, naming the field that’s missing.

agent_responsibility — suggests

Attaches non-blocking suggestions to matching writes. Every write returns an envelope listing the policies that fired.

human_only — the gate an agent cannot clear

Mark a field human_only and an agent’s write tools refuse to set it — only a person can, from the CLI. A guard that requires one is a sign-off an unattended agent structurally cannot give itself.

What the agent gets back when it tries to skip a stage:
{
  "ok": false,
  "error": {
    "code": "transition_blocked",
    "message": "Policy 'tests-before-review' blocks moving from 'Build & Test' to 'Review'.",
    "details": {
      "policy_id": "pol_01HX…",
      "from_group": "Build & Test",
      "to_group": "Review"
    }
  }
}

What a gate does not do

The field a gate checks is self-attested — the agent sets tests_passing: true itself; nothing runs your tests. A gate is a confession step, not a control: it records the claim and blocks until the claim is made, but it does not verify the claim is true. A perfectly-timed hard rail still beats advisory prose an agent has drifted from — but it’s worth being precise about.

The one real rail: human_only fields

Mark a field human_only and an agent’s write tools refuse to set it — and update_board refuses to un-protect it. Only a person can set it, from the CLI: substrate approve <task_id> <field>. A guard that requires a human_only field is a sign-off an unattended agent structurally cannot clear on its own. substrate pending-approval lists everything waiting on a human.

Quick start

Node 20 or newer, and a few minutes.

Today: install from source

Substrate isn’t on npm yet. Clone the repo, build it, and link the binary once — after that, substrate works the same everywhere.

shell
git clone https://github.com/42pe/substrate.git
cd substrate && pnpm install && pnpm build && pnpm link --global
substrate install-skill        # installs the agent skill into ~/.claude/skills/
cd /path/to/your-project && substrate init
substrate serve                # inspect at http://localhost:7475

Point your agent at it

Add the stdio MCP server to your agent runtime’s config. From there the agent calls whoami and takes it from there — 32 tools, one documented set of conventions.

.mcp.json
{
  "mcpServers": {
    "substrate": {
      "command": "substrate",
      "args": ["mcp"]
    }
  }
}

Status & scope

What you’re getting into, before you spend an afternoon on it.

  • Version 0.7.0, pre-release. The package isn’t published to npm yet.
  • Solo-maintained, open source (MIT). Triage is roughly weekly and there are no SLAs. Bug reports with a reproduction get looked at first.
  • Node.js 20 or newer. macOS and Linux are primary and covered by CI. Windows is best-effort — WSL is the recommended path — and Windows on ARM isn’t supported, because the SQLite driver ships no native binding for it.
  • One checkout per project, for now. Runtime state is gitignored, so a git worktree or a fresh clone gets the boards but starts with an empty task database. Substrate warns on startup when that happens, so it doesn’t bite silently.

What Substrate is not

  • Not hosted, not a service. Localhost only: no accounts, no cloud, no telemetry — and the CLI never makes a network call.
  • Not multiplayer. One project, one machine. Runtime state is per-machine, so two people on one repo don’t see each other’s tasks — the workflow JSON syncs through git, the tasks don’t.
  • Not a verifier. Gates record claims; they don’t check them.
  • Not an access-control system. A board’s team roster is descriptive metadata for orientation, never a permission.

Roadmap

What isn’t ready yet, and what changes when it is. Each of these disappears from this list the day it ships.

  • Published to npm

    Today Substrate is installed from source. When the package is published, the install becomes one npx command and the MCP config stops pointing at a local path.

  • Documentation site

    Installation, concepts, gates, the agent workflow and the CLI reference are written and waiting on a deploy.

  • Talk slides

    The deck from the f13 talk, posted as it was given.

Hear about it when it ships

No marketing, just news about how Substrate is coming along.

Subscribe

Your address goes to Mailchimp, our email provider, and nowhere else. No tracking pixels, nothing shared, nothing sold. Every email has an unsubscribe link. More on privacy.

Rather not give an email? Watch releases on GitHub instead.

Privacy

The tool itself. Substrate collects nothing and sends nothing. There is no telemetry, and the CLI never makes a network call — your boards, tasks and logs stay on your machine.