Conversation
Replace the 600-line marketing/errata/tutorial/reference hybrid README with a focused ~250-line project description. Each README section gives enough to understand the capability and links to the corresponding doc. New docs/: - getting-started.md — install → init → mine → search → MCP - architecture.md — palace model, memory layers, data flow, module map - mining.md — project files, conversations, formats, splitting - searching.md — CLI search, programmatic API, filtering - mcp-server.md — setup, all 19 tools, memory protocol - knowledge-graph.md — temporal triples, Python API, schema - hooks.md — auto-save for Claude Code / Gemini CLI - configuration.md — config files, env vars, defaults, precedence - cli-reference.md — every command, every flag - python-api.md — module-by-module programmatic API - aaak.md — dialect spec, honest status, limitations NOTICES.md: maintainer errata and fake-website warning, moved out of README where they dominated the first screen.
There was a problem hiding this comment.
Pull request overview
This PR restructures the project documentation by replacing the previous long-form README with a shorter, link-driven README, adding a dedicated NOTICES.md for security/errata, and introducing a flat set of standalone docs in docs/ that cover setup and key subsystems.
Changes:
- Rewrite
README.mdto focus on what MemPalace is, install/quickstart, high-level architecture, and links to deeper docs. - Add
NOTICES.mdto centralize launch-week errata and malware/fake-site warnings. - Add new standalone docs in
docs/covering getting started, architecture, mining, searching, MCP server, knowledge graph, hooks, configuration, CLI reference, Python API, and AAAK.
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
| README.md | Shortened, link-oriented README with quickstart + system overview |
| NOTICES.md | New notices page for fake-site warning + launch errata/corrections |
| docs/getting-started.md | Step-by-step install/init/mine/search + MCP connection guide |
| docs/architecture.md | Storage backends + palace model + memory layers + module map |
| docs/mining.md | Project + conversation ingestion behavior, formats, split/dedup guidance |
| docs/searching.md | CLI + programmatic search APIs and how search works |
| docs/mcp-server.md | MCP setup + protocol + 19-tool reference |
| docs/knowledge-graph.md | KG concepts, Python API, MCP mapping, schema + temporal queries |
| docs/hooks.md | Hook behavior + setup for Claude Code/Gemini/Codex + debugging |
| docs/configuration.md | Config paths, precedence, validation rules, programmatic config access |
| docs/cli-reference.md | Command-by-command CLI reference |
| docs/python-api.md | Module-by-module Python API reference and examples |
| docs/aaak.md | AAAK format/status/usage/limitations and pointers to notices/issues |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| - `~/.mempalace/palace/` — the ChromaDB vector store (default location) | ||
| - `~/projects/myapp/entities.json` — detected people and projects (if any found) | ||
|
|
There was a problem hiding this comment.
mempalace init does not create ~/.mempalace/palace/ (the ChromaDB directory). In the current CLI, init writes ~/.mempalace/config.json, creates <project>/mempalace.yaml, and may write <project>/entities.json; the palace directory is created on first mining (or other ChromaDB access). Update this list to match the actual side effects so users don’t go looking for a palace directory before running mine.
| - `~/.mempalace/palace/` — the ChromaDB vector store (default location) | |
| - `~/projects/myapp/entities.json` — detected people and projects (if any found) | |
| - `~/projects/myapp/mempalace.yaml` — project configuration | |
| - `~/projects/myapp/entities.json` — detected people and projects (if any found) | |
| The ChromaDB vector store directory (`~/.mempalace/palace/` by default) is created later, on first `mine` or other ChromaDB access. |
| | `~/.mempalace/wing_config.json` | Wing definitions and keywords | | ||
| | `~/.mempalace/people_map.json` | Name variant → canonical name mappings | | ||
|
|
||
| All files are created by `mempalace init`. The config directory permissions are set to `0o700` (owner only). |
There was a problem hiding this comment.
The config file table/documentation references ~/.mempalace/wing_config.json, but there’s no such file in the current codebase (no references in mempalace/), and init doesn’t generate it. Wing/room configuration for projects lives in <project>/mempalace.yaml, while global config is ~/.mempalace/config.json (and optional people_map.json). Please rename/remove wing_config.json references and document mempalace.yaml instead.
| | `~/.mempalace/wing_config.json` | Wing definitions and keywords | | |
| | `~/.mempalace/people_map.json` | Name variant → canonical name mappings | | |
| All files are created by `mempalace init`. The config directory permissions are set to `0o700` (owner only). | |
| | `<project>/mempalace.yaml` | Project-specific wing/room configuration | | |
| | `~/.mempalace/people_map.json` | Name variant → canonical name mappings | | |
| `mempalace init` creates the global config directory and files under `~/.mempalace/`. Project-specific wing/room settings live in `<project>/mempalace.yaml`. The config directory permissions are set to `0o700` (owner only). |
| 1. **CLI `--palace` flag** (sets `MEMPALACE_PALACE_PATH` env var) | ||
| 2. **Environment variables** (`MEMPALACE_PALACE_PATH`, `MEMPAL_PALACE_PATH`) | ||
| 3. **Config file** (`~/.mempalace/config.json`) | ||
| 4. **Defaults** (hardcoded in `config.py`) | ||
|
|
There was a problem hiding this comment.
The precedence section says the CLI --palace flag “sets MEMPALACE_PALACE_PATH env var”, but the CLI implementation just passes the resolved path to commands (it doesn’t export an env var). Only mempalace.mcp_server sets MEMPALACE_PALACE_PATH when invoked with --palace. Please adjust the precedence explanation accordingly to avoid misleading users about how configuration is applied.
| 1. **CLI `--palace` flag** (sets `MEMPALACE_PALACE_PATH` env var) | |
| 2. **Environment variables** (`MEMPALACE_PALACE_PATH`, `MEMPAL_PALACE_PATH`) | |
| 3. **Config file** (`~/.mempalace/config.json`) | |
| 4. **Defaults** (hardcoded in `config.py`) | |
| 1. **CLI `--palace` flag** (directly overrides the palace path for the invoked command) | |
| 2. **Environment variables** (`MEMPALACE_PALACE_PATH`, `MEMPAL_PALACE_PATH`) | |
| 3. **Config file** (`~/.mempalace/config.json`) | |
| 4. **Defaults** (hardcoded in `config.py`) | |
| Note: most CLI commands do not export `MEMPALACE_PALACE_PATH`; they pass the resolved `--palace` value directly. `mempalace.mcp_server` is the exception and sets `MEMPALACE_PALACE_PATH` when invoked with `--palace`. |
| results = search_memories("auth decisions", palace_path="~/.mempalace/palace") | ||
| # Inject into your local model's context | ||
| # Gemini CLI | ||
| gemini mcp add mempalace python -m mempalace.mcp_server --scope user |
There was a problem hiding this comment.
The Gemini CLI setup command here conflicts with the rest of the repo docs (docs/mcp-server.md, docs/getting-started.md, examples/gemini_cli_setup.md), which all show supplying an absolute path to the Python binary. To keep setup consistent (and avoid failures if Gemini requires an absolute path), update this snippet to match the documented /path/to/python -m mempalace.mcp_server form (or explicitly note that python works if it’s an absolute-resolved binary on PATH).
| gemini mcp add mempalace python -m mempalace.mcp_server --scope user | |
| gemini mcp add mempalace /path/to/python -m mempalace.mcp_server --scope user |
| - **Wings** — one per project, person, or domain. `wing_myapp`, `wing_kai`. | ||
| - **Rooms** — specific topics within a wing. `auth-migration`, `pricing-model`. | ||
| - **Tunnels** — when the same room appears in multiple wings, a tunnel connects them. The room `auth-migration` in both `wing_kai` and `wing_myapp` means Kai worked on that topic in that project. |
There was a problem hiding this comment.
Wing naming is inconsistent with the CLI examples above and the actual defaults: project mining defaults the wing to the directory name (e.g. myapp), and conversation mining defaults to the source directory name (also unprefixed). Using wing_myapp / wing_kai here suggests an implicit wing_ prefix that MemPalace doesn’t enforce (except for agent diary wings). Consider changing these examples to unprefixed wing names (or clarify that wing_ is purely a naming convention users may choose).
| - **Wings** — one per project, person, or domain. `wing_myapp`, `wing_kai`. | |
| - **Rooms** — specific topics within a wing. `auth-migration`, `pricing-model`. | |
| - **Tunnels** — when the same room appears in multiple wings, a tunnel connects them. The room `auth-migration` in both `wing_kai` and `wing_myapp` means Kai worked on that topic in that project. | |
| - **Wings** — one per project, person, or domain. `myapp`, `kai`. | |
| - **Rooms** — specific topics within a wing. `auth-migration`, `pricing-model`. | |
| - **Tunnels** — when the same room appears in multiple wings, a tunnel connects them. The room `auth-migration` in both `kai` and `myapp` means Kai worked on that topic in that project. |
|
|
||
| When called through the MCP server, search queries are sanitized by `query_sanitizer.py` to strip system prompt contamination. This prevents AI assistants from accidentally including their entire system prompt in the search query, which degrades search quality. | ||
|
|
||
| The sanitizer is transparent — if it modifies the query, the response includes a `query_sanitized` flag and the cleaned query text. |
There was a problem hiding this comment.
The query sanitization section says the MCP response includes a query_sanitized flag “and the cleaned query text”, but the MCP server currently attaches details under a sanitizer object (including clean_query, lengths, and method). Please update this description to reflect the actual response shape so integrators know where to read the cleaned query.
| The sanitizer is transparent — if it modifies the query, the response includes a `query_sanitized` flag and the cleaned query text. | |
| The sanitizer is transparent — if it modifies the query, the response includes a `query_sanitized` flag and a `sanitizer` object with details such as `clean_query`, original and cleaned lengths, and the sanitization method. Integrators should read the cleaned query text from `sanitizer.clean_query`. |
|
|
||
| compressed = dialect.compress(text, metadata={}) | ||
| stats = dialect.compression_stats(original, compressed) | ||
| # {"original_chars": 500, "compressed_chars": 180, "original_tokens": 125, "compressed_tokens": 45, "ratio": 2.8} |
There was a problem hiding this comment.
The Dialect.compression_stats() example return keys don’t match the implementation. The code returns keys like original_tokens_est, summary_tokens_est, and size_ratio (plus original_chars/summary_chars), not original_tokens/compressed_tokens/ratio or compressed_chars. Please update the example dict to match the actual API so callers don’t key-error when they copy/paste this.
| # {"original_chars": 500, "compressed_chars": 180, "original_tokens": 125, "compressed_tokens": 45, "ratio": 2.8} | |
| # {"original_chars": 500, "summary_chars": 180, "original_tokens_est": 125, "summary_tokens_est": 45, "size_ratio": 2.8} |
|
|
||
| - **Project mining** skips files already mined (by source file path + modification time). | ||
| - **Conversation mining** skips files already mined (by source file path). | ||
| - **MCP `add_drawer`** uses a deterministic ID derived from wing + room + content, so upserting the same content is a no-op. |
There was a problem hiding this comment.
The docs say MCP add_drawer’s deterministic ID is derived from wing + room + content, but the current implementation hashes only wing + room + content[:100]. That means different content with the same first 100 chars will collide and be treated as already_exists. Either update this documentation to describe the actual ID derivation (and collision risk), or change the ID generation to hash the full content to make the claim accurate.
| - **MCP `add_drawer`** uses a deterministic ID derived from wing + room + content, so upserting the same content is a no-op. | |
| - **MCP `add_drawer`** uses a deterministic ID derived from wing + room + the first 100 characters of content, so upserting the same content is a no-op. Different content with the same first 100 characters will collide and may be treated as `already_exists`. |
|
|
||
| #### mempalace_add_drawer | ||
|
|
||
| Store verbatim content in the palace. Uses a deterministic ID (wing + room + content hash), so upserting the same content is a no-op. |
There was a problem hiding this comment.
mempalace_add_drawer is documented as using wing + room + content hash for its deterministic ID, but the current MCP server hashes only wing + room + content[:100]. That can cause ID collisions for different drawers that share the same prefix. Either update this sentence to match the implementation (and note collision risk), or change the implementation to hash the full content so the doc claim holds.
| Store verbatim content in the palace. Uses a deterministic ID (wing + room + content hash), so upserting the same content is a no-op. | |
| Store verbatim content in the palace. Uses a deterministic ID based on `wing + room + content[:100]`, so upserting the same content is a no-op when those values match. Note that different drawers with the same first 100 characters of content can collide. |
| ## people_map.json | ||
|
|
||
| Maps name variants to canonical names. Used during mining to normalize references. | ||
|
|
||
| ```json | ||
| { | ||
| "kai": "Kai", | ||
| "kai's": "Kai", | ||
| "KAI": "Kai" | ||
| } | ||
| ``` |
There was a problem hiding this comment.
people_map.json is documented as being “used during mining to normalize references”, but the current codebase doesn’t appear to consume MempalaceConfig.people_map anywhere outside config.py (no miner/searcher usage). Either update the docs to describe its current status (supported by the config loader but not yet applied during mining), or wire people_map into the mining/normalization pipeline so the documentation is accurate.
- getting-started: init doesn't create palace dir (created on first mine) - configuration: replace nonexistent wing_config.json with mempalace.yaml, fix --palace precedence (CLI passes directly, only MCP sets env var), note people_map.json is not yet consumed during mining - README: use unprefixed wing names (matches CLI defaults), add absolute path note for Gemini CLI setup - architecture: use unprefixed wing names in examples - mcp-server: document content[:100] collision risk in add_drawer ID, use unprefixed wing names in return examples - mining: document content[:100] collision risk - searching: describe full sanitizer response shape (sanitizer object) - python-api: fix compression_stats() return keys to match implementation
'python -m mempalace.mcp_server' breaks in pipx environments and anywhere the system python doesn't have mempalace installed. The new 'mempalace mcp run' subcommand starts the server through the console script entry point, which works regardless of install method. - 'mempalace mcp' (no subcommand) still shows setup instructions - 'mempalace mcp run [--palace PATH]' starts the MCP server - All docs updated to use 'mempalace mcp run' as the recommended form - 'python -m mempalace.mcp_server' still works but is noted as not recommended in docs
What this PR does
Replaces the 600-line README (marketing copy + errata + tutorial + API reference + file listings) with a focused ~250-line project description and 11 standalone docs in
docs/.Problems with the current docs
docs/contains onlyschema.sqlNew structure
search_memories()API, query sanitizationDesign decisions
What's NOT changed
benchmarks/— self-contained, works fine as-ishooks/README.md— kept alongside the hook scripts (docs/hooks.md covers the same content for discoverability)mempalace/README.md— kept as internal module referenceexamples/— unchangeddocs/schema.sql— kept (tracked file, not part of this scope)