v0.4.1 · 17 editor adapters · MIT

Your agents forget.
The house remembers.

Every coding-agent session on every machine you install it on — Claude Code, Codex, Cursor, Gemini CLI, Devin, Zed and a dozen more — parsed on your machine and shipped to one typed ClickHouse store you own. Then your next agent can read what the last one already worked out.

$ npm install -g memhouse --allow-scripts=better-sqlite3

then memhouse onboard — discover, configure, ship, start.
keep --allow-scripts: five adapters read SQLite and need the native binding.

17
editor adapters
JSONL and SQLite-backed
3
rooms per credential
one set per member, or per agent
1
command to install
dual-mode: human or agent
0
clouds to trust
your ClickHouse, your rules

One shipper · seventeen adapters · whatever you switched to last month

localhost:4640 — memhouse dashboard
The memhouse dashboard: sessions per editor, token and cost tiles, a coding-activity heatmap and per-editor monthly trends

// shown in dark mode — the dashboard ships both themes, like this page. It is agentlytics' UI, unforked: memhouse serves the same bundle over its own typed store

01  /  The problem

Your history already exists. It's just unusable.

Every agent you run already writes down what it did — into its own directory, in its own format, on whichever laptop you happened to use. Which means the answer you worked out three weeks ago is on disk and out of reach: not to you, and definitely not to the agent that is about to re-derive it.

Session files as they shipExport + index (RAG)memhouse
Where it lives A dozen app directories, per machine A vector store you now operate One ClickHouse you already trust
Coverage Whatever one editor wrote Whatever exports cleanly to text 17 adapters, JSONL and SQLite-backed editors
Shape of the data Raw JSONL, or an app's private SQLite Chunks and embeddings Typed rows: messages, sessions, tool calls
Answering a question grep, if you remember which folder Approximate recall, no exact filters SQL and full-text — exact, filterable, joinable
A second machine A second pile of files Re-export and re-index it Install there too, same credential — it ships into your rooms, tagged with a stable host
Sharing with a teammate Paste a transcript Copy the whole index, or nothing One GRANT — theirs stays theirs
Not a chat-log warehouse. memhouse parses before anyone asks and writes the result down, so what lands in the house is already structured: who said it, in which session, in which project, with which model, at what cost, calling which tools. The query does no archaeology.

02  /  Alternatives

Four ways to give an agent a memory

Agent memory is a crowded field, and the projects in it do not disagree about the goal — they disagree about where you tap the stream. That choice decides everything downstream: what gets captured, whether your existing history counts, and who your prompts pass through on the way to the model.

Nothing
the files as they ship
Proxy at the model boundary Memory framework
vector / graph store
memhouse
Where it taps in Nowhere — each app writes its own files In front of the LLM API; you point agents at it SDK calls you add to your own app Reads the session files each editor already writes
Your history from before you installed it On disk, unread Gone — only new traffic is seen Gone, unless you write an importer Ingested — that is the whole point
What it can see Everything, unusably The model conversation Whatever you remembered to pass it Tool calls, timing, project, model, cost — what actually ran
Where your prompts travel Nowhere Through the proxy, then upstream To an embedding API, usually Nowhere — parsing is local, rows go to your ClickHouse
Infrastructure it adds None Several services to run and keep up A vector DB, often a graph DB too One ClickHouse — or the one you already run
Who enforces isolation The filesystem Application code, over an app-level store Application code, over an app-level store The database — GRANT and currentUser(), not a service you have to trust
Cost of coverage One integration catches every agent One integration, but only your own app 17 adapters to maintain — deliberately paid
Where the proxy approach genuinely wins. One integration point catches every agent, because every agent talks to a model API — while adapters are one per editor, forever, and they break when an editor changes its on-disk layout. memhouse pays that maintenance on purpose, for the two things a proxy structurally cannot do: read the history already sitting on your disk, and stay out of the path between you and your model. If you would rather not run a man-in-the-middle on every prompt you send, that is the trade.

03  /  How it works

Three moving parts. One of them writes.

memhouse is a house — a ClickHouse database — plus one resident: the shipper. Everything else in the system only reads, which is why there is so little of it.

STEP 01

Parse on the client

The shipper runs all 17 adapters locally — JSONL transcripts and the private SQLite databases Cursor, Zed, Goose, OpenCode and Antigravity keep — and emits typed rows. Nothing raw leaves the disk.

STEP 02

Ship into typed rooms

messages, sessions, tool_calls as real columns, plus one extra JSON escape hatch so no adapter field is ever lost. Incremental by default; a re-ship of a grown session replaces the stale rows instead of duplicating them.

STEP 03

Ask — human or agent

A dashboard for eyes, memhouse search for terms, plain SQL for everything else, and a skills payload so an agent queries its own past sessions before it claims it doesn't know.

04  /  Who it's for

One person with six agents. Or six people with sixty.

Same install, same rooms. The only difference is who holds a grant.

Solo builders

One place your whole agent history lives

You switch editors. You switch machines. You do not switch memory — point each machine at the same house with the same credential and every session lands in the same three rooms, each row tagged with the machine it came from. "How did I fix that" is then one query, not an archaeology dig through four app directories on two laptops.

  • All of it, not the last one. The editor you abandoned in March still ships.
  • Costs you can actually see. Spend, model mix and tool usage across every agent at once.
  • Runs on your laptop. memhouse deploy --local stands up a loopback-bound ClickHouse in one command.
Teams

Shared memory that fails closed

Every member owns their own three rooms — messages_alice, sessions_alice, tool_calls_alice. Isolation is a grant that is simply absent, not a row policy that has to be right on every table and every read path.

  • Sharing is one GRANT, issued by the member or the house owner — no operator in the loop.
  • A shared read is a Merge room (all_sessions) that reduces to whatever the caller can already read.
  • Install centrally as an agency on an ultimagent kernel, members provisioned with their own credentials.

Agents that see only their slice

A crew is not one memory. Each agent gets a credential, and a credential is three rooms — so a scout, a builder and a reviewer each hold their own history and none of them can read the others by default. What one agent may see another agent's work is a decision you make, not a filter you hope holds.

  • Share a whole memory, self-serve. Three GRANTs, issued by the owner of the rooms — no operator, no ticket. Measured end to end: a grant took what the recipient could see from 0 rows to 22,413, and the revoke put it back to 0.
  • Share a slice, owner-mediated. A subset is a grant plus a row policy, and policies are house-scoped, so this one goes through the house owner deliberately. Both halves are required: privilege without a policy shares everything, a policy without privilege shares nothing.
  • Read-only by construction. The grant option a member holds is attached to SELECT, so sharing hands over reading — never writing or dropping.
The line that actually matters. Separation is between credentials, not between agents. A crew running under one shared credential reads and writes the same rooms, and any per-agent tag in that setup is client-supplied — which means it is a label, not a boundary. Enforced separation means a credential each.
# one credential per agent — one isolated memory each
$ memhouse install --yes --user scout    …
$ memhouse install --yes --user builder  …
 messages_scout, sessions_scout, tool_calls_scout
 messages_builder, …  # invisible to scout

# let the builder read what the scout found
$ GRANT SELECT ON mem.messages_scout   TO builder;
$ GRANT SELECT ON mem.sessions_scout   TO builder;
$ GRANT SELECT ON mem.tool_calls_scout TO builder;

# and take it back
$ REVOKE SELECT ON mem.messages_scout FROM builder;

05  /  What you get

Memory that behaves like a database

Because it is one.

Typed common schema

Physical columns for what other tools derive at query time, a tool_calls table most don't have at all, and one extra JSON field per table so unnormalized adapter data is never dropped.

Full-text search built in

memhouse search <terms> across every session you have ever had, on any machine, in any editor — ClickHouse text indexes, not a grep over files that may already be rotated away.

An isolated room per agent

Give an agent its own credential and it gets its own three rooms — it can see its memory and nobody else's. Isolation is a grant that is simply absent, so it fails closed rather than depending on a filter being right everywhere.

Agent-native, not agent-adjacent

Every command is dual-mode: interactive for humans, --yes / flags / --json for agents. An agent can install its own memory and its own skills, unattended.

Costs, models, tools

A cost engine over per-model token sums, and a dashboard showing sessions, spend, model mix, peak hours and tool usage across all your agents at once.

Survives a reboot

memhouse service install writes a real user service — systemd --user on Linux, a launchd agent on macOS — and takes over from the pidfile daemons.

06  /  Where the memory lives

Your ClickHouse, your rules

memhouse does not embed a database and does not run a cloud you have to trust. Point it at a ClickHouse — or let it stand one up for you.

PathWhat it runsWho it's for
deploy --local Stock ClickHouse in docker or podman, bound to loopback. It labels what it creates and refuses to touch a container or volume it did not create, so a name collision costs you an error rather than somebody else's data. One machine — or several members later.
kernel install An agency house on an ultimagent kernel: house, owner, credential, and members provisioned with grants on their own rooms. A team, provisioned centrally.
your own Any reachable ClickHouse — a server you run, ClickHouse Cloud, whatever you already pay for. You already have one.

07  /  The CLI

One binary, no dashboard tour required

Config resolves flags > MEMHOUSE_* env > ~/.memhouse/env > defaults.

# install (keep the flag — five adapters read SQLite)
$ npm install -g memhouse --allow-scripts=better-sqlite3

# no ClickHouse yet? one command stands one up
$ memhouse deploy --local

# the wizard: discover → configure → ship → start
$ memhouse onboard
 17 adapters · 9 with sessions on this machine
 sessions shipped · dashboard on http://localhost:4640

# then, any time
$ memhouse search clickhouse ttl
$ memhouse stats
$ memhouse status --json
$ memhouse doctor

Want to look before it writes anything?

discover is a read-only preflight: which editors it found, how many sessions are sitting on this disk, and which ClickHouses it can reach. It writes nothing.

$ npx --allow-scripts=better-sqlite3 -y memhouse discover
  • Incremental. A pass skips every session that hasn't grown or changed; a full re-ship stays safe.
  • Idempotent. Re-shipping a known session clears its old message and tool rows first, so a shrunken re-parse can't leave a stale tail behind.
  • Honest about failure. doctor diagnoses the whole pipeline, and discover says out loud when the SQLite binding is missing rather than silently shipping a partial history.

08  /  For agents

The next agent starts where the last one stopped

A house full of past sessions is only worth it if the next session can read it. memhouse ships the delivery kit that makes that the default behaviour rather than a thing you remember to do.

"Did we ever solve this before?" — asked before the answer is re-derived, not after.

  • Skills. /memhouse:search, /memhouse:sessions, /memhouse:sql — full text, session listing, free-form read-only SQL.
  • A plugin. memhouse plugins install claude drops them into Claude Code.
  • A prompt snippet. memhouse prompt prints the system-prompt block that tells an agent to search memory before claiming ignorance.
  • Read-only by construction. Agents query; only the shipper writes. Other members' sessions stay invisible unless they granted you their rooms.
# give an agent its own memory, unattended
$ memhouse install --yes \
    --url https://ch.example.com:8443 \
    --user alice --password ***** --db mem
 rooms minted: messages_alice, sessions_alice, tool_calls_alice
 verified as alice

$ memhouse plugins install claude
 skills installed: search · sessions · sql

$ memhouse prompt >> CLAUDE.md

Start remembering

One command to see what every agent on your machines has actually been doing — and to let the next one read it.

$ npm install -g memhouse --allow-scripts=better-sqlite3

09  /  Questions

Before you install it

Does anything leave my machine?

Only what you point it at. Parsing happens locally, and the shipper writes typed rows to the ClickHouse you configure — which can be a container on the same laptop (memhouse deploy --local, bound to loopback). There is no memhouse cloud and no phone-home.

Why do I need --allow-scripts=better-sqlite3?

Five adapters — Cursor, Goose, OpenCode, Zed and Antigravity — read sessions out of SQLite files, and better-sqlite3 builds its native binding from an install script. npm 12 blocks install scripts by default, so without the flag those five read nothing and you would silently ship a partial history. discover and doctor both say so when the binding is missing.

What if the install fails with EACCES?

Check ls -ld "$(npm prefix -g)" — the prefix root is what decides, not the path and not the failing file. Owned by root: a system-managed Node, so re-run with sudo. Owned by you (Homebrew, fnm, nvm, volta): the prefix is yours and the root-owned file npm tripped on is a stray from an earlier sudo npm — another sudo just adds more. Fix that one path with chown instead.

How is this different from RAG over my transcripts?

memhouse doesn't chunk and embed — it parses. What lands in the house is typed rows you can filter, aggregate and join: by project, by model, by editor, by cost, by tool call. Full-text search is a ClickHouse text index over those rows, so a query is exact rather than approximate, and the same data also answers "what did I spend on Opus last month".

Can a team share memory?

Yes, and sharing is the exception rather than the default. Every member owns their own three rooms; a shared read is a Merge room plus a GRANT, issued by the member themselves or the house owner. Nothing is visible by accident, because visibility has to be given rather than enforced.

Which editors, exactly?

Seventeen adapters, covering: Claude Code, Codex, Cursor, Cursor Agent, VS Code, VS Code Insiders, GitHub Copilot (CLI and JetBrains), Gemini CLI, Devin, Devin Next, Zed, Goose, OpenCode, Kiro, Antigravity, Codebuff, Command Code and GSD Workflow.

Where does this come from?

The adapters, dashboard and cost engine are built on agentlytics by Fatih Kadir Akın (MIT); the repo's history carries the full lineage. memhouse adds the typed store, per-member rooms, the shipper and the agent delivery kit. It is part of the Ultimagent constellation, where it installs as an agency.