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.
Files changed (60) hide show
  1. package/AGENTS.md +194 -0
  2. package/CHANGELOG.md +1097 -0
  3. package/README.md +54 -423
  4. package/SECURITY.md +68 -0
  5. package/bin/memhouse.js +299 -133
  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 +93 -0
  16. package/docs/guides/troubleshooting.md +78 -0
  17. package/docs/guides/uninstall.md +37 -0
  18. package/docs/guides/update.md +68 -0
  19. package/docs/releases/README.md +11 -0
  20. package/docs/releases/v0.18.10.md +226 -0
  21. package/docs/releases/v0.18.11.md +191 -0
  22. package/docs/tutorials/01-first-house.md +132 -0
  23. package/docs/tutorials/02-join-a-house.md +91 -0
  24. package/docs/tutorials/03-share-your-memory.md +96 -0
  25. package/editors/claude.js +68 -10
  26. package/examples/01-local-one-machine/README.md +99 -0
  27. package/examples/01-local-one-machine/run.sh +61 -0
  28. package/examples/02-existing-clickhouse/README.md +121 -0
  29. package/examples/02-existing-clickhouse/run.sh +71 -0
  30. package/examples/03-team-house/README.md +129 -0
  31. package/examples/03-team-house/run.sh +124 -0
  32. package/examples/04-self-hosted-team/.env.example +22 -0
  33. package/examples/04-self-hosted-team/README.md +187 -0
  34. package/examples/04-self-hosted-team/compose.yml +158 -0
  35. package/examples/04-self-hosted-team/smoke.sh +113 -0
  36. package/examples/README.md +42 -0
  37. package/examples/fixtures/README.md +24 -0
  38. package/examples/fixtures/make-sessions.js +63 -0
  39. package/memhouse/DESIGN.md +9 -2
  40. package/memhouse/admin-secret.js +81 -0
  41. package/memhouse/delivery/plugin/.claude-plugin/plugin.json +1 -1
  42. package/memhouse/delivery/plugin/reference/HOUSE.md +18 -6
  43. package/memhouse/delivery/plugin/skills/access/SKILL.md +1 -1
  44. package/memhouse/delivery/plugin/skills/admin/SKILL.md +1 -1
  45. package/memhouse/delivery/plugin/skills/house/SKILL.md +1 -1
  46. package/memhouse/delivery/plugin/skills/recall/SKILL.md +34 -14
  47. package/memhouse/delivery/plugin/skills/sql/SKILL.md +1 -1
  48. package/memhouse/deploy.js +4 -2
  49. package/memhouse/flags.js +32 -5
  50. package/memhouse/host.js +11 -6
  51. package/memhouse/house/HOUSE.md +1 -1
  52. package/memhouse/house/house.js +27 -1
  53. package/memhouse/invite-target.js +37 -0
  54. package/memhouse/provision.js +12 -3
  55. package/memhouse/server/queries.js +9 -4
  56. package/memhouse/service.js +5 -0
  57. package/memhouse/shipper/ship.js +148 -31
  58. package/package.json +10 -2
  59. package/public/THIRD_PARTY_NOTICES.txt +2114 -0
  60. package/ui/vite.config.js +4 -1
@@ -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.
@@ -0,0 +1,102 @@
1
+ # Share and revoke
2
+
3
+ A share lets another member of the same server read your rooms. It is a ClickHouse
4
+ `GRANT SELECT`, so it is read-only, and you can withdraw it. Run these on a machine
5
+ installed as yourself. Each command acts on your own rooms only.
6
+
7
+ ```bash
8
+ memhouse share bob # full: everything in mem.<you>_*
9
+ memhouse share bob --only project=billing # scoped: three rooms, filtered
10
+ memhouse share --list # what memhouse has recorded
11
+ memhouse share bob --revoke # take it back
12
+ ```
13
+
14
+ ## Full or scoped
15
+
16
+ | | full (`share bob`) | scoped (`share bob --only …`) |
17
+ |---|---|---|
18
+ | grant | `SELECT ON mem.<you>_*` | `SELECT` on `<you>_sessions`, `<you>_messages`, `<you>_tool_calls` |
19
+ | rows | all | those matching the scope, through row policies |
20
+ | stats tables (`<you>_session_stats`, model and tool stats) | readable: first prompts, folders, projects and tokens of every session | not granted |
21
+ | `<you>_meta`, `<you>_events` | readable, including your other share records | not granted |
22
+ | rooms created later | readable | not granted |
23
+
24
+ **A full share is for someone you would hand your laptop to.** It reaches every table in
25
+ your pattern, including ones memhouse adds in a later release. The command says so when
26
+ you run it.
27
+
28
+ ## Scopes
29
+
30
+ `--only key=value[,key=value…]`. All the keys must hold (AND):
31
+
32
+ | key | filters on |
33
+ |---|---|
34
+ | `project=` | the project name |
35
+ | `folder=` | the working directory |
36
+ | `session=` | one session id |
37
+ | `host=` | one machine (its fingerprint, as `status` shows it) |
38
+ | `source=` | one editor, by the value stored in the `source` column (below) |
39
+ | `since=` / `until=` | a date range: message time, or session creation time for `sessions` |
40
+
41
+ `source=` compares against the stored value, which is not always the adapter name you
42
+ use in `MEMHOUSE_EDITORS`. Claude Code rows, for example, say `claude-code`, not `claude`.
43
+ The values:
44
+
45
+ | editor | `source` |
46
+ |---|---|
47
+ | Claude Code | `claude-code` |
48
+ | Codex | `codex` |
49
+ | Cursor / Cursor Agent | `cursor` / `cursor-agent` |
50
+ | VS Code / VS Code Insiders | `vscode` / `vscode-insiders` |
51
+ | GitHub Copilot / Copilot for JetBrains | `copilot-cli` / `copilot-jetbrains` |
52
+ | Gemini CLI | `gemini-cli` |
53
+ | Zed, OpenCode, Goose, Kiro, Codebuff, Antigravity | `zed`, `opencode`, `goose`, `kiro`, `codebuff`, `antigravity` |
54
+ | Devin / Devin Next | `devin` / `devin-next` |
55
+ | Command Code | `commandcode` |
56
+
57
+ To see what your rooms actually hold:
58
+ `SELECT source, count() FROM mem.<you>_sessions FINAL GROUP BY source`.
59
+
60
+ An empty scope (`--only ""`, or `--only "$SCOPE"` with the variable unset) is refused.
61
+ It never falls back to a full share.
62
+
63
+ ## How the server must be configured
64
+
65
+ Row policies in ClickHouse have one sharp edge. On some server configurations, the first
66
+ policy on a table hides every row from readers who have no policy of their own: you, and
67
+ your full-share grantees. Before it creates the first policy, `share` measures how this
68
+ server behaves, and refuses if a policy would blind you. The fix is server configuration
69
+ (`users_without_row_policies_can_read_rows`), and it is the administrator's to make.
70
+
71
+ ## Changing a share
72
+
73
+ - **Scoped to full:** `memhouse share bob`.
74
+ - **Full to scoped:** `memhouse share bob --only …`. The wildcard grant is withdrawn
75
+ first, so a failure part-way leaves bob with less access, never more.
76
+ - **One scope to another:** run `--only` again with the new scope. It replaces the
77
+ policies.
78
+
79
+ **Scoped shares made before 0.18.10** granted the whole pattern while filtering only three
80
+ rooms. Re-run `memhouse share <user> --only <scope>` once for each, and it is narrowed to
81
+ the three rooms.
82
+
83
+ ## Revoking
84
+
85
+ `--revoke` withdraws the grants (the wildcard and the three rooms), then drops the row
86
+ policies. If the server refuses a step, the policies are kept unless every grant is
87
+ confirmed gone, so a failed revoke never leaves an unfiltered share behind.
88
+
89
+ A revoke cannot recall what was already read.
90
+
91
+ ## What `--list` shows
92
+
93
+ `share --list` reads memhouse's own record, the `share:` keys in `<you>_meta`. A grant
94
+ someone made by hand in SQL does not appear there. A member cannot read `system.grants`;
95
+ an administrator can, with `SHOW GRANTS FOR <user>`.
96
+
97
+ ## Reading what was shared with you
98
+
99
+ Shared rooms sit in the same database as yours, under the other member's name, for
100
+ example `mem.alice_messages`. Query them with `/mem:sql` or any ClickHouse client, joining
101
+ on `(session_id, user_id)` as you would on your own rooms. A table you were not granted is
102
+ refused, and a scope you are under returns only its rows.
@@ -0,0 +1,93 @@
1
+ # How memory is stored
2
+
3
+ ## A house, rooms, and members
4
+
5
+ - **A house is a ClickHouse database,** normally `mem`.
6
+ - **A member is a ClickHouse user** who ships into it.
7
+ - **Each member's rooms are tables named for them:**
8
+
9
+ | room | holds |
10
+ |---|---|
11
+ | `<member>_sessions` | one row per session: editor, project, folder, branch, timestamps, title |
12
+ | `<member>_messages` | every turn: role, text, model, tokens, timestamp, position |
13
+ | `<member>_tool_calls` | every tool call: name, arguments, which message made it |
14
+ | `<member>_session_stats`, `_session_model_stats`, `_session_tool_stats` | precomputed rollups for the dashboard, refreshed after each pass |
15
+ | `<member>_meta` | memhouse's own records: schema version, writers, shares |
16
+ | `<member>_events` | an append-only log: migrations, version changes |
17
+
18
+ **A member holds one grant: `ON mem.<member>_*`.** That covers their own rooms, present and
19
+ future, and nothing else in the database. Nobody is granted the database itself:
20
+ `ALL ON mem.*` would also reach rooms created later, which is how two people in one
21
+ database once leaked into each other. A member can read their isolation back with
22
+ `SHOW GRANTS`.
23
+
24
+ | | rooms | each member holds |
25
+ |---|---|---|
26
+ | alone on a laptop | `mem.polat_*` | one grant on `mem.polat_*` |
27
+ | a team on one server | `mem.polat_*`, `mem.alice_*`, … | one grant each, on their own |
28
+
29
+ Reading across members is a `UNION ALL` over the rooms you hold: your own, and any shared
30
+ with you. Naming a room you were not granted is an error, never a silent omission.
31
+
32
+ ## Every row says where it came from
33
+
34
+ - **`user_id`** is stamped by the server: `MATERIALIZED currentUser()`. Async inserts are
35
+ pinned off for members, so the stamp cannot be skipped. `WHERE user_id = 'alice'` is one
36
+ person.
37
+ - **`host`** is the machine. Every row carries `<hostname>-<8 hex>`, where the 8 hex come
38
+ from a fingerprint of the OS's own machine id (IOPlatformUUID on macOS,
39
+ `/etc/machine-id` on Linux), hashed so the raw id never leaves the machine. It is kept in
40
+ `$MEMHOUSE_HOME/host.json`. It is not taken from the hostname:
41
+ - two laptops that both answer to `MacBook-Pro` still get different ids;
42
+ - a renamed machine keeps its id, and `status` reports the new name beside it;
43
+ - reinstalling, even after `uninstall --full-removal`, brings the same machine back
44
+ under the same id. Where no machine id can be read, it falls back to a random one.
45
+
46
+ `memhouse status` shows this machine's id. `memhouse doctor` names every host in your
47
+ rooms.
48
+ - **`origin`** says who wrote the row. The shipper writes `ship`; an import writes its own
49
+ value.
50
+
51
+ ## The house never destroys what it cannot rebuild
52
+
53
+ **The shipper is insert-only.** It runs no `DELETE`, no `TRUNCATE`, and no mutation of
54
+ any kind, so no privilege it holds can lose you a row.
55
+
56
+ That has a cost. ReplacingMergeTree deduplicates but does not diff: a re-parse that yields
57
+ *fewer* messages leaves the old, higher-positioned rows in place. A shorter re-parse has
58
+ three possible causes:
59
+
60
+ - an adapter bug was fixed, and the extra rows were junk;
61
+ - Claude Code **compacted** the transcript;
62
+ - the editor's retention window removed it.
63
+
64
+ In the last two cases the house holds the only surviving copy. So rows carry an `epoch`,
65
+ which says which parse of the session they belong to:
66
+
67
+ - **Nothing changed**, or the session just grew: the same epoch. Rows deduplicate exactly,
68
+ and no extra storage is used.
69
+ - **Shorter, or rewritten at a position the house already holds:** the new parse goes to
70
+ `epoch + 1`. The old parse stays complete and readable.
71
+
72
+ Reads show one parse per session, the newest, so counts, tokens and cost are not
73
+ inflated. The skills, the dashboard and `memhouse search` all filter this way; hand-written
74
+ queries should too ([the clause](search-and-resume.md#writing-your-own-queries)).
75
+
76
+ **Imported history is protected the same way.** `origin` is in the sorting key of
77
+ `messages` and `tool_calls`, so a shipped row can never collapse an imported one. Anything
78
+ imported from an older house, another product, or a machine that no longer exists survives
79
+ every re-ship. `sessions` is the deliberate exception: it holds one row per session, with
80
+ no `origin` or `epoch` in its key. A session's metadata has a single current version, and
81
+ a second row would make every rollup count its messages twice.
82
+
83
+ The shipper checks the rooms' sorting keys before it writes, and refuses if they are
84
+ wrong. See [Update](update.md#when-the-house-itself-must-change).
85
+
86
+ ## What is not in the house
87
+
88
+ - Nothing is embedded, summarised or rewritten. Text is stored as the editor wrote it,
89
+ truncated at 50,000 characters per message and 20,000 per tool argument.
90
+ - No LLM runs anywhere in memhouse's write or read path. The skills are read by your agent,
91
+ which does the reading and reasoning.
92
+ - The local transcript files stay where the editor put them. memhouse reads them and never
93
+ modifies them.
@@ -0,0 +1,78 @@
1
+ # Troubleshooting
2
+
3
+ Start with the two diagnostics. Both are read-only.
4
+
5
+ ```bash
6
+ memhouse doctor # the whole pipeline, one line per check
7
+ memhouse discover # what each editor adapter sees on this machine
8
+ ```
9
+
10
+ ## An editor ships nothing
11
+
12
+ `discover` lists every adapter. Each one is in one of three states:
13
+
14
+ - it has sessions, with a count;
15
+ - it has none, because the editor is not used on this machine;
16
+ - it was **skipped**, with the reason.
17
+
18
+ A skipped adapter and an editor you do not have both contribute zero sessions, so
19
+ memhouse always says which one it is. Common causes, one store at a time:
20
+
21
+ - **A SQLite store locked by the running editor:** `state.vscdb` for Cursor and VS Code.
22
+ The next pass retries.
23
+ - **A store the editor moved or changed** in a new release.
24
+ - **A scope that excludes it:** `MEMHOUSE_EDITORS` or a `MEMHOUSE_<EDITOR>_ROOTS` in the
25
+ env file. See [Configuration](configuration.md#which-sessions-ship).
26
+
27
+ SQLite comes from Node itself (`node:sqlite`), so there is no native module to rebuild.
28
+
29
+ ## Status says the shipper runs, but nothing new arrives
30
+
31
+ `memhouse status` reads the shipper's last pass from its log, and shows a failing pass
32
+ as a failure.
33
+
34
+ - **`Authentication failed`:** the password in `~/.memhouse/env` is no longer the
35
+ member's. This happens after a `passwd` on another machine, or a reset by the admin. Put
36
+ the current password into `MEMHOUSE_PASSWORD` in `~/.memhouse/env` (or run
37
+ `memhouse setup`, which asks), then restart the shipper.
38
+ - **A pass that keeps withholding a session:** an adapter returned nothing for a session
39
+ the house already holds. The shipper refuses to replace a transcript with an empty one,
40
+ and says so on every pass, until the store is readable again.
41
+ - **Nothing to ship:** sessions are only shipped once the editor has written them.
42
+
43
+ ## Daemons don't survive a reboot
44
+
45
+ `memhouse start` uses pidfiles. Its daemons outlive the shell but not a restart. Use
46
+ `memhouse service install` ([Daemons](daemons.md)). On Linux, also enable lingering, or
47
+ user services stop at logout. A rootless podman house from `deploy --local` has the same
48
+ exposure, and `deploy` prints the fix.
49
+
50
+ ## The dashboard is empty, or stale
51
+
52
+ - **It reads the house, not the machine.** Check `memhouse status` for the connection
53
+ first.
54
+ - **It reads precomputed stats,** refreshed at the end of each pass that shipped
55
+ something. On a house where nothing has shipped for a day, the stats age out, and a
56
+ running dashboard keeps reading them. Restart it (`memhouse stop && memhouse start`). It
57
+ then reads the rooms directly, until the next pass that ships refreshes the stats.
58
+ A fix is planned.
59
+ - **After an upgrade it shows the old version:** restart it (`memhouse update` does this).
60
+
61
+ ## `EACCES` during `npm install -g`
62
+
63
+ See [Install](install.md#eacces-on-install). `sudo` is right only when the npm prefix is
64
+ owned by root.
65
+
66
+ ## `refused`, `ACCESS_DENIED`, `Not enough privileges`
67
+
68
+ - For a member, these are expected outside `mem.<you>_*` and the rooms shared with you.
69
+ `memhouse whoami` shows what your credential may do.
70
+ - For `invite`, `members` or `convert`: you need the admin credential. See
71
+ [Admin password](admin-password.md).
72
+ - A room that should be yours but is refused usually means the house is older than this
73
+ version. Run `memhouse doctor`, then `memhouse migrate` if it says so.
74
+
75
+ ## Still stuck
76
+
77
+ Run `memhouse doctor` and `memhouse status --json`, and open an issue with both outputs.
78
+ Check them before posting, and remove anything private, such as a host name.
@@ -0,0 +1,37 @@
1
+ # Uninstall
2
+
3
+ Three tiers. **None of them touches the memory in the house.**
4
+
5
+ ```bash
6
+ memhouse uninstall # stop everything; KEEP the config and this machine's identity
7
+ memhouse uninstall --credentials # also forget the house and its password
8
+ memhouse uninstall --full-removal # all of ~/.memhouse, identity included
9
+ npm uninstall -g memhouse # then remove the package
10
+ ```
11
+
12
+ - **The default is the conservative one.** Stopping the shipper is routine: before an
13
+ upgrade, while debugging, or when a laptop should go quiet for a week. It should not
14
+ also mean "forget which house I use and who this machine is".
15
+ - **`--full-removal` asks first.** It deletes `host.json`. A later reinstall derives the
16
+ same identity again from the machine's own id, so your history stays one machine, unless
17
+ the machine was renamed in between or has no readable machine id. Then it comes back as
18
+ a new host.
19
+ - **Your memory stays.** The rooms in ClickHouse are untouched by every tier. What the
20
+ shipper wrote can be rebuilt from the local session stores with `memhouse ship --full`,
21
+ for as long as the editors keep them.
22
+
23
+ ## Removing the house itself
24
+
25
+ - **A local house** from `deploy --local`: `memhouse deploy --down` removes the container
26
+ **and its data volume**. That deletes the memory, and there is no undo.
27
+ - **A shared server:** an administrator drops your rooms and user. See
28
+ [Operate a house](operate.md).
29
+
30
+ ## Removing the skills
31
+
32
+ ```bash
33
+ memhouse plugins remove claude
34
+ ```
35
+
36
+ This removes the `/mem:*` skills, and the instance binding, from the Claude Code config
37
+ directories they were installed into.
@@ -0,0 +1,68 @@
1
+ # Update
2
+
3
+ ```bash
4
+ memhouse update # upgrade along this install's channel, restart the daemons, check the house
5
+ memhouse update --check # compare versions, change nothing
6
+ ```
7
+
8
+ `update` does three things that a bare `npm install -g memhouse@latest` does not:
9
+
10
+ 1. **It restarts the daemons.** A running shipper keeps parsing with the code it booted
11
+ with. One once ran for 1 day 16 hours out of a directory that had since been moved.
12
+ 2. **It checks whether the house needs a migration** for the new version, and offers to run
13
+ it. `--migrate` runs it without asking.
14
+ 3. **It stays on your channel** (`MEMHOUSE_CHANNEL`). See
15
+ [Configuration](configuration.md#channels).
16
+
17
+ Upgraded by hand already? Finish the job without reinstalling:
18
+
19
+ ```bash
20
+ npm install -g memhouse@latest
21
+ memhouse update --no-install
22
+ ```
23
+
24
+ The daemons also notice on their own. Each one compares the installed version with the
25
+ version it booted with, and hands over when they differ: under systemd or launchd it
26
+ exits so the supervisor restarts it; with nothing supervising, it re-executes itself.
27
+ `update` just makes the switch immediate.
28
+
29
+ ## Several machines on one house
30
+
31
+ Every machine of every member runs its own shipper. Upgrade them all.
32
+
33
+ - The release notes for each version say whether the order matters and whether mixed
34
+ versions can ship side by side. See [`docs/releases/`](../releases/).
35
+ - `memhouse status` lists every machine writing to your rooms, with the version each
36
+ last reported and when it last shipped. A machine that is behind is named there.
37
+ - Machines that stopped writing long ago are folded into one line. That is history, not
38
+ a fault. `memhouse status --all` lists them.
39
+
40
+ ## When the house itself must change
41
+
42
+ Some releases need the rooms rebuilt, for example when a sorting key changes. The shipper
43
+ checks the rooms' keys before it writes, and **refuses** to write into a house it does not
44
+ match, so an old house cannot be corrupted by a new shipper. To bring the house up to
45
+ date:
46
+
47
+ ```bash
48
+ memhouse migrate --dry-run # what would run
49
+ memhouse migrate # copy, atomic swap; nothing is deleted
50
+ memhouse doctor # every line a check mark
51
+ ```
52
+
53
+ A migration copies each room, swaps it in atomically, and keeps the old one as
54
+ `<room>_pre_<migration>` for you to drop when you are satisfied. The house records the move
55
+ in its `events` room, and `doctor` reads it back.
56
+
57
+ ## Upgrading from 0.9.x
58
+
59
+ 0.9.x predates migrations, and `update` runs the **old** version's code (it replaces itself
60
+ mid-run), so it cannot prompt. After the upgrade, the first ship refuses (nothing is lost)
61
+ and names the one command to run by hand: `memhouse migrate`.
62
+
63
+ ## Upgrading a pre-0.18 house (a database per member)
64
+
65
+ 0.18 moved every member's rooms into one database, as `mem.<member>_*`. An operator moves
66
+ an old house once with `memhouse convert`; see [Operate a house](operate.md#convert). After
67
+ that, members upgrade with `memhouse update`, and the shipper adopts the moved rooms
68
+ itself.
@@ -0,0 +1,11 @@
1
+ # Release notes
2
+
3
+ One document per release, from 0.18.10 onward. Each says what changed, what you need to
4
+ do, how to upgrade, what is deprecated and when it goes, and what was deferred.
5
+
6
+ | version | date | headline |
7
+ |---|---|---|
8
+ | [0.18.11](v0.18.11.md) | 2026-10-10 | sessions with subagents stop re-shipping; security: no stored credential sent to `invite --url` |
9
+ | [0.18.10](v0.18.10.md) | 2026-10-08 | security: the admin password never on argv; no member password printed; a scoped share reaches only its scope |
10
+
11
+ Earlier versions: [`CHANGELOG.md`](../../CHANGELOG.md).