ocbrain
Install · upgrade · verify

One checkout. One local core. Your choice of clients.

Start with the smallest useful shape: install the strict v1 core into its own virtual environment, initialize its local event ledger, and register the same launcher with one or more compatible MCP clients. Codex, Claude Code, Hermes, and OpenClaw can share the same brain; OpenClaw is optional. Then ask each configured client to use the core. A green config line is not the finish line.

Requirements

  • Python 3.11 or newer, Git, and at least one compatible stdio MCP client.
  • macOS and Linux are supported. Public CI runs the complete source gate on Ubuntu with Python 3.11. Dated model-driven client acceptance records remain macOS-only; WSL is expected to work but is not release-accepted. The code uses POSIX facilities including bash and fcntl, so native Windows is not supported.
  • Install from source. ocbrain is available from its public Git repository and GitHub releases; it is not currently published to PyPI.
  • OpenClaw is not required. OCBrain itself also needs no API key, hosted memory service, vector database, or background daemon. Optional dense retrieval uses a separate loopback-only Ollama sidecar; lexical retrieval works without it. Your chosen client still has its own installation and authentication requirements.
  • Protect the local data. The SQLite database is not encrypted at rest. Keep it mode 0600, keep runtime data out of Git, and use full-disk encryption when its evidence is sensitive.

The latest packaged release is v1.1.0. Current main contains the newer thirteen-tool harness and supersession contract documented here. Its public Linux CI is a source gate, not a claim that every MCP host or model-driven client flow has been accepted on Linux or WSL.

1. Install the source

The core has no runtime package dependencies. Install it into a dedicated virtual environment, create its database under a restrictive process mask, and verify its health before connecting a client.

git clone https://github.com/jonathangu/ocbrain.git
cd ocbrain
git checkout main
git pull --ff-only
python3 -m venv .venv
.venv/bin/python -m pip install -e .
.venv/bin/ocbrain --version

umask 077
.venv/bin/ocbrain --db data/ocbrain.sqlite init
chmod 600 data/ocbrain.sqlite
.venv/bin/ocbrain --db data/ocbrain.sqlite status
.venv/bin/ocbrain --db data/ocbrain.sqlite doctor \
  --launcher "$PWD/scripts/ocbrain-mcp"

These instructions follow current main, which is the latest documented behavior. For the latest packaged release instead, replace those two Git lines with git checkout v1.1.0 and use that tag's eight-tool documentation. The database, snapshots, migration manifests, and private evidence stay under ignored owner-controlled paths. A fresh init creates the event-authoritative v1 schema.

2. Check the portable launcher

scripts/ocbrain-mcp resolves the repository from its own location and prefers .venv/bin/python. That makes the path you register with each client stable even when the clone is not in the same home directory as mine. The doctor command above starts the launcher as a real stdio MCP subprocess and checks its tool surface.

If you deliberately keep the database or interpreter somewhere else, set OCBRAIN_DB or OCBRAIN_PYTHON in the client's MCP environment. Otherwise the launcher reads the ignored data/active-core.path pointer when present, then falls back to data/ocbrain.sqlite. The pointer contains one absolute core-database path. A pointer-selected MCP process rechecks that choice before every request and exits if it changes, so an old client cannot silently keep writing a database that is no longer active.

3. Connect the clients you use

Run only the applicable commands from the repository root. Any one client is a valid configuration; every configured client saves the same absolute launcher path.

LAUNCHER="$PWD/scripts/ocbrain-mcp"

codex mcp add ocbrain -- "$LAUNCHER"
claude mcp add --scope user ocbrain -- "$LAUNCHER"
hermes mcp add ocbrain --command "$LAUNCHER"

OpenClaw is optional. Only run this if OpenClaw is already installed:

openclaw mcp add ocbrain --command "$LAUNCHER"

ChatGPT and Codex

The ChatGPT desktop app's Codex mode reads the user Codex MCP configuration. Its conversation rollouts continue under ~/.codex/sessions, which ocbrain can harvest alongside standalone Codex work.

Claude Code

--scope user makes the launcher available across projects. Authenticate Claude Code separately with claude auth login --claudeai when the subscription session is not already active.

Hermes

hermes mcp test ocbrain verifies the saved stdio launcher. Hermes gateways may multiplex sessions over one MCP child, so omit context.session when the runtime cannot provide its real session identifier; OCBrain records the connection identity.

OpenClaw (optional)

The current openclaw mcp add command probes the stdio server before saving it under mcp.servers. If OpenClaw should host Claude, authenticate that provider inside OpenClaw separately; standalone Claude login does not create OpenClaw's auth profile. Use reload after a source upgrade.

The launcher marks ordinary stdio MCP delivery as hosted_model. That target is controlled by the server and cannot be changed by a tool argument. It is the conservative default for Codex, Claude Code, Hermes, OpenClaw, and other clients whose model may run outside this machine.

4. Verify configuration and real tool use

First inspect what each configured client actually saved. Run only the lines for clients you use:

codex mcp get ocbrain
claude mcp get ocbrain
hermes mcp test ocbrain

For an optional OpenClaw connection:

openclaw config validate
openclaw doctor --lint --json
openclaw mcp doctor ocbrain
openclaw mcp probe ocbrain

Then start a fresh task in each configured client so it launches a new MCP process, and give it a narrow, harmless acceptance request:

Use OCBrain for this check. First call brain.briefing with project="ocbrain".
Call brain.ledger for task_ref="inspect-ocbrain-context", then brain.context
with a focused installation query and the same project/task scope. If it issues
a source handle, expand exactly one with brain.source. Record honest feedback
for every retrieval that influenced the check. Finish with brain.closeout,
linking the retrievals and a passed MCP smoke verifier. Use the runtime's real
session id, or omit session rather than inventing one.

A healthy result proves more than transport:

  • The model discovered and called the ocbrain tool.
  • brain.briefing returned deterministic bounded orientation, and brain.ledger reported whether this stable task reference was already verified, failed, or in flight.
  • The context call returned the stable ocbrain.context.v1 envelope or an honest empty result within the hard 32 KB serialized-packet limit.
  • Coverage reported the eligible inventory and actual local scope_mix. A hosted packet reported delivery exclusions while listing no excluded ID, body, path, or object sample.
  • When a source handle was issued, it expanded with scope and content-hash checks; hosted output used an ocbrain:// locator rather than a local filesystem path.
  • Feedback was recorded when an audit handle existed, and closeout appended an outcome receipt.
  • A long writer window did not turn a successful read into a retry storm.

A fresh brain starts empty on purpose

A brand-new v1 database has no promoted beliefs, so brain.context may return an honest empty packet and no source handle. That is a successful client/server smoke test, not a full source-expansion acceptance test. brain.ingest records evidence but deliberately does not promote that text directly into a serving belief.

v1.1.0 includes a small public demonstration for a real hosted context → source turn. Before applying it, review examples/hosted-context-demo/source.md and its manifest. The command verifies the pinned SHA-256, prevalidates the complete manifest, then atomically appends evidence, proposal, and approval events:

.venv/bin/ocbrain --db data/ocbrain.sqlite curated-apply \
  examples/hosted-context-demo/manifest.json \
  --allow-hosted-egress \
  --actor "human-curated:YOUR-NAME"

The explicit flag acknowledges that the four reviewed public fact bodies may be returned to a hosted model. It does not authorize delivery of the SQLite database, the complete source file, any unlisted text, or a local path. If any source or fact is invalid, or a manifest contains hosted_ok facts without the flag, the entire apply is refused or rolled back. Confidential or secret facts cannot be marked hosted_ok.

Start a fresh configured client and run the acceptance request above. With project=ocbrain, it should return at least one curated fact and an issued source that expands with hash_verified=true. Applying the same unchanged manifest again is idempotent.

For your own starter facts, copy examples/curated-memory, replace the synthetic source and fact bodies, update the source SHA-256, and review the result before applying it. That example is local_only, so it does not need the hosted acknowledgement and will not appear in an ordinary hosted-model packet.

Do not seed a new brain with secrets, copied transcripts, or facts you cannot verify. Use a separate ignored demonstration database when you do not want these public facts in your real brain. Existing v0.x users should use archive-first migration instead of importing somebody else's database.

Optional: add local dense candidates

FTS5 lexical retrieval is always available and remains the deterministic fallback. If you already run Ollama locally, v1.1.0 can build a disposable vector sidecar and combine lexical and dense candidates with reciprocal-rank fusion. This is optional; it adds no hosted embedding fallback and changes no ledger authority.

ollama pull qwen3-embedding:4b-fp16

.venv/bin/ocbrain --db data/ocbrain.sqlite vector-build
.venv/bin/ocbrain --db data/ocbrain.sqlite vector-status

The embedding endpoint must be loopback HTTP at 127.0.0.1, localhost, or ::1. The sidecar records the core event head, model digest, dimensions, and query-instruction hash. A missing, stale, incompatible, or unavailable sidecar reports a dense_fallback reason and continues lexically. Rebuild it after semantic ledger changes when you want dense retrieval again.

Lifecycle, scope, visibility, and delivery policy are applied before either candidate list is ranked. Dense retrieval cannot make a private, foreign, or hosted-ineligible object eligible.

5. Upgrade without replacing the brain

The source checkout and the local database have different jobs. Pull the source forward, reinstall the editable package, run the gate, and keep the database in place.

cd /absolute/path/to/ocbrain
git pull --ff-only
.venv/bin/python -m pip install -e ".[dev]"

.venv/bin/python -m pytest -q tests/test_golden_context_v1.py
PYTHONPATH=src .venv/bin/pytest -q
.venv/bin/ruff check .
.venv/bin/python -m compileall src tests
git diff --check

If OpenClaw is one of your clients, also run:

openclaw mcp reload

Start a new Codex task and restart or reconnect each other configured client after the upgrade so it creates a new stdio process. Existing tasks can retain the older process they already started. Do not delete data/ocbrain.sqlite as an upgrade step.

6. Migrate v0.x archive-first

Do not convert a live v0.x database in place. Plan an archive, strict core, training extract, operations extract, and manifest at five fresh paths:

.venv/bin/ocbrain --db /absolute/legacy.sqlite core-migrate-v1 \
  --core-db /absolute/v1/core.sqlite \
  --archive-db /absolute/archive/legacy.sqlite \
  --training-db /absolute/v1/training.sqlite \
  --ops-db /absolute/v1/ops.sqlite \
  --manifest /absolute/v1/migration.json \
  --plan

Plan mode opens the source read-only and creates nothing. Run the same command without --plan to build fresh outputs. The command preserves and verifies the exact legacy event sequence, accounts for every source table, rebuilds projections and FTS, verifies database integrity and hashes, and never activates the candidate.

.venv/bin/ocbrain --db /absolute/v1/core.sqlite status
.venv/bin/ocbrain --db /absolute/v1/core.sqlite doctor

printf '%s\n' '/absolute/v1/core.sqlite' > data/active-core.path
chmod 600 data/active-core.path

Write the ignored pointer only after the manifest, hashes, integrity, projection rebuild, and package gates pass. This is a provisional activation for acceptance, not a migration side effect or final cutover. Start fresh clients and complete the real acceptance flow above. Retain the pointer only if every client you configured passes against that same v1 live copy; otherwise remove or replace it and reconnect clients. Pointer rollback does not mutate either database.

The July 13 full rehearsal produced a verified candidate and all companion artifacts while deliberately leaving the activation pointer unchanged. After final gates passed, the operator—not migration—performed the provisional pointer step. Fresh Codex, Claude Code, and OpenClaw processes all passed, so that pointer is now retained.

7. Exchange evidence explicitly

Evidence bundles are manual files, not synchronization daemons or MCP tools. Export requires explicit evidence IDs and writes a fresh owner-only path after scope, egress, approval, size, and secret-redaction checks:

.venv/bin/ocbrain --db /absolute/source.sqlite export-bundle \
  --evidence-id evd_example \
  --project source-project \
  --output /absolute/fresh.bundle.json

local_only and prohibited evidence cannot be exported. Approval-gated evidence also needs --approve-egress. Import validates the complete envelope and payload hash without opening a database unless --apply is present:

.venv/bin/ocbrain import-bundle /absolute/fresh.bundle.json \
  --project destination-project

.venv/bin/ocbrain --db /absolute/destination.sqlite import-bundle \
  /absolute/fresh.bundle.json \
  --project destination-project \
  --apply

Import ignores sender IDs as authority, derives local content IDs, and appends evidence only. The arriving evidence is confidential and local_only; beliefs, source handles, retrieval receipts, closeouts, and companion state never cross in a bundle.

8. Keep maintenance operator-owned

MCP gives the runtimes one brain on demand. The default install creates no recurring light autopilot, heavy autopilot, or stallcheck job; the tracked legacy launchd artifacts are inert retirement markers. Do not recreate those schedules as part of installation.

For the core projection, use the explicit bounded command below. It is local-only and reports the stages it refuses to cross:

.venv/bin/ocbrain --db data/ocbrain.sqlite sync \
  --max-events 1000 \
  --time-budget 10

The normal launcher exposes exactly thirteen runtime tools: briefing, ledger, goal open/close, context, source, search, digest, get, feedback, ingest, closeout, and supersede. The admin profile adds six protected local lifecycle and review controls for nineteen total. It has no hosted judgment, hosted embedding, training, scheduler, or watchdog tool. --allow-writes remains only as a deprecated alias for that broader profile; it is not a no-op and should not be added to ordinary runtime registrations.

ocbrain is now one distribution. The former ocbrain-training and ocbrain-ops companion packages were removed; there is no separate package installation or extension mechanism.

Contribute through a reviewed pull request

jonathangu/ocbrain is a public Apache-2.0 repository. Anyone can read it, fork it, open an issue, and propose a pull request. Public does not mean that anyone can push to main or merge a change.

  1. Fork the repository and create a focused branch.
  2. Add or update tests for behavior changes, then run pytest, Ruff, compilation, git diff --check, and the public-safety scan.
  3. Open a pull request that explains the change, its verification, and any privacy or migration impact.
  4. Address review comments. The current main rule requires one approving review and resolved conversations before a normal merge.
.venv/bin/python -m pip install -e ".[dev]"
.venv/bin/python -m pytest -q tests/test_golden_context_v1.py
PYTHONPATH=src .venv/bin/python -m pytest -q
.venv/bin/ruff check .
.venv/bin/python -m compileall -q src tests
git diff --check
.venv/bin/ocbrain public-safety-check --root "$PWD"

@jonathangu is currently the only write collaborator, so an outside contributor cannot approve or merge their own PR; the qualifying approval normally comes from that account. New commits dismiss stale approvals, force pushes and branch deletion are disabled, and repository administrators retain a maintenance bypass. Never attach live databases, transcripts, tokens, credentials, private absolute paths, or other owner data.

Troubleshooting

Claude says the OAuth session expired

Run claude auth login --claudeai, finish the browser flow, and confirm claude auth status reports loggedIn: true.

Codex is missing a native binary

Repair or upgrade the official Codex CLI, confirm codex --version, and then re-check codex mcp get ocbrain.

OpenClaw sees stale tools

Run openclaw mcp reload, then openclaw mcp probe ocbrain. A gateway restart should not be the first response to an MCP source edit.

Retrieval reports database_busy

The read succeeded while another local writer owned the audit window. Use the result and skip feedback for that call. Do not hammer the database until an id appears.

The active database pointer changed

The old MCP process intentionally stopped. Start a fresh task or reconnect the client; do not retry writes against the retired process.

The client says Transport closed

Stop after the first failure. Preserve the exact arguments, execute that runtime call once through scripts/ocbrain-runtime-call, then reconnect or start a fresh task. Never kill a client-owned MCP child to force an upgrade.