memhouse 0.18.9 → 0.18.11
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.
- package/AGENTS.md +194 -0
- package/CHANGELOG.md +1097 -0
- package/README.md +54 -423
- package/SECURITY.md +68 -0
- package/bin/memhouse.js +299 -133
- package/docs/README.md +46 -0
- package/docs/guides/admin-password.md +95 -0
- package/docs/guides/configuration.md +109 -0
- package/docs/guides/daemons.md +53 -0
- package/docs/guides/install.md +128 -0
- package/docs/guides/invite.md +87 -0
- package/docs/guides/operate.md +112 -0
- package/docs/guides/search-and-resume.md +95 -0
- package/docs/guides/share.md +102 -0
- package/docs/guides/storage.md +93 -0
- package/docs/guides/troubleshooting.md +78 -0
- package/docs/guides/uninstall.md +37 -0
- package/docs/guides/update.md +68 -0
- package/docs/releases/README.md +11 -0
- package/docs/releases/v0.18.10.md +226 -0
- package/docs/releases/v0.18.11.md +191 -0
- package/docs/tutorials/01-first-house.md +132 -0
- package/docs/tutorials/02-join-a-house.md +91 -0
- package/docs/tutorials/03-share-your-memory.md +96 -0
- package/editors/claude.js +68 -10
- package/examples/01-local-one-machine/README.md +99 -0
- package/examples/01-local-one-machine/run.sh +61 -0
- package/examples/02-existing-clickhouse/README.md +121 -0
- package/examples/02-existing-clickhouse/run.sh +71 -0
- package/examples/03-team-house/README.md +129 -0
- package/examples/03-team-house/run.sh +124 -0
- package/examples/04-self-hosted-team/.env.example +22 -0
- package/examples/04-self-hosted-team/README.md +187 -0
- package/examples/04-self-hosted-team/compose.yml +158 -0
- package/examples/04-self-hosted-team/smoke.sh +113 -0
- package/examples/README.md +42 -0
- package/examples/fixtures/README.md +24 -0
- package/examples/fixtures/make-sessions.js +63 -0
- package/memhouse/DESIGN.md +9 -2
- package/memhouse/admin-secret.js +81 -0
- package/memhouse/delivery/plugin/.claude-plugin/plugin.json +1 -1
- package/memhouse/delivery/plugin/reference/HOUSE.md +18 -6
- package/memhouse/delivery/plugin/skills/access/SKILL.md +1 -1
- package/memhouse/delivery/plugin/skills/admin/SKILL.md +1 -1
- package/memhouse/delivery/plugin/skills/house/SKILL.md +1 -1
- package/memhouse/delivery/plugin/skills/recall/SKILL.md +34 -14
- package/memhouse/delivery/plugin/skills/sql/SKILL.md +1 -1
- package/memhouse/deploy.js +4 -2
- package/memhouse/flags.js +32 -5
- package/memhouse/host.js +11 -6
- package/memhouse/house/HOUSE.md +1 -1
- package/memhouse/house/house.js +27 -1
- package/memhouse/invite-target.js +37 -0
- package/memhouse/provision.js +12 -3
- package/memhouse/server/queries.js +9 -4
- package/memhouse/service.js +5 -0
- package/memhouse/shipper/ship.js +148 -31
- package/package.json +10 -2
- package/public/THIRD_PARTY_NOTICES.txt +2114 -0
- package/ui/vite.config.js +4 -1
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
# memhouse 0.18.10 — 2026-10-08
|
|
2
|
+
|
|
3
|
+
A security release:
|
|
4
|
+
|
|
5
|
+
- an admin password no longer has to go on the command line;
|
|
6
|
+
- no command prints a member password;
|
|
7
|
+
- a scoped share no longer reaches past its scope.
|
|
8
|
+
|
|
9
|
+
Everyone on 0.18.x should upgrade.
|
|
10
|
+
|
|
11
|
+
**No drill was run for this release; waived by the pilot (2026-10-08). The drill runs before 0.19.0.**
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
memhouse update # or: npm install -g memhouse@latest, then memhouse update --no-install
|
|
15
|
+
memhouse status # every line a check mark
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Nothing in the house changes: no migration, no new room, no re-ship. Machines on 0.18.9
|
|
19
|
+
and 0.18.10 can ship into the same house side by side.
|
|
20
|
+
|
|
21
|
+
## Security
|
|
22
|
+
|
|
23
|
+
### An admin password never has to go on the command line (#14)
|
|
24
|
+
|
|
25
|
+
The admin-assisted commands (`install --member`, `invite`, `passwd`, `convert`,
|
|
26
|
+
`members`) now take the admin password from, in order:
|
|
27
|
+
|
|
28
|
+
1. `--admin-password-file <file>`, a file holding the password (one trailing newline is
|
|
29
|
+
dropped), or `--admin-password-file -` to read it from stdin;
|
|
30
|
+
2. `--admin-password <value>` (still accepted, with a warning; see below);
|
|
31
|
+
3. `MEMHOUSE_ADMIN_PASSWORD` in the environment, which is how `with-secret` lends a secret
|
|
32
|
+
to one command;
|
|
33
|
+
4. a credential this install already keeps, but only for the same admin user;
|
|
34
|
+
5. a prompt, when there is a terminal to prompt on.
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
with-secret MEMHOUSE_ADMIN_PASSWORD=keychain:pilot/house-admin -- \
|
|
38
|
+
memhouse invite alice --url https://house.example.com --admin-user default
|
|
39
|
+
printf '%s' "$ADMIN_PASSWORD" | memhouse invite alice --url … --admin-user default --admin-password-file -
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Before this release, `--admin-user` as a flag switched every other source off. The only
|
|
43
|
+
scriptable admin path therefore put the password on argv, where `ps` shows it for as long
|
|
44
|
+
as the command runs and shell history keeps it. Found by O's sandbox rehearsal (finding 6).
|
|
45
|
+
With no source and no terminal, the command stops and prints the three ways above instead
|
|
46
|
+
of hanging or guessing.
|
|
47
|
+
|
|
48
|
+
### An admin install no longer saves the admin credential (#14)
|
|
49
|
+
|
|
50
|
+
`install --admin-user …` builds the member and then ships as the member. It used to write
|
|
51
|
+
the admin credential into `~/.memhouse/env` as well. The help said it was saved; every
|
|
52
|
+
agent-facing text said it never was. Now it is saved only with `--keep-admin`, or when
|
|
53
|
+
the env file already keeps that same admin. Credentials already saved keep working.
|
|
54
|
+
|
|
55
|
+
### A daemon never carries the admin credential (#14)
|
|
56
|
+
|
|
57
|
+
- Service units (systemd, launchd) drop `MEMHOUSE_ADMIN_*` before they inline the env.
|
|
58
|
+
- The shipper and the dashboard are started without it, even when the shell exported it.
|
|
59
|
+
- `deploy --local` passes the ClickHouse password to `docker run` through the environment,
|
|
60
|
+
no longer as `-e CLICKHOUSE_PASSWORD=<value>` on its argv.
|
|
61
|
+
|
|
62
|
+
A unit test now fails on any spawn or exec in the shipped code that puts a password on
|
|
63
|
+
argv.
|
|
64
|
+
|
|
65
|
+
### No command prints a member password (G23)
|
|
66
|
+
|
|
67
|
+
`install --admin-user` used to show the generated member password once, on the terminal.
|
|
68
|
+
It was already written to the env file, so the terminal copy served no one. It landed in
|
|
69
|
+
scrollback and, through `/mem:access` and `/mem:admin`, in an agent's transcript, which
|
|
70
|
+
memhouse ships into the house, where the archive is insert-only. (#20)
|
|
71
|
+
|
|
72
|
+
- **Install and invite never print a generated member password.** It goes to the env file
|
|
73
|
+
(install) or the invite file (invite), and nowhere else.
|
|
74
|
+
- **A failed install cleans up after itself.** If the grant fails after the member was
|
|
75
|
+
created, the run drops that member, so no account is left with a password nobody holds.
|
|
76
|
+
- **`install --print-sql` and `invite --print-sql` print a placeholder,
|
|
77
|
+
`IDENTIFIED BY <member-password>`.** As printed, that line does not parse. The
|
|
78
|
+
administrator puts a quoted password they generate in its place, and the same password
|
|
79
|
+
goes into the env-file lines the command prints for the member. From `invite`, those
|
|
80
|
+
lines carry `MEMHOUSE_INVITE=1`, so the member's `install --env` offers to rotate it.
|
|
81
|
+
A `--member-password` given with `--print-sql` is not echoed.
|
|
82
|
+
- **Tests guard it.**
|
|
83
|
+
- A unit test fails on any print call that evaluates a password: as an argument,
|
|
84
|
+
concatenated, or interpolated.
|
|
85
|
+
- `misc/invite-matrix.sh` runs every install, invite and passwd path against a real
|
|
86
|
+
ClickHouse and checks each output against the real passwords.
|
|
87
|
+
|
|
88
|
+
### A scoped share shares only what its scope filters (#13)
|
|
89
|
+
|
|
90
|
+
`memhouse share <user> --only <scope>` granted `SELECT` on the member's whole pattern,
|
|
91
|
+
`mem.<member>_*`, while its row policies covered only `sessions`, `messages` and
|
|
92
|
+
`tool_calls`. A grantee scoped to one project could therefore read these in full:
|
|
93
|
+
|
|
94
|
+
- `<member>_session_stats`: the opening prompt, folder, project and token totals of
|
|
95
|
+
every session in every project;
|
|
96
|
+
- the model and tool stats;
|
|
97
|
+
- `<member>_meta`, including the member's other `share:` records;
|
|
98
|
+
- `<member>_events`;
|
|
99
|
+
- any table the pattern matched later.
|
|
100
|
+
|
|
101
|
+
Now:
|
|
102
|
+
|
|
103
|
+
- **A scoped share is granted table by table,** on exactly the three filtered rooms.
|
|
104
|
+
Narrowing an existing full share to a scope takes the wildcard back first, so a failure
|
|
105
|
+
part-way leaves the grantee with less access, never more.
|
|
106
|
+
- **`--revoke` withdraws the grants before it drops the row policies.** The old order
|
|
107
|
+
failed open: a `REVOKE` refused after the policies were gone left an unfiltered share.
|
|
108
|
+
A failed cleanup now keeps the policies unless every grant is confirmed withdrawn.
|
|
109
|
+
- **`--only ""` and whitespace-only scopes are refused.** An unset `--only "$SCOPE"`
|
|
110
|
+
used to fall through to a full share.
|
|
111
|
+
- **The permissive-server check before a scoped share runs.** Its probe table sat
|
|
112
|
+
outside the member's grant, so it was refused on every server and always reported
|
|
113
|
+
"could not verify".
|
|
114
|
+
|
|
115
|
+
A full share (no `--only`) is unchanged: it reaches everything in `mem.<member>_*`, by
|
|
116
|
+
design, and says so.
|
|
117
|
+
|
|
118
|
+
**Action for existing scoped shares:** they keep their old wildcard until re-run. On the
|
|
119
|
+
sharing member's machine, run `memhouse share <user> --only <scope>` again for each one;
|
|
120
|
+
`memhouse share --list` shows them.
|
|
121
|
+
|
|
122
|
+
## Deprecations
|
|
123
|
+
|
|
124
|
+
| what | since | removed in | use instead |
|
|
125
|
+
|---|---|---|---|
|
|
126
|
+
| `--admin-password <value>` on the command line | 0.18.10 (2026-10-08) | **0.19.0** | `MEMHOUSE_ADMIN_PASSWORD` (via `with-secret`), `--admin-password-file <file>`, or `--admin-password-file -` |
|
|
127
|
+
|
|
128
|
+
It still works in 0.18.x and prints one warning on stderr. Move scripts now.
|
|
129
|
+
|
|
130
|
+
## Upgrading
|
|
131
|
+
|
|
132
|
+
- **One machine:** `memhouse update`. The daemons restart on the new code.
|
|
133
|
+
- **Upgraded by hand** (`npm install -g memhouse@latest`): run
|
|
134
|
+
`memhouse update --no-install` afterwards to restart the daemons.
|
|
135
|
+
- **Several machines on one house:** no ordering is needed. This release changes no row
|
|
136
|
+
shape, no room and no shipper behaviour.
|
|
137
|
+
- **Share owners:** re-run each scoped share once (above).
|
|
138
|
+
- **Scripts and CI that pass `--admin-password`:** move to `MEMHOUSE_ADMIN_PASSWORD` or
|
|
139
|
+
`--admin-password-file` before 0.19.0.
|
|
140
|
+
- **Scripts that read a member password from `install --admin-user` output:** read
|
|
141
|
+
`MEMHOUSE_PASSWORD` from the env file instead. The output no longer contains it.
|
|
142
|
+
- **Scripts that run `--print-sql` output as is:** put a quoted password where
|
|
143
|
+
`<member-password>` stands. As printed, the line is refused by the server.
|
|
144
|
+
- **If an admin credential is in `~/.memhouse/env`** and you did not mean to keep it,
|
|
145
|
+
remove the `MEMHOUSE_ADMIN_USER` / `MEMHOUSE_ADMIN_PASSWORD` lines. memhouse never
|
|
146
|
+
needs it to ship.
|
|
147
|
+
|
|
148
|
+
## Also in this release
|
|
149
|
+
|
|
150
|
+
- **The documentation standard** (#17). See [Documentation](#documentation) below. This
|
|
151
|
+
does change the package: it now also ships `docs/`, `examples/`, `AGENTS.md`,
|
|
152
|
+
`SECURITY.md` and `CHANGELOG.md`.
|
|
153
|
+
|
|
154
|
+
These do not change the installed package:
|
|
155
|
+
|
|
156
|
+
- **CI's tarball audit can fail now.** Its forbidden-file check was `! grep`, which
|
|
157
|
+
`set -e` never acts on, so it passed whatever the tarball held.
|
|
158
|
+
- **gentar arena adoption** (#10). memhouse is now a gentar subject. Its suites are
|
|
159
|
+
`memhouse-house` and `memhouse-install`, kit v0.9.2, and they install from `npm pack`
|
|
160
|
+
exactly as a publish ships. The phase-1 check runs on GitHub-hosted runners on every
|
|
161
|
+
push and PR. Full arena runs need a self-hosted bench; the one used before the
|
|
162
|
+
repository went public was deregistered then.
|
|
163
|
+
- **memhouse.io describes 0.18** (#12): one layout, five skills, the honest editor count
|
|
164
|
+
(16 adapters reading 18 apps).
|
|
165
|
+
- `memhouse.io/.wrangler` (wrangler's local cache) is no longer tracked.
|
|
166
|
+
- `misc/one-layout-matrix.sh` now asserts the scoped-share boundary, and
|
|
167
|
+
`misc/invite-matrix.sh` the admin-password sources: environment, stdin, `--keep-admin`,
|
|
168
|
+
and none. The file source is covered by unit tests. CI runs both matrices against
|
|
169
|
+
ClickHouse 25.11 and 26.7.
|
|
170
|
+
|
|
171
|
+
## Not in this release
|
|
172
|
+
|
|
173
|
+
**The gentar kit v0.9.3 bump (#18) also moves to 0.18.11.** It changes CI only.
|
|
174
|
+
|
|
175
|
+
**The subagent re-ship fix moves to 0.18.11.** It is on branch `claude/subagent-stable-seq`
|
|
176
|
+
and stops a Claude Code session with subagents from re-shipping whole on every pass, which
|
|
177
|
+
is what grew one house to 16.2 M message rows for about 295 k real ones. It was reviewed
|
|
178
|
+
before release by four models. Three said "ship with fixes"; the fourth said "do not ship",
|
|
179
|
+
mostly for pre-existing issues. Its pre-tag fixes are not all done, and this release was
|
|
180
|
+
not held for them.
|
|
181
|
+
|
|
182
|
+
Status of the 0.18.10 pre-tag list (`review-0.18.10-consolidated`):
|
|
183
|
+
|
|
184
|
+
| item | what | status |
|
|
185
|
+
|---|---|---|
|
|
186
|
+
| B1 | scoped share reads past its scope | **landed** (#13) |
|
|
187
|
+
| G3 | share re-scope or revoke fails open | **landed** (#13) |
|
|
188
|
+
| G24 | `--only ""` is a full share | **landed** (#13) |
|
|
189
|
+
| B7 | permissive-server probe never runs | **landed** (#13) |
|
|
190
|
+
| B5 (part) | admin password in argv, units and daemons | **landed** (#14); `0600` enforcement on existing env/unit files is still open |
|
|
191
|
+
| A1 | version bump incl. `package-lock.json` | **landed** here |
|
|
192
|
+
| G23 | admin install and `--print-sql` print the member password | **landed** (#20) |
|
|
193
|
+
| A2 | `/mem:recall` "recent sessions" uses a column the table lacks | deferred to 0.18.11 |
|
|
194
|
+
| A3 | plugin `HOUSE.md` subagent queries lack the epoch filter | deferred to 0.18.11 (with the RC, which makes it matter) |
|
|
195
|
+
| A4–A7 | RC log text, `update --no-install` checks, RC changelog notes | deferred to 0.18.11 (they are the RC's own surface) |
|
|
196
|
+
| A8 | stale prose (ts interpolation, shrink, host id) | deferred to 0.18.11 |
|
|
197
|
+
| G4 | `invite --url` connects with the stored credential to the invitee-facing URL | deferred to 0.18.11 (security) |
|
|
198
|
+
| G26 | skills point at `../reference/HOUSE.md`; the file is `../../reference/HOUSE.md` | deferred to 0.18.11 |
|
|
199
|
+
| G11 | an idle house's dashboard goes empty after the stats TTL | deferred to 0.18.11 |
|
|
200
|
+
| GLM-F1 | a subagent file read before its first line is written re-sorts its siblings | deferred to 0.18.11 (with the RC) |
|
|
201
|
+
|
|
202
|
+
## Documentation
|
|
203
|
+
|
|
204
|
+
This release meets the documentation standard (#17):
|
|
205
|
+
|
|
206
|
+
- a short README: what memhouse is, why, and how to install it;
|
|
207
|
+
- `docs/`, with three tutorials and twelve guides;
|
|
208
|
+
- `examples/`, four runnable setups from one machine to a self-hosted team house, each
|
|
209
|
+
with its own README;
|
|
210
|
+
- an install and deploy section for agents in `AGENTS.md`.
|
|
211
|
+
|
|
212
|
+
The npm package now ships `docs/`, `examples/`, `AGENTS.md`, `SECURITY.md` and
|
|
213
|
+
`CHANGELOG.md`, so an installed copy carries its own manual. `change.log` (#19) lists
|
|
214
|
+
every tag and what it changed.
|
|
215
|
+
|
|
216
|
+
## Verification
|
|
217
|
+
|
|
218
|
+
- `npm test` passes.
|
|
219
|
+
- CI is green on `main` at the release commit: the syntax gate, unit tests, the
|
|
220
|
+
one-layout and invite matrices, and a headless e2e on ClickHouse 25.11 and 26.7.
|
|
221
|
+
- No live house was touched to prepare this release.
|
|
222
|
+
- **No drill was run for this release; waived by the pilot (2026-10-08). The drill runs before 0.19.0.**
|
|
223
|
+
`AGENTS.md` asks for a drill before a release that changes a surface a person touches,
|
|
224
|
+
and this one changes install, invite and share. A drill was prepared on the testbed, but
|
|
225
|
+
its setup was refused by this session's permission layer, and the pilot chose to release
|
|
226
|
+
without it.
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
# memhouse 0.18.11 — 2026-10-10
|
|
2
|
+
|
|
3
|
+
This release does three things:
|
|
4
|
+
|
|
5
|
+
- **Sessions with subagents stop re-shipping.** A Claude Code session that used subagents
|
|
6
|
+
now ships only its new rows. Before, it re-sent itself whole on every pass, and that was
|
|
7
|
+
most of the house's write load.
|
|
8
|
+
- **A security fix.** `invite` no longer sends a stored credential to whatever `--url` is
|
|
9
|
+
typed on the command line.
|
|
10
|
+
- **The 0.18.10 pre-tag list is finished**, and the gentar test kit is bumped.
|
|
11
|
+
|
|
12
|
+
**No drill was run for this release; waived (2026-10-08) under the pilot's 0.18.10 ruling. The drill runs before 0.19.0.**
|
|
13
|
+
|
|
14
|
+
## Read this before upgrading
|
|
15
|
+
|
|
16
|
+
**The first pass after the upgrade is a one-time bulk write.** It re-sends, whole and once,
|
|
17
|
+
every stored session that has subagents; after that, those sessions ship only their new
|
|
18
|
+
rows. Two things widen that first pass:
|
|
19
|
+
|
|
20
|
+
- **Sessions whose subagents wrote recently.** A session whose subagent files are newer
|
|
21
|
+
than the house's record of it is read again even if it did not grow, because
|
|
22
|
+
`lastUpdatedAt` now counts subagent writes.
|
|
23
|
+
- **Installs that share session files.** Two installs that ship the same session files
|
|
24
|
+
(two instances on one machine, or a synced directory) must be upgraded together. A
|
|
25
|
+
0.18.10 and a 0.18.11 number the same session differently, and each would fork it back
|
|
26
|
+
on every pass.
|
|
27
|
+
|
|
28
|
+
**Where that write lands, and when to do it (2026-10-08):**
|
|
29
|
+
|
|
30
|
+
- The pilot's machines (macminim, macbokum) ship to **zeo.memhouse.io**: VM 146 on arf,
|
|
31
|
+
ClickHouse 26.7.4.58.
|
|
32
|
+
- It is **not** LXC 112 "memhouse-production"; that is an archive, not a live house.
|
|
33
|
+
- zeo's data disk still sits on arf's degraded array. It was backed up to SSD on
|
|
34
|
+
2026-10-08 (data and access storage), but the disk itself has not moved.
|
|
35
|
+
- **Upgrade those machines only once zeo's data disk is off the degraded array, or once
|
|
36
|
+
the array is repaired. Time it against the SSD moves.**
|
|
37
|
+
- Any house on healthy storage can upgrade normally.
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
memhouse update # then: memhouse status — every line a check mark
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Security
|
|
44
|
+
|
|
45
|
+
### `invite` never sends a stored credential to `--url` (G4)
|
|
46
|
+
|
|
47
|
+
`--url` is the invitee's address, typed on a command line. A typo, a tunnel, or somebody
|
|
48
|
+
else's server received credentials it should never have seen:
|
|
49
|
+
|
|
50
|
+
- the member's own credential, through the reachability probe and the read of its grants;
|
|
51
|
+
- an admin credential the install keeps, through provisioning.
|
|
52
|
+
|
|
53
|
+
The cause: `resolveConfig()` lets a flag outrank the env file, so the "configured house" URL
|
|
54
|
+
the code used *was* `--url`.
|
|
55
|
+
|
|
56
|
+
Now:
|
|
57
|
+
|
|
58
|
+
- **A stored credential goes only to the house it was saved for.** That covers the
|
|
59
|
+
member's own, a `--keep-admin` admin, and a password read from the env file.
|
|
60
|
+
- **`--url` gets an unauthenticated `/ping`**, only to confirm the invitee can reach it.
|
|
61
|
+
- **An admin given for this command** (`--admin-user`, or an exported
|
|
62
|
+
`MEMHOUSE_ADMIN_USER`, with its password from a file, stdin, the environment or a prompt)
|
|
63
|
+
still provisions at `--url`. That is what the person typing the command asked for.
|
|
64
|
+
- **`misc/invite-matrix.sh` points `--url` at a spy server** and asserts that it receives
|
|
65
|
+
nothing but a ping. On 0.18.10 the spy received two authenticated requests.
|
|
66
|
+
|
|
67
|
+
**Action:**
|
|
68
|
+
|
|
69
|
+
- If you ran `memhouse invite … --url <something unusual>` on 0.18.10 or earlier against a
|
|
70
|
+
host you do not control, rotate the member's password with `memhouse passwd`.
|
|
71
|
+
- If an admin credential is kept in the env file and the same applies, rotate that too.
|
|
72
|
+
|
|
73
|
+
## The re-ship fix (#21)
|
|
74
|
+
|
|
75
|
+
Folded subagent rows were numbered by position, after the parent's turns. One new parent
|
|
76
|
+
turn moved every one of them, so the session forked to a new epoch and was re-sent whole.
|
|
77
|
+
Measured on a real house:
|
|
78
|
+
|
|
79
|
+
- 1.07 M message rows written in 24 h, against 10.2 M in total;
|
|
80
|
+
- one 6,120-line session stored 60 times in a day;
|
|
81
|
+
- polat's house at about 19 M message rows for roughly 295 k real ones.
|
|
82
|
+
|
|
83
|
+
What changed:
|
|
84
|
+
|
|
85
|
+
- **Subagent rows get a numbering block of their own:**
|
|
86
|
+
`seq = 1,000,000,000 + slot × 100,000 + turn`, and the same for tool calls' `idx`.
|
|
87
|
+
`slot` is the subagent's rank by start time, so neither the parent growing, a subagent
|
|
88
|
+
growing, nor a new subagent appearing moves a stored row.
|
|
89
|
+
- **A session without subagents is numbered exactly as before.**
|
|
90
|
+
- **`seq` is sparse.** Count rows with `count()`, never `max(seq) + 1`.
|
|
91
|
+
- **`ORDER BY seq` groups subagents.** Readers see the parent first, then each subagent's
|
|
92
|
+
turns together, in the order the subagents started. They used to be in agent-id order,
|
|
93
|
+
which is random.
|
|
94
|
+
- **A parse too big for the blocks falls back to positional numbering:**
|
|
95
|
+
- a parent past 1e9 turns;
|
|
96
|
+
- a subagent past 100,000 turns;
|
|
97
|
+
- more than 32,949 subagents.
|
|
98
|
+
|
|
99
|
+
Positional numbering is correct, and merely re-ships whole as before.
|
|
100
|
+
- **Subagent writes count as session activity.** A subagent that keeps running after its
|
|
101
|
+
parent goes quiet is shipped on the next pass.
|
|
102
|
+
- **A subagent caught before its first line is written holds its session for one pass.**
|
|
103
|
+
It is then ranked by its real start time; it no longer ranks last and moves later. A
|
|
104
|
+
file that never gets a timestamped line stops holding the session after 10 minutes.
|
|
105
|
+
- **Existing copies are not cleaned up.** Superseded epochs already in a house stay;
|
|
106
|
+
memhouse never deletes to make room. Reclaiming that space is a separate operator
|
|
107
|
+
decision, and no such cleanup may run on a house on degraded storage.
|
|
108
|
+
|
|
109
|
+
## Also fixed
|
|
110
|
+
|
|
111
|
+
- **The dashboard no longer goes empty on a quiet house (G11).** The stats tables carry a
|
|
112
|
+
one-day TTL and were refreshed only by passes that shipped something.
|
|
113
|
+
- The shipper now also refreshes them when the newest generation is over an hour old.
|
|
114
|
+
- The dashboard re-resolves its tables every five minutes, falling back to the live
|
|
115
|
+
rollup when a stats table is empty.
|
|
116
|
+
- **The skills find their reference again (G26).** All five pointed at
|
|
117
|
+
`../reference/HOUSE.md`, a path that does not exist in the installed plugin; the file is
|
|
118
|
+
at `../../reference/HOUSE.md`.
|
|
119
|
+
- **`/mem:recall`'s queries run (A2).**
|
|
120
|
+
- "Recent sessions" used a column the room does not have.
|
|
121
|
+
- The search now returns the `hit_seq` that the transcript read needs.
|
|
122
|
+
- The read takes its window by position, so the subagent blocks cannot break it.
|
|
123
|
+
- **`HOUSE.md`'s subagent queries keep to the current parse (A3).** They used to double a
|
|
124
|
+
re-parsed session's subagent turns.
|
|
125
|
+
- **An option that takes no value no longer swallows the next word (A6).**
|
|
126
|
+
`update --no-install yes` ran the install it was told to skip, and `share --revoke bob`
|
|
127
|
+
revoked nobody.
|
|
128
|
+
- **`update --channel <name>` pins only a tag the registry has (A5).** Before, it never
|
|
129
|
+
wrote the pin at all.
|
|
130
|
+
- **`update --no-install` restarts a tarball or nightly install.** That is the command
|
|
131
|
+
every nightly build prints for itself. On exactly those builds it stopped at "no
|
|
132
|
+
automatic update for this install" and exited 1, leaving the old shipper running old
|
|
133
|
+
code. It now restarts the daemons, runs any migration, and checks the schema; it needs
|
|
134
|
+
no channel.
|
|
135
|
+
- **`update --no-install` (A6)** no longer prints "files updated", and it is no longer
|
|
136
|
+
refused on a project-dependency install.
|
|
137
|
+
- **The epoch log line counts rows (A4).**
|
|
138
|
+
- **Docs (A8): the host id is derived from the machine's own id**, as it has been since
|
|
139
|
+
0.18.6, so a reinstall keeps it. Stale prose about timestamps and `extra.turn` is fixed
|
|
140
|
+
too.
|
|
141
|
+
|
|
142
|
+
## License notices
|
|
143
|
+
|
|
144
|
+
**The dashboard now ships the license notices of what it bundles.** The built dashboard
|
|
145
|
+
(`public/`) includes React, chart.js, lucide-react, react-markdown, tailwindcss and every
|
|
146
|
+
other package it bundles. Their licenses (MIT, ISC) require the notice to travel with each
|
|
147
|
+
copy, and minification strips it from the code.
|
|
148
|
+
- `public/THIRD_PARTY_NOTICES.txt` is now generated at build time from the bundle's module
|
|
149
|
+
graph, and ships in the npm package.
|
|
150
|
+
- CI fails a package that lacks it.
|
|
151
|
+
|
|
152
|
+
Earlier published packages carried those copies without the notices.
|
|
153
|
+
|
|
154
|
+
## Test infrastructure
|
|
155
|
+
|
|
156
|
+
- **gentar kit v0.9.3 (#18).** In phase 1, `memhouse-house` is reported UNVERIFIED (bench
|
|
157
|
+
only) instead of being dry-run on the CI host.
|
|
158
|
+
- **The suite tears down only a house it created.** It refuses to deploy over an existing
|
|
159
|
+
house, and a failed teardown fails it.
|
|
160
|
+
- **`misc/skill-recipe.sh` runs the skills' queries verbatim, extracted from the docs.**
|
|
161
|
+
The fixture includes a superseded parse and a subagent block.
|
|
162
|
+
|
|
163
|
+
## Pre-tag list (0.18.10 review): final status
|
|
164
|
+
|
|
165
|
+
| item | where |
|
|
166
|
+
|---|---|
|
|
167
|
+
| A1 version bump | this release |
|
|
168
|
+
| A2 `/mem:recall` queries | #22 |
|
|
169
|
+
| A3 `HOUSE.md` subagent queries, epoch filter | #22 |
|
|
170
|
+
| A4 epoch log count | #21 |
|
|
171
|
+
| A5 `update --channel` validation | #21 |
|
|
172
|
+
| A6 `--no-install` checks; switches swallowing values | #21 |
|
|
173
|
+
| A7 upgrade-cost notes | #21, and this document |
|
|
174
|
+
| A8 stale prose (ts, shrink, `extra` turn, host id) | #21 |
|
|
175
|
+
| G4 `invite --url` and stored credentials (**security**) | #22 |
|
|
176
|
+
| G26 skills' reference path | #22 |
|
|
177
|
+
| G11 idle house's dashboard | #22 |
|
|
178
|
+
| GLM-F1 unstamped subagent file | #21 |
|
|
179
|
+
|
|
180
|
+
## Verification
|
|
181
|
+
|
|
182
|
+
- **Unit tests:** `npm test` passes on main, 125 checks.
|
|
183
|
+
- **CI:** green on ClickHouse 25.11 and 26.7.
|
|
184
|
+
- **Matrices in a lab**, on ClickHouse 26.7.4.58 (production's version) and 26.7.1.1315.
|
|
185
|
+
They were run during #22 on main with #21 and #18 merged:
|
|
186
|
+
- skill recipe 18/18;
|
|
187
|
+
- invite 58/58;
|
|
188
|
+
- one-layout 62/62.
|
|
189
|
+
- **Second looks:** agy (gemini-3.8-flash-high) on #21 and #22. Codex was at its daily
|
|
190
|
+
quota.
|
|
191
|
+
- **Labs:** kept light, because arf's RAID is degraded. No live house was touched.
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# Tutorial 1: your first house
|
|
2
|
+
|
|
3
|
+
One machine, about ten minutes. At the end, every coding-agent session on this machine
|
|
4
|
+
is in a ClickHouse you own. You can see them in a dashboard, search them, and ask an agent
|
|
5
|
+
about them.
|
|
6
|
+
|
|
7
|
+
**You need:**
|
|
8
|
+
|
|
9
|
+
- Node 24 or newer;
|
|
10
|
+
- docker or podman, for the local ClickHouse;
|
|
11
|
+
- at least one editor that has written sessions: Claude Code, Codex, Cursor, Zed, and so on.
|
|
12
|
+
|
|
13
|
+
## 1. Install
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install -g memhouse
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
On a distro-packaged Node (Linux, global prefix under `/usr`) this needs `sudo`. On
|
|
20
|
+
Homebrew, nvm, fnm or volta it must not have it. [The install guide](../guides/install.md#eacces-on-install)
|
|
21
|
+
tells the two apart.
|
|
22
|
+
|
|
23
|
+
## 2. See what is on this machine
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
memhouse discover
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
This is a read-only preflight. It lists every editor it found, how many sessions each one
|
|
30
|
+
holds, the directories it watches, and any ClickHouse it can reach. Nothing is written
|
|
31
|
+
anywhere.
|
|
32
|
+
|
|
33
|
+
## 3. Stand up a house
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
memhouse deploy --local
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
This does four things:
|
|
40
|
+
|
|
41
|
+
1. It starts ClickHouse in a container bound to `127.0.0.1:8123`, so only this machine
|
|
42
|
+
can reach it. The data lives in a named volume.
|
|
43
|
+
2. It creates two users. `memhouse_root` administers the house. A **member** named after
|
|
44
|
+
your OS user (`polat`, say) ships your sessions, and holds one grant: `mem.polat_*`.
|
|
45
|
+
Your rooms are `mem.polat_sessions`, `mem.polat_messages`, `mem.polat_tool_calls`, and
|
|
46
|
+
so on.
|
|
47
|
+
3. It writes both credentials to `~/.memhouse/env`, mode 600. A local house is the one
|
|
48
|
+
case where the admin credential is kept, so that `memhouse invite` works later with
|
|
49
|
+
no flags.
|
|
50
|
+
4. It installs against the house and ships everything once.
|
|
51
|
+
|
|
52
|
+
Already have a ClickHouse? Skip this step and use `memhouse onboard`, which asks for
|
|
53
|
+
it. See [the install guide](../guides/install.md).
|
|
54
|
+
|
|
55
|
+
## 4. Check it worked
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
memhouse status
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Look for a connection check mark, row counts in your rooms, and a recent "last shipped"
|
|
62
|
+
time. `memhouse doctor` goes further. It checks the whole pipeline and names anything
|
|
63
|
+
skipped.
|
|
64
|
+
|
|
65
|
+
## 5. Keep it shipping, and open the dashboard
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
memhouse start
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
This starts two background daemons. The shipper runs an incremental pass every five
|
|
72
|
+
minutes. The dashboard runs at **http://localhost:4640**: sessions, cost by model and
|
|
73
|
+
editor, tool calls, and which machine wrote what.
|
|
74
|
+
|
|
75
|
+
Those daemons do not survive a reboot. To make them permanent:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
memhouse service install # systemd --user on Linux, a LaunchAgent on macOS
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## 6. Find something
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
memhouse search "connection refused"
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Each hit names the session, its project and its date. Reopen one:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
memhouse resume claude-code:6b1f…
|
|
91
|
+
# cd /path/to/project && claude --resume 6b1f…
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
`resume` **prints** the command rather than running it. You see the directory and the id
|
|
95
|
+
before anything opens.
|
|
96
|
+
|
|
97
|
+
## 7. Let your agents remember
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
memhouse plugins install claude
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
This installs five skills into every Claude Code config directory it finds. You choose
|
|
104
|
+
which ones; all are selected by default. In any Claude Code session afterwards:
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
/mem:recall how did I fix the ClickHouse auth error last month?
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
The agent searches your house, reads the sessions that match, answers from them, and
|
|
111
|
+
cites the sessions it used. `/mem:house` reports the state of the house.
|
|
112
|
+
|
|
113
|
+
## What you have now
|
|
114
|
+
|
|
115
|
+
- `~/.memhouse/env` holds the connection and both credentials. Never paste it anywhere.
|
|
116
|
+
- `~/.memhouse/host.json` holds this machine's identity. Every row it ships carries it.
|
|
117
|
+
- A ClickHouse container with your memory in a named volume.
|
|
118
|
+
|
|
119
|
+
## Undo it
|
|
120
|
+
|
|
121
|
+
- `memhouse uninstall` stops everything and keeps the house.
|
|
122
|
+
- `memhouse deploy --down` removes the container **and its volume**, which **deletes the
|
|
123
|
+
memory**.
|
|
124
|
+
|
|
125
|
+
See [Uninstall](../guides/uninstall.md).
|
|
126
|
+
|
|
127
|
+
## Next
|
|
128
|
+
|
|
129
|
+
- [Tutorial 2](02-join-a-house.md): join a team's house instead of running your own.
|
|
130
|
+
- [Configuration](../guides/configuration.md): ship only some editors or directories.
|
|
131
|
+
- [How memory is stored](../guides/storage.md): what a room holds, and why nothing is
|
|
132
|
+
ever deleted to make room.
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# Tutorial 2: join a team's house
|
|
2
|
+
|
|
3
|
+
Someone runs a house and invited you. They gave you a file named `invite-<you>.env`. At the
|
|
4
|
+
end of this tutorial your sessions ship into your own rooms in their house, under a
|
|
5
|
+
password only you know.
|
|
6
|
+
|
|
7
|
+
**You need:**
|
|
8
|
+
|
|
9
|
+
- Node 24 or newer;
|
|
10
|
+
- the invite file, received over a trusted channel: croc, a password manager, or a USB
|
|
11
|
+
stick. Not chat or email. **The file contains a password.**
|
|
12
|
+
|
|
13
|
+
## 1. Install memhouse
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install -g memhouse
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
On Linux with a distro-packaged Node, prefix with `sudo`. See
|
|
20
|
+
[the install guide](../guides/install.md#eacces-on-install).
|
|
21
|
+
|
|
22
|
+
## 2. Install from the invite
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
memhouse install --env invite-<you>.env
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
This reads the house's address, your member name and a starting password from the file.
|
|
29
|
+
It then connects, checks that you can write to your rooms, and ships every session on
|
|
30
|
+
this machine. Your rooms already exist and are named for you: `mem.<you>_messages`,
|
|
31
|
+
`mem.<you>_sessions`, and so on. You hold one grant, on `mem.<you>_*`, and nothing else in
|
|
32
|
+
the database.
|
|
33
|
+
|
|
34
|
+
Then it **offers to change the password** to one only this machine knows. Say yes. The
|
|
35
|
+
person who invited you set the starting password, and once you rotate it, theirs stops
|
|
36
|
+
working. Then it deletes the invite file, which is spent.
|
|
37
|
+
|
|
38
|
+
Scripted, with no terminal: `--yes` rotates without asking.
|
|
39
|
+
|
|
40
|
+
## 3. Check who you are
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
memhouse whoami
|
|
44
|
+
memhouse status
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
`whoami` names the credential in use and what it may do. You should be a **member**,
|
|
48
|
+
not an administrator. `status` shows the connection, your row counts and freshness.
|
|
49
|
+
|
|
50
|
+
## 4. Keep shipping
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
memhouse start # shipper + dashboard, until the next reboot
|
|
54
|
+
memhouse service install # or: survive reboots (systemd --user / LaunchAgent)
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Your dashboard is at http://localhost:4640. It reads the house, so it shows your
|
|
58
|
+
sessions from every machine you install on, not just this one.
|
|
59
|
+
|
|
60
|
+
## 5. More machines
|
|
61
|
+
|
|
62
|
+
Every machine you own ships into the same rooms, and the `host` column tells them apart.
|
|
63
|
+
The invite file is spent, so set up the next machine from this one's env file:
|
|
64
|
+
|
|
65
|
+
1. Copy `~/.memhouse/env` to the new machine over a trusted channel, to any path, say
|
|
66
|
+
`~/mh.env`. It holds your connection and your new password.
|
|
67
|
+
2. On the new machine, install from that copy:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
memhouse install --env ~/mh.env
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
This installs and then deletes the copy. It does not offer to rotate: only an invite
|
|
74
|
+
file does, and rotating here would lock out your first machine.
|
|
75
|
+
|
|
76
|
+
Do not copy `~/.memhouse/host.json`. It is the first machine's identity, and each machine
|
|
77
|
+
mints its own.
|
|
78
|
+
|
|
79
|
+
## 6. Read your teammates' memory
|
|
80
|
+
|
|
81
|
+
Not yet. Nobody can read your rooms, and you cannot read theirs, until someone runs
|
|
82
|
+
`memhouse share`. [Tutorial 3](03-share-your-memory.md) covers it from both sides.
|
|
83
|
+
|
|
84
|
+
## When something goes wrong
|
|
85
|
+
|
|
86
|
+
- **`Authentication failed`** right after install: the inviter may have re-issued your
|
|
87
|
+
invite, or you rotated and another machine still has the old password. `memhouse passwd`
|
|
88
|
+
sets a new one; then update the other machines.
|
|
89
|
+
- **`invite file … no such file`**: check the path. The file is deleted only after a
|
|
90
|
+
successful install.
|
|
91
|
+
- Anything else: `memhouse doctor`, then [Troubleshooting](../guides/troubleshooting.md).
|