memhouse 0.18.12 → 0.20.1
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 +22 -151
- package/CHANGELOG.md +263 -29
- package/LICENSE +202 -22
- package/LICENSES/agentlytics-MIT.txt +21 -0
- package/LICENSES/memhouse-MIT-until-0.18.11.txt +22 -0
- package/LICENSES/models.dev-MIT.txt +22 -0
- package/NOTICE +28 -0
- package/README.md +42 -20
- package/SECURITY.md +21 -8
- package/bin/memhouse.js +2223 -311
- package/docs/README.md +11 -9
- package/docs/guides/admin-password.md +37 -10
- package/docs/guides/configuration.md +13 -6
- package/docs/guides/daemons.md +64 -3
- package/docs/guides/import-claude-ai.md +204 -0
- package/docs/guides/install.md +11 -6
- package/docs/guides/invite.md +21 -7
- package/docs/guides/operate.md +114 -7
- package/docs/guides/search-and-resume.md +72 -3
- package/docs/guides/share.md +91 -52
- package/docs/guides/storage.md +44 -4
- package/docs/guides/troubleshooting.md +121 -14
- package/docs/guides/uninstall.md +4 -3
- package/docs/guides/update.md +16 -0
- package/docs/guides/upgrade-to-0.20.md +188 -0
- package/docs/releases/README.md +2 -1
- package/docs/releases/v0.18.10.md +5 -5
- package/docs/releases/v0.18.11.md +3 -3
- package/docs/releases/v0.20.0.md +627 -0
- package/docs/releases/v0.20.1.md +114 -0
- package/docs/tutorials/01-first-house.md +10 -7
- package/docs/tutorials/02-join-a-house.md +24 -15
- package/docs/tutorials/03-share-your-memory.md +40 -31
- package/editors/antigravity.js +1 -80
- package/editors/base.js +463 -9
- package/editors/bridge.js +119 -0
- package/editors/claude.js +273 -105
- package/editors/codex.js +278 -52
- package/editors/copilot.js +1 -70
- package/editors/cursor.js +1 -75
- package/editors/derive-fingerprints.json +18 -0
- package/editors/harness-paths.js +69 -0
- package/editors/index.js +1 -20
- package/editors/normalise/agy.js +910 -0
- package/editors/normalise/copilot-cli.js +321 -0
- package/editors/normalise/cursor-agent.js +852 -0
- package/editors/normalise/cursor.js +474 -0
- package/editors/normalise/devin.js +575 -0
- package/editors/normalise/gemini-cli.js +602 -0
- package/editors/normalise/goose.js +673 -0
- package/editors/normalise/opencode.js +633 -0
- package/editors/normalise/vscode.js +549 -0
- package/editors/normalise/zed.js +473 -0
- package/editors/opencode-v4.js +119 -0
- package/editors/scope.js +14 -3
- package/editors/sessions-log.js +349 -0
- package/editors/sqlite.js +28 -1
- package/editors/vscode.js +1 -72
- package/editors/windsurf.js +1 -143
- package/examples/01-local-one-machine/README.md +24 -19
- package/examples/01-local-one-machine/run.sh +1 -1
- package/examples/02-existing-clickhouse/README.md +30 -22
- package/examples/02-existing-clickhouse/run.sh +5 -4
- package/examples/03-team-house/README.md +44 -37
- package/examples/03-team-house/run.sh +35 -18
- package/examples/04-self-hosted-team/README.md +29 -14
- package/examples/04-self-hosted-team/compose.yml +5 -2
- package/examples/04-self-hosted-team/smoke.sh +26 -12
- package/examples/README.md +8 -4
- package/examples/fixtures/README.md +4 -1
- package/examples/fixtures/make-sessions.js +8 -5
- package/memhouse/admin-secret.js +89 -24
- package/memhouse/argv-secrets.js +64 -0
- package/memhouse/channel.js +49 -9
- package/memhouse/codex-plugin.js +194 -0
- package/memhouse/delivery/AGENT-INSTALL-PROMPT.md +2 -1
- package/memhouse/delivery/AGENT-INSTALL.md +22 -11
- package/memhouse/delivery/INVITATION.md.tpl +44 -45
- package/memhouse/delivery/PROMPT.md +53 -5
- package/memhouse/delivery/UPGRADE.md.tpl +1 -1
- package/memhouse/delivery/codex/AGENTS-BLOCK.md +11 -0
- package/memhouse/delivery/codex/SKILL.md +50 -0
- package/memhouse/delivery/kernel-install.md +17 -9
- package/memhouse/delivery/plugin/.claude-plugin/plugin.json +2 -2
- package/memhouse/delivery/plugin/reference/HOUSE.md +168 -41
- package/memhouse/delivery/plugin/skills/access/SKILL.md +13 -5
- package/memhouse/delivery/plugin/skills/admin/SKILL.md +14 -6
- package/memhouse/delivery/plugin/skills/house/SKILL.md +25 -8
- package/memhouse/delivery/plugin/skills/recall/SKILL.md +66 -8
- package/memhouse/delivery/plugin/skills/sql/SKILL.md +66 -7
- package/memhouse/deploy.js +1 -1
- package/memhouse/flags.js +35 -18
- package/memhouse/help.js +37 -0
- package/memhouse/host.js +82 -2
- package/memhouse/house/HOUSE.md +2 -2
- package/memhouse/house/convert-profile.js +638 -0
- package/memhouse/house/convert-v3.js +742 -0
- package/memhouse/house/doctor-v3.js +324 -0
- package/memhouse/house/host-alias.js +85 -0
- package/memhouse/house/house.js +3 -3
- package/memhouse/house/migrate.js +2 -2
- package/memhouse/house/profile-dedupe.js +183 -0
- package/memhouse/house/profile-edges.js +554 -0
- package/memhouse/house/profile-house.js +430 -0
- package/memhouse/house/profile-rollup.js +190 -0
- package/memhouse/house/q-cli.js +863 -0
- package/memhouse/house/queries-v3.js +1013 -0
- package/memhouse/house/reconcile-v3.js +192 -0
- package/memhouse/house/records-to-profile.js +174 -0
- package/memhouse/house/records-to-rows.js +169 -0
- package/memhouse/house/relocate.js +2 -1
- package/memhouse/house/schema-choice.js +121 -0
- package/memhouse/house/schema-profile.js +290 -0
- package/memhouse/house/schema-profile.sql.tpl +398 -0
- package/memhouse/house/schema-v3.js +267 -0
- package/memhouse/house/schema-v3.sql.tpl +213 -0
- package/memhouse/import/claude-ai.js +420 -0
- package/memhouse/import/import.js +372 -0
- package/memhouse/import/pyjson.js +206 -0
- package/memhouse/import/records.js +64 -0
- package/memhouse/import/writer-profile.js +192 -0
- package/memhouse/import/writer-v3.js +240 -0
- package/memhouse/import/zip.js +112 -0
- package/memhouse/invitation.js +102 -0
- package/memhouse/invitefile.js +5 -2
- package/memhouse/plugin-copies.js +176 -0
- package/memhouse/provision.js +7 -2
- package/memhouse/release-hint.js +24 -0
- package/memhouse/resume.js +4 -4
- package/memhouse/server/api-v3.js +632 -0
- package/memhouse/server/dashboard-auth.js +181 -0
- package/memhouse/server/dashboard-port.js +91 -0
- package/memhouse/server/queries.js +30 -0
- package/memhouse/server/server.js +118 -20
- package/memhouse/service.js +1 -1
- package/memhouse/share.js +687 -1
- package/memhouse/shipper/adapter-capture.js +756 -0
- package/memhouse/shipper/capture.js +2571 -0
- package/memhouse/shipper/dedupe-profile.js +237 -0
- package/memhouse/shipper/dedupe-v3.js +1027 -0
- package/memhouse/shipper/forks.js +233 -0
- package/memhouse/shipper/log-adapter.js +219 -0
- package/memhouse/shipper/maintenance.js +49 -0
- package/memhouse/shipper/normalise-run.js +148 -0
- package/memhouse/shipper/passlog.js +68 -5
- package/memhouse/shipper/profile-capture.js +903 -0
- package/memhouse/shipper/ship.js +91 -8
- package/memhouse/shipper/snapshots.js +193 -0
- package/memhouse/shipper/source-roots.js +111 -0
- package/memhouse/version-notice.js +66 -0
- package/package.json +14 -7
- package/public/THIRD_PARTY_NOTICES.txt +2 -2
- package/public/assets/index-CcNnhfM3.js +78 -0
- package/public/index.html +1 -1
- package/ui/package-lock.json +56 -37
- package/ui/package.json +1 -0
- package/ui/src/App.jsx +29 -14
- package/ui/src/components/ChatSidebar.jsx +69 -12
- package/ui/src/lib/api.js +76 -0
- package/ui/src/lib/dashboard-token.js +41 -0
- package/ui/src/main.jsx +22 -5
- package/ui/src/pages/Dashboard.jsx +22 -36
- package/ui/third-party-notices.js +119 -0
- package/ui/vite.config.js +5 -1
- package/docs/releases/v0.18.12.md +0 -59
- package/memhouse/COMPETITION.md +0 -221
- package/memhouse/DESIGN.md +0 -222
- package/memhouse/RESUME-AND-UPDATE.md +0 -182
- package/public/assets/index-CnWzrjF3.js +0 -78
package/docs/README.md
CHANGED
|
@@ -22,12 +22,14 @@ One common operation each.
|
|
|
22
22
|
| [Install and onboard](guides/install.md) | install against a local, existing, or invited house; fix `EACCES` |
|
|
23
23
|
| [Configuration](guides/configuration.md) | choose which editors and directories ship; run several instances; follow a channel |
|
|
24
24
|
| [Update](guides/update.md) | stay current, and upgrade every machine of a house |
|
|
25
|
-
| [
|
|
25
|
+
| [Upgrade to 0.20](guides/upgrade-to-0.20.md) | move a 0.18 house to schema 3: prepare, convert, reconcile, then switch each machine |
|
|
26
|
+
| [Daemons and services](guides/daemons.md) | keep the shipper and dashboard running, across reboots; open the dashboard |
|
|
26
27
|
| [Invite members](guides/invite.md) | bring a teammate into a house you administer |
|
|
27
|
-
| [Share and revoke](guides/share.md) | let someone read your
|
|
28
|
+
| [Share and revoke](guides/share.md) | let someone read your memory, scoped or whole |
|
|
28
29
|
| [Admin password](guides/admin-password.md) | run an admin command without the password reaching `ps`, history, or a transcript |
|
|
29
30
|
| [Search, resume and skills](guides/search-and-resume.md) | find an old session, reopen it, let an agent answer from history |
|
|
30
|
-
| [
|
|
31
|
+
| [Import claude.ai conversations](guides/import-claude-ai.md) | bring a claude.ai data export into your house, and the next export after it |
|
|
32
|
+
| [How memory is stored](guides/storage.md) | houses, a member's tables, machine identity, what is never deleted |
|
|
31
33
|
| [Operate a house](guides/operate.md) | members, migrations, moving a house, backups |
|
|
32
34
|
| [Troubleshooting](guides/troubleshooting.md) | an editor ships nothing, daemons stop, a dashboard looks empty |
|
|
33
35
|
| [Uninstall](guides/uninstall.md) | stop, forget the house, or remove everything |
|
|
@@ -37,10 +39,10 @@ One common operation each.
|
|
|
37
39
|
- `memhouse <command> --help`: every command's own usage. It always prints usage and
|
|
38
40
|
never runs the command.
|
|
39
41
|
- [Release notes](releases/): what changed in each version, and what to do about it.
|
|
40
|
-
- [`../memhouse/house/HOUSE.md`](../memhouse/house/HOUSE.md): the
|
|
41
|
-
column
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
- [`../memhouse/house/HOUSE.md`](../memhouse/house/HOUSE.md): the 0.18 rooms, column by
|
|
43
|
+
column. Schema 3's tables are in
|
|
44
|
+
[`../memhouse/house/schema-profile.sql.tpl`](../memhouse/house/schema-profile.sql.tpl).
|
|
45
|
+
- `memhouse/DESIGN.md` (repository, not yet public): the design, and why it is shaped
|
|
46
|
+
this way.
|
|
44
47
|
- [`../SECURITY.md`](../SECURITY.md): what holds, and what does not.
|
|
45
|
-
-
|
|
46
|
-
repository): designs captured before they are built.
|
|
48
|
+
- `docs/design/` (repository, not yet public): designs captured before they are built.
|
|
@@ -6,9 +6,13 @@ A few commands need the ClickHouse server's administrator:
|
|
|
6
6
|
- `invite`;
|
|
7
7
|
- `passwd --admin-user …`, for a member whose account predates self-rotation (0.11);
|
|
8
8
|
- `members`;
|
|
9
|
-
- `convert
|
|
9
|
+
- `convert`;
|
|
10
|
+
- `migrate --v3-prepare`, `--v3-convert`, `--v3-reconcile` and `--v3-shares`, which move a 0.18
|
|
11
|
+
house to schema 3 ([Upgrade to 0.20](upgrade-to-0.20.md)). `--v3-switch` is the member's own
|
|
12
|
+
step.
|
|
10
13
|
|
|
11
|
-
|
|
14
|
+
They name the admin with `--admin-user` or `MEMHOUSE_ADMIN_USER` (or the admin this install
|
|
15
|
+
keeps); `MEMHOUSE_USER` names the member. Shipping, searching and sharing never need it.
|
|
12
16
|
|
|
13
17
|
**The admin password owns the whole server.** Keep it out of three places:
|
|
14
18
|
|
|
@@ -16,7 +20,9 @@ Shipping, searching and sharing never need it.
|
|
|
16
20
|
runs, and shell history keeps it afterwards;
|
|
17
21
|
- **an agent's conversation**, because memhouse ships that conversation into the house,
|
|
18
22
|
and the archive is insert-only;
|
|
19
|
-
- **disk**, unless you chose that: `--keep-admin`, or `deploy --local`.
|
|
23
|
+
- **disk**, unless you chose that: `--keep-admin`, or `deploy --local`. `memhouse setup`
|
|
24
|
+
given a credential that administers the server writes nothing without `--keep-admin` (a
|
|
25
|
+
terminal is asked, default no), and refuses that password on the command line outright.
|
|
20
26
|
|
|
21
27
|
## Where memhouse takes it from
|
|
22
28
|
|
|
@@ -26,14 +32,19 @@ In order, first answer wins:
|
|
|
26
32
|
|---|---|---|
|
|
27
33
|
| 1 | `--admin-password-file <file>` | a file you control, mode 600. One trailing newline is dropped |
|
|
28
34
|
| 1 | `--admin-password-file -` | piping it in: `printf '%s' "$P" \| memhouse … --admin-password-file -` |
|
|
29
|
-
| 2 |
|
|
30
|
-
| 3 |
|
|
31
|
-
| 4 |
|
|
32
|
-
| 5 | a prompt | when there is a terminal; input is hidden, and pasting works |
|
|
35
|
+
| 2 | `MEMHOUSE_ADMIN_PASSWORD` | a secret manager lends it to one command (below) |
|
|
36
|
+
| 3 | the credential this install keeps | only when it belongs to the same admin user |
|
|
37
|
+
| 4 | a prompt | when there is a terminal; input is hidden, and pasting works |
|
|
33
38
|
|
|
34
|
-
The two forms of `--admin-password-file` are one option
|
|
35
|
-
|
|
36
|
-
|
|
39
|
+
The two forms of `--admin-password-file` are one option. A file that group or other users
|
|
40
|
+
can read or write is refused, like an ssh key, with the `chmod 600` that fixes it; the
|
|
41
|
+
secret mounts of a container (`/run/secrets/`, `/var/run/secrets/`) are the exception.
|
|
42
|
+
With no source and no terminal, the command stops and prints these options. It never
|
|
43
|
+
hangs, and it never guesses.
|
|
44
|
+
|
|
45
|
+
`--admin-password <value>` is refused. It was deprecated in 0.18.10 and removed in 0.20.0:
|
|
46
|
+
the command stops before doing anything, exits 2, names the forms above, and never prints
|
|
47
|
+
the value.
|
|
37
48
|
|
|
38
49
|
## With a secret manager
|
|
39
50
|
|
|
@@ -93,3 +104,19 @@ it before a scripted run, rather than guessing from a grant string.
|
|
|
93
104
|
Treat it as burned. Rotate it on the server (`ALTER USER … IDENTIFIED BY …`, as the
|
|
94
105
|
admin) and update every place that legitimately holds it. Deleting the transcript does
|
|
95
106
|
not help: the house is insert-only, and it may already have shipped.
|
|
107
|
+
|
|
108
|
+
## The other passwords a command takes
|
|
109
|
+
|
|
110
|
+
The same rule holds for `--password` (install, setup, onboard; for `passwd`, the new
|
|
111
|
+
password), `--member-password` (install, invite) and relocate's `--to-password`. Each has a
|
|
112
|
+
file form that takes a path at mode 600 or `-` for stdin, and the two that are not the
|
|
113
|
+
member's own have an environment variable:
|
|
114
|
+
|
|
115
|
+
| flag on the command line | instead |
|
|
116
|
+
|---|---|
|
|
117
|
+
| `--password <value>` | `MEMHOUSE_PASSWORD`, or `--password-file <file>` / `--password-file -` |
|
|
118
|
+
| `--member-password <value>` | `MEMHOUSE_MEMBER_PASSWORD`, or `--member-password-file …` |
|
|
119
|
+
| `--to-password <value>` | `MEMHOUSE_TO_PASSWORD`, or `--to-password-file …` |
|
|
120
|
+
|
|
121
|
+
The command-line forms still work in 0.20, with a warning on every run, and are refused
|
|
122
|
+
from the next minor release. Only one password can come from stdin per command.
|
|
@@ -12,14 +12,15 @@ default house.
|
|
|
12
12
|
|
|
13
13
|
| Variable | Meaning |
|
|
14
14
|
|---|---|
|
|
15
|
-
| `MEMHOUSE_URL` | the house
|
|
15
|
+
| `MEMHOUSE_URL` | the house: its ClickHouse HTTP(S) endpoint, port included |
|
|
16
16
|
| `MEMHOUSE_USER` / `MEMHOUSE_PASSWORD` | the member credential the shipper writes as |
|
|
17
|
+
| `MEMHOUSE_ADMIN_USER` / `MEMHOUSE_ADMIN_PASSWORD` | the server's administrator, for the admin commands only ([admin password](admin-password.md)); never passed to the shipper or the dashboard |
|
|
17
18
|
| `MEMHOUSE_DB` | the database holding the rooms, normally `mem` |
|
|
18
|
-
| `MEMHOUSE_PORT` |
|
|
19
|
+
| `MEMHOUSE_PORT` | this machine's dashboard port, default `4640`; never the house's port, which is part of `MEMHOUSE_URL`. When it is in use the dashboard takes the next free one, up to 10 above |
|
|
19
20
|
| `MEMHOUSE_CHANNEL` | the npm dist-tag `update` follows |
|
|
20
21
|
| `MEMHOUSE_EDITORS` | which adapters run (default: all) |
|
|
21
22
|
| `MEMHOUSE_<EDITOR>_ROOTS` | where one adapter looks |
|
|
22
|
-
| `MEMHOUSE_HOME` | where the env file, host identity, logs and
|
|
23
|
+
| `MEMHOUSE_HOME` | where the env file, host identity, logs, pidfiles and the dashboard's token live |
|
|
23
24
|
| `MEMHOUSE_ENGINE` | `docker` or `podman`, for `deploy --local` |
|
|
24
25
|
|
|
25
26
|
Never print this file or these variables in a terminal an agent is reading. memhouse ships
|
|
@@ -46,7 +47,11 @@ MEMHOUSE_EDITORS='claude'
|
|
|
46
47
|
MEMHOUSE_CLAUDE_ROOTS='~/.claude-playbooks/work-team'
|
|
47
48
|
```
|
|
48
49
|
|
|
49
|
-
- `MEMHOUSE_EDITORS` names the adapters to run.
|
|
50
|
+
- `MEMHOUSE_EDITORS` names the adapters to run. On schema 3 it also names the normalisers,
|
|
51
|
+
which read ten editors' stores directly: `agy` (also answers to `antigravity`),
|
|
52
|
+
`copilot-cli`, `cursor`, `cursor-agent`, `devin`, `gemini-cli`, `goose`, `opencode`,
|
|
53
|
+
`vscode`, `zed`. An editor left out is never read, and logs its normaliser wrote earlier
|
|
54
|
+
are no longer captured.
|
|
50
55
|
- `MEMHOUSE_<EDITOR>_ROOTS` replaces one adapter's location. The variable name is the
|
|
51
56
|
adapter's name upper-cased, with dashes turned into underscores.
|
|
52
57
|
- Claude is the one adapter with many roots, one per Claude Code config directory, so its
|
|
@@ -90,8 +95,10 @@ MEMHOUSE_HOME=~/.memhouse-work memhouse instance # which memhouse this is
|
|
|
90
95
|
`plugins install claude`, run from an instance, installs the skills into exactly the
|
|
91
96
|
playbooks that instance ships, and **binds** them. It writes `MEMHOUSE_HOME` and
|
|
92
97
|
`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
|
-
|
|
98
|
+
every session there. So the `/mem:*` skills in a bound playbook read that instance's house,
|
|
99
|
+
whatever the launching shell had set. The skills run plain `memhouse`, so the read commands they
|
|
100
|
+
pre-approve match without a prompt; `MEMHOUSE_BIN` is the instance's binary, which they use
|
|
101
|
+
instead only when `memhouse` is not on PATH or is a different binary. `plugins list` shows
|
|
95
102
|
the binding; `plugins remove claude` takes it out.
|
|
96
103
|
|
|
97
104
|
## Channels
|
package/docs/guides/daemons.md
CHANGED
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
memhouse runs two long-lived processes:
|
|
4
4
|
|
|
5
5
|
- the **shipper**, which runs an incremental pass every 300 seconds;
|
|
6
|
-
- the **dashboard**, on
|
|
6
|
+
- the **dashboard**, on port 4640 of `127.0.0.1` (`MEMHOUSE_PORT` changes it). Open it with
|
|
7
|
+
`memhouse dashboard`; see [The dashboard](#the-dashboard).
|
|
7
8
|
|
|
8
9
|
## Until the next reboot
|
|
9
10
|
|
|
@@ -34,6 +35,37 @@ memhouse service status | stop | start | restart | uninstall
|
|
|
34
35
|
upgrade, run `memhouse service uninstall`, then `memhouse service install`, so the unit
|
|
35
36
|
points at the new one.
|
|
36
37
|
|
|
38
|
+
## The dashboard
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
memhouse dashboard # open it in your browser
|
|
42
|
+
memhouse dashboard --no-open # write the page, open nothing
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
- **Every /api request needs this machine's token.** It is a random secret in
|
|
46
|
+
`$MEMHOUSE_HOME/dashboard-token` (default `~/.memhouse/dashboard-token`), mode 600, made by
|
|
47
|
+
the first `memhouse start`. A token file that group or other users can read is refused, with
|
|
48
|
+
the `chmod 600` that fixes it. To replace the token, delete the file and restart the
|
|
49
|
+
dashboard (`memhouse stop && memhouse start`).
|
|
50
|
+
- **`memhouse dashboard` checks the dashboard, then opens a file.** It first asks the server on
|
|
51
|
+
`127.0.0.1:<port>` to prove it holds the token, without sending it; anything else listening
|
|
52
|
+
there gets nothing, and the command exits 1 with "port N is not your dashboard". Then it
|
|
53
|
+
writes `$MEMHOUSE_HOME/dashboard.html` (mode 600), a page that sends the browser to
|
|
54
|
+
`http://127.0.0.1:<port>/` with the token in the URL's fragment, and opens that file (`open` on
|
|
55
|
+
macOS, `xdg-open` on Linux). The page keeps the token for that browser tab only and removes it
|
|
56
|
+
from the address bar; no cookie is set. A new tab, or a restarted browser, needs
|
|
57
|
+
`memhouse dashboard` again. The URL with the token is printed only when standard output is a
|
|
58
|
+
terminal, never with `--json` or into a pipe or file.
|
|
59
|
+
- **Scripts send the token as a header:** `Authorization: Bearer <token>`, read from the file.
|
|
60
|
+
- **Without it,** `/api/*` answers 401, and a page opened without the token says to open the
|
|
61
|
+
dashboard with `memhouse dashboard`. The page itself holds no house data.
|
|
62
|
+
- **When port 4640 is in use** (possibly by another account on this machine), the dashboard takes
|
|
63
|
+
the next free port, up to 4650, and `memhouse start` says which. `memhouse status` and
|
|
64
|
+
`memhouse dashboard` use the port it took. Set `MEMHOUSE_PORT` to choose the port.
|
|
65
|
+
- **From another machine,** forward the port over SSH (`ssh -L 4640:127.0.0.1:4640 <host>`)
|
|
66
|
+
and keep the default bind. `MEMHOUSE_HOST=0.0.0.0` makes the dashboard reachable from other
|
|
67
|
+
machines over plain HTTP, token included; prefer the tunnel.
|
|
68
|
+
|
|
37
69
|
## One pass by hand
|
|
38
70
|
|
|
39
71
|
```bash
|
|
@@ -49,5 +81,34 @@ never deletes anything: see [How memory is stored](storage.md).
|
|
|
49
81
|
## Logs
|
|
50
82
|
|
|
51
83
|
The daemons log to `$MEMHOUSE_HOME/logs/` (default `~/.memhouse/logs/`): `shipper.log` and
|
|
52
|
-
`dashboard.log`. `memhouse
|
|
53
|
-
|
|
84
|
+
`dashboard.log`. `memhouse start` exits 1 when the shipper exits right after starting; a
|
|
85
|
+
dashboard that does is reported as a warning, with the reason from its log. `memhouse status`
|
|
86
|
+
reads the shipper's last pass from its log, and reports a failing pass as a failure even while
|
|
87
|
+
the process is alive.
|
|
88
|
+
|
|
89
|
+
A pass that would not record an editor's deleted sessions as gone prints one line per store
|
|
90
|
+
and cause after its own line, `[memhouse] vanish refused: <editor> <store>: <why>`: the store's
|
|
91
|
+
list named none of the sessions the house holds of it (an empty or unreadable store), or left
|
|
92
|
+
out a session the store still has, or one that could not be read. Nothing is recorded as
|
|
93
|
+
vanished or removed, and `memhouse doctor` fails a line naming the store until a later pass
|
|
94
|
+
has no such line.
|
|
95
|
+
|
|
96
|
+
A store whose every session was deleted is refused in the same way, because an empty list is
|
|
97
|
+
also what an unreadable store gives. Its line ends with the command for that case:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
memhouse doctor --confirm-empty-store <editor>:<store>
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Copy it from the line as printed: a store path with spaces is quoted there. It confirms the
|
|
104
|
+
sessions that pass refused (sessions recorded as gone already replay without it), and records
|
|
105
|
+
the confirmation in this machine's capture state, beside the store's sweep state under
|
|
106
|
+
`$MEMHOUSE_HOME/state/derive-profile/stores/`; it needs no house. Removing that folder drops a
|
|
107
|
+
confirmation not yet used. The next pass that finds the store there, its list still empty and
|
|
108
|
+
no other session held takes each as gone where the editor's reader says it is gone, and no
|
|
109
|
+
longer refuses the store. A list that names a session again, or a session held that the
|
|
110
|
+
confirmation does not name, cancels it; a store with more than 100 sessions is taken over
|
|
111
|
+
several passes on the one confirmation.
|
|
112
|
+
|
|
113
|
+
A `[memhouse] vanish warning: …` line names a listed session's source the list left out that
|
|
114
|
+
still reads: it is captured as usual, and doctor shows the warning without failing.
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
# Import claude.ai conversations
|
|
2
|
+
|
|
3
|
+
claude.ai keeps your conversations on its servers, not on your machine, so the shipper never
|
|
4
|
+
sees them. `memhouse import claude-ai` reads a claude.ai data export and stores its conversations
|
|
5
|
+
in your house beside your editor sessions. They then show up in search, in `memhouse q` and in
|
|
6
|
+
the `/mem` skills.
|
|
7
|
+
|
|
8
|
+
Each run is one **batch**. A later export adds only the conversations the house does not hold
|
|
9
|
+
yet, so there is nothing to clean up between exports.
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
memhouse import claude-ai ~/Downloads/claude-export.zip # dry run: counts only
|
|
13
|
+
memhouse import claude-ai ~/Downloads/claude-export.zip --write # import
|
|
14
|
+
memhouse import claude-ai --list # the batches in your house
|
|
15
|
+
memhouse import claude-ai --undo <batch> --write # take a batch back out
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
The command needs schema 3: the profile tables (`<member>_session_parts`, `_calls`,
|
|
19
|
+
`_sessions`), or a development house's layout 3.2 tables (`<member>_turns`). A member with both is
|
|
20
|
+
written on the profile, which its readers read. It refuses any other layout before it reads or
|
|
21
|
+
writes anything.
|
|
22
|
+
|
|
23
|
+
## 1. Get an export
|
|
24
|
+
|
|
25
|
+
In claude.ai, go to Settings, then Privacy, and choose **Export data**.
|
|
26
|
+
|
|
27
|
+
The export arrives as **part zips**, one per kind: `conversations-000.zip`,
|
|
28
|
+
`design_chats-000.zip`, `memories-000.zip`, `projects-000.zip` and so on. A large export can have
|
|
29
|
+
more than one part of a kind (`conversations-001.zip`). Pass them all, or the folder that holds
|
|
30
|
+
them:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
memhouse import claude-ai ~/Downloads/*-000.zip # every part, by name
|
|
34
|
+
memhouse import claude-ai ~/Downloads/claude-export/ # a folder holding the parts
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
- **What is read.** Every `conversations` part and every `design_chats` part, in index order. The
|
|
38
|
+
other parts are listed as ignored: they hold no conversations.
|
|
39
|
+
- **A conversation in two parts** is stored once, from the first part, and counted as a duplicate.
|
|
40
|
+
- **Refused before anything is read from the house:** no `conversations` part among the inputs,
|
|
41
|
+
the same part twice (a re-downloaded `conversations-000 (1).zip`, say), or a damaged zip.
|
|
42
|
+
|
|
43
|
+
`memhouse import claude-ai` takes these forms:
|
|
44
|
+
|
|
45
|
+
| Input | What it is | `project` of a chat |
|
|
46
|
+
|---|---|---|
|
|
47
|
+
| part zips, or their folder | the export as downloaded now, read in place | `claude-ai` |
|
|
48
|
+
| one `.zip` | an older export, everything in one zip | `claude-ai` |
|
|
49
|
+
| an unpacked folder | an export unpacked: `conversations.json`, `design_chats/` | `claude-ai` |
|
|
50
|
+
| an archive folder | one JSON file per conversation: `projects/<project>/chats/`, `chats-unfiled/<year>/`, `design-chats/` | the folder name under `projects/`, or `claude-ai-unfiled` |
|
|
51
|
+
|
|
52
|
+
- **Projects come only from an archive folder.** The export does not record which claude.ai
|
|
53
|
+
project a conversation belongs to. If an archive folder files conversations by project, the
|
|
54
|
+
import uses that folder's name as `project` and the folder's path as `folder`. From zips or an
|
|
55
|
+
unpacked export, every chat gets project `claude-ai` and an empty folder.
|
|
56
|
+
- **Design chats** get project `claude-ai-design` from any of the three inputs.
|
|
57
|
+
|
|
58
|
+
## 2. Dry run
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
memhouse import claude-ai ~/Downloads/claude-export.zip
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
The dry run connects to the house, and reads it, but writes nothing. It prints counts only, no
|
|
65
|
+
titles or text:
|
|
66
|
+
|
|
67
|
+
- conversations found, by category;
|
|
68
|
+
- how many are **new**, how many are **already imported**, and how many have **changed since**
|
|
69
|
+
they were imported;
|
|
70
|
+
- how many are **empty** (no message with any text), and therefore skipped;
|
|
71
|
+
- what a `--write` would add: sessions, turns and tool calls;
|
|
72
|
+
- blocks that are never stored (empty text, token budget markers and the like), by reason.
|
|
73
|
+
|
|
74
|
+
Add `--json` to get the same as one JSON object.
|
|
75
|
+
|
|
76
|
+
## 3. Import
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
memhouse import claude-ai ~/Downloads/claude-export.zip --write
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
It writes the new conversations as one batch, reads the batch back, and checks that the counts
|
|
83
|
+
match. It prints the batch id and the command that undoes it. Batch ids look like
|
|
84
|
+
`claude-ai-2026-01-15-160405`. `--batch <id>` names one yourself, and an id the house already has
|
|
85
|
+
is refused.
|
|
86
|
+
|
|
87
|
+
Check the result:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
memhouse q coverage # a claude-ai row: sessions, span, origin import
|
|
91
|
+
memhouse q recent --harness claude-ai
|
|
92
|
+
memhouse q search <words> --harness claude-ai
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## 4. The next export
|
|
96
|
+
|
|
97
|
+
Run the same two commands on the new export. A conversation already in the house is skipped.
|
|
98
|
+
Only conversations the house has never held are written.
|
|
99
|
+
|
|
100
|
+
**Changed conversations** are listed, but not written, unless you ask:
|
|
101
|
+
|
|
102
|
+
- **How a change is detected.** A conversation counts as *changed since* in two cases:
|
|
103
|
+
- **newer:** the export's `updated_at` is later than the one stored. claude.ai moves it when a
|
|
104
|
+
chat gets a new message or a new name;
|
|
105
|
+
- **same time, other content:** `updated_at` is the same, but what the conversation says
|
|
106
|
+
differs. claude.ai can add a summary, or a later export can carry what an earlier copy lacked,
|
|
107
|
+
without moving `updated_at`. The import compares the stored rows with the export's, row by
|
|
108
|
+
row: the conversation's name, mode and start, and each message part, tool call and result.
|
|
109
|
+
It ignores what only says where and when the conversation was imported: project, folder,
|
|
110
|
+
batch, `rev`.
|
|
111
|
+
- **Older is never written.** A conversation whose `updated_at` in the export is earlier than the
|
|
112
|
+
stored one is counted as already imported, and as *older*. Its content is not compared, and
|
|
113
|
+
`--update` leaves the newer stored version in place.
|
|
114
|
+
- **`--update` replaces it whole.** Every stored row of the conversation is tombstoned, and the
|
|
115
|
+
export's version is written above them. A message that is no longer in the export is gone
|
|
116
|
+
from reads. It is not kept as a removed version, because the export you keep is the record.
|
|
117
|
+
- **The project stays.** From zips or an unpacked export, a replaced conversation keeps the
|
|
118
|
+
project the house already has, since the export carries none. From an archive folder it takes
|
|
119
|
+
the folder's.
|
|
120
|
+
- **Without `--update`** the stored version stays as it is.
|
|
121
|
+
- **A stopped `--update` hides what it was replacing.** The old rows are tombstoned before the
|
|
122
|
+
new ones are written. If the run stops in between, those conversations are missing from reads
|
|
123
|
+
until you run the same command again, which writes them above the tombstones.
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
memhouse import claude-ai ~/Downloads/claude-export-2.zip --update # dry run
|
|
127
|
+
memhouse import claude-ai ~/Downloads/claude-export-2.zip --update --write
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## 5. Batches and undo
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
memhouse import claude-ai --list
|
|
134
|
+
memhouse import claude-ai --undo claude-ai-2026-01-15-160405 # dry run: what it would remove
|
|
135
|
+
memhouse import claude-ai --undo claude-ai-2026-01-15-160405 --write
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
- **What `--list` shows.** Every batch with live sessions in the house, with its span and what
|
|
139
|
+
the house recorded about it. Each batch is recorded in the member's `meta` table under
|
|
140
|
+
`import:<batch>`:
|
|
141
|
+
- `applying`: the write started and has not finished;
|
|
142
|
+
- `applied`: the write finished;
|
|
143
|
+
- `undoing`: an undo started and has not finished (run the same `--undo ... --write` again; it
|
|
144
|
+
keeps the counts the first run found);
|
|
145
|
+
- `undone`: the undo finished.
|
|
146
|
+
- **What `--undo` writes.** A tombstone for every live row of the batch: a full copy at the next
|
|
147
|
+
`rev`, with `is_deleted = 1`. Nothing is deleted outright. Reads hide the rows at once, and the
|
|
148
|
+
shipper's maintenance removes them later.
|
|
149
|
+
- **What an undo leaves.** A conversation that a later batch replaced with `--update` belongs to
|
|
150
|
+
that later batch. Undoing the earlier batch leaves it alone. Undoing the later one removes the
|
|
151
|
+
conversation; import it again to bring it back.
|
|
152
|
+
- **Re-importing after an undo works.** A new import writes above any tombstones it finds, so
|
|
153
|
+
a conversation is never hidden behind its own undo.
|
|
154
|
+
- **A run that stops part way (profile tables).** A session whose rows went in but whose totals
|
|
155
|
+
were not filled yet (`started` empty) is listed as `repair` by the next run, and a `--write`
|
|
156
|
+
fills it, with or without anything new to import. A batch whose run stopped after all its rows
|
|
157
|
+
went in is listed as `stopped`, and that `--write` records it `applied`, whatever it writes
|
|
158
|
+
again with `--update`. A batch whose insert stopped part way stays `applying`: the sessions it
|
|
159
|
+
did not write are new to the next run, which writes them in its own batch.
|
|
160
|
+
- **One at a time per member.** Imports and undos take no lock, so run them one after another on
|
|
161
|
+
a member. Two imports at once can split a new conversation's rows between their two batches
|
|
162
|
+
(undo both and import again). An import beside an undo can record the undo's batch `applied`:
|
|
163
|
+
re-running the undo puts that right while any of its rows are still live.
|
|
164
|
+
|
|
165
|
+
## What is stored
|
|
166
|
+
|
|
167
|
+
Each conversation is one session: harness `claude-ai`, origin `import`, and the conversation's
|
|
168
|
+
uuid as its id (ref `claude-ai:<uuid>`). Its store is the service, not a machine:
|
|
169
|
+
|
|
170
|
+
- **On the profile tables:** host `s-` plus the first 32 hex of the sha256 of
|
|
171
|
+
`sessions-model/service-host/v0:claude.ai` (sessions-model's service host), `harness_path`
|
|
172
|
+
`https://claude.ai`, `host_label` `claude.ai`, adapter `memhouse-import`. A block is a part of its
|
|
173
|
+
message (`text`, `reasoning` for thinking, `tool_call`, `tool_result`; the summary is a `summary`
|
|
174
|
+
part in a system message of its own), and a tool use is also a row in `calls`.
|
|
175
|
+
- **On layout 3.2:** host and data folder `claude.ai`, and a block is a turn, as the table below
|
|
176
|
+
shows.
|
|
177
|
+
|
|
178
|
+
| From the export | Stored as |
|
|
179
|
+
|---|---|
|
|
180
|
+
| text and thinking blocks | one turn each (`text`, `thinking`) |
|
|
181
|
+
| a tool use | a `tool_call` turn, `Name(args)`, and a row in `calls` |
|
|
182
|
+
| a tool result | a `tool_result` turn with the result as text; its call gets `is_error` and `result_len` |
|
|
183
|
+
| an attachment with extracted text | an extra user `text` turn, `[attachment: <name>]` and the text |
|
|
184
|
+
| attached file names | the turn's `extra` |
|
|
185
|
+
| the conversation's summary | one `summary` turn at the time of the last message |
|
|
186
|
+
| a design chat's messages | one `text` turn each |
|
|
187
|
+
|
|
188
|
+
- **Keys are stable.** A turn's key is the message uuid plus the block's position in the
|
|
189
|
+
message, and a call's is the tool use id. When a tool use has no id, the key is
|
|
190
|
+
`<message uuid>:<position>`, and its result is the next result without an id in the same
|
|
191
|
+
message. Importing the same conversation again produces the same keys.
|
|
192
|
+
- **No tokens or models.** The export carries neither. On the profile no usage row is written. On
|
|
193
|
+
layout 3.2 they read as 0, with `usage_basis` set to
|
|
194
|
+
`none`: unmeasured, not free.
|
|
195
|
+
- **Not imported:** project documents, memories, account data and artifact files. They are not
|
|
196
|
+
conversations.
|
|
197
|
+
|
|
198
|
+
## How it fits with the rest of memhouse
|
|
199
|
+
|
|
200
|
+
- **The shipper never touches imported sessions.** It captures only the stores on your
|
|
201
|
+
machines, and a `claude.ai` session is in none of them.
|
|
202
|
+
- **`memhouse resume` refuses an imported session.** There is no local session to reopen.
|
|
203
|
+
- **A full share includes them.** A share of your whole house reaches every row of your
|
|
204
|
+
tables, so a teammate you share it with sees your imported conversations too.
|
package/docs/guides/install.md
CHANGED
|
@@ -41,8 +41,9 @@ memhouse deploy --local --tag 26.7 # another ClickHouse version
|
|
|
41
41
|
|
|
42
42
|
It runs ClickHouse in a container bound to loopback, with the data in a named volume. The
|
|
43
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).
|
|
45
|
-
|
|
44
|
+
**member** named after your OS user (the command asks; `--user` sets it). A new house is
|
|
45
|
+
schema 3: the member holds `mem.<you>_*`, its tables in the house, and `SELECT, INSERT` on its two
|
|
46
|
+
capture tables in `mem_archive`. Both credentials go into `~/.memhouse/env`, mode 600, so that
|
|
46
47
|
inviting someone later needs no flags. It then installs and ships.
|
|
47
48
|
|
|
48
49
|
The user name and password are fixed when the volume is first initialised and reused on
|
|
@@ -81,7 +82,7 @@ Useful flags:
|
|
|
81
82
|
| `--claude-roots DIR[,DIR]` | ship only these Claude Code config directories |
|
|
82
83
|
| `--channel team` | follow this npm dist-tag on `update` |
|
|
83
84
|
| `--keep-admin` | keep the admin credential in the env file (not done by default) |
|
|
84
|
-
| `--
|
|
85
|
+
| `--schema 2` / `--schema 3` | for a member not yet in the house: which layout its tables take. A house holding members on both (mid-upgrade) needs it; otherwise the install follows the house |
|
|
85
86
|
|
|
86
87
|
The admin password never needs to be on the command line. See
|
|
87
88
|
[Admin password](admin-password.md).
|
|
@@ -93,7 +94,7 @@ what an invite install ships, pass `--editors` / `--claude-roots` as flags.
|
|
|
93
94
|
### What install checks
|
|
94
95
|
|
|
95
96
|
Before it writes any config, install connects, confirms who the credential is, and checks
|
|
96
|
-
that it can reach its
|
|
97
|
+
that it can reach its tables. The config is written last, so a refused install leaves no
|
|
97
98
|
half-configured machine behind.
|
|
98
99
|
|
|
99
100
|
Configuration resolves in this order: flags, then exported `MEMHOUSE_*` variables, then
|
|
@@ -124,5 +125,9 @@ The path proves nothing on its own: Homebrew's prefix is `/usr/local` on Intel a
|
|
|
124
125
|
|
|
125
126
|
- `memhouse status`: connection, counts, freshness.
|
|
126
127
|
- `memhouse start` or `memhouse service install`: keep shipping. See [Daemons](daemons.md).
|
|
127
|
-
- `memhouse plugins install claude`: the `/mem:*` skills.
|
|
128
|
-
|
|
128
|
+
- `memhouse plugins install claude`: the `/mem:*` skills, for Claude Code only. Codex and the
|
|
129
|
+
other editors' sessions ship all the same; an agent there reads the house with the CLI
|
|
130
|
+
(`memhouse q`, `memhouse room-sql`). See [Search, resume and skills](search-and-resume.md).
|
|
131
|
+
- `memhouse plugins install codex`: for Codex, a short block in its `AGENTS.md` (the rules) and
|
|
132
|
+
a `memhouse` skill (the read recipes). Nothing is written under the Codex home unless you run
|
|
133
|
+
it. See [Codex](search-and-resume.md#codex).
|
package/docs/guides/invite.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Invite members
|
|
2
2
|
|
|
3
|
-
Inviting creates a ClickHouse user and their
|
|
3
|
+
Inviting creates a ClickHouse user and their tables, and writes one file the invitee
|
|
4
4
|
installs from. It needs a credential that can create users, which means the server's
|
|
5
5
|
admin.
|
|
6
6
|
|
|
@@ -13,15 +13,27 @@ memhouse invite alice --url https://house.example.com
|
|
|
13
13
|
loopback: `localhost` on their machine is their machine. Use a LAN address, a hostname
|
|
14
14
|
or a tunnel. `--allow-local` overrides this, for the case where the invitee is on the
|
|
15
15
|
same machine.
|
|
16
|
-
- **The
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
- **The tables are named for them:** `mem.alice_session_parts`, `mem.alice_sessions` and four
|
|
17
|
+
more conversation tables, and her capture archive `mem_archive.alice_session_units` and `_session_sources`.
|
|
18
|
+
Alice is granted `mem.alice_*` and her two archive tables, nothing else. A different
|
|
19
|
+
database: `--db <name>`.
|
|
20
|
+
- **The house decides the layout,** as it does for an install: a new house is schema 3, a
|
|
21
|
+
house still on the 0.18 rooms gets rooms (`mem.alice_messages`, …), and a house with
|
|
22
|
+
members on both is refused until `--schema 3` or `--schema 2` says which.
|
|
19
23
|
- **The file is a credential.** It holds the house URL, alice's user name, a generated
|
|
20
24
|
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.
|
|
25
|
+
Not chat or email. `--out <path>` writes it somewhere else. The invitation page,
|
|
26
|
+
`MEMHOUSE-INVITATION.md`, is written beside it and names that file and the invitee's tables.
|
|
22
27
|
- **Alice installs with `memhouse install --env invite-alice.env`.** It offers to rotate
|
|
23
28
|
the password to one only she knows, which works because she is granted `ALTER USER` on
|
|
24
29
|
herself. Then it deletes the file. Once she rotates, the password you saw stops working.
|
|
30
|
+
- **The invite expires.** The password in the file stops working 7 days after the invite
|
|
31
|
+
(`--expires <days>` sets 1 to 365), counted by the server's clock. The output, the file and
|
|
32
|
+
the invitation page say when. Installing lifts the expiry, whether she changes the password
|
|
33
|
+
or keeps it with `--keep-password`. After the date, `install` refuses the file and tells her
|
|
34
|
+
to ask for a new invite. Her account is still there, so remove it first (`DROP USER alice`, as
|
|
35
|
+
the administrator; `invite` says so when it meets it), then invite her again. Her tables are
|
|
36
|
+
kept and reused.
|
|
25
37
|
|
|
26
38
|
## Which admin credential
|
|
27
39
|
|
|
@@ -83,5 +95,7 @@ memhouse members --db other # another database
|
|
|
83
95
|
## Removing a member
|
|
84
96
|
|
|
85
97
|
There is no `memhouse` verb for it yet. With the admin credential, `DROP USER <name>`
|
|
86
|
-
stops every machine shipping as them. Their
|
|
87
|
-
[Operate a house](operate.md)
|
|
98
|
+
stops every machine shipping as them. Their shares and tables stay until you remove them too,
|
|
99
|
+
in `mem` and in `mem_archive`, shares first: [Operate a house](operate.md#removing-a-member) has
|
|
100
|
+
the order and lists the tables by exact name. Read it before you drop anything: there is no
|
|
101
|
+
undo.
|