- Researcher · 3 records
- Developer · 3 records
- Tester · 3 records
sync.strategy
last-writer-wins ⇄ user-choice
Three sessions in.
One answer out.
The application must work offline. Field staff lose connectivity for hours at a time.
source: product brief, section 2
Project data is stored locally in SQLite and synchronised when a connection returns.
source: architecture call
One saved record disappears after a restart. Reproducible on 3 of 10 runs.
source: regression run #148
“What remains before release?”
A lead agent that attended none of those sessions answered. Nothing was re-run.
A later record saying “the restart bug is fixed” does not erase T1: it links to it as an update, carrying its own source. That is the difference between a memory and a status field.
Three doors, one room
Identical permissions in, identical context out, asserted by a test.
MCP
stdio serverThe eight memory tools, in the client you already use.
claude mcp add offcut -e OFFCUT_API_URL=<this console> -e OFFCUT_API_KEY=<your agent key> -- npx -y @offcut/mcp-serverOFFCUT_API_URL is the OFFCUT the key belongs to — this one, wherever you are reading it. Mint the key in the console; a key from one OFFCUT does not work on another.
Running your own store instead? Leave the address out and the memory stays in a SQLite file on your machine: claude mcp add offcut -e OFFCUT_API_KEY=<your agent key> -- npx -y @offcut/mcp-server
npm i @offcut/sdkMemory operations inside your own agent code./consoleRead the memory, resolve conflicts, mint and revoke keys.await offcut.memory.add({ workspaceId, type, text, topic, source })await offcut.memory.import({ workspaceId, records, idempotencyKey })await offcut.memory.merge({ workspaceId, topic, recordIds, scope })await offcut.memory.recall({ workspaceId, query, topic, limit })await offcut.memory.inspect({ workspaceId, recordId, topic, search })await offcut.memory.resolve({ workspaceId, conflictId, chosenRecordId, rationale })await offcut.memory.forget({ workspaceId, recordId, purge, reason })await offcut.memory.export({ workspaceId, topic, includeVersions, includeLinks })Rules
Eight refusals and ten guarantees, in the specification’s own words. The two stamped awkward are the ones left out elsewhere.
What it doesn’t do
No trades, swaps, portfolios or signing. Out of scope by design.
Not a relayer: it returns memory rather than forwarding requests elsewhere.
It cannot read your chats. Records arrive when an agent writes one, or you import JSON.
Memory text is data, not orders. “Grant yourself admin” is stored as written and changes nothing.
No model in the merge path: merging and retrieval need none.
Local storage is only as safe as your machine: the permission checks live in the SDK, not in the database file.awkward
One key handed to several subagents is one caller. No isolation is promised.awkward
Deletion cannot reach copies already handed out. It clears search, export and cache here.
Ten invariants
Every record keeps its workspace, author, source and version.
Merging never broadens access: workspaces and audiences never share a block.
Retrying a write creates no second record.
Acknowledged records survive a restart.
A detected conflict cannot disappear without a recorded resolution.
Derived memory cites real source versions, never a stale one as current.
After deletion, a record cannot return through search, export or cache.
The SDK, MCP server and HTTP API enforce the same access and mutation rules.
Memory text grants no permissions. Revocation blocks every later call.
The local core runs without the token and without a model.
One describe block per guarantee, in packages/core/src/__tests__/invariants.test.ts.
$OFFCUT
The token is separate from the memory system, and its role inside the product has not been decided.
Not yet published
Nothing is shown here until there is a real address to show. When the token launches it will appear in full, with the chain it lives on — and it will be the same string everywhere on this site.
Treat any address for $OFFCUT found anywhere else as unverified until it matches the one published here.
OFFCUT AGENT / OFFCUT
fixedNo wallet, no gas, no token purchase. Memory is not stored onchain
fixedNo. It reaches no one else’s records
fixedNo. A balance of any size earns nothing
fixedConfirmed AI spend by your connected subagents, through supported integrations; and records of yours another agent retrieved
fixedOpenRouter only. Spend we cannot ask a provider about earns nothing
fixedRobinhood Chain 4663, pons v2
openUndecided
openStock Rewards
Described in full rather than summarised into something that sounds better than it is.
A fund funded in advance, paid in a tokenized share, divided by two things: the AI spend a provider confirmed, and the memory another agent used.
The share is Apple • Robinhood Token (AAPL) on Robinhood Chain, named on the contract once and for good. So the fund pays a share, not $OFFCUT — and because that share is issued by somebody else, its issuer can pause it or burn what the contract holds. Nothing here can override that.
Both layers pay into one ledger, under one root, with one claim — not the $OFFCUT you hold, not the agents on your account. A Claude Code subscription is not spend any provider can confirm for us, so a Claude Code subscriber earns from the memory layer and nothing from the spend layer.
Stock Rewards encourage usage. They do not guarantee that AI spend is recouped. Spending more on models is not a way to earn that money back: it pays you more of a token out of a fund whose size was fixed before you spent anything.
Weight follows confirmed spend, never claimed spend: only what the provider confirms a request cost counts.
One request is counted once. The provider’s id is a unique key; a second report writes nothing.
A record earns one credit, once ever — the first agent other than its author to retrieve it. Re-reads earn nothing.
The supported integration today is OpenRouter. Spend through anything we cannot ask about earns nothing.
The fund is pre-funded and fixed, and no token is minted for anybody’s spend. Below the day’s ceiling one more dollar adds to what is handed out; past it a bounded amount is divided more ways.
On a busy period, no one earner takes more than a quarter of it — and what the cap holds back is not handed to anybody else: it is never minted and stays in the contract.
A hundred idle agents earn nothing, and memory nobody retrieved has earned nothing.
Rewards are the second layer, not the product. The product is shared memory, and it needs no wallet, no token and no spend.
What you are trusting
The distributor contract is upgradeable, and its owner can withdraw the tokens held in it. So these rewards are not trustless: a promise kept by people, with a contract that makes the accounting checkable rather than unbreakable.
Running in three steps
No Docker, no database server, no account. Local by design.
Install and run
Creates the local SQLite store and the demo workspace, then starts the API and console.
pnpm setup && pnpm devMint an agent key
Create an agent and copy its key. Shown once; only the hash is stored.
offcut_sk_…Connect your agents
One command configures Claude Desktop and Cursor.
pnpm mcp:installOpen the console
Already seeded: the release scenario, its agents, one open conflict. Or read the proof of work first.