memhouse 0.18.8 → 0.18.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/AGENTS.md +194 -0
  2. package/CHANGELOG.md +970 -0
  3. package/README.md +54 -423
  4. package/SECURITY.md +68 -0
  5. package/bin/memhouse.js +202 -92
  6. package/docs/README.md +46 -0
  7. package/docs/guides/admin-password.md +95 -0
  8. package/docs/guides/configuration.md +109 -0
  9. package/docs/guides/daemons.md +53 -0
  10. package/docs/guides/install.md +128 -0
  11. package/docs/guides/invite.md +87 -0
  12. package/docs/guides/operate.md +112 -0
  13. package/docs/guides/search-and-resume.md +95 -0
  14. package/docs/guides/share.md +102 -0
  15. package/docs/guides/storage.md +90 -0
  16. package/docs/guides/troubleshooting.md +78 -0
  17. package/docs/guides/uninstall.md +35 -0
  18. package/docs/guides/update.md +68 -0
  19. package/docs/releases/README.md +10 -0
  20. package/docs/releases/v0.18.10.md +226 -0
  21. package/docs/tutorials/01-first-house.md +132 -0
  22. package/docs/tutorials/02-join-a-house.md +91 -0
  23. package/docs/tutorials/03-share-your-memory.md +96 -0
  24. package/examples/01-local-one-machine/README.md +99 -0
  25. package/examples/01-local-one-machine/run.sh +61 -0
  26. package/examples/02-existing-clickhouse/README.md +121 -0
  27. package/examples/02-existing-clickhouse/run.sh +71 -0
  28. package/examples/03-team-house/README.md +129 -0
  29. package/examples/03-team-house/run.sh +124 -0
  30. package/examples/04-self-hosted-team/.env.example +22 -0
  31. package/examples/04-self-hosted-team/README.md +187 -0
  32. package/examples/04-self-hosted-team/compose.yml +158 -0
  33. package/examples/04-self-hosted-team/smoke.sh +113 -0
  34. package/examples/README.md +42 -0
  35. package/examples/fixtures/README.md +24 -0
  36. package/examples/fixtures/make-sessions.js +63 -0
  37. package/memhouse/admin-secret.js +81 -0
  38. package/memhouse/delivery/plugin/.claude-plugin/plugin.json +1 -1
  39. package/memhouse/deploy.js +4 -2
  40. package/memhouse/flags.js +4 -4
  41. package/memhouse/provision.js +12 -3
  42. package/memhouse/server/queries.js +18 -4
  43. package/memhouse/server/server.js +9 -1
  44. package/memhouse/service.js +5 -0
  45. package/package.json +10 -2
@@ -0,0 +1,95 @@
1
+ # Admin password
2
+
3
+ A few commands need the ClickHouse server's administrator:
4
+
5
+ - `install --admin-user …`, which creates a member;
6
+ - `invite`;
7
+ - `passwd --admin-user …`, for a member whose account predates self-rotation (0.11);
8
+ - `members`;
9
+ - `convert`.
10
+
11
+ Shipping, searching and sharing never need it.
12
+
13
+ **The admin password owns the whole server.** Keep it out of three places:
14
+
15
+ - **the command line**, where `ps` shows it to every user on the machine while the command
16
+ runs, and shell history keeps it afterwards;
17
+ - **an agent's conversation**, because memhouse ships that conversation into the house,
18
+ and the archive is insert-only;
19
+ - **disk**, unless you chose that: `--keep-admin`, or `deploy --local`.
20
+
21
+ ## Where memhouse takes it from
22
+
23
+ In order, first answer wins:
24
+
25
+ | # | source | use it when |
26
+ |---|---|---|
27
+ | 1 | `--admin-password-file <file>` | a file you control, mode 600. One trailing newline is dropped |
28
+ | 1 | `--admin-password-file -` | piping it in: `printf '%s' "$P" \| memhouse … --admin-password-file -` |
29
+ | 2 | `--admin-password <value>` | **deprecated**: works in 0.18.x with a warning, **removed in 0.19.0** |
30
+ | 3 | `MEMHOUSE_ADMIN_PASSWORD` | a secret manager lends it to one command (below) |
31
+ | 4 | the credential this install keeps | only when it belongs to the same admin user |
32
+ | 5 | a prompt | when there is a terminal; input is hidden, and pasting works |
33
+
34
+ The two forms of `--admin-password-file` are one option, and it cannot be combined with
35
+ `--admin-password`. With no source and no terminal, the command stops and prints these
36
+ options. It never hangs, and it never guesses.
37
+
38
+ ## With a secret manager
39
+
40
+ The best form: the value exists only in the one command's environment.
41
+
42
+ ```bash
43
+ with-secret MEMHOUSE_ADMIN_PASSWORD=keychain:pilot/house-admin -- \
44
+ memhouse invite alice --url https://house.example.com --admin-user default
45
+
46
+ # 1Password
47
+ op run --env-file=<(echo 'MEMHOUSE_ADMIN_PASSWORD=op://Infra/house-admin/password') -- \
48
+ memhouse members --admin-user default
49
+ ```
50
+
51
+ In CI, put it in the job's secret store and expose it as `MEMHOUSE_ADMIN_PASSWORD` for
52
+ that step only.
53
+
54
+ ## Typing it once, in a terminal
55
+
56
+ ```bash
57
+ memhouse invite alice --url https://house.example.com --admin-user default
58
+ # prompts for the admin password; what you type or paste is not shown
59
+ ```
60
+
61
+ Or, to reuse it for a few commands in one shell without it reaching history:
62
+
63
+ ```bash
64
+ read -rs MEMHOUSE_ADMIN_PASSWORD && export MEMHOUSE_ADMIN_PASSWORD
65
+ memhouse members --admin-user default
66
+ unset MEMHOUSE_ADMIN_PASSWORD
67
+ ```
68
+
69
+ ## Keeping it on this machine
70
+
71
+ `install --admin-user … --keep-admin` writes the admin credential into
72
+ `~/.memhouse/env`, so later `invite` and `members` need no flags. `deploy --local` does
73
+ the same, because a local house's admin is yours. Otherwise memhouse does not save it.
74
+
75
+ Even when it is saved, the daemons never carry it: service units and the started
76
+ shipper and dashboard have `MEMHOUSE_ADMIN_*` removed from their environment.
77
+
78
+ To stop keeping it, delete the `MEMHOUSE_ADMIN_USER` and `MEMHOUSE_ADMIN_PASSWORD` lines
79
+ from the env file.
80
+
81
+ ## What `whoami --admin` tells you
82
+
83
+ ```bash
84
+ memhouse whoami --admin --json
85
+ ```
86
+
87
+ This reports what the admin credential (`MEMHOUSE_ADMIN_*`, or the kept one) may
88
+ actually do on the server, for example `canProvision`. It never prints the password. Use
89
+ it before a scripted run, rather than guessing from a grant string.
90
+
91
+ ## If a password reached a transcript
92
+
93
+ Treat it as burned. Rotate it on the server (`ALTER USER … IDENTIFIED BY …`, as the
94
+ admin) and update every place that legitimately holds it. Deleting the transcript does
95
+ not help: the house is insert-only, and it may already have shipped.
@@ -0,0 +1,109 @@
1
+ # Configuration
2
+
3
+ Everything memhouse needs is in one env file, `~/.memhouse/env` (mode 600), or in the
4
+ directory named by `MEMHOUSE_HOME`. Values resolve in this order:
5
+
6
+ 1. command-line flags;
7
+ 2. exported `MEMHOUSE_*` variables;
8
+ 3. `$MEMHOUSE_HOME/env`.
9
+
10
+ With nothing configured, commands that touch the house refuse and say so. There is no
11
+ default house.
12
+
13
+ | Variable | Meaning |
14
+ |---|---|
15
+ | `MEMHOUSE_URL` | the house's HTTP(S) endpoint |
16
+ | `MEMHOUSE_USER` / `MEMHOUSE_PASSWORD` | the member credential the shipper writes as |
17
+ | `MEMHOUSE_DB` | the database holding the rooms, normally `mem` |
18
+ | `MEMHOUSE_PORT` | the dashboard port, default `4640` |
19
+ | `MEMHOUSE_CHANNEL` | the npm dist-tag `update` follows |
20
+ | `MEMHOUSE_EDITORS` | which adapters run (default: all) |
21
+ | `MEMHOUSE_<EDITOR>_ROOTS` | where one adapter looks |
22
+ | `MEMHOUSE_HOME` | where the env file, host identity, logs and pidfiles live |
23
+ | `MEMHOUSE_ENGINE` | `docker` or `podman`, for `deploy --local` |
24
+
25
+ Never print this file or these variables in a terminal an agent is reading. memhouse ships
26
+ transcripts, and a password that appears in one is in the archive.
27
+
28
+ ## Which sessions ship
29
+
30
+ By default, everything on the machine: every adapter, from wherever that editor keeps its
31
+ sessions. `memhouse discover` prints what each adapter watches and the variable that moves
32
+ it:
33
+
34
+ ```
35
+ Watched directories (override with the variable shown, in the env file):
36
+ claude ~/.claude, ~/.claude-playbooks/kommander, … [MEMHOUSE_CLAUDE_ROOTS]
37
+ codex ~/.codex [MEMHOUSE_CODEX_ROOTS]
38
+ gemini-cli ~/.gemini [MEMHOUSE_GEMINI_CLI_ROOTS]
39
+ cursor ~/Library/Application Support/Cursor/User, … [built-in]
40
+ ```
41
+
42
+ Two kinds of line in the env file narrow it, or `--editors` / `--claude-roots` at install:
43
+
44
+ ```
45
+ MEMHOUSE_EDITORS='claude'
46
+ MEMHOUSE_CLAUDE_ROOTS='~/.claude-playbooks/kommander-chaos'
47
+ ```
48
+
49
+ - `MEMHOUSE_EDITORS` names the adapters to run.
50
+ - `MEMHOUSE_<EDITOR>_ROOTS` replaces one adapter's location. The variable name is the
51
+ adapter's name upper-cased, with dashes turned into underscores.
52
+ - Claude is the one adapter with many roots, one per Claude Code config directory, so its
53
+ list may hold several. Every other adapter has one store and takes one path.
54
+ - Adapters marked `[built-in]` resolve a platform app-data directory and cannot be moved
55
+ yet.
56
+
57
+ An adapter name or a directory that does not exist is refused and reported against that
58
+ adapter. It is never shipped from the default instead: a typo that quietly shipped
59
+ nothing would look like a working install with an empty house.
60
+
61
+ Restart the shipper after changing these (`memhouse stop && memhouse start`, or
62
+ `memhouse service restart`).
63
+
64
+ ## Instances: several memhouses on one machine
65
+
66
+ An **instance** is a home. It has:
67
+
68
+ - an env file naming a house;
69
+ - the daemons shipping to that house;
70
+ - the playbooks whose sessions it ships (`MEMHOUSE_CLAUDE_ROOTS`).
71
+
72
+ A machine can run several, each under its own `MEMHOUSE_HOME` and on its own channel:
73
+
74
+ ```bash
75
+ MEMHOUSE_HOME=~/.memhouse-work memhouse install --env invite-work.env
76
+ MEMHOUSE_HOME=~/.memhouse-work memhouse instance # which memhouse this is
77
+ ```
78
+
79
+ `memhouse instance` prints one screen:
80
+
81
+ - the instance's name and home;
82
+ - the binary and its channel;
83
+ - the house, its database and member, and whether an admin credential is present;
84
+ - the rooms, with row counts;
85
+ - what this machine ships;
86
+ - the host identity;
87
+ - the daemons;
88
+ - which playbooks are bound to this instance.
89
+
90
+ `plugins install claude`, run from an instance, installs the skills into exactly the
91
+ playbooks that instance ships, and **binds** them. It writes `MEMHOUSE_HOME` and
92
+ `MEMHOUSE_BIN` into each playbook's `settings.json` `env`, and Claude Code applies that to
93
+ every session there. So the `/mem:*` skills in a bound playbook read that instance's house
94
+ and run that instance's binary, whatever the launching shell had set. `plugins list` shows
95
+ the binding; `plugins remove claude` takes it out.
96
+
97
+ ## Channels
98
+
99
+ `memhouse update` follows the npm dist-tag the install came from, not `latest` by reflex.
100
+
101
+ - The channel is inferred from the installed version.
102
+ - To pin it, add `MEMHOUSE_CHANNEL='team'` to the env file, or run
103
+ `memhouse update --channel team`, which writes the same line.
104
+ - An invite from a house on a channel carries that channel, so the invitee follows it
105
+ too.
106
+ - A tarball or checkout build sits on no tag and is never auto-updated. `update --check`
107
+ says so.
108
+
109
+ Today there is one release line: `latest`, with `team` as an alias for the same build.
@@ -0,0 +1,53 @@
1
+ # Daemons and services
2
+
3
+ memhouse runs two long-lived processes:
4
+
5
+ - the **shipper**, which runs an incremental pass every 300 seconds;
6
+ - the **dashboard**, on `http://localhost:4640` (`MEMHOUSE_PORT` changes it).
7
+
8
+ ## Until the next reboot
9
+
10
+ ```bash
11
+ memhouse start # both, detached, with pidfiles in $MEMHOUSE_HOME
12
+ memhouse stop
13
+ memhouse status # running or not, and whether the last pass succeeded
14
+ ```
15
+
16
+ `start` detaches, so the processes outlive the shell, but not a restart.
17
+
18
+ ## Across reboots
19
+
20
+ ```bash
21
+ memhouse service install # systemd --user on Linux, a LaunchAgent on macOS
22
+ memhouse service install --interval 600
23
+ memhouse service status | stop | start | restart | uninstall
24
+ ```
25
+
26
+ `service install` writes a real user service and takes over from any `start` daemons.
27
+
28
+ - **The unit gets the member credential only.** `MEMHOUSE_ADMIN_*` is dropped before the
29
+ environment is written into the unit, and the shipper and dashboard are started without
30
+ it, even when your shell exported it.
31
+ - **On Linux, a `--user` unit stops at logout unless lingering is on.** `service install`
32
+ detects this and prints the `loginctl enable-linger <you>` command.
33
+ - **The unit runs the Node binary that installed it.** After a Homebrew or nvm Node
34
+ upgrade, run `memhouse service uninstall`, then `memhouse service install`, so the unit
35
+ points at the new one.
36
+
37
+ ## One pass by hand
38
+
39
+ ```bash
40
+ memhouse ship # one incremental pass, in the foreground
41
+ memhouse ship --full # re-read every session, not just the changed ones
42
+ ```
43
+
44
+ A pass is incremental. A session is skipped when the house already holds it at least as
45
+ fresh and at least as large. For a session that grew, only the new turns are sent, when
46
+ every earlier turn is already in the house unchanged. `--full` rereads everything. It
47
+ never deletes anything: see [How memory is stored](storage.md).
48
+
49
+ ## Logs
50
+
51
+ The daemons log to `$MEMHOUSE_HOME/logs/` (default `~/.memhouse/logs/`): `shipper.log` and
52
+ `dashboard.log`. `memhouse status` reads the shipper's last pass from its log, and reports
53
+ a failing pass as a failure even while the process is alive.
@@ -0,0 +1,128 @@
1
+ # Install and onboard
2
+
3
+ memhouse is one npm package with no build step and no native dependency. It needs
4
+ **Node 24 or newer**. SQLite comes from `node:sqlite`, which is stable in 24. On 22.13+ it
5
+ works but prints an `ExperimentalWarning` on every command, and Node 20 is past end of life.
6
+
7
+ ```bash
8
+ npm install -g memhouse
9
+ ```
10
+
11
+ Then pick the path that matches your situation.
12
+
13
+ | You have | Run |
14
+ |---|---|
15
+ | nothing yet, and want the guided route | `memhouse onboard` |
16
+ | nothing, but docker or podman | `memhouse deploy --local` |
17
+ | an invite file from someone's house | `memhouse install --env invite-<you>.env` |
18
+ | a ClickHouse and a member credential | `memhouse install --url … --user … --db mem` |
19
+ | a ClickHouse and its admin credential | `memhouse install --url … --admin-user … --member <you>` |
20
+ | a ClickHouse someone else administers | `memhouse install --print-sql`, then hand them the SQL |
21
+
22
+ ## `onboard`: the guided route
23
+
24
+ `memhouse onboard` is interactive:
25
+
26
+ 1. it discovers your editors;
27
+ 2. it asks where the house is. If none exists and docker or podman is present, it offers
28
+ to run one locally;
29
+ 3. it ships;
30
+ 4. it offers to start the daemons and to install the Claude Code skills.
31
+
32
+ Everything it does can also be done with the scriptable commands below.
33
+
34
+ ## `deploy --local`: a house on this machine
35
+
36
+ ```bash
37
+ memhouse deploy --local # ClickHouse 25.11 on 127.0.0.1:8123
38
+ memhouse deploy --local --house-port 18123 # another port, if 8123 is taken
39
+ memhouse deploy --local --tag 26.7 # another ClickHouse version
40
+ ```
41
+
42
+ It runs ClickHouse in a container bound to loopback, with the data in a named volume. The
43
+ container's superuser is `memhouse_root`, which administers the house. You ship as a
44
+ **member** named after your OS user (the command asks; `--user` sets it). The member holds
45
+ one grant, on `mem.<you>_*`. Both credentials go into `~/.memhouse/env`, mode 600, so that
46
+ inviting someone later needs no flags. It then installs and ships.
47
+
48
+ The user name and password are fixed when the volume is first initialised and reused on
49
+ every redeploy. `memhouse deploy --down` removes the container **and the volume, which
50
+ deletes the memory**.
51
+
52
+ When both docker and podman are installed and one of them cannot answer, choose with
53
+ `MEMHOUSE_ENGINE=docker` or `MEMHOUSE_ENGINE=podman`. With rootless podman on Linux, the
54
+ container may stop at logout unless lingering is on. `deploy` detects this and prints the
55
+ `loginctl enable-linger` command.
56
+
57
+ ## `install`: the scriptable route
58
+
59
+ ```bash
60
+ # a member credential you already have
61
+ MEMHOUSE_PASSWORD=… memhouse install --url https://house.example.com --user alice --db mem --yes
62
+
63
+ # from an invite file (the usual way to join a team)
64
+ memhouse install --env invite-alice.env
65
+
66
+ # you hold the server's admin: memhouse creates the member, then ships as the member
67
+ with-secret MEMHOUSE_ADMIN_PASSWORD=keychain:pilot/house-admin -- \
68
+ memhouse install --url https://house.example.com --admin-user default --member alice
69
+
70
+ # you hold nothing: print the SQL for whoever administers the server
71
+ memhouse install --print-sql --member alice
72
+ ```
73
+
74
+ Useful flags:
75
+
76
+ | Flag | Effect |
77
+ |---|---|
78
+ | `--yes` | no questions; take the defaults |
79
+ | `--no-ship` | configure and verify, but do not ship yet |
80
+ | `--editors claude,codex` | ship only these adapters ([configuration](configuration.md)) |
81
+ | `--claude-roots DIR[,DIR]` | ship only these Claude Code config directories |
82
+ | `--channel team` | follow this npm dist-tag on `update` |
83
+ | `--keep-admin` | keep the admin credential in the env file (not done by default) |
84
+ | `--ensure-schema` | create any room or stats table the house is missing |
85
+
86
+ The admin password never needs to be on the command line. See
87
+ [Admin password](admin-password.md).
88
+
89
+ `install --env <file>` reads the connection **only** from the file. Exported `MEMHOUSE_*`
90
+ variables are ignored, including `MEMHOUSE_EDITORS` and `MEMHOUSE_CLAUDE_ROOTS`. To narrow
91
+ what an invite install ships, pass `--editors` / `--claude-roots` as flags.
92
+
93
+ ### What install checks
94
+
95
+ Before it writes any config, install connects, confirms who the credential is, and checks
96
+ that it can reach its rooms. The config is written last, so a refused install leaves no
97
+ half-configured machine behind.
98
+
99
+ Configuration resolves in this order: flags, then exported `MEMHOUSE_*` variables, then
100
+ `~/.memhouse/env`. There is no built-in default house. With nothing configured, commands
101
+ that read or write memory refuse and say so. They never guess `localhost:8123`, which on
102
+ many machines is somebody else's house.
103
+
104
+ ## `EACCES` on install
105
+
106
+ `sudo` is right for only one of the two causes. What tells them apart is **who owns the
107
+ prefix root**, not the path, and not the file npm named.
108
+
109
+ ```bash
110
+ ls -ld "$(npm prefix -g)"
111
+ ```
112
+
113
+ - **Owned by `root`:** a system-managed Node (distro packages under `/usr`). Re-run with
114
+ `sudo npm install -g memhouse`.
115
+ - **Owned by you:** the prefix is yours (Homebrew, fnm, nvm, volta). The root-owned file
116
+ npm tripped on is left over from an earlier `sudo npm`, and another `sudo` adds more.
117
+ Repair just that path: `sudo chown -R "$(id -u):$(id -g)" <the path npm named>`. Do the
118
+ same for `~/.npm` if npm names it.
119
+
120
+ The path proves nothing on its own: Homebrew's prefix is `/usr/local` on Intel and
121
+ `/opt/homebrew` on Apple Silicon, and it is yours in both cases.
122
+
123
+ ## After installing
124
+
125
+ - `memhouse status`: connection, counts, freshness.
126
+ - `memhouse start` or `memhouse service install`: keep shipping. See [Daemons](daemons.md).
127
+ - `memhouse plugins install claude`: the `/mem:*` skills. See
128
+ [Search, resume and skills](search-and-resume.md).
@@ -0,0 +1,87 @@
1
+ # Invite members
2
+
3
+ Inviting creates a ClickHouse user and their rooms, and writes one file the invitee
4
+ installs from. It needs a credential that can create users, which means the server's
5
+ admin.
6
+
7
+ ```bash
8
+ memhouse invite alice --url https://house.example.com
9
+ # invite written: invite-alice.env
10
+ ```
11
+
12
+ - **`--url` is the address the invitee will reach the house at,** not yours. It cannot be
13
+ loopback: `localhost` on their machine is their machine. Use a LAN address, a hostname
14
+ or a tunnel. `--allow-local` overrides this, for the case where the invitee is on the
15
+ same machine.
16
+ - **The rooms are named for them:** `mem.alice_sessions`, `mem.alice_messages`, and so on.
17
+ Alice is granted exactly `mem.alice_*`, nothing else. A different database:
18
+ `--db <name>`.
19
+ - **The file is a credential.** It holds the house URL, alice's user name, a generated
20
+ password and the database. Hand it over a channel you trust: croc, a password manager.
21
+ Not chat or email. `--out <path>` writes it somewhere else.
22
+ - **Alice installs with `memhouse install --env invite-alice.env`.** It offers to rotate
23
+ the password to one only she knows, which works because she is granted `ALTER USER` on
24
+ herself. Then it deletes the file. Once she rotates, the password you saw stops working.
25
+
26
+ ## Which admin credential
27
+
28
+ `invite` uses, in order:
29
+
30
+ 1. the admin credential this install keeps. `deploy --local` keeps one;
31
+ `install --keep-admin` keeps one;
32
+ 2. otherwise, `--admin-user <name>` plus the password from `MEMHOUSE_ADMIN_PASSWORD`, from
33
+ `--admin-password-file`, or from a prompt.
34
+
35
+ ```bash
36
+ with-secret MEMHOUSE_ADMIN_PASSWORD=keychain:pilot/house-admin -- \
37
+ memhouse invite alice --url https://house.example.com --admin-user default
38
+ ```
39
+
40
+ Never paste the admin password into an agent's conversation. memhouse ships that
41
+ conversation into the house. See [Admin password](admin-password.md).
42
+
43
+ Not the admin? `memhouse invite alice --url … --print-sql` prints the statements for
44
+ whoever is, plus the env-file lines to hand alice. The printed plan never holds a password:
45
+ it says `IDENTIFIED BY <member-password>`, which does not parse until the administrator
46
+ puts a quoted password they generate in its place, and the same password goes into the
47
+ env file. `install --print-sql` works the same way.
48
+
49
+ ## When the name is taken
50
+
51
+ `invite` refuses a name whose messages room already holds rows. Inviting into it would
52
+ hand the newcomer somebody else's memory, and their first ship would land on top of it.
53
+ It suggests another name or another database.
54
+
55
+ `--adopt` overrides the refusal for one case: **the same person with a new credential**.
56
+ For example, someone lost their password and their old machine. The rooms and their
57
+ history stay; the new credential takes them over.
58
+
59
+ **Inviting a ClickHouse user who already exists is refused.** memhouse does not reset an
60
+ existing member's password through an invite.
61
+
62
+ - To change your own password: `memhouse passwd`. Since 0.11 a member may alter their own
63
+ account, so no admin is needed. memhouse writes the new password to the env file and
64
+ never prints it.
65
+ - There is no verb for resetting **someone else's** password. If a member is locked out,
66
+ an administrator runs `ALTER USER <name> IDENTIFIED BY '<new password>'` in a ClickHouse
67
+ client, then hands the member an env file holding it, the way an invite does. Keep the
68
+ new password out of any agent's conversation.
69
+
70
+ Either way, every machine shipping under the old password fails authentication until its
71
+ env file has the new one.
72
+
73
+ ## Seeing who is in a house
74
+
75
+ ```bash
76
+ memhouse members # every member, and what each one's grants reach
77
+ memhouse members --db other # another database
78
+ ```
79
+
80
+ `members` needs the admin credential. A member sees their own grants with
81
+ `memhouse whoami`.
82
+
83
+ ## Removing a member
84
+
85
+ There is no `memhouse` verb for it yet. With the admin credential, `DROP USER <name>`
86
+ stops every machine shipping as them. Their rooms stay until you drop them too. See
87
+ [Operate a house](operate.md) before you drop anything: there is no undo.
@@ -0,0 +1,112 @@
1
+ # Operate a house
2
+
3
+ For whoever administers the ClickHouse server behind a house. Each command below takes the
4
+ admin credential as described in [Admin password](admin-password.md). From Claude
5
+ Code, `/mem:admin` does the same work and keeps the password out of the conversation.
6
+
7
+ ## Who is here
8
+
9
+ ```bash
10
+ memhouse members # every member of the house, and what each grant reaches
11
+ memhouse members --db other
12
+ memhouse whoami --admin # what the admin credential may actually do
13
+ ```
14
+
15
+ Useful read-only SQL, run as the admin:
16
+
17
+ ```sql
18
+ -- every house and its size
19
+ SELECT database, formatReadableSize(sum(bytes_on_disk)) AS disk, sum(rows) AS rows
20
+ FROM system.parts WHERE active GROUP BY database ORDER BY sum(bytes_on_disk) DESC;
21
+
22
+ -- one member's rooms
23
+ SELECT table, formatReadableSize(sum(bytes_on_disk)) AS disk, sum(rows) AS rows
24
+ FROM system.parts WHERE active AND database = 'mem' AND table LIKE 'alice\_%'
25
+ GROUP BY table;
26
+
27
+ -- what someone may do
28
+ SHOW GRANTS FOR alice;
29
+ ```
30
+
31
+ ## Adding and removing people
32
+
33
+ - **Add:** [`memhouse invite`](invite.md).
34
+ - **Reset a member's password:** the member runs `memhouse passwd` themselves. For a
35
+ member who is locked out there is no verb: run `ALTER USER <name> IDENTIFIED BY '…'` as
36
+ the admin, and hand them an env file with the new password. Every machine shipping as
37
+ them stops until its env file has it.
38
+ - **Remove:** there is no verb yet. `DROP USER <name>` stops every machine shipping as
39
+ that member. Their rooms remain until you drop them as well.
40
+
41
+ **Before any destructive statement, look first.**
42
+
43
+ - Count the rows in each room, find who wrote them and when, and from which machines.
44
+ - Run every predicate as a `SELECT` before you run it as a `DELETE` or `DROP`.
45
+
46
+ There are no backups unless you made them, and the transcripts behind a room may already
47
+ be gone from the editors that produced them.
48
+
49
+ ## Migrations
50
+
51
+ When a release needs the rooms rebuilt, the shipper refuses to write until the house is
52
+ migrated:
53
+
54
+ ```bash
55
+ memhouse migrate --dry-run
56
+ memhouse migrate # copy, atomic swap; the old room is kept as <room>_pre_<suffix>
57
+ memhouse migrate-rooms # the same, rooms only
58
+ ```
59
+
60
+ Nothing is deleted. Drop the `_pre_` tables when you are satisfied. See
61
+ [Update](update.md#when-the-house-itself-must-change).
62
+
63
+ ## Convert
64
+
65
+ A house from before 0.18 has a database per member. `memhouse convert` moves it to the one
66
+ layout, `mem.<member>_*`:
67
+
68
+ ```bash
69
+ memhouse convert --admin-user default --dry-run # what would move
70
+ memhouse convert --admin-user default --print-sql # the statements, to run yourself
71
+ memhouse convert --admin-user default # do it
72
+ memhouse convert --admin-user default --guides --out ~/Downloads/upgrade
73
+ ```
74
+
75
+ `--guides` writes a per-member upgrade guide. Members then run `memhouse update`, and
76
+ their shipper adopts the moved rooms itself. Take a server snapshot first.
77
+
78
+ ## Moving a house to another server
79
+
80
+ `memhouse relocate --to <url>` copies a whole house server-to-server and repoints this
81
+ install. **Known gap:** relocate predates the one layout and fails on a one-layout house
82
+ before it changes anything. Until it is updated, moving a house is an operator
83
+ task with ClickHouse's own tools (`BACKUP`/`RESTORE`, or `INSERT … SELECT FROM remote()`).
84
+ Afterwards, point each member at the new URL with `memhouse setup --url …`.
85
+
86
+ ## Backups
87
+
88
+ memhouse does not back up the house. Use ClickHouse's own `BACKUP DATABASE mem TO …`, to a
89
+ disk or an object store, on a schedule, and test a `RESTORE` into a scratch server.
90
+ [`examples/04-self-hosted-team`](../../examples/04-self-hosted-team/README.md) shows a nightly job,
91
+ rotation, and a tested restore.
92
+
93
+ - **Keep backups as private as the house.** They hold every member's transcripts.
94
+ - **Backups outlive deletions.** A row removed from the house remains in every backup
95
+ taken before the removal, until that backup rotates out.
96
+
97
+ ## Server settings that matter
98
+
99
+ | setting | why |
100
+ |---|---|
101
+ | async inserts off for members | `user_id` is stamped at insert; memhouse pins `async_insert=0` on each member, and the shipper sets it per insert too |
102
+ | `users_without_row_policies_can_read_rows` | scoped shares need it to behave as memhouse expects; `share` measures it and refuses if a policy would blind the owner |
103
+ | `old_parts_lifetime` | how long replaced parts stay on disk after merges and mutations (480 s by default) |
104
+ | HTTP behind TLS | members connect over HTTP(S); put the server behind TLS before exposing it beyond a LAN |
105
+
106
+ ClickHouse 25.11 and 26.x are tested in CI.
107
+
108
+ ## A build to test with
109
+
110
+ `memhouse nightly --out DIR`, run from a checkout, builds an installable, version-stamped
111
+ tarball and publishes nothing. Install it on a test machine with
112
+ `npm install -g <tarball>`.
@@ -0,0 +1,95 @@
1
+ # Search, resume and skills
2
+
3
+ ## Search
4
+
5
+ ```bash
6
+ memhouse search "connection refused"
7
+ memhouse search clickhouse auth --limit 50
8
+ ```
9
+
10
+ This is a full-text search across every session in your rooms, from every machine and
11
+ every editor. Each hit names the session id, project, date and the matching line.
12
+
13
+ ## Resume
14
+
15
+ ```bash
16
+ memhouse resume claude-code:6b1f…
17
+ # cd /path/to/project && claude --resume 6b1f…
18
+ ```
19
+
20
+ `resume` **prints** the command and does not run it. A resume from the wrong directory,
21
+ or with a stale id, does not fail: it opens a **new** session, and the tool reports
22
+ success while the transcript you wanted is still gone. Printing it lets you see the
23
+ directory and the id first.
24
+
25
+ | editor | resume |
26
+ |---|---|
27
+ | Claude Code, Codex, OpenCode | verified: prints the command |
28
+ | Cursor, Zed, VS Code, Kiro, Copilot for JetBrains, Antigravity, Devin | no CLI that takes a session id; `resume` says so |
29
+ | goose, Gemini CLI, Cursor Agent, Copilot CLI | refused as *unverified*: nobody has confirmed the flag from the tool's own `--help` yet |
30
+
31
+ ## Numbers
32
+
33
+ ```bash
34
+ memhouse stats # sessions, messages and tokens per editor
35
+ memhouse sessions-query # the per-session rollup as SQL, to paste into your own queries
36
+ ```
37
+
38
+ The dashboard (`memhouse start`, then http://localhost:4640) shows the same and more:
39
+
40
+ - cost by model, editor and project;
41
+ - tool-call rankings;
42
+ - activity over time;
43
+ - which machine wrote what.
44
+
45
+ **Some editors record no token usage.** Kiro, VS Code, Zed and one of Cursor's two
46
+ storage paths extract none, so their cost shows as zero. Read that as *unknown*, not
47
+ *free*.
48
+
49
+ ## Skills for your agents
50
+
51
+ ```bash
52
+ memhouse plugins install claude # every Claude Code config dir found; choose, or --yes for all
53
+ memhouse plugins install claude --target ~/.claude
54
+ memhouse plugins list
55
+ memhouse plugins remove claude
56
+ ```
57
+
58
+ The five skills:
59
+
60
+ | skill | for |
61
+ |---|---|
62
+ | `/mem:recall` | answer a question from past sessions: search, read the transcripts, answer, cite |
63
+ | `/mem:house` | is memory working, what does the house hold, which machines write, who can read it |
64
+ | `/mem:sql` | read-only SQL for numbers: spend, models, tools, activity |
65
+ | `/mem:access` | invite someone, share your house, list or revoke shares |
66
+ | `/mem:admin` | operate the server as its administrator, without the password entering the conversation |
67
+
68
+ `plugins install` acts on **every** Claude Code config directory on the machine:
69
+ `~/.claude`, whatever `CLAUDE_CONFIG_DIR` points at, and each playbook under
70
+ `~/.claude-playbooks/`. All are selected by default. Installing into the default config
71
+ alone is how `/mem:recall` ends up missing from the playbook you actually work in, and a
72
+ missing skill never announces itself.
73
+
74
+ For an agent that does not use Claude Code skills, `memhouse prompt` prints a snippet for
75
+ its system prompt: where memory lives and how to query it.
76
+
77
+ ## Writing your own queries
78
+
79
+ The rooms are documented column by column in
80
+ [`memhouse/house/HOUSE.md`](../../memhouse/house/HOUSE.md). Two rules matter for every
81
+ query:
82
+
83
+ 1. **Join on `(session_id, user_id)`**, never on `session_id` alone. Two members' editors
84
+ can produce the same local session id.
85
+ 2. **Filter to the current parse.** A session's rows can hold more than one parse (an
86
+ `epoch`; see [How memory is stored](storage.md)). Counts must keep only the newest:
87
+
88
+ ```sql
89
+ WHERE origin != 'ship'
90
+ OR (session_id, user_id, epoch) IN (
91
+ SELECT session_id, user_id, max(epoch) FROM mem.<you>_messages
92
+ WHERE origin = 'ship' GROUP BY session_id, user_id)
93
+ ```
94
+
95
+ Read with `FINAL`, or the `final=1` setting, so that ReplacingMergeTree versions collapse.