a second memory for your agents

Your agents forget everything. mindOS doesn’t.

Every session starts from zero. Every question stops the work. Every “done” is just a claim. mindOS is a memory that survives the session, an autopilot that keeps going while you’re away, and a receipt at the end of every job. All on your machine. No server. No account.

python 3.9+one file you ownstops rather than guessesfsl-1.1-mit
scroll
the human half
01why

Agents are fast. Then they forget, stall, and can’t prove it.

The hour an agent saves you comes straight back out of your day — re-explaining, restarting, double-checking. Three places it leaks.

01

AIt forgets everything you told it

Every new session starts cold. You re-describe the project, the conventions, the thing you already decided twice. The agent isn’t learning — you’re repeating. Whatever it worked out last Tuesday died with the window.

02

BIt stops the moment you look away

It hits a question only you can answer — and then just sits there. Or it dies, and nothing notices. You come back after two hours to work that stopped after ten minutes, with no note explaining why.

03

CYou can’t check what it did

“It’s done.” Nothing sits behind that sentence you can open. So you take its word and hope, or you spend an hour confirming — the same hour it was supposed to save you.

the turn

All three are the same problem: everything your agents know lives inside a session that ends. mindOS moves it outside — into one place on your machine that remembers between sessions, keeps the work moving while you’re gone, and writes down what happened as it happens. Not the agent’s account of the day. The day itself.

02what it is

The part of your agents that doesn’t reset

Your agents come and go; this stays. It holds what they learned, what you decided, who is working on what, and how each job ended — so the next session starts where the last one stopped instead of at zero. Eight things it remembers for you, and what each one saves you:

DIM 01
who’s doing what
two agents never quietly work on the same thing
DIM 02
what it already learned
your setup, explained once — not at the top of every session
DIM 03
what’s true today
last month’s decision doesn’t get quoted back at you as current
DIM 04
what it read first
when it gets something wrong, you can see what it was working from
DIM 05
handing work over
a job passed between agents doesn’t get dropped in the gap
DIM 06
proof it happened
one small file to open instead of re-reading the whole conversation
DIM 07
picking itself back up
an agent that dies overnight doesn’t cost you the morning
DIM 08
what it’s allowed to do
an agent can’t quietly widen its own permissions
one job+one owner+a timer=no duplicated work
rules+a receipt+a log nobody can edit=a “done” you can check
memory+decisions+what it read=it starts already knowing
03completion

“Done” is a document

A job does not finish because an agent says so. It finishes when the system writes a receipt — a small file on your disk listing what was done, what it rests on, and when. Answering “so what actually happened?” becomes opening one file instead of re-reading a 40,000-word conversation. And if the agent has quietly lost its hold on the job, the close is refused — mindOS would rather stop than write down something it can’t stand behind.

receipt · runner/v1sample — illustrative
idrcpt-8f2a1c…d902
tasktask-41 · rebuild ingest pipeline
statuscompleted · lease L-1187 live at close
cited evidenceev-3341 · ev-3342 · ev-3343
budget12,404 / 40,000 tokens · 0 retries
chainaudit event e-2291 · checkpoint v1 pinned
filereceipts/rcpt-8f2a1c…d902.json · mode 0600
01

Written before it counts

The receipt is created and fingerprinted before the job is marked done. An agent that has quietly lost its claim cannot close the job — the system stops instead of papering over it.

02

Evidence, not a summary

A receipt points at the specific things it relied on, so you can follow each one back yourself. It also records exactly what the agent had been given to read — so “it didn’t know” is something you can check.

03

Private to you

Receipts are readable by your user account and nobody else’s. Anything that looks like a password or a key is stripped on the way in — secrets never get into the system, so they can never leak back out of it.

04the boundary

The seam it will not cross

Agents only get the freedom you hand them — in writing, tied to a specific model, with an expiry date. Every time one tries to step outside that, the attempt is written down. And there are four things it will never do on its own, no matter what you grant:

merge

Stays with a human. mindOS gets the change ready; a person decides.

deploy

Stays with a human. No self-release, ever.

external communication

Stays with a human. It can draft, and the draft is tagged with where it came from — but a person sends it.

live-data remediation

Stays with a human. Nothing is rewritten in production without a person.

verbatim · docs/releases/2026-08-22-autopilot-v3.md

“The system remains deliberately bounded: it can recover and continue approved work, but merge, deploy, external communication, and live-data remediation remain explicit human seams.

05while you’re away

What it does when you’re not watching

You queue a job in the morning and close the laptop. Here is what happens without you — including the part where it needs you, waits properly, and picks up again. Every line is a real command against a real setup.

09:00 · operator

Queue the work

The job is written down with its priority, what it waits on, and how much it may spend. From this moment it is a fact every agent can see — not a message someone might miss.

$ python3 autopilot.py create "rebuild ingest pipeline" --tag critical --project trove
09:04 · hermes

Claim with context

Hermes takes the job, and now nobody else can. Before it does any work, the system records exactly what background it was handed — so later you can see what it knew, not what it says it knew.

$ python3 autopilot.py next --claim --recall
14:52 · hermes

Ask, and stop cleanly

The agent hits a decision only a person can make. It parks the job, hands its claim back, and stops. The question is written down and waiting — nothing burns time spinning while you read it.

$ python3 autopilot.py update task-41 --status waiting_for_user
15:01 · operator

Answer, and resume

Your answer is recorded as a fact, not a chat message. The job picks up where it left off — same identity, same budget, same trail behind it.

$ python3 autopilot.py resume task-41
17:40 · hermes

Close with a receipt

To finish, the agent must still hold the job. The receipt is written, locked to your account, and the record extends by one link that cannot be edited later.

$ python3 autopilot.py complete task-41 --recall-digest 3c1e…77aa
23:59 · the plane

The bounded tick

Once a day the system checks itself: jobs abandoned by crashed agents are released, budgets and handoffs are reviewed, and you get one of four answers — all clear · working · hit a snag · needs a decision.

$ python3 ops.py nanny
06install

Two commands. No server. No packages.

Python 3.9 or newer and nothing else — no packages to install, no service to run, no account to sign up for. Everything it stores lives in one folder on your machine, under your user, at MINDOS_HOME (or HERMES_AUTOPILOT_HOME). Nothing leaves it.

autopilot · local
python 3.9+ · stdlib onlyno network at runtimeverify: python3 verify.pyfsl-1.1-mit
part two of two

Everything above, as mechanism

Leases, fencing epochs, hash chains, FTS5, sealed files. The first half made the promises; this half is the code that keeps them. It gets technical from here.

INV 1single authorityone sqlite file owns the home
INV 2fail closedunclear is unsafe — the gate holds
INV 3evidence over claimsstates carry citations
INV 4dry-run firstevery mutation can be shown
INV 5source immutabilitythe repo is never the state
the technical half
07architecture

Four layers, one authority

From the CLI surface down to the optional embed worker, every layer reads and writes the same durable home. There is no cache above the truth — because the truth is the file.

layer 1 · cli surface

autopilot.py — tasks, leases, notes, handoffs, memory, facts, receipts.  ·  ops.py — fleet ops: doctor, recover, nanny, migration, brain ingest, policy. Both are single-file, stdlib-only programs.

layer 2 · guarantee layer

Leases with fencing epochs · the audit hash chain · sealed receipts written 0600 · the secret guard · FTS5 ranked retrieval (with a LIKE fallback when the extension is absent). This layer is where “fail closed” is enforced.

layer 3 · durable state — $MINDOS_HOME

state.db (tasks, leases, notes, handoffs) · temporal.db (facts with validity windows) · receipts/ · backups/ · memories + memories_fts — the memory engine lives in the same authority as the task state. No side store, no sync, no drift.

layer 4 · optional embed worker

embed_worker.py — out-of-process, read-only, never on the pack path. Embeddings are an enrichment, not a dependency: recall works identically with the worker off.

six capability surfaces × eight durable dimensions — from ARCHITECTURE.md
raw sessions

Raw session stores are read-only transcript adapters into a rebuildable cache — the plane ingests them, redacts them, and indexes them, but they are never the authority. Delete the cache and it rebuilds; the truth does not move.

08execution

Ownership is a lease, not a claim

Every task moves through a small, strict lifecycle. Every transition is atomic, lease-gated, and hash-chained into the audit log. The fencing epoch is the difference between “an agent said it was working” and “the plane knows exactly who holds it.”

claim · next --claim complete · receipt cited fail · --no-retry / budget exhausted update --status resume release · retry −1 · backoff block --reason unblock cancel · operator cancel · operator heartbeat · lease renewal queuedbudget · deps · tags runninglease · epoch completedreceipt sealed blockedreason on record waiting_for_userhuman in the loop failedterminal or retryable cancelledoperator call
  1. queuedbudget · deps · tags
  2. claim · next --claim
  3. runninglease · epoch · heartbeat renews
  4. complete · receipt cited · live lease
  5. completedreceipt sealed
  • blockedblock --reason parks a queued task with the reason on record; unblock returns it.
  • waiting_for_userupdate --status releases the lease cleanly while a human reads; resume returns to running.
  • failedfail types the cause; --no-retry or an exhausted budget makes it terminal. Otherwise it releases with retry −1 and backoff.
  • cancelled — an operator call, from blocked or from waiting_for_user.
hover a state — every transition is atomic, lease-gated, and hash-chained into the audit log

Fencing epochs, not names

A stale holder is rejected by its epoch — even if it still claims the right name. ops.py recover sweeps stale leases; the task re-enters the queue with retry −1 and backoff.

Failures are typed

fail records a cause — transient · infra · defect — and --no-retry or an exhausted budget makes it terminal. Either way it is a chain event.

Waiting is a state, not a spin

update --status waiting_for_user releases the lease cleanly. The question is durable; nothing burns budget while a human reads it.

Completion is gated

complete requires a live lease at close time and receipt citations. The receipt is sealed before the status flips — never after.

09memory

memory-fts-v1: memory where the state is

The v0.5.0 memory engine keeps memories and memories_fts (FTS5, with a LIKE fallback when the extension is absent) in the same authority as the task state. No side store, no sync step, no drift between “what the agent remembers” and “what the plane knows.”

# retain a decision — audited $ python3 autopilot.py memory-retain --text "we chose FTS5 over embeddings" --kind decision retained mem-2091 · fts index updated · chain seq 44182 # ranked search, rerank optional $ python3 autopilot.py memory-search "why fts5" --rerank 1. mem-2091 · decision · score 0.94 · pinned 2. mem-1842 · note · score 0.71 · “fts fallback keeps recall offline” 2 results · 18ms · fts5 # git ingest is idempotent by content address $ python3 autopilot.py memory-ingest-git origin/main ingested 47 · skipped 112 (already known) $ python3 autopilot.py memory-ingest-git origin/main ingested 0 · skipped 159 (already known) # where the memory actually lives $ python3 autopilot.py memory-status memories 8,412 memories_fts 8,412 drift 0 authority ~/.mindos/mind.db wal single writer embeddings worker idle optional # sample output — illustrative
01

Idempotent by content address

Re-ingesting a branch changes nothing. The git adapter fingerprints content, not timestamps — memory-ingest-git is safe to run from any cron.

02

Embeddings are optional

memory-embed · memory-search · memory-consolidate-brief run through the out-of-process worker — always off the pack path. Turn the worker off and recall is unchanged.

03

Consolidation knows git

Consolidation excludes commit and pull_request memories by default — 63 of 122 clusters were pure git. --include-git opts back in.

04

Every mutation audited

memory-retain · memory-forget · memory-list · memory-status · memory-import — each write lands in the same authority, replayable from the chain.

10audit

The chain that proves it

Every transition writes one hash-chained event. Each event carries the hash of the one before it; verify-chain and doctor replay it. Append takes BEGIN IMMEDIATE before reading the tail — the chain-fork race is closed at the write, not detected after it.

e-2289 · claimedprev — → 8f2a…c1 e-2290 · lease_renewedprev 8f2a…c1 → 7d40…9b e-2291 · completedprev 7d40…9b → 1a02…e4 e-2292 · context_recalledprev 1a02…e4 → 3c1e…77 e-2293 · claimedprev 3c1e…77 → 9e55…0d appending autopilot-checkpoint-v1 pinned head · e-2291
  1. e-2289 · claimedprev — → 8f2a…c1
  2. e-2290 · lease_renewedprev 8f2a…c1 → 7d40…9b
  3. e-2291 · completedprev 7d40…9b → 1a02…e4
  4. e-2292 · context_recalledprev 1a02…e4 → 3c1e…77
  5. e-2293 · claimedprev 3c1e…77 → 9e55…0d
autopilot-checkpoint-v1pinned head · e-2291
hover an event — each hash seals the one before it; checkpoints pin the head so removals are detectable

chain_truncated

the chain stops short of its recorded head

checkpoint_head_mismatch

the pinned checkpoint no longer matches the chain head

events_removed_since_checkpoint

events vanished after the pin was taken

receipt_file_hash_mismatch

a sealed receipt’s bytes no longer match its recorded hash

11recall

The recall ritual

Before an agent’s first turn, the plane assembles a bounded, digest-sealed context pack. context, recall, resume, and next --claim --recall all share this one pack path — same digest, same rules, every time.

$ python3 autopilot.py context task-41 --budget 4000 --related 5 ── pack sealed · digest sha256 3c1e…77aa · budget 4,000 ── header task-41 · rebuild ingest pipeline · L2 deps task-38 (completed) · task-39 (completed) handoff h-2214 · “schema question answered, see note” notes n-881 (pinned) · n-882 · n-879 related h-2198 · n-871 · f-1120 (valid) · mem-2091 facts 3 currently-valid · 2 historical (labelled) sessions redacted cache · rebuildable · never the authority → context_recalled · digest + bundle params written to the chain # sample output — illustrative
01

One pack path

FTS5 candidates (own notes pinned first, related notes, related handoffs, dependency context, redacted session cache, currently-valid facts) → optional --rerank (BM25 × recency decay + pin boost) → the budget packer: header → deps → handoff → notes → related.

02

Sealed before the first turn

The pack’s deterministic SHA-256 digest is written to the chain as context_recalled, with bundle parameters. complete --recall-digest later ties the receipt back to exactly this pack.

03

Replayable, diffable, staleness-checked

recall-verify replays the pack; recall-diff shows what changed; ops.py recall-stale flags packs whose evidence has since expired or been superseded.

04

Provenance for context

Every item in a pack has a source id and a validity state. ARCHITECTURE.md puts it plainly: provenance for context, not vibes.

12supervision

The bounded tick

The Autopilot v3 nanny is a bounded loop, not a daemon with opinions. Each tick it senses the plane, runs only the repair policies eligible to run (capped, dry-run first, every repair audited), and reports in exactly four states. Out of grant windows it refuses — and the refusal is audited.

stale lease budget burn unacked handoff drifted digest
one tick · sense → repair → report

sense

Stale leases · budgets burning · unacked handoffs · digests that no longer match. Read-only, every tick.

repair

Only tier-0 repair policies eligible to run — capped per tick, dry-run first, each repair an audited event. ops.py repair-list shows what would run before anything does.

report

A compact state summary — activity, stalls, findings — in exactly four states: all_clear · working · hit_snag · decision_needed.

$ python3 ops.py nanny --dry-run stale lease L-1181 → recovered · task-37 resumed finding: unacked handoff h-2198 (age 26h) repairs eligible: 1 of 3 (cap 1/tick) · dry-run only state: working · 3 active · 0 stale · budget burn normal # sample output — illustrative
autonomy grants

A declaration binds the exact model and provider, with a grant window and a human grantor: declare task-41 with autonomy level, --grant-hours, and the operator who granted it. Inside the window the plane acts; outside it, it refuses — and the refusal is written to the chain, not logged in a side file.

13recovery & migration

Moving without breaking

Migrations are the one operation that touches two homes at once — so they are the most instrumented. Read-only inventory first, dry-run second, one transaction third, and a rollback path that fails closed on drift.

01

brain-inventory · migrate-inventory

Read-only. Every source is enumerated, hashed, and sealed into an autopilot-migration-inventory-v1 before anything moves. The brain path takes nine source kinds — and makes no outbound calls.

02

migrate-import --dry-run

The merge is computed and shown. Nothing is written. You can read exactly what would happen to every row.

03

migrate-import --apply

One transaction, with a rollback journal. The result is sealed as an autopilot-migration-result-v1 — which doubles as the rollback journal itself.

04

migrate-rollback

Dry-run first; apply reverses the merge. Drifted rows and local dependents fail closed--force is explicit, and it is audited.

05

ops.py doctor

Integrity, foreign keys, and the audit chain — verified after, not promised. The migration is done when the chain verifies.

Source never mutated

The origin home is never written during a migration. Everything happens in the target; the source stays exactly as inventoried.

Quarantine-first brain import

brain-import quarantines untrusted content before it is read as memory. brain-inventory-check re-verifies the inventory any time.

Work orders vs archives

Archives move retired fleet history; portable work orders move live work across homes. Both are sealed before flight.

Secret guard on the way in

Notes and handoffs are scanned at entry. A secret is blocked, the block is audited as secret_blocked, and --allow-secret is a verbatim, audited override — errors and payloads never echo the value.

14the surface

Two programs, one vocabulary

The entire plane is reachable from autopilot.py (task-level) and ops.py (fleet-level). A cross-section of the surface — the full inventories live in the README.

autopilot.pytask-level
initseed the home; create the authority
create --depends-on --tagqueue a task with deps and budget
next --claim --recallclaim the best task; take the lease; seal the pack
update --statusmove the task; release or hold the lease
complete --recall-digestclose with a live lease and receipt
fail --no-retryrecord a typed failure; terminal or retryable
context --relatedbuild the bounded, digest-sealed pack
recall-verify · recall-diffreplay and diff past packs
memory-retain · search · forgetthe memory engine, same authority
fact-assert · fact-retracttemporal facts with validity windows
declare --grant-hoursautonomy declaration with model binding
verify-chainreplay the audit hash chain
ops.pyfleet-level
doctorintegrity · foreign keys · audit chain
recoversweep stale leases; resume by epoch
nanny --dry-runthe bounded tick: sense, repair, report
repair-listwhich tier-0 repairs are eligible
migrate-inventoryread-only sealed inventory of the old home
migrate-import --applyone-transaction merge with rollback journal
migrate-rollbackreverse a merge; fails closed on drift
brain-inventory -checknine source kinds, read-only, no outbound
brain-importquarantine-first content import
recall-staleflag packs whose evidence expired
policyfleet policy surface
secret-scanscreen stored content for surfaced secrets
the verify gate

CI byte-compiles every module and runs the component suites plus the context-pack sentinel and the full verify.py. If the plane ships, it verified itself first.

15the record

Three notes, one week

v0.3.0 → v0.5.0 landed in four days of release notes. Each one is a durable document in docs/releases/ — the same evidence-over-claims rule, applied to the project itself.

v0.4.0
2026-08-22 · autopilot-v3

Autopilot v3

Session-start context packs; autonomy grants bound to the exact model and provider with expiry windows and audited refusal; the bounded nanny tick; four-state impulse reporting.

git c7a6480d · docs/releases/2026-08-22-autopilot-v3.md
v0.4.0+
2026-08-23 · botmail

Managed botmail

Provider-neutral envelopes: bot, harness, peer, profile, direction, capability epoch, provenance — receipts accepted, rejected, duplicate, expired, or failed. Hindsight retired across all three surfaces.

docs/releases/2026-08-23-autopilot-botmail.md
v0.5.0
2026-08-24 · memory engine

Local memory engine

memories + memories_fts (FTS5, LIKE fallback) in the same authority; idempotent git ingest by content address; optional embeddings off the pack path; consolidation excludes pure-git clusters by default.

git 4512351f · docs/releases/2026-08-24-autopilot-memory-engine.md