---
title: How instibrain works — the record, the rule, the wire
description: How a page travels between your computers and the brain: the page record, the version rule the server enforces, the merge on your computer, and the two doors.
url: https://instibrain.ai/how-it-works
updated: 2026-11-04
site: https://instibrain.ai/llms.txt
---

# The server compares. Your computer merges.

The server compares two version vectors, nothing else. It cannot read a sealed page, so it cannot merge one.

Request access  →  Connect Claude Code

one 409, start to finish

the record

## Eleven fields make a page.

A page travels as one record. `key_id` decides whether we can read it.

| Field | Meaning |
| id | uuid, the only stable identity on the server |
| path | Where the page sits. Ciphertext once `key_id` is not `none` |
| scope | The sealed space, by an id that says nothing; empty when open |
| key_id | Names a key, never holds one. `none` means readable here |
| version | A counter; in an open space, the server's concurrency guard |
| vclock | `{deviceId: counter}`, the concurrency truth for a sync write |
| content_b64 | The body. Opaque to us in a sealed space |
| content_hash | SHA-256 of the stored bytes; of ciphertext, in a sealed space |
| deleted | Tombstone flag |
| updated_at | Server clock, to the microsecond |
| seq | The write's number in commit order: the pull cursor |

what the two values of key_id mean

`none` means an open space: markdown we index, search, and keep history of.

A real key means a sealed space: ciphertext, and only vectors for the server to compare.

the rule

## The server's one decision is arithmetic.

Every page carries a version vector. A push lands only when its vector dominates the stored one.

case 01 It dominates
push laptop 5desk 2
stored laptop 4desk 2

Your computer has seen everything the server has.
200 accepted
case 02 It is identical
push laptop 5desk 2
stored laptop 5desk 2

Equal vectors advance nothing.
409 + server_vclock
case 03 Neither dominates
push laptop 4desk 3
stored laptop 5desk 2

Two computers edited offline. The server cannot merge ciphertext.
409 + server_vclock
1 · a write lands
laptop edits, pushes `{laptop:5, desk:2}`
server 200 it dominates `{laptop:4, desk:2}`
desk edits offline `{laptop:4, desk:3}`
2 · a fork
desk pushes `{laptop:4, desk:3}`
server 409 neither dominates. It returns `{laptop:5, desk:2}`
3 · the computer merges
server waits it holds ciphertext and cannot merge
desk decrypts both, merges joins to `{laptop:5, desk:3}`
4 · the merge lands
desk bumps, pushes `{laptop:5, desk:4}`
server 200 it dominates `{laptop:5, desk:2}`

The server decides whether. Your computer decides what.

the rejection

## Refusals name the field, never the value.

The refusal says which field failed and why. Echoing the value would leak it, and a test forbids that.

In an open space the brain refuses a path over 512 characters, a body over 1,000,000 characters, or a NUL in either. A sealed page's path travels as at most 1024 characters of ciphertext, from a bucketed path of about 500 bytes.

PUT /v0/nodes/7f3a4c-…-9d21  ·  a path over the 1024-character limit

```
# sent
{ "path": "cGF0aC9jaXBoZXJ0ZXh0…1400 characters…",
"vclock": { "laptop": 5 } }

# returned — 400
{ "code": "invalid_request",
"message": "The brain did not accept that request.",
"field": "path",
"reason": "too long" }

# the field. the reason. never the bytes.
```

the client's half

## Four functions close any fork.

The vector arithmetic ships in `@instibrain/protocol`, which the server and the sync client both import.

| Function | What it does |
| join(a, b) | Gives the vector a merged page carries |
| bump(v, deviceId) | Counts one local edit, on your device's counter |
| concurrent(a, b) | Names a real fork |
| isValidVClock(v) | Refuses a shape that would poison the ordering |

the 409 path

Fetch, decrypt both, merge, `join`, `bump`, push again. None of it happens on our side.

the wire

## HTTP for a client you write, MCP for an AI, one contract.

The sync client calls the routes, and your AI calls the tools. Every tool is on the tool reference.

| Call | What it does |
| POST /v0/nodes | Mints a uuid. No row is written. |
| GET /v0/nodes | Everything after your `seq` cursor, 500 at a time, in commit order |
| GET /v0/nodes/:id | One page: the server's copy, for a merge |
| PUT /v0/nodes/:id | `200` when your vector dominates; otherwise `409` with the server's vector, or a named code |
| search_brain | Open spaces only. Up to 500 characters in, the first 20 words counted; paths and the matching paragraph out. |
| read_node | One open page by path, as markdown |
| write_node, append_node, patch_node, move_node, delete_node | Edit an open space. The server reads it, so `expected_version` guards instead of a vector. |

500
records per HTTP response

79
MCP tools, in three scopes

10 MiB
of base64 content in one sync record

256
counters in one version vector

what a client must do

## A client follows six rules.

Skip the second, and your client re-reads one page forever.

- Mint the page id locally, or call POST /v0/nodes.
- Carry the cursor as the seq of the last record you took.
- Keep a stable deviceId; bump it on every local edit.
- On 409 concurrent: fetch, merge, join, bump, retry.
- Validate against the contract package before sending.
- Never expect the server to resolve a sealed fork. It refuses.
the write side

Every write needs a credential, held to its person's role. Who reads a sealed space is signed, in its chain.

## A sync clash never loses a word: your computer merges it, not our server.

The keys and their limits are on the security page.

Request access  →  Connect Claude Code
next  The Blind Vault

Primitives, keys, and limits, stated plainly.
next  The sync client

The side that runs on your machine.

---

instibrain is made by WebWork AI, Inc. Everyone uses the same models · the difference is what yours knows.
