DOCS
This page is generated by hand from the same source the CLI's own memhouse --help
and README.md come from, kept here so it works whether or not you have access to
the source repository. Install, concepts, the full command reference, team & sharing,
staying current, troubleshooting.
One command, no flags, no compiler — Node 24's own node:sqlite covers every adapter that used to need a native binding.
# install $ npm install -g memhouse # no ClickHouse yet? stand one up locally, loopback-bound $ 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 # read-only preflight — writes nothing $ npx -y memhouse discover
Already have a ClickHouse — your own server, ClickHouse Cloud, one provisioned by an
ultimagent kernel? memhouse setup --yes --url … --user … --password … --db …
writes the config directly, no wizard.
Every command is dual-mode: interactive for a human, --yes / flags / --json
for an agent. An agent can install its own memory, unattended.
A house is a ClickHouse database. Three shared tables are its rooms. Everything else follows from that.
sessions, messages, tool_calls — real typed columns for what other
tools derive at query time, plus one extra JSON escape hatch per table so no adapter field is
ever dropped. A member is a ClickHouse user with a database (their house) and full grants on it.
user_id is MATERIALIZED currentUser() — the server stamps it during the
insert, with async inserts pinned off so the stamp cannot be skipped. host is a random
fingerprint minted once per install (~/.memhouse/host.json), not derived from the hostname —
two laptops both called MacBook-Pro stay two machines, and renaming one doesn't split its
history.
WHERE user_id = 'alice'. One machine: WHERE host = 'macbook-4127a95b'.
The whole house: no filter.
A re-ship that comes back shorter used to overwrite the longer parse it replaced. Now every row
in messages/tool_calls carries an epoch: unchanged sessions keep their
epoch, a changed session writes under a new one, and the old epoch stays complete and queryable. Reads
default to the current epoch only; sessions is the deliberate exception — one row per session,
no epoch in its key. Rows also carry origin (ship vs import), so the
shipper's own clear can never touch history it didn't write.
Every command is scriptable. --help or -h on any of them prints this same reference instead of running anything.
| Command | What it does |
|---|---|
| onboard | Interactive wizard: discover → configure → ship → start. |
| install | Scriptable setup — --url --user --password --db [--yes] [--no-ship]. --env FILE installs from an invite file. |
| invite <name> | Mint a member + house on the server, write the env file their install needs — --url --admin-user --admin-password [--db NAME] [--out FILE]. This machine untouched; the admin credential is never stored. |
| passwd | Rotate this member's password and rewrite the env file. Admin-assisted (--admin-user --admin-password) or --print-sql to run it yourself. |
| setup | (Re)write the connection config only. --yes skips every prompt. |
| discover | Read-only preflight: editors found, sessions on disk, reachable ClickHouses. Writes nothing. |
| uninstall | Stop daemons + service, clear runtime state. Default tier keeps config and host identity — --credentials also forgets the house, --full-removal takes everything (asks first). No tier touches house data. |
| update | Upgrade the package, restart the daemons, migrate the house if needed. --check compares versions only. |
| reset | Clear the shipper's rows and re-ship everything (asks; --yes skips). Imported rows are kept unless --all-origins. |
| nightly | Build an installable, version-stamped tarball from this checkout. Publishes nothing. [--out DIR] |
| ship | One incremental pass. --full re-ships everything; --loop [sec] runs continuously. |
| stats | Per-source session/message/token counts. |
| search <terms…> | Full-text search across every session. |
| resume <session-id> | Print (not run) the command that reopens that session in its editor. |
| sessions-query | Print the session-rollup SQL for the configured credential. |
| start / stop | Shipper loop + dashboard as background (pidfile) daemons. |
| status | Daemons, connection, counts, freshness. --json for scripts. |
| doctor | Diagnose the whole pipeline — schema, fleet, pricing coverage, daemons. |
| plugins | list / install claude [--target DIR] / remove claude — acts on every Claude config dir found (~/.claude, CLAUDE_CONFIG_DIR, every ~/.claude-playbooks/*), all selected by default. |
| prompt | Print the memory system-prompt snippet. --install prints an install prompt for an agent instead. |
| deploy --local | Run ClickHouse in docker/podman, bound to loopback, then install. --down removes it (container + volume). |
| migrate / migrate-rooms | Run every migration the house still needs (or just the rooms) — copy + atomic swap, deletes nothing. [--dry-run] [--yes] |
| relocate --to URL | Copy the whole house to a new ClickHouse, server-to-server, and repoint this install. The shipper does not re-ingest; source is untouched until confirmed. |
| service install | Run the shipper as a real user service (systemd --user / launchd). Also stop | start | restart | uninstall | status. |
Config resolves: flags > MEMHOUSE_* env > ~/.memhouse/env > defaults. There is no house-shaped default — with nothing configured, commands that touch memory refuse rather than guess localhost:8123.
Two different things: owning a house (invite) and reading someone else's (share).
memhouse invite <name> mints the ClickHouse user, their database, and the grants —
GRANT ALL … WITH GRANT OPTION, so a member is a full owner of their own house and can hand
grants on to someone else, but still cannot CREATE USER or reach another house. It writes a
portable env file; the admin credential used to run invite is never stored anywhere. The
invitee runs one command:
$ memhouse invite alice --url https://ch.example.com:8443 \ --admin-user root --admin-password ***** ✓ alice.env written # alice runs, on her own machine: $ memhouse install --env alice.env
memhouse share opens a read-only SELECT window into your house for another
member — for asking "how did bob fix this" without handing bob write access to your rooms. Members can
also see who else is on the server (GRANT SHOW USERS ON *.*), so /mem:users can
answer "everyone on this ClickHouse" without an admin.
$ memhouse passwd ✓ password rotated and ~/.memhouse/env updated • every OTHER machine shipping under this user now needs the new password too — run `memhouse setup --password …` there.
memhouse passwd --help prints this reference instead of rotating anything — every command
honors --help / -h before it touches the house.
A bare npm i -g memhouse@latest does about two-thirds of the job.
memhouse update upgrades the package, restarts the daemons (which otherwise keep parsing
with the code they booted with — one shipper here ran 1d16h out of a directory that had been moved),
and checks whether the house is missing something the new shipper needs. update --check
compares versions and changes nothing. Each daemon also checks on its own, once per pass, and hands over
when it's behind — exiting under a supervisor (systemd/launchd) so it restarts on the new code, or
re-executing itself when nothing is supervising it.
memhouse migrate runs whatever this house still needs — detected from the house's own
house_meta record, not from anything the client remembers. Every migration is copy + atomic
swap; the old room is kept as <room>_pre_epoch for you to drop once you've checked it.
migrate --dry-run shows the plan without touching anything.
memhouse relocate --to <url> copies the whole house server-to-server
(remoteSecure()/remote() INSERT SELECT, preserving provenance) and repoints this
install at the new one. It gates on a matching row count before switching, and the old env is kept until
you confirm.
Five adapters — cursor, zed, opencode, goose, antigravity — read sessions out of SQLite files. On
versions before node:sqlite that meant a native binding and an easy-to-forget
--allow-scripts flag; that failure class is gone now. What can still go wrong is one store at
a time — a locked state.vscdb, a corrupt file, a schema an editor release changed —
and it's never silent: memhouse discover and memhouse doctor both name the
skipped adapter and say why, while the other sixteen keep working.
EACCES on installCheck who owns the prefix root, not the path: ls -ld "$(npm prefix -g)". Owned by
root (a system-managed Node) — re-run with sudo. Owned by you (Homebrew, fnm,
nvm, volta) — the prefix is already yours, and the root-owned file npm tripped on is a stray from an
earlier sudo npm; fix just that path with chown instead of adding another
sudo.
memhouse start detaches with pidfiles, which outlive the shell but not a restart.
memhouse service install writes a real user service — systemd --user on Linux, a
launchd agent on macOS — and takes over. On Linux, a --user unit stops at logout unless
lingering is enabled; install detects that and prints the exact loginctl command.
memhouse doctor diagnoses the whole pipeline in one pass — schema, fleet health, pricing
coverage, daemon state — and says in words what's wrong rather than leaving you to infer it from a low
number.