@cerefox/memory 0.9.2 → 0.9.3

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/AGENT_GUIDE.md CHANGED
@@ -359,7 +359,7 @@ If you're using Cerefox via the local CLI (Path C from `connect-agents.md`), the
359
359
  ## Governance
360
360
 
361
361
  - **Review status**: agent writes set `pending_review`; human edits set `approved`. Both are searchable.
362
- - **Soft delete**: deleted documents go to trash (recoverable). They are excluded from search. You can soft-delete via MCP (`cerefox_delete_document` if your client exposes it) or CLI (`cerefox document delete --yes --author <you> --author-type agent`).
362
+ - **Soft delete**: deleted documents go to trash (recoverable). They are excluded from search. There is no delete MCP tool soft-delete is done via the CLI (`cerefox document delete --yes --author <you> --author-type agent`) or the web UI.
363
363
  - **Permanent purge and restore-from-trash are web-UI-only**, by design. If you decide to delete something, **tell the user explicitly** that you soft-deleted it and that they can review or restore it via the Cerefox web UI. You cannot un-do your own soft-delete from agent code; only the human can. See [`docs/guides/access-paths.md` → Destructive operations and the trust model](docs/guides/access-paths.md#destructive-operations-and-the-trust-model).
364
364
  - **Versioning**: every update via `update_if_exists` creates an archived version. Old content is always recoverable.
365
365
  - **Audit log**: all write operations are recorded with author, timestamp, and size changes.
@@ -378,7 +378,7 @@ The Cerefox CLI is the TypeScript binary from `@cerefox/memory` (`npm install -g
378
378
 
379
379
  The legacy Python `uv run cerefox` is a frozen husk as of v0.9 — only `uv run cerefox mcp` (the standalone Python MCP fallback) still works; every other verb has moved to the TypeScript `cerefox` binary.
380
380
 
381
- > Full per-flag reference lives in [`docs/guides/cli.md`](docs/guides/cli.md). The mapping table below is the agent-facing summary. **CLI flag names match MCP parameter names exactly** (kebab-case); short forms like `--project`, `--filter`, `--count`, `--update`, `--version` are accepted as aliases.
381
+ > Full per-flag reference lives in [`docs/guides/cli.md`](docs/guides/cli.md). The mapping table below is the agent-facing summary. **CLI flag names match MCP parameter names exactly** (kebab-case), each with a single-letter short form (`-p`, `-f`, `-c`, `-m`, `-u`, `-a`, `-r`). Use the canonical long name or its short form — there are no long-form aliases like `--project` or `--count`.
382
382
 
383
383
  ### MCP tool ↔ CLI command mapping
384
384
 
@@ -407,7 +407,7 @@ Alternative: have your user set `CEREFOX_AUTHOR_NAME`, `CEREFOX_AUTHOR_TYPE`, `C
407
407
 
408
408
  ### Behavioural differences worth knowing
409
409
 
410
- 1. **CLI output is human-formatted by default.** `cerefox search` returns a numbered, indented text block with title, score, and a 300-char preview per result. To extract document IDs reliably, parse the `Doc: <title> (<source>)` lines or fall back to `cerefox document list` for a clean tabular listing. `cerefox document get <id>` prints raw Markdown to stdout. **For scripted access to audit data**, use `cerefox audit list --json` one JSON object per line, ideal for piping to `jq`.
410
+ 1. **CLI output is human-formatted by default.** In the default `docs` mode, `cerefox search` prints, per match, a header line `## <title> [id: <uuid>] · score · N chunks · M chars · partial|full` followed by the document body. Grab the document ID from the `[id: <uuid>]` tag, or use `cerefox document list` for a clean tabular listing. For structured output, `cerefox search --json` and `cerefox audit list --json` emit machine-readable JSON (the latter one object per line, ideal for `jq`). `cerefox document get <id>` prints raw Markdown to stdout.
411
411
 
412
412
  2. **Every invocation is independent.** With MCP, your tool framework can pass `requestor` once per session. With the CLI, every command is a separate process — pass `--requestor` / `--author` / `--author-type` on every relevant invocation, or set the env-var defaults once at the start.
413
413
 
@@ -53,7 +53,7 @@ metadata_search(metadata_filter={"type": "decision-log"}, updated_since="2026-03
53
53
 
54
54
  If `cerefox_search` is not in your tool list, your user has likely installed the Cerefox CLI. The canonical invocation is plain **`cerefox <subcommand>`** (the TypeScript CLI, installed via `npm install -g @cerefox/memory`). It uses a resource-verb shape (`cerefox document get`, `cerefox project list`, …). The legacy Python `uv run cerefox` is now a frozen husk as of v0.9 — only `uv run cerefox mcp` still works.
55
55
 
56
- Same operations, same conventions. Full reference: [`docs/guides/cli.md`](docs/guides/cli.md). CLI flag names match MCP parameter names exactly (e.g. `metadata_filter` ↔ `--metadata-filter`); short forms (`--filter`, `--project`, `--count`, `--update`, `--version`) work as aliases.
56
+ Same operations, same conventions. Full reference: [`docs/guides/cli.md`](docs/guides/cli.md). CLI flag names match MCP parameter names exactly (e.g. `metadata_filter` ↔ `--metadata-filter`); common flags also have single-letter short forms (`-f`, `-p`, `-c`, `-m`, `-u`, `-a`, `-r`). Use the canonical long name (what `--help` shows) or its short form — there are no long-form aliases like `--filter` or `--count`.
57
57
 
58
58
  | MCP tool | CLI |
59
59
  |---|---|
package/README.md CHANGED
@@ -9,7 +9,7 @@ curated knowledge layer that multiple AI tools can read and write.
9
9
  > Supabase project** (Postgres + pgvector; free tier works). Installing this
10
10
  > npm package does **not** give you a working KB on its own; you also need a
11
11
  > Supabase project + an embedding API key, and a one-time server-side deploy
12
- > from the source repo. **See "Before you install" below.**
12
+ > (`cerefox server deploy` — no repo clone needed). **See "Before you install" below.**
13
13
 
14
14
  **Why cloud-backed?** Cerefox is designed as a *cloud-backed* memory layer so
15
15
  the same knowledge is reachable from every agent you run — Claude Code on
@@ -45,7 +45,7 @@ Cerefox is a self-hosted memory layer with two halves you set up independently:
45
45
  **Client side** (this npm package, runs on your machine):
46
46
  - `cerefox` CLI + `cerefox mcp` (local stdio MCP) + `cerefox web` (local UI at `http://localhost:8000`)
47
47
 
48
- The server side ships with the source repo, not this npm package. Both halves are required for a working install.
48
+ You deploy the server side with this package's CLI — `cerefox server deploy` stands up the schema, RPCs, and all 9 Edge Functions from bundled assets (no repo clone). Both halves are required for a working install.
49
49
 
50
50
  ### What you need
51
51
 
@@ -55,23 +55,20 @@ The server side ships with the source repo, not this npm package. Both halves ar
55
55
  | An **embedding API key** | OpenAI `text-embedding-3-small` (default) or Fireworks AI. Pennies/month for typical personal use (see [operational-cost.md](https://github.com/fstamatelopoulos/cerefox/blob/main/docs/guides/operational-cost.md)). | Get an [OpenAI API key](https://platform.openai.com/api-keys). |
56
56
  | **Node ≥ 20** or **Bun ≥ 1.0** | Runtime for the `cerefox` bin (and the bundled `cerefox mcp` server). | [nodejs.org](https://nodejs.org) · [bun.sh](https://bun.sh). The one-line installer below bootstraps Bun if neither is present. |
57
57
 
58
- ### One-time server-side setup (~10 min — clone required)
58
+ ### One-time server-side setup (~10 min — no clone needed)
59
59
 
60
- The schema, RPCs, and Edge Functions ship with the source repo, not this npm package. Clone once, configure, deploy:
60
+ The CLI stands up the whole server side schema, RPCs, and all 9 Edge
61
+ Functions — from bundled assets:
61
62
 
62
63
  ```bash
63
- git clone https://github.com/fstamatelopoulos/cerefox.git
64
- cd cerefox && cp .env.example .env # fill in CEREFOX_SUPABASE_* + OPENAI_API_KEY + CEREFOX_DATABASE_URL
65
- bun install # workspace deps for the deploy scripts
66
- bun scripts/db_deploy.ts # creates tables, indexes, RPCs in your Supabase
67
- npx supabase functions deploy cerefox-mcp cerefox-search cerefox-ingest \
68
- cerefox-metadata cerefox-get-document \
69
- cerefox-list-versions cerefox-get-audit-log \
70
- cerefox-metadata-search cerefox-list-projects
71
- npx supabase secrets set OPENAI_API_KEY=sk-...
64
+ cerefox init # enter your Supabase URL/keys + embedding key
65
+ cerefox server deploy # schema + RPCs + Edge Functions
72
66
  ```
73
67
 
74
- Full walkthrough (connection-pooling quirks, Supabase API-key flavors, troubleshooting): [setup-supabase.md](https://github.com/fstamatelopoulos/cerefox/blob/main/docs/guides/setup-supabase.md).
68
+ Details (Supabase login/linking, connection-pooling quirks, API-key flavors,
69
+ troubleshooting, and the contributor clone-and-deploy path) live in the
70
+ [quickstart](https://github.com/fstamatelopoulos/cerefox/blob/main/docs/guides/quickstart.md)
71
+ and [setup-supabase.md](https://github.com/fstamatelopoulos/cerefox/blob/main/docs/guides/setup-supabase.md).
75
72
 
76
73
  If you don't yet have Supabase + an OpenAI key, the [Cerefox
77
74
  quickstart](https://github.com/fstamatelopoulos/cerefox/blob/main/docs/guides/quickstart.md)
@@ -113,7 +110,7 @@ already provisioned (see "Before you install").
113
110
  > **Already ran the server-side setup above?** Then your schema is in place and
114
111
  > `cerefox init` only needs the URL + keys. If you skipped that step,
115
112
  > `cerefox doctor` will flag it and point you back to
116
- > `bun scripts/db_deploy.ts` from a repo clone.
113
+ > `cerefox server deploy`.
117
114
 
118
115
  > **Upgrading from the Python `cerefox` CLI?** If you have a working
119
116
  > `.env` in your repo clone, init detects it and offers to **copy** it to
@@ -160,17 +157,18 @@ the 10 MCP tools (`cerefox_search`, `cerefox_ingest`, `cerefox_get_document`,
160
157
  ## Common commands
161
158
 
162
159
  ```bash
163
- cerefox search "second brain" # hybrid (FTS + semantic)
164
- cerefox ingest notes.md --project "Personal" # add a doc
165
- cerefox list-projects # discover projects
166
- cerefox metadata-search --metadata-filter '{"type":"decision-log"}'
167
- cerefox get-audit-log --since 2026-05-01 # immutable history
168
- cerefox doctor # diagnose your install
169
- cerefox upgrade # alias for self-update
160
+ cerefox search "second brain" # hybrid (FTS + semantic)
161
+ cerefox document ingest notes.md --project "Personal" # add a doc
162
+ cerefox project list # discover projects
163
+ cerefox metadata search --metadata-filter '{"type":"decision-log"}'
164
+ cerefox audit list --since 2026-05-01 # immutable history
165
+ cerefox doctor # diagnose your install
166
+ cerefox upgrade # alias for self-update
170
167
  ```
171
168
 
172
- Run `cerefox --help` for the full command surface (28 subcommands grouped
173
- by category).
169
+ Run `cerefox --help` for the full command surface a resource-verb shape
170
+ (`document …`, `project …`, `metadata …`, `server …`) plus flat commands
171
+ like `search` and the lifecycle verbs.
174
172
 
175
173
  ---
176
174
 
@@ -181,8 +179,8 @@ MCP client) gives your AI agent full access to the knowledge base on
181
179
  its own. The rest of the `cerefox` CLI is useful for:
182
180
 
183
181
  - **One-off shell operations**: search, ingest, list, audit-log.
184
- - **Power-user workflows**: `cerefox ingest-dir ./meeting-notes`,
185
- `cerefox metadata-search --metadata-filter …`, `cerefox backup`.
182
+ - **Power-user workflows**: `cerefox document ingest-dir ./meeting-notes`,
183
+ `cerefox metadata search --metadata-filter …`, `cerefox backup create`.
186
184
  - **Setup + diagnostics**: `cerefox init`, `cerefox doctor`,
187
185
  `cerefox configure-agent`, `cerefox self-update`.
188
186
  - **Agents via local Bash tool**: some coding agents prefer running
@@ -196,7 +194,7 @@ its own. The rest of the `cerefox` CLI is useful for:
196
194
  - **Architecture overview**: [`CLAUDE.md`](https://github.com/fstamatelopoulos/cerefox/blob/main/CLAUDE.md)
197
195
  - **Setup guides**: [`docs/guides/`](https://github.com/fstamatelopoulos/cerefox/tree/main/docs/guides)
198
196
  - **Migration from v0.4.x**: [`docs/guides/migration-v0.5.md`](https://github.com/fstamatelopoulos/cerefox/blob/main/docs/guides/migration-v0.5.md)
199
- - **For AI agents using Cerefox**: [`AGENT_GUIDE.md`](https://github.com/fstamatelopoulos/cerefox/blob/main/AGENT_GUIDE.md), [`AGENT_QUICK_REFERENCE.md`](https://github.com/fstamatelopoulos/cerefox/blob/main/AGENT_QUICK_REFERENCE.md), or run `cerefox docs --list`.
197
+ - **For AI agents using Cerefox**: [`AGENT_GUIDE.md`](https://github.com/fstamatelopoulos/cerefox/blob/main/AGENT_GUIDE.md), [`AGENT_QUICK_REFERENCE.md`](https://github.com/fstamatelopoulos/cerefox/blob/main/AGENT_QUICK_REFERENCE.md), or run `cerefox guides list`.
200
198
  - **Changelog**: [`CHANGELOG.md`](https://github.com/fstamatelopoulos/cerefox/blob/main/CHANGELOG.md)
201
199
 
202
200
  ---
@@ -7184,7 +7184,7 @@ var exports_meta = {};
7184
7184
  __export(exports_meta, {
7185
7185
  PKG_VERSION: () => PKG_VERSION
7186
7186
  });
7187
- var PKG_VERSION = "0.9.2";
7187
+ var PKG_VERSION = "0.9.3";
7188
7188
  var init_meta = () => {};
7189
7189
 
7190
7190
  // ../../node_modules/.bun/tslib@2.8.1/node_modules/tslib/tslib.js
@@ -25748,7 +25748,7 @@ var init_get_document = __esm(() => {
25748
25748
  });
25749
25749
 
25750
25750
  // ../../_shared/mcp-tools/get-help-content.ts
25751
- var HELP_FULL = '# Cerefox Knowledge Base -- Agent Quick Reference\n\nCerefox is a persistent, shared knowledge base. You have **10 MCP tools** (9 of them have CLI equivalents — `cerefox_get_help` is MCP-only). For the full guide, search Cerefox for "How AI Agents Use Cerefox" or call `cerefox_get_help` to retrieve this content over MCP.\n\n## Tools\n\n| Tool | Purpose | Key params |\n|------|---------|------------|\n| `cerefox_search` | Find documents (hybrid FTS + semantic) | `query` (required), `project_name`, `metadata_filter`, `requestor` |\n| `cerefox_ingest` | Save or update a document | `title`, `content` (required), `document_id` (update by ID), `update_if_exists`, `project_name` (single, non-destructive add on update), `project_names` (list, destructive replace on update), `metadata`, `author` |\n| `cerefox_get_document` | Get full document by ID | `document_id` (required) |\n| `cerefox_list_versions` | Version history of a document | `document_id` (required) |\n| `cerefox_metadata_search` | Find docs by metadata (no text query) | `metadata_filter` (required), `include_content`, `updated_since` |\n| `cerefox_list_metadata_keys` | Discover available metadata keys | (none required) |\n| `cerefox_list_projects` | List all projects | (none required) |\n| `cerefox_set_document_projects` | Set doc\'s project memberships to exactly the given list (destructive replace; metadata-only, no content change) | `document_id`, `project_names` (required) |\n| `cerefox_get_audit_log` | Query write operation history | `document_id`, `author`, `operation`, `since` |\n| `cerefox_get_help` | Retrieve Cerefox conventions (this reference) over MCP. **Call this whenever uncertain.** | `topic` (optional, case-insensitive H2 substring match) |\n\n## Essential Rules\n\n1. **Search before ingesting** -- check if the document exists first.\n2. **Prefer ID-based updates** -- pass `document_id` from search results for deterministic updates. Falls back to title-matching with `update_if_exists: true`.\n3. **Set `author`/`requestor`** to your name on every call (e.g., "Claude Code", "archiver"). On MCP, pass as parameters. On CLI, pass `--author`/`--author-type`/`--requestor` flags, or rely on `CEREFOX_AUTHOR_NAME`/`CEREFOX_AUTHOR_TYPE`/`CEREFOX_REQUESTOR_NAME` env vars set in the user\'s `.env`.\n4. **Use `document_id` from search results** `[id: uuid]` for get_document and list_versions.\n5. **Add metadata** -- at minimum `type` ("decision-log", "research", "design-doc") and `status` ("active", "draft").\n6. **Write structured Markdown** with H1/H2/H3 headings for good chunking and search.\n7. **Deletes are soft (recoverable); purge is web-UI-only.** If you decide to delete, surface it to the user (`I soft-deleted X — recoverable from the Cerefox web UI trash`). You cannot un-do your own delete from agent code by design.\n8. **Cross-doc links inside content**: **always use `[Text](document-uuid)`.** UUIDs are the only fully reliable link form — stable across title changes, never ambiguous, no encoding gotchas. Every `cerefox_search` result shows `[id: <uuid>]` after the title; grab it and use it. Title-based linking (`[Text](<Title With Spaces>)`) is fragile (breaks on colons, parens, ampersands, brackets — silently navigates to wrong page) — **don\'t write title-based links**; do an extra search to get the UUID instead. Repo-path forms (`[Text](docs/path.md)`) exist for repo-ingested files; don\'t construct manually. See `AGENT_GUIDE.md → Writing linkable content` for the full rule.\n9. **Project memberships — non-destructive by default**: on `cerefox_ingest` updates, **`project_name` (singular) is a non-destructive add** (ensures membership, preserves others). Use **`project_names` (list)** when you want to set the doc\'s full project set in one call (destructive replace). For metadata-only project changes without writing content, use **`cerefox_set_document_projects(document_id, project_names)`** — that tool is the destructive-replace contract made explicit. Never call `cerefox_set_document_projects` with a single name when you mean "add" — that would REMOVE the doc from all other projects. When in doubt, use `cerefox_ingest` with singular `project_name`.\n\n## Update Workflow (ID-based -- preferred)\n\n```\nsearch("topic") -> find doc [id: abc123] -> get_document(abc123) -> modify ->\ningest(title="Same Title", content="...", document_id="abc123", author="my-agent")\n```\n\n## Update Workflow (title-based -- fallback)\n\n```\nsearch("topic") -> find doc -> modify ->\ningest(title="Same Title", content="...", update_if_exists=true, author="my-agent")\n```\n\n## Catch-Up Workflow\n\n```\nmetadata_search(metadata_filter={"type": "decision-log"}, updated_since="2026-03-28T00:00:00Z")\n```\n\n## CLI fallback (when MCP is unavailable)\n\nIf `cerefox_search` is not in your tool list, your user has likely installed the Cerefox CLI. The canonical invocation is plain **`cerefox <subcommand>`** (the TypeScript CLI, installed via `npm install -g @cerefox/memory`). It uses a resource-verb shape (`cerefox document get`, `cerefox project list`, …). The legacy Python `uv run cerefox` is now a frozen husk as of v0.9 — only `uv run cerefox mcp` still works.\n\nSame operations, same conventions. Full reference: [`docs/guides/cli.md`](docs/guides/cli.md). CLI flag names match MCP parameter names exactly (e.g. `metadata_filter` ↔ `--metadata-filter`); short forms (`--filter`, `--project`, `--count`, `--update`, `--version`) work as aliases.\n\n| MCP tool | CLI |\n|---|---|\n| `cerefox_search` | `cerefox search "<q>" --requestor "<your-name>"` |\n| `cerefox_ingest` (paste) | `printf \'...\' \\| cerefox document ingest --paste --title "<t>" --author "<your-name>" --author-type agent` |\n| `cerefox_ingest` (update by ID) | `printf \'...\' \\| cerefox document ingest --paste --title "<t>" --document-id "<uuid>" --author "<your-name>" --author-type agent` |\n| `cerefox_get_document` | `cerefox document get <id> --version-id <vid> --requestor "<your-name>"` |\n| `cerefox_list_versions` | `cerefox document version list <id> --requestor "<your-name>"` |\n| `cerefox_list_projects` | `cerefox project list --requestor "<your-name>"` |\n| `cerefox_list_metadata_keys` | `cerefox metadata keys` |\n| `cerefox_metadata_search` | `cerefox metadata search --metadata-filter \'<json>\' --requestor "<your-name>"` |\n| `cerefox_set_document_projects` | _MCP-only; a CLI command will be added in a future release. Until then, run via MCP if available._ |\n| `cerefox_get_audit_log` | `cerefox audit list --requestor "<your-name>"` (add `--json` for scripted access) |\n| `cerefox_get_help` | `cerefox guides show agent-quick-reference` (or `cerefox guides list` for the full bundled-docs index) |\n\n**Set identity on every call**, exactly as you would on MCP:\n- Writes (`document ingest`, `document ingest-dir`): `--author "<your-name>" --author-type agent`\n- Reads: `--requestor "<your-name>"`\n\nOr have your user set `CEREFOX_AUTHOR_NAME` / `CEREFOX_AUTHOR_TYPE` / `CEREFOX_REQUESTOR_NAME` in their `.env` to apply defaults once.\n', HELP_SECTIONS, HELP_SECTION_HEADINGS;
25751
+ var HELP_FULL = '# Cerefox Knowledge Base -- Agent Quick Reference\n\nCerefox is a persistent, shared knowledge base. You have **10 MCP tools** (9 of them have CLI equivalents — `cerefox_get_help` is MCP-only). For the full guide, search Cerefox for "How AI Agents Use Cerefox" or call `cerefox_get_help` to retrieve this content over MCP.\n\n## Tools\n\n| Tool | Purpose | Key params |\n|------|---------|------------|\n| `cerefox_search` | Find documents (hybrid FTS + semantic) | `query` (required), `project_name`, `metadata_filter`, `requestor` |\n| `cerefox_ingest` | Save or update a document | `title`, `content` (required), `document_id` (update by ID), `update_if_exists`, `project_name` (single, non-destructive add on update), `project_names` (list, destructive replace on update), `metadata`, `author` |\n| `cerefox_get_document` | Get full document by ID | `document_id` (required) |\n| `cerefox_list_versions` | Version history of a document | `document_id` (required) |\n| `cerefox_metadata_search` | Find docs by metadata (no text query) | `metadata_filter` (required), `include_content`, `updated_since` |\n| `cerefox_list_metadata_keys` | Discover available metadata keys | (none required) |\n| `cerefox_list_projects` | List all projects | (none required) |\n| `cerefox_set_document_projects` | Set doc\'s project memberships to exactly the given list (destructive replace; metadata-only, no content change) | `document_id`, `project_names` (required) |\n| `cerefox_get_audit_log` | Query write operation history | `document_id`, `author`, `operation`, `since` |\n| `cerefox_get_help` | Retrieve Cerefox conventions (this reference) over MCP. **Call this whenever uncertain.** | `topic` (optional, case-insensitive H2 substring match) |\n\n## Essential Rules\n\n1. **Search before ingesting** -- check if the document exists first.\n2. **Prefer ID-based updates** -- pass `document_id` from search results for deterministic updates. Falls back to title-matching with `update_if_exists: true`.\n3. **Set `author`/`requestor`** to your name on every call (e.g., "Claude Code", "archiver"). On MCP, pass as parameters. On CLI, pass `--author`/`--author-type`/`--requestor` flags, or rely on `CEREFOX_AUTHOR_NAME`/`CEREFOX_AUTHOR_TYPE`/`CEREFOX_REQUESTOR_NAME` env vars set in the user\'s `.env`.\n4. **Use `document_id` from search results** `[id: uuid]` for get_document and list_versions.\n5. **Add metadata** -- at minimum `type` ("decision-log", "research", "design-doc") and `status` ("active", "draft").\n6. **Write structured Markdown** with H1/H2/H3 headings for good chunking and search.\n7. **Deletes are soft (recoverable); purge is web-UI-only.** If you decide to delete, surface it to the user (`I soft-deleted X — recoverable from the Cerefox web UI trash`). You cannot un-do your own delete from agent code by design.\n8. **Cross-doc links inside content**: **always use `[Text](document-uuid)`.** UUIDs are the only fully reliable link form — stable across title changes, never ambiguous, no encoding gotchas. Every `cerefox_search` result shows `[id: <uuid>]` after the title; grab it and use it. Title-based linking (`[Text](<Title With Spaces>)`) is fragile (breaks on colons, parens, ampersands, brackets — silently navigates to wrong page) — **don\'t write title-based links**; do an extra search to get the UUID instead. Repo-path forms (`[Text](docs/path.md)`) exist for repo-ingested files; don\'t construct manually. See `AGENT_GUIDE.md → Writing linkable content` for the full rule.\n9. **Project memberships — non-destructive by default**: on `cerefox_ingest` updates, **`project_name` (singular) is a non-destructive add** (ensures membership, preserves others). Use **`project_names` (list)** when you want to set the doc\'s full project set in one call (destructive replace). For metadata-only project changes without writing content, use **`cerefox_set_document_projects(document_id, project_names)`** — that tool is the destructive-replace contract made explicit. Never call `cerefox_set_document_projects` with a single name when you mean "add" — that would REMOVE the doc from all other projects. When in doubt, use `cerefox_ingest` with singular `project_name`.\n\n## Update Workflow (ID-based -- preferred)\n\n```\nsearch("topic") -> find doc [id: abc123] -> get_document(abc123) -> modify ->\ningest(title="Same Title", content="...", document_id="abc123", author="my-agent")\n```\n\n## Update Workflow (title-based -- fallback)\n\n```\nsearch("topic") -> find doc -> modify ->\ningest(title="Same Title", content="...", update_if_exists=true, author="my-agent")\n```\n\n## Catch-Up Workflow\n\n```\nmetadata_search(metadata_filter={"type": "decision-log"}, updated_since="2026-03-28T00:00:00Z")\n```\n\n## CLI fallback (when MCP is unavailable)\n\nIf `cerefox_search` is not in your tool list, your user has likely installed the Cerefox CLI. The canonical invocation is plain **`cerefox <subcommand>`** (the TypeScript CLI, installed via `npm install -g @cerefox/memory`). It uses a resource-verb shape (`cerefox document get`, `cerefox project list`, …). The legacy Python `uv run cerefox` is now a frozen husk as of v0.9 — only `uv run cerefox mcp` still works.\n\nSame operations, same conventions. Full reference: [`docs/guides/cli.md`](docs/guides/cli.md). CLI flag names match MCP parameter names exactly (e.g. `metadata_filter` ↔ `--metadata-filter`); common flags also have single-letter short forms (`-f`, `-p`, `-c`, `-m`, `-u`, `-a`, `-r`). Use the canonical long name (what `--help` shows) or its short form — there are no long-form aliases like `--filter` or `--count`.\n\n| MCP tool | CLI |\n|---|---|\n| `cerefox_search` | `cerefox search "<q>" --requestor "<your-name>"` |\n| `cerefox_ingest` (paste) | `printf \'...\' \\| cerefox document ingest --paste --title "<t>" --author "<your-name>" --author-type agent` |\n| `cerefox_ingest` (update by ID) | `printf \'...\' \\| cerefox document ingest --paste --title "<t>" --document-id "<uuid>" --author "<your-name>" --author-type agent` |\n| `cerefox_get_document` | `cerefox document get <id> --version-id <vid> --requestor "<your-name>"` |\n| `cerefox_list_versions` | `cerefox document version list <id> --requestor "<your-name>"` |\n| `cerefox_list_projects` | `cerefox project list --requestor "<your-name>"` |\n| `cerefox_list_metadata_keys` | `cerefox metadata keys` |\n| `cerefox_metadata_search` | `cerefox metadata search --metadata-filter \'<json>\' --requestor "<your-name>"` |\n| `cerefox_set_document_projects` | _MCP-only; a CLI command will be added in a future release. Until then, run via MCP if available._ |\n| `cerefox_get_audit_log` | `cerefox audit list --requestor "<your-name>"` (add `--json` for scripted access) |\n| `cerefox_get_help` | `cerefox guides show agent-quick-reference` (or `cerefox guides list` for the full bundled-docs index) |\n\n**Set identity on every call**, exactly as you would on MCP:\n- Writes (`document ingest`, `document ingest-dir`): `--author "<your-name>" --author-type agent`\n- Reads: `--requestor "<your-name>"`\n\nOr have your user set `CEREFOX_AUTHOR_NAME` / `CEREFOX_AUTHOR_TYPE` / `CEREFOX_REQUESTOR_NAME` in their `.env` to apply defaults once.\n', HELP_SECTIONS, HELP_SECTION_HEADINGS;
25752
25752
  var init_get_help_content = __esm(() => {
25753
25753
  HELP_SECTIONS = {
25754
25754
  Tools: "## Tools\n\n| Tool | Purpose | Key params |\n|------|---------|------------|\n| `cerefox_search` | Find documents (hybrid FTS + semantic) | `query` (required), `project_name`, `metadata_filter`, `requestor` |\n| `cerefox_ingest` | Save or update a document | `title`, `content` (required), `document_id` (update by ID), `update_if_exists`, `project_name` (single, non-destructive add on update), `project_names` (list, destructive replace on update), `metadata`, `author` |\n| `cerefox_get_document` | Get full document by ID | `document_id` (required) |\n| `cerefox_list_versions` | Version history of a document | `document_id` (required) |\n| `cerefox_metadata_search` | Find docs by metadata (no text query) | `metadata_filter` (required), `include_content`, `updated_since` |\n| `cerefox_list_metadata_keys` | Discover available metadata keys | (none required) |\n| `cerefox_list_projects` | List all projects | (none required) |\n| `cerefox_set_document_projects` | Set doc's project memberships to exactly the given list (destructive replace; metadata-only, no content change) | `document_id`, `project_names` (required) |\n| `cerefox_get_audit_log` | Query write operation history | `document_id`, `author`, `operation`, `since` |\n| `cerefox_get_help` | Retrieve Cerefox conventions (this reference) over MCP. **Call this whenever uncertain.** | `topic` (optional, case-insensitive H2 substring match) |",
@@ -25756,7 +25756,7 @@ var init_get_help_content = __esm(() => {
25756
25756
  "Update Workflow (ID-based -- preferred)": '## Update Workflow (ID-based -- preferred)\n\n```\nsearch("topic") -> find doc [id: abc123] -> get_document(abc123) -> modify ->\ningest(title="Same Title", content="...", document_id="abc123", author="my-agent")\n```',
25757
25757
  "Update Workflow (title-based -- fallback)": '## Update Workflow (title-based -- fallback)\n\n```\nsearch("topic") -> find doc -> modify ->\ningest(title="Same Title", content="...", update_if_exists=true, author="my-agent")\n```',
25758
25758
  "Catch-Up Workflow": '## Catch-Up Workflow\n\n```\nmetadata_search(metadata_filter={"type": "decision-log"}, updated_since="2026-03-28T00:00:00Z")\n```',
25759
- "CLI fallback (when MCP is unavailable)": '## CLI fallback (when MCP is unavailable)\n\nIf `cerefox_search` is not in your tool list, your user has likely installed the Cerefox CLI. The canonical invocation is plain **`cerefox <subcommand>`** (the TypeScript CLI, installed via `npm install -g @cerefox/memory`). It uses a resource-verb shape (`cerefox document get`, `cerefox project list`, …). The legacy Python `uv run cerefox` is now a frozen husk as of v0.9 — only `uv run cerefox mcp` still works.\n\nSame operations, same conventions. Full reference: [`docs/guides/cli.md`](docs/guides/cli.md). CLI flag names match MCP parameter names exactly (e.g. `metadata_filter` ↔ `--metadata-filter`); short forms (`--filter`, `--project`, `--count`, `--update`, `--version`) work as aliases.\n\n| MCP tool | CLI |\n|---|---|\n| `cerefox_search` | `cerefox search "<q>" --requestor "<your-name>"` |\n| `cerefox_ingest` (paste) | `printf \'...\' \\| cerefox document ingest --paste --title "<t>" --author "<your-name>" --author-type agent` |\n| `cerefox_ingest` (update by ID) | `printf \'...\' \\| cerefox document ingest --paste --title "<t>" --document-id "<uuid>" --author "<your-name>" --author-type agent` |\n| `cerefox_get_document` | `cerefox document get <id> --version-id <vid> --requestor "<your-name>"` |\n| `cerefox_list_versions` | `cerefox document version list <id> --requestor "<your-name>"` |\n| `cerefox_list_projects` | `cerefox project list --requestor "<your-name>"` |\n| `cerefox_list_metadata_keys` | `cerefox metadata keys` |\n| `cerefox_metadata_search` | `cerefox metadata search --metadata-filter \'<json>\' --requestor "<your-name>"` |\n| `cerefox_set_document_projects` | _MCP-only; a CLI command will be added in a future release. Until then, run via MCP if available._ |\n| `cerefox_get_audit_log` | `cerefox audit list --requestor "<your-name>"` (add `--json` for scripted access) |\n| `cerefox_get_help` | `cerefox guides show agent-quick-reference` (or `cerefox guides list` for the full bundled-docs index) |\n\n**Set identity on every call**, exactly as you would on MCP:\n- Writes (`document ingest`, `document ingest-dir`): `--author "<your-name>" --author-type agent`\n- Reads: `--requestor "<your-name>"`\n\nOr have your user set `CEREFOX_AUTHOR_NAME` / `CEREFOX_AUTHOR_TYPE` / `CEREFOX_REQUESTOR_NAME` in their `.env` to apply defaults once.'
25759
+ "CLI fallback (when MCP is unavailable)": '## CLI fallback (when MCP is unavailable)\n\nIf `cerefox_search` is not in your tool list, your user has likely installed the Cerefox CLI. The canonical invocation is plain **`cerefox <subcommand>`** (the TypeScript CLI, installed via `npm install -g @cerefox/memory`). It uses a resource-verb shape (`cerefox document get`, `cerefox project list`, …). The legacy Python `uv run cerefox` is now a frozen husk as of v0.9 — only `uv run cerefox mcp` still works.\n\nSame operations, same conventions. Full reference: [`docs/guides/cli.md`](docs/guides/cli.md). CLI flag names match MCP parameter names exactly (e.g. `metadata_filter` ↔ `--metadata-filter`); common flags also have single-letter short forms (`-f`, `-p`, `-c`, `-m`, `-u`, `-a`, `-r`). Use the canonical long name (what `--help` shows) or its short form — there are no long-form aliases like `--filter` or `--count`.\n\n| MCP tool | CLI |\n|---|---|\n| `cerefox_search` | `cerefox search "<q>" --requestor "<your-name>"` |\n| `cerefox_ingest` (paste) | `printf \'...\' \\| cerefox document ingest --paste --title "<t>" --author "<your-name>" --author-type agent` |\n| `cerefox_ingest` (update by ID) | `printf \'...\' \\| cerefox document ingest --paste --title "<t>" --document-id "<uuid>" --author "<your-name>" --author-type agent` |\n| `cerefox_get_document` | `cerefox document get <id> --version-id <vid> --requestor "<your-name>"` |\n| `cerefox_list_versions` | `cerefox document version list <id> --requestor "<your-name>"` |\n| `cerefox_list_projects` | `cerefox project list --requestor "<your-name>"` |\n| `cerefox_list_metadata_keys` | `cerefox metadata keys` |\n| `cerefox_metadata_search` | `cerefox metadata search --metadata-filter \'<json>\' --requestor "<your-name>"` |\n| `cerefox_set_document_projects` | _MCP-only; a CLI command will be added in a future release. Until then, run via MCP if available._ |\n| `cerefox_get_audit_log` | `cerefox audit list --requestor "<your-name>"` (add `--json` for scripted access) |\n| `cerefox_get_help` | `cerefox guides show agent-quick-reference` (or `cerefox guides list` for the full bundled-docs index) |\n\n**Set identity on every call**, exactly as you would on MCP:\n- Writes (`document ingest`, `document ingest-dir`): `--author "<your-name>" --author-type agent`\n- Reads: `--requestor "<your-name>"`\n\nOr have your user set `CEREFOX_AUTHOR_NAME` / `CEREFOX_AUTHOR_TYPE` / `CEREFOX_REQUESTOR_NAME` in their `.env` to apply defaults once.'
25760
25760
  };
25761
25761
  HELP_SECTION_HEADINGS = ["Tools", "Essential Rules", "Update Workflow (ID-based -- preferred)", "Update Workflow (title-based -- fallback)", "Catch-Up Workflow", "CLI fallback (when MCP is unavailable)"];
25762
25762
  });
@@ -45783,7 +45783,7 @@ import { homedir as homedir5 } from "node:os";
45783
45783
  import { join as join8 } from "node:path";
45784
45784
 
45785
45785
  // ../../_shared/ef-meta/index.ts
45786
- var EF_VERSION = "0.9.1";
45786
+ var EF_VERSION = "0.9.3";
45787
45787
 
45788
45788
  // src/cli/util/checks.ts
45789
45789
  init_config();
@@ -18,7 +18,7 @@
18
18
  * doesn't touch `supabase/functions/` leaves it alone).
19
19
  */
20
20
 
21
- export const EF_VERSION = "0.9.1";
21
+ export const EF_VERSION = "0.9.3";
22
22
 
23
23
  /**
24
24
  * The 8 peer EFs the cerefox-mcp aggregator probes (excludes cerefox-mcp
@@ -11,7 +11,7 @@
11
11
  * docs/specs/polish-and-distribution-design.md §10d.
12
12
  */
13
13
 
14
- export const HELP_FULL = "# Cerefox Knowledge Base -- Agent Quick Reference\n\nCerefox is a persistent, shared knowledge base. You have **10 MCP tools** (9 of them have CLI equivalents — `cerefox_get_help` is MCP-only). For the full guide, search Cerefox for \"How AI Agents Use Cerefox\" or call `cerefox_get_help` to retrieve this content over MCP.\n\n## Tools\n\n| Tool | Purpose | Key params |\n|------|---------|------------|\n| `cerefox_search` | Find documents (hybrid FTS + semantic) | `query` (required), `project_name`, `metadata_filter`, `requestor` |\n| `cerefox_ingest` | Save or update a document | `title`, `content` (required), `document_id` (update by ID), `update_if_exists`, `project_name` (single, non-destructive add on update), `project_names` (list, destructive replace on update), `metadata`, `author` |\n| `cerefox_get_document` | Get full document by ID | `document_id` (required) |\n| `cerefox_list_versions` | Version history of a document | `document_id` (required) |\n| `cerefox_metadata_search` | Find docs by metadata (no text query) | `metadata_filter` (required), `include_content`, `updated_since` |\n| `cerefox_list_metadata_keys` | Discover available metadata keys | (none required) |\n| `cerefox_list_projects` | List all projects | (none required) |\n| `cerefox_set_document_projects` | Set doc's project memberships to exactly the given list (destructive replace; metadata-only, no content change) | `document_id`, `project_names` (required) |\n| `cerefox_get_audit_log` | Query write operation history | `document_id`, `author`, `operation`, `since` |\n| `cerefox_get_help` | Retrieve Cerefox conventions (this reference) over MCP. **Call this whenever uncertain.** | `topic` (optional, case-insensitive H2 substring match) |\n\n## Essential Rules\n\n1. **Search before ingesting** -- check if the document exists first.\n2. **Prefer ID-based updates** -- pass `document_id` from search results for deterministic updates. Falls back to title-matching with `update_if_exists: true`.\n3. **Set `author`/`requestor`** to your name on every call (e.g., \"Claude Code\", \"archiver\"). On MCP, pass as parameters. On CLI, pass `--author`/`--author-type`/`--requestor` flags, or rely on `CEREFOX_AUTHOR_NAME`/`CEREFOX_AUTHOR_TYPE`/`CEREFOX_REQUESTOR_NAME` env vars set in the user's `.env`.\n4. **Use `document_id` from search results** `[id: uuid]` for get_document and list_versions.\n5. **Add metadata** -- at minimum `type` (\"decision-log\", \"research\", \"design-doc\") and `status` (\"active\", \"draft\").\n6. **Write structured Markdown** with H1/H2/H3 headings for good chunking and search.\n7. **Deletes are soft (recoverable); purge is web-UI-only.** If you decide to delete, surface it to the user (`I soft-deleted X — recoverable from the Cerefox web UI trash`). You cannot un-do your own delete from agent code by design.\n8. **Cross-doc links inside content**: **always use `[Text](document-uuid)`.** UUIDs are the only fully reliable link form — stable across title changes, never ambiguous, no encoding gotchas. Every `cerefox_search` result shows `[id: <uuid>]` after the title; grab it and use it. Title-based linking (`[Text](<Title With Spaces>)`) is fragile (breaks on colons, parens, ampersands, brackets — silently navigates to wrong page) — **don't write title-based links**; do an extra search to get the UUID instead. Repo-path forms (`[Text](docs/path.md)`) exist for repo-ingested files; don't construct manually. See `AGENT_GUIDE.md → Writing linkable content` for the full rule.\n9. **Project memberships — non-destructive by default**: on `cerefox_ingest` updates, **`project_name` (singular) is a non-destructive add** (ensures membership, preserves others). Use **`project_names` (list)** when you want to set the doc's full project set in one call (destructive replace). For metadata-only project changes without writing content, use **`cerefox_set_document_projects(document_id, project_names)`** — that tool is the destructive-replace contract made explicit. Never call `cerefox_set_document_projects` with a single name when you mean \"add\" — that would REMOVE the doc from all other projects. When in doubt, use `cerefox_ingest` with singular `project_name`.\n\n## Update Workflow (ID-based -- preferred)\n\n```\nsearch(\"topic\") -> find doc [id: abc123] -> get_document(abc123) -> modify ->\ningest(title=\"Same Title\", content=\"...\", document_id=\"abc123\", author=\"my-agent\")\n```\n\n## Update Workflow (title-based -- fallback)\n\n```\nsearch(\"topic\") -> find doc -> modify ->\ningest(title=\"Same Title\", content=\"...\", update_if_exists=true, author=\"my-agent\")\n```\n\n## Catch-Up Workflow\n\n```\nmetadata_search(metadata_filter={\"type\": \"decision-log\"}, updated_since=\"2026-03-28T00:00:00Z\")\n```\n\n## CLI fallback (when MCP is unavailable)\n\nIf `cerefox_search` is not in your tool list, your user has likely installed the Cerefox CLI. The canonical invocation is plain **`cerefox <subcommand>`** (the TypeScript CLI, installed via `npm install -g @cerefox/memory`). It uses a resource-verb shape (`cerefox document get`, `cerefox project list`, …). The legacy Python `uv run cerefox` is now a frozen husk as of v0.9 — only `uv run cerefox mcp` still works.\n\nSame operations, same conventions. Full reference: [`docs/guides/cli.md`](docs/guides/cli.md). CLI flag names match MCP parameter names exactly (e.g. `metadata_filter` ↔ `--metadata-filter`); short forms (`--filter`, `--project`, `--count`, `--update`, `--version`) work as aliases.\n\n| MCP tool | CLI |\n|---|---|\n| `cerefox_search` | `cerefox search \"<q>\" --requestor \"<your-name>\"` |\n| `cerefox_ingest` (paste) | `printf '...' \\| cerefox document ingest --paste --title \"<t>\" --author \"<your-name>\" --author-type agent` |\n| `cerefox_ingest` (update by ID) | `printf '...' \\| cerefox document ingest --paste --title \"<t>\" --document-id \"<uuid>\" --author \"<your-name>\" --author-type agent` |\n| `cerefox_get_document` | `cerefox document get <id> --version-id <vid> --requestor \"<your-name>\"` |\n| `cerefox_list_versions` | `cerefox document version list <id> --requestor \"<your-name>\"` |\n| `cerefox_list_projects` | `cerefox project list --requestor \"<your-name>\"` |\n| `cerefox_list_metadata_keys` | `cerefox metadata keys` |\n| `cerefox_metadata_search` | `cerefox metadata search --metadata-filter '<json>' --requestor \"<your-name>\"` |\n| `cerefox_set_document_projects` | _MCP-only; a CLI command will be added in a future release. Until then, run via MCP if available._ |\n| `cerefox_get_audit_log` | `cerefox audit list --requestor \"<your-name>\"` (add `--json` for scripted access) |\n| `cerefox_get_help` | `cerefox guides show agent-quick-reference` (or `cerefox guides list` for the full bundled-docs index) |\n\n**Set identity on every call**, exactly as you would on MCP:\n- Writes (`document ingest`, `document ingest-dir`): `--author \"<your-name>\" --author-type agent`\n- Reads: `--requestor \"<your-name>\"`\n\nOr have your user set `CEREFOX_AUTHOR_NAME` / `CEREFOX_AUTHOR_TYPE` / `CEREFOX_REQUESTOR_NAME` in their `.env` to apply defaults once.\n";
14
+ export const HELP_FULL = "# Cerefox Knowledge Base -- Agent Quick Reference\n\nCerefox is a persistent, shared knowledge base. You have **10 MCP tools** (9 of them have CLI equivalents — `cerefox_get_help` is MCP-only). For the full guide, search Cerefox for \"How AI Agents Use Cerefox\" or call `cerefox_get_help` to retrieve this content over MCP.\n\n## Tools\n\n| Tool | Purpose | Key params |\n|------|---------|------------|\n| `cerefox_search` | Find documents (hybrid FTS + semantic) | `query` (required), `project_name`, `metadata_filter`, `requestor` |\n| `cerefox_ingest` | Save or update a document | `title`, `content` (required), `document_id` (update by ID), `update_if_exists`, `project_name` (single, non-destructive add on update), `project_names` (list, destructive replace on update), `metadata`, `author` |\n| `cerefox_get_document` | Get full document by ID | `document_id` (required) |\n| `cerefox_list_versions` | Version history of a document | `document_id` (required) |\n| `cerefox_metadata_search` | Find docs by metadata (no text query) | `metadata_filter` (required), `include_content`, `updated_since` |\n| `cerefox_list_metadata_keys` | Discover available metadata keys | (none required) |\n| `cerefox_list_projects` | List all projects | (none required) |\n| `cerefox_set_document_projects` | Set doc's project memberships to exactly the given list (destructive replace; metadata-only, no content change) | `document_id`, `project_names` (required) |\n| `cerefox_get_audit_log` | Query write operation history | `document_id`, `author`, `operation`, `since` |\n| `cerefox_get_help` | Retrieve Cerefox conventions (this reference) over MCP. **Call this whenever uncertain.** | `topic` (optional, case-insensitive H2 substring match) |\n\n## Essential Rules\n\n1. **Search before ingesting** -- check if the document exists first.\n2. **Prefer ID-based updates** -- pass `document_id` from search results for deterministic updates. Falls back to title-matching with `update_if_exists: true`.\n3. **Set `author`/`requestor`** to your name on every call (e.g., \"Claude Code\", \"archiver\"). On MCP, pass as parameters. On CLI, pass `--author`/`--author-type`/`--requestor` flags, or rely on `CEREFOX_AUTHOR_NAME`/`CEREFOX_AUTHOR_TYPE`/`CEREFOX_REQUESTOR_NAME` env vars set in the user's `.env`.\n4. **Use `document_id` from search results** `[id: uuid]` for get_document and list_versions.\n5. **Add metadata** -- at minimum `type` (\"decision-log\", \"research\", \"design-doc\") and `status` (\"active\", \"draft\").\n6. **Write structured Markdown** with H1/H2/H3 headings for good chunking and search.\n7. **Deletes are soft (recoverable); purge is web-UI-only.** If you decide to delete, surface it to the user (`I soft-deleted X — recoverable from the Cerefox web UI trash`). You cannot un-do your own delete from agent code by design.\n8. **Cross-doc links inside content**: **always use `[Text](document-uuid)`.** UUIDs are the only fully reliable link form — stable across title changes, never ambiguous, no encoding gotchas. Every `cerefox_search` result shows `[id: <uuid>]` after the title; grab it and use it. Title-based linking (`[Text](<Title With Spaces>)`) is fragile (breaks on colons, parens, ampersands, brackets — silently navigates to wrong page) — **don't write title-based links**; do an extra search to get the UUID instead. Repo-path forms (`[Text](docs/path.md)`) exist for repo-ingested files; don't construct manually. See `AGENT_GUIDE.md → Writing linkable content` for the full rule.\n9. **Project memberships — non-destructive by default**: on `cerefox_ingest` updates, **`project_name` (singular) is a non-destructive add** (ensures membership, preserves others). Use **`project_names` (list)** when you want to set the doc's full project set in one call (destructive replace). For metadata-only project changes without writing content, use **`cerefox_set_document_projects(document_id, project_names)`** — that tool is the destructive-replace contract made explicit. Never call `cerefox_set_document_projects` with a single name when you mean \"add\" — that would REMOVE the doc from all other projects. When in doubt, use `cerefox_ingest` with singular `project_name`.\n\n## Update Workflow (ID-based -- preferred)\n\n```\nsearch(\"topic\") -> find doc [id: abc123] -> get_document(abc123) -> modify ->\ningest(title=\"Same Title\", content=\"...\", document_id=\"abc123\", author=\"my-agent\")\n```\n\n## Update Workflow (title-based -- fallback)\n\n```\nsearch(\"topic\") -> find doc -> modify ->\ningest(title=\"Same Title\", content=\"...\", update_if_exists=true, author=\"my-agent\")\n```\n\n## Catch-Up Workflow\n\n```\nmetadata_search(metadata_filter={\"type\": \"decision-log\"}, updated_since=\"2026-03-28T00:00:00Z\")\n```\n\n## CLI fallback (when MCP is unavailable)\n\nIf `cerefox_search` is not in your tool list, your user has likely installed the Cerefox CLI. The canonical invocation is plain **`cerefox <subcommand>`** (the TypeScript CLI, installed via `npm install -g @cerefox/memory`). It uses a resource-verb shape (`cerefox document get`, `cerefox project list`, …). The legacy Python `uv run cerefox` is now a frozen husk as of v0.9 — only `uv run cerefox mcp` still works.\n\nSame operations, same conventions. Full reference: [`docs/guides/cli.md`](docs/guides/cli.md). CLI flag names match MCP parameter names exactly (e.g. `metadata_filter` ↔ `--metadata-filter`); common flags also have single-letter short forms (`-f`, `-p`, `-c`, `-m`, `-u`, `-a`, `-r`). Use the canonical long name (what `--help` shows) or its short form — there are no long-form aliases like `--filter` or `--count`.\n\n| MCP tool | CLI |\n|---|---|\n| `cerefox_search` | `cerefox search \"<q>\" --requestor \"<your-name>\"` |\n| `cerefox_ingest` (paste) | `printf '...' \\| cerefox document ingest --paste --title \"<t>\" --author \"<your-name>\" --author-type agent` |\n| `cerefox_ingest` (update by ID) | `printf '...' \\| cerefox document ingest --paste --title \"<t>\" --document-id \"<uuid>\" --author \"<your-name>\" --author-type agent` |\n| `cerefox_get_document` | `cerefox document get <id> --version-id <vid> --requestor \"<your-name>\"` |\n| `cerefox_list_versions` | `cerefox document version list <id> --requestor \"<your-name>\"` |\n| `cerefox_list_projects` | `cerefox project list --requestor \"<your-name>\"` |\n| `cerefox_list_metadata_keys` | `cerefox metadata keys` |\n| `cerefox_metadata_search` | `cerefox metadata search --metadata-filter '<json>' --requestor \"<your-name>\"` |\n| `cerefox_set_document_projects` | _MCP-only; a CLI command will be added in a future release. Until then, run via MCP if available._ |\n| `cerefox_get_audit_log` | `cerefox audit list --requestor \"<your-name>\"` (add `--json` for scripted access) |\n| `cerefox_get_help` | `cerefox guides show agent-quick-reference` (or `cerefox guides list` for the full bundled-docs index) |\n\n**Set identity on every call**, exactly as you would on MCP:\n- Writes (`document ingest`, `document ingest-dir`): `--author \"<your-name>\" --author-type agent`\n- Reads: `--requestor \"<your-name>\"`\n\nOr have your user set `CEREFOX_AUTHOR_NAME` / `CEREFOX_AUTHOR_TYPE` / `CEREFOX_REQUESTOR_NAME` in their `.env` to apply defaults once.\n";
15
15
 
16
16
  /** Sections keyed by their H2 heading text (lower-cased for matching). */
17
17
  export const HELP_SECTIONS: Record<string, string> = {
@@ -20,7 +20,7 @@ export const HELP_SECTIONS: Record<string, string> = {
20
20
  "Update Workflow (ID-based -- preferred)": "## Update Workflow (ID-based -- preferred)\n\n```\nsearch(\"topic\") -> find doc [id: abc123] -> get_document(abc123) -> modify ->\ningest(title=\"Same Title\", content=\"...\", document_id=\"abc123\", author=\"my-agent\")\n```",
21
21
  "Update Workflow (title-based -- fallback)": "## Update Workflow (title-based -- fallback)\n\n```\nsearch(\"topic\") -> find doc -> modify ->\ningest(title=\"Same Title\", content=\"...\", update_if_exists=true, author=\"my-agent\")\n```",
22
22
  "Catch-Up Workflow": "## Catch-Up Workflow\n\n```\nmetadata_search(metadata_filter={\"type\": \"decision-log\"}, updated_since=\"2026-03-28T00:00:00Z\")\n```",
23
- "CLI fallback (when MCP is unavailable)": "## CLI fallback (when MCP is unavailable)\n\nIf `cerefox_search` is not in your tool list, your user has likely installed the Cerefox CLI. The canonical invocation is plain **`cerefox <subcommand>`** (the TypeScript CLI, installed via `npm install -g @cerefox/memory`). It uses a resource-verb shape (`cerefox document get`, `cerefox project list`, …). The legacy Python `uv run cerefox` is now a frozen husk as of v0.9 — only `uv run cerefox mcp` still works.\n\nSame operations, same conventions. Full reference: [`docs/guides/cli.md`](docs/guides/cli.md). CLI flag names match MCP parameter names exactly (e.g. `metadata_filter` ↔ `--metadata-filter`); short forms (`--filter`, `--project`, `--count`, `--update`, `--version`) work as aliases.\n\n| MCP tool | CLI |\n|---|---|\n| `cerefox_search` | `cerefox search \"<q>\" --requestor \"<your-name>\"` |\n| `cerefox_ingest` (paste) | `printf '...' \\| cerefox document ingest --paste --title \"<t>\" --author \"<your-name>\" --author-type agent` |\n| `cerefox_ingest` (update by ID) | `printf '...' \\| cerefox document ingest --paste --title \"<t>\" --document-id \"<uuid>\" --author \"<your-name>\" --author-type agent` |\n| `cerefox_get_document` | `cerefox document get <id> --version-id <vid> --requestor \"<your-name>\"` |\n| `cerefox_list_versions` | `cerefox document version list <id> --requestor \"<your-name>\"` |\n| `cerefox_list_projects` | `cerefox project list --requestor \"<your-name>\"` |\n| `cerefox_list_metadata_keys` | `cerefox metadata keys` |\n| `cerefox_metadata_search` | `cerefox metadata search --metadata-filter '<json>' --requestor \"<your-name>\"` |\n| `cerefox_set_document_projects` | _MCP-only; a CLI command will be added in a future release. Until then, run via MCP if available._ |\n| `cerefox_get_audit_log` | `cerefox audit list --requestor \"<your-name>\"` (add `--json` for scripted access) |\n| `cerefox_get_help` | `cerefox guides show agent-quick-reference` (or `cerefox guides list` for the full bundled-docs index) |\n\n**Set identity on every call**, exactly as you would on MCP:\n- Writes (`document ingest`, `document ingest-dir`): `--author \"<your-name>\" --author-type agent`\n- Reads: `--requestor \"<your-name>\"`\n\nOr have your user set `CEREFOX_AUTHOR_NAME` / `CEREFOX_AUTHOR_TYPE` / `CEREFOX_REQUESTOR_NAME` in their `.env` to apply defaults once.",
23
+ "CLI fallback (when MCP is unavailable)": "## CLI fallback (when MCP is unavailable)\n\nIf `cerefox_search` is not in your tool list, your user has likely installed the Cerefox CLI. The canonical invocation is plain **`cerefox <subcommand>`** (the TypeScript CLI, installed via `npm install -g @cerefox/memory`). It uses a resource-verb shape (`cerefox document get`, `cerefox project list`, …). The legacy Python `uv run cerefox` is now a frozen husk as of v0.9 — only `uv run cerefox mcp` still works.\n\nSame operations, same conventions. Full reference: [`docs/guides/cli.md`](docs/guides/cli.md). CLI flag names match MCP parameter names exactly (e.g. `metadata_filter` ↔ `--metadata-filter`); common flags also have single-letter short forms (`-f`, `-p`, `-c`, `-m`, `-u`, `-a`, `-r`). Use the canonical long name (what `--help` shows) or its short form — there are no long-form aliases like `--filter` or `--count`.\n\n| MCP tool | CLI |\n|---|---|\n| `cerefox_search` | `cerefox search \"<q>\" --requestor \"<your-name>\"` |\n| `cerefox_ingest` (paste) | `printf '...' \\| cerefox document ingest --paste --title \"<t>\" --author \"<your-name>\" --author-type agent` |\n| `cerefox_ingest` (update by ID) | `printf '...' \\| cerefox document ingest --paste --title \"<t>\" --document-id \"<uuid>\" --author \"<your-name>\" --author-type agent` |\n| `cerefox_get_document` | `cerefox document get <id> --version-id <vid> --requestor \"<your-name>\"` |\n| `cerefox_list_versions` | `cerefox document version list <id> --requestor \"<your-name>\"` |\n| `cerefox_list_projects` | `cerefox project list --requestor \"<your-name>\"` |\n| `cerefox_list_metadata_keys` | `cerefox metadata keys` |\n| `cerefox_metadata_search` | `cerefox metadata search --metadata-filter '<json>' --requestor \"<your-name>\"` |\n| `cerefox_set_document_projects` | _MCP-only; a CLI command will be added in a future release. Until then, run via MCP if available._ |\n| `cerefox_get_audit_log` | `cerefox audit list --requestor \"<your-name>\"` (add `--json` for scripted access) |\n| `cerefox_get_help` | `cerefox guides show agent-quick-reference` (or `cerefox guides list` for the full bundled-docs index) |\n\n**Set identity on every call**, exactly as you would on MCP:\n- Writes (`document ingest`, `document ingest-dir`): `--author \"<your-name>\" --author-type agent`\n- Reads: `--requestor \"<your-name>\"`\n\nOr have your user set `CEREFOX_AUTHOR_NAME` / `CEREFOX_AUTHOR_TYPE` / `CEREFOX_REQUESTOR_NAME` in their `.env` to apply defaults once.",
24
24
  };
25
25
 
26
26
  export const HELP_SECTION_HEADINGS: string[] = ["Tools", "Essential Rules", "Update Workflow (ID-based -- preferred)", "Update Workflow (title-based -- fallback)", "Catch-Up Workflow", "CLI fallback (when MCP is unavailable)"];
@@ -227,8 +227,8 @@ If you're building tooling that uses the CLI (Path C) or any MCP/Edge Function p
227
227
 
228
228
  ### CLI delete-doc — interactive vs scripted
229
229
 
230
- `cerefox document delete` prompts for confirmation by default (since `click.confirm` requires
231
- a TTY, an agent's Bash tool will get an abort instead of accidentally deleting). Agents
230
+ `cerefox document delete` prompts for confirmation by default (the prompt requires a TTY, so
231
+ an agent's Bash tool gets an abort instead of accidentally deleting). Agents
232
232
  that legitimately need to soft-delete must pass `--yes` *and* set `--author` /
233
233
  `--author-type` so the audit log captures who acted:
234
234
 
@@ -30,7 +30,7 @@ cerefox document ingest --paste --title "<title>" [OPTIONS] # stdin
30
30
 
31
31
  **Options**:
32
32
 
33
- > **Flag naming**: every flag below matches its MCP-tool parameter name (e.g. `project_name` → `--project-name`). Short forms (`--project`, `-p`) remain as aliases the long form is the canonical name shown in `--help`.
33
+ > **Flag naming**: every flag below matches its MCP-tool parameter name (e.g. `project_name` → `--project-name`). Common flags also have a single-letter short form (`-p`, `-c`, `-f`, `-m`, `-u`, `-a`, `-r`, `-l`, `-t`, `-i`); the long form is canonical. There are **no** long-form aliases such as `--project`, `--count`, `--filter`, `--update`, or `--version` — use the canonical long name or its single-letter short form.
34
34
 
35
35
  | Flag (canonical) | Aliases | Type | Default | Description |
36
36
  |---|---|---|---|---|
@@ -38,8 +38,8 @@ cerefox document ingest --paste --title "<title>" [OPTIONS] # stdin
38
38
  | `--project-name` | `--project`, `-p` | str | _none_ | Project name to assign the document to (created if missing). |
39
39
  | `--paste` | — | flag | off | Read markdown from stdin. Requires `--title`. |
40
40
  | `--metadata` | `-m` | JSON | `{}` | Extra metadata as a JSON object, e.g. `'{"tags":["work"]}'`. |
41
- | `--update-if-exists` | `--update` | flag | off | Title/source-path-based fallback update. Mutually exclusive with `--document-id`. |
42
- | `--document-id` | | UUID | _none_ | Deterministic ID-based update. Errors if the document doesn't exist. |
41
+ | `--update-if-exists` | `-u` | flag | off | Title/source-path-based fallback update. Mutually exclusive with `--document-id`. |
42
+ | `--document-id` | `-i` | UUID | _none_ | Deterministic ID-based update. Errors if the document doesn't exist. |
43
43
  | `--source` | — | str | `paste` / `file` | Source label recorded on the document. |
44
44
  | `--author` | — | str | `CEREFOX_AUTHOR_NAME` or `unknown` | Audit-log author identity. |
45
45
  | `--author-type` | — | `user`\|`agent` | `CEREFOX_AUTHOR_TYPE` or `user` | Caller type. Agent writes auto-routed to `pending_review`. |
@@ -82,23 +82,27 @@ cerefox document ingest-dir [OPTIONS] DIRECTORY
82
82
 
83
83
  **Options**:
84
84
 
85
+ Walks `DIRECTORY` **recursively** (always — there is no recurse toggle) and ingests every file whose extension is in `--extensions`.
86
+
85
87
  | Flag | Type | Default | Description |
86
88
  |---|---|---|---|
87
- | `--pattern TEXT` | glob | `*.md` | Glob pattern. Examples: `**/*.md`, `*.txt`. |
88
- | `--project-name TEXT` (alias: `--project`, `-p`) | str | _none_ | Project to assign every document to. |
89
- | `--recursive / --no-recursive` | flag | `--no-recursive` | Recurse into sub-directories. |
90
- | `--dry-run` | flag | off | Print files that would be ingested; do nothing. |
91
- | `--update-if-exists` (alias: `--update`) | flag | off | Update existing documents by source path. |
92
- | `-m, --metadata TEXT` | JSON | `{}` | JSON metadata applied to every file in the run. |
93
- | `--author TEXT` | str | `CEREFOX_AUTHOR_NAME` or `unknown` | Audit-log author identity (applies to every write). |
94
- | `--author-type [user\|agent]` | choice | `CEREFOX_AUTHOR_TYPE` or `user` | Caller type. |
89
+ | `--extensions <list>` (`-e`) | comma list | `.md,.txt` | File extensions to ingest, e.g. `--extensions .md`. |
90
+ | `--project-name <name>` (`-p`) | str | _none_ | Project to assign every document to. |
91
+ | `--update-if-exists` (`-u`) | flag | off | Update existing documents by source path / title. |
92
+ | `--metadata <json>` (`-m`) | JSON | `{}` | JSON metadata applied to every file in the run. |
93
+ | `--source <label>` | str | `cli` | Source label recorded on each document. |
94
+ | `--author <name>` (`-a`) | str | `CEREFOX_AUTHOR_NAME` or `unknown` | Audit-log author identity (applies to every write). |
95
+ | `--author-type <type>` | `user`\|`agent` | `CEREFOX_AUTHOR_TYPE` or `user` | Caller type. |
95
96
 
96
97
  **Examples**:
97
98
  ```bash
98
- # Bulk import research notes with shared metadata
99
- cerefox document ingest-dir ./research-notes --recursive \
99
+ # Bulk import research notes with shared metadata (recurses automatically)
100
+ cerefox document ingest-dir ./research-notes \
100
101
  --project-name "research" --metadata '{"type":"research","status":"active"}'
101
102
 
103
+ # Only .md files
104
+ cerefox document ingest-dir ./notes --extensions .md
105
+
102
106
  # Re-ingest after editing files
103
107
  cerefox document ingest-dir ./notes --update-if-exists
104
108
  ```
@@ -122,14 +126,16 @@ cerefox search [OPTIONS] QUERY
122
126
 
123
127
  | Flag | Type | Default | Description |
124
128
  |---|---|---|---|
125
- | `-m, --mode [hybrid\|fts\|semantic]` | choice | `hybrid` | Search mode. |
126
- | `--match-count INTEGER` (alias: `--count`, `-n`) | int | `10` | Number of results. |
127
- | `--project-name TEXT` (alias: `--project`, `-p`) | str | _none_ | Limit to a project by name. |
128
- | `--alpha FLOAT` | float | `0.7` | FTS/semantic weight (hybrid only). |
129
- | `--min-score FLOAT` | float | `CEREFOX_MIN_SEARCH_SCORE` or `0.50` | Minimum cosine similarity (hybrid/semantic only). |
130
- | `--metadata-filter TEXT` (alias: `--filter`, `-f`) | JSON | _none_ | JSONB metadata containment filter, e.g. `'{"type":"decision"}'`. |
131
- | `--only-metadata` | flag | off | Return only document titles + metadata (no chunk content / previews) — a compact listing. |
132
- | `--requestor TEXT` | str | `CEREFOX_REQUESTOR_NAME` or `user` | Identity recorded in the usage log. |
129
+ | `--mode <mode>` | `docs`\|`hybrid`\|`fts` | `docs` | `docs` = reconstructed documents (recommended); `hybrid` = ranked chunks; `fts` = keyword-only (no embedding / API key needed). |
130
+ | `--match-count <n>` (`-c`) | int | `5` | Number of results. |
131
+ | `--project-name <name>` (`-p`) | str | _none_ | Limit to a project by name. |
132
+ | `--alpha <float>` | float | `0.7` | Semantic weight 0..1 (`docs`/`hybrid`). |
133
+ | `--min-score <float>` | float | `0.5` | Minimum cosine similarity (`docs`/`hybrid`; not applied to `fts`). |
134
+ | `--metadata-filter <json>` (`-f`) | JSON | _none_ | JSONB metadata containment filter, e.g. `'{"type":"decision"}'`. |
135
+ | `--max-bytes <n>` | int | `200000` | Response size budget in bytes. |
136
+ | `--only-metadata` | flag | off | List matching docs (id, score, chunks, chars) without content — a compact listing. |
137
+ | `--requestor <name>` (`-r`) | str | `CEREFOX_REQUESTOR_NAME` or `user` | Identity recorded in the usage log. |
138
+ | `--json` | flag | off | Machine-readable JSON output. |
133
139
 
134
140
  **Examples**:
135
141
  ```bash
@@ -139,7 +145,7 @@ cerefox search "what we tried" --mode semantic --requestor "claude-code"
139
145
  cerefox search "design docs" --only-metadata
140
146
  ```
141
147
 
142
- **Output**: numbered result list with title, score, and 300-char preview per hit. Final line shows total results + bytes.
148
+ **Output**: in `docs` mode (default), each match prints `## Title [id: …] · score · N chunks · M chars · partial|full` followed by the (re)constructed document body; `hybrid`/`fts` print ranked chunks. A truncation note appears if the byte budget is hit.
143
149
 
144
150
  **Exit codes**: `0` on success. Note: as of v0.1.17, the CLI logs usage in a try/except so a usage-logging error does not affect the user-visible output (closes the failure mode that produced cerefox#27).
145
151
 
@@ -160,8 +166,9 @@ cerefox document get [OPTIONS] DOCUMENT_ID
160
166
 
161
167
  | Flag | Type | Default | Description |
162
168
  |---|---|---|---|
163
- | `--version-id TEXT` (alias: `--version`) | UUID | _none_ (current) | Archived version UUID — get from `cerefox document version list`. |
164
- | `--requestor TEXT` | str | `CEREFOX_REQUESTOR_NAME` or `user` | Identity recorded in the usage log. |
169
+ | `--version-id <uuid>` | UUID | _none_ (current) | Archived version UUID — get from `cerefox document version list`. |
170
+ | `--requestor <name>` (`-r`) | str | `CEREFOX_REQUESTOR_NAME` or `user` | Identity recorded in the usage log. |
171
+ | `--json` | flag | off | Machine-readable JSON output. |
165
172
 
166
173
  **Examples**:
167
174
  ```bash
@@ -189,8 +196,9 @@ cerefox document list [OPTIONS]
189
196
 
190
197
  | Flag | Type | Default | Description |
191
198
  |---|---|---|---|
192
- | `--project-name TEXT` (alias: `--project`, `-p`) | str | _none_ | Filter by project ID or name. |
193
- | `-n, --limit INTEGER` | int | `20` | Max rows. |
199
+ | `--project <name>` (`-p`) | str | _none_ | Filter by project name. |
200
+ | `--limit <n>` (`-l`) | int | `100` | Max rows. |
201
+ | `--json` | flag | off | Machine-readable JSON output. |
194
202
 
195
203
  **Output**: tabular `id | chunk_count | total_chars | title` listing. CLI-only — there is no MCP equivalent.
196
204
 
@@ -347,8 +355,8 @@ cerefox metadata search --metadata-filter '<json>' [OPTIONS]
347
355
 
348
356
  | Flag | Type | Default | Description |
349
357
  |---|---|---|---|
350
- | `--metadata-filter TEXT` (alias: `--filter`) | JSON | **required** | Metadata filter, e.g. `'{"type":"decision-log"}'`. |
351
- | `--project-name TEXT` (alias: `--project`) | str | _none_ | Filter by project name. |
358
+ | `--metadata-filter <json>` (`-f`) | JSON | **required** | Metadata filter, e.g. `'{"type":"decision-log"}'`. |
359
+ | `--project-name <name>` (`-p`) | str | _none_ | Filter by project name. |
352
360
  | `--updated-since TEXT` | ISO-8601 | _none_ | Documents updated after this timestamp. |
353
361
  | `--created-since TEXT` | ISO-8601 | _none_ | Documents created after this timestamp. |
354
362
  | `--limit INTEGER` | int | `10` | Max results. |
@@ -413,9 +421,10 @@ cerefox audit list --json --limit 1000 | jq 'select(.author_type == "agent")'
413
421
 
414
422
  | Flag | Type | Default | Description |
415
423
  |---|---|---|---|
416
- | `-y, --yes` | flag | off | Skip confirmation prompt. Required for non-interactive use (agents, scripts). |
417
- | `--author` | str | `CEREFOX_AUTHOR_NAME` or `unknown` | Identity recorded in the audit log. |
418
- | `--author-type` | `user`\|`agent` | `CEREFOX_AUTHOR_TYPE` or `user` | Caller type, recorded in the audit log. |
424
+ | `--yes` | flag | off | Skip confirmation prompt. Required for non-interactive use (agents, scripts). |
425
+ | `--reason <text>` | str | _none_ | Optional reason recorded on the delete audit entry. |
426
+ | `--author <name>` (`-a`) | str | `CEREFOX_AUTHOR_NAME` or `unknown` | Identity recorded in the audit log. |
427
+ | `--author-type <type>` | `user`\|`agent` | `CEREFOX_AUTHOR_TYPE` or `user` | Caller type, recorded in the audit log. |
419
428
 
420
429
  **What this command does:**
421
430
  - Sets `deleted_at` on the document row. The document stays in the database.
@@ -486,7 +495,7 @@ cerefox config get KEY
486
495
  cerefox config set KEY VALUE
487
496
  ```
488
497
 
489
- Used for toggling features at runtime without a redeploy — see [Decision Log Q1 Part 2 — usage tracking opt-in](https://github.com/fstamatelopoulos/cerefox) entry.
498
+ Used for toggling features at runtime without a redeploy — see the "Decision Log Q1 Part 2 — usage tracking opt-in" entry (stored in the Cerefox knowledge base).
490
499
 
491
500
  ---
492
501
 
@@ -595,7 +604,7 @@ None outstanding as of v0.1.17 (cerefox#27 — the `cerefox search` NameError
595
604
 
596
605
  ### Bulk-import a directory with shared metadata
597
606
  ```bash
598
- cerefox document ingest-dir ./papers --recursive --pattern '*.md' \
607
+ cerefox document ingest-dir ./papers --extensions .md \
599
608
  --project-name "literature" \
600
609
  --metadata '{"type":"paper","status":"reviewed"}'
601
610
  ```
@@ -616,7 +625,7 @@ printf '%s' "$NEW_CONTENT" | cerefox document ingest --paste \
616
625
  ### Unattended sync job
617
626
  ```bash
618
627
  # In a cron job / launchd plist. Set CEREFOX_AUTHOR_NAME=sync-script in env.
619
- cerefox document ingest-dir ~/notes --recursive --update-if-exists
628
+ cerefox document ingest-dir ~/notes --update-if-exists
620
629
  ```
621
630
 
622
631
  ### Use the CLI from an agent's Bash tool
@@ -80,7 +80,7 @@ The `cerefox-search` and `cerefox-ingest` Supabase Edge Functions handle embeddi
80
80
 
81
81
  ### Embedding API retry
82
82
 
83
- All embedding API calls (Python `CloudEmbedder` and Edge Functions) include automatic retry with exponential backoff for transient failures:
83
+ All embedding API calls (TS embedder and Edge Functions) include automatic retry with exponential backoff for transient failures:
84
84
 
85
85
  - **3 attempts** with backoff: 500ms, 1s, 2s
86
86
  - **Retried**: HTTP 5xx server errors, network timeouts, connection failures
@@ -125,7 +125,7 @@ The `metadata_filter` search parameter (available in all search modes, all acces
125
125
 
126
126
  Access paths:
127
127
  - **MCP tool**: `metadata_filter` argument on `cerefox_search`
128
- - **CLI**: `cerefox search "query" --metadata-filter '{"type": "decision"}'` (alias: `--filter`, `-f`)
128
+ - **CLI**: `cerefox search "query" --metadata-filter '{"type": "decision"}'` (short form: `-f`)
129
129
  - **Web UI**: Metadata Filter section (collapsible) in the Knowledge Browser
130
130
  - **GPT Actions**: `metadata_filter` field in `searchKnowledgeBase` request body (schema v1.4.0)
131
131
  - **HTTP API**: `metadata_filter` JSON key in the `cerefox-search` Edge Function POST body
@@ -1022,7 +1022,7 @@ If the same content was already ingested (SHA-256 hash match), returns `"skipped
1022
1022
  | `full_content` | string | Reconstructed document content (may be partial — see `is_partial`) |
1023
1023
  | `chunk_count` | integer | Number of chunks in `full_content` |
1024
1024
  | `total_chars` | integer | Full document size in characters (always the whole doc, even when `is_partial` is true) |
1025
- | `is_partial` | boolean | `true` when `full_content` contains only matched chunks + neighbours instead of the complete document. Triggered when the document exceeds the small-to-big threshold (default 40 000 chars). Use `getDocument` to retrieve the full text. |
1025
+ | `is_partial` | boolean | `true` when `full_content` contains only matched chunks + neighbours instead of the complete document. Triggered when the document exceeds the small-to-big threshold (default 20 000 chars). Use `getDocument` to retrieve the full text. |
1026
1026
  | `doc_updated_at` | string | ISO 8601 timestamp of the last document update |
1027
1027
  | `version_count` | integer | Number of archived versions (0 if never updated) |
1028
1028
  | `doc_project_ids` | string[] | Project UUIDs the document belongs to |
@@ -1124,7 +1124,7 @@ from the knowledge base.
1124
1124
 
1125
1125
  ### MCP tool ↔ CLI command mapping
1126
1126
 
1127
- The agent docs are written around MCP tool names. **CLI flag names match MCP parameter names exactly** (kebab-cased) short forms like `--project`, `--filter`, `--count`, `--update`, `--version` are accepted as aliases. Full per-flag reference: [`docs/guides/cli.md`](cli.md).
1127
+ The agent docs are written around MCP tool names. **CLI flag names match MCP parameter names exactly** (kebab-cased), each with a single-letter short form (`-p`, `-f`, `-c`, `-m`, `-u`, `-a`, `-r`). There are no long-form aliases like `--project` or `--count` — use the canonical long name or its short form. Full per-flag reference: [`docs/guides/cli.md`](cli.md).
1128
1128
 
1129
1129
  | MCP tool | CLI command |
1130
1130
  |---|---|
@@ -1344,7 +1344,7 @@ recommended RPC for agent use** — agents receive complete notes, not isolated
1344
1344
  | `p_alpha` | FLOAT | 0.7 | Semantic weight |
1345
1345
  | `p_project_id` | UUID | null | Filter by project |
1346
1346
  | `p_min_score` | FLOAT | 0.0 | Minimum cosine similarity |
1347
- | `p_small_to_big_threshold` | INT | 40000 | Documents larger than this return matched chunks + neighbours instead of the full document. Set to `0` to always return full content. Change the DEFAULT in `rpcs.sql` to apply server-wide. |
1347
+ | `p_small_to_big_threshold` | INT | 20000 | Documents larger than this return matched chunks + neighbours instead of the full document. Set to `0` to always return full content. Change the DEFAULT in `rpcs.sql` to apply server-wide. |
1348
1348
  | `p_context_window` | INT | 1 | Neighbour chunks on each side of each matched chunk. `1` → up to 3 contiguous chunks per hit. `0` → matched chunks only. |
1349
1349
 
1350
1350
  Returns: `document_id`, `doc_title`, `doc_source`, `doc_metadata`, `doc_project_ids`,
@@ -14,7 +14,7 @@ and gives rough estimates for two common deployment scenarios.
14
14
 
15
15
  | Component | Cost driver |
16
16
  |-----------|-------------|
17
- | **Supabase** | Database storage and API calls. The free tier is generous and covers a typical personal knowledge base indefinitely. |
17
+ | **Supabase** | Database storage and **Edge Function invocations** — the latter is the binding free-tier limit for cloud / remote-MCP usage (see below). Direct Data API requests are unlimited. The free tier covers typical personal use indefinitely. |
18
18
  | **OpenAI embeddings** | Charged per token when ingesting content or running searches. The default model (`text-embedding-3-small`) is among the cheapest available. |
19
19
  | **Cloud Run** (optional) | Compute for the web UI if you deploy it to GCP rather than running it locally. |
20
20
  | **Artifact Registry** (optional) | Docker image storage on GCP, if you deploy to Cloud Run. |
@@ -46,14 +46,38 @@ The web UI's built-in search bar and document browser make no embedding calls.
46
46
 
47
47
  ### Supabase free tier limits
48
48
 
49
- Supabase's free tier is sufficient for a personal knowledge base. Key limits as of early 2026:
50
-
51
- - 500 MB database storage (text + vectors; a typical knowledge base is well under this)
52
- - 50,000 API calls/month (for queries via supabase-py)
53
- - 2 active projects
54
-
55
- If you exceed these limits, Supabase's Pro plan is the next step check
56
- [supabase.com/pricing](https://supabase.com/pricing) for current rates.
49
+ Supabase's free tier is sufficient for a personal knowledge base. Current limits
50
+ (verify at [supabase.com/pricing](https://supabase.com/pricing)):
51
+
52
+ - **500 MB database storage** text + 768-dim vectors; a typical personal KB is well under this.
53
+ - **500,000 Edge Function invocations / month** — *the limit that matters most for Cerefox* (see below).
54
+ - **5 GB egress / month**.
55
+ - **2 active projects**, paused after ~1 week of inactivity (a single request unpauses).
56
+ - **Unlimited Data API (REST/PostgREST) requests** on all plans — direct database reads/writes are not metered.
57
+
58
+ (Supabase's "50,000 monthly active users" figure is an **Auth** limit; Cerefox
59
+ doesn't use Supabase Auth, so it never applies.)
60
+
61
+ #### Edge Function invocations are the real free-tier limiter
62
+
63
+ Most of Cerefox runs against the **Data API** (unlimited), but the **remote** agent
64
+ paths go through **Edge Functions**, which the free tier caps at 500,000/month:
65
+
66
+ | Access path | Uses Edge Functions? | Cost per call |
67
+ |---|---|---|
68
+ | Remote MCP (`cerefox-mcp`) — Claude/Cursor/etc. over HTTP | **Yes** | ~1 invocation per agent tool call (calls the RPC directly — no fan-out) |
69
+ | GPT Actions (Custom GPT) → primitive Edge Functions | **Yes** | 1 invocation per action call |
70
+ | `cerefox doctor` | **Yes** | several (it calls the `/version?peers=true` aggregator) |
71
+ | **Local stdio MCP (`cerefox mcp`)** | **No** | 0 — talks to the Data API directly |
72
+ | `cerefox` CLI and `cerefox web` (web UI) | **No** | 0 — Data API directly |
73
+
74
+ 500K/month is generous for a single human-driven agent. But **automated or
75
+ high-frequency agents on the remote path** can approach it. The lever: point those
76
+ agents at the **local stdio MCP server** (`cerefox mcp`) instead of the remote Edge
77
+ Function — it exposes the identical 10 tools, talks to the Data API directly, and
78
+ costs **zero** Edge Function invocations (bonus: lower latency, and it works offline
79
+ against a reachable database). If you do exceed the free EF quota, Supabase's Pro
80
+ plan ($25/mo, 2M invocations included) is the next step.
57
81
 
58
82
  ---
59
83
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  Reference guide for the operational scripts in `scripts/`. Run these from the project root.
4
4
 
5
- > Looking for `cerefox <subcommand>` reference (ingest, search, get-doc, etc.)? See [`docs/guides/cli.md`](cli.md). This guide covers the `scripts/` directory only.
5
+ > Looking for `cerefox <subcommand>` reference (`document ingest`, `search`, `document get`, etc.)? See [`docs/guides/cli.md`](cli.md). This guide covers the `scripts/` directory only.
6
6
 
7
7
  ## Who this guide is for
8
8
 
@@ -100,7 +100,7 @@ for the legacy Python MCP fallback. See [`setup-local.md`](setup-local.md) and
100
100
  ## What's next
101
101
 
102
102
  - **Ingest your notes**: `cerefox document ingest my-notes.md`, or
103
- `cerefox document ingest-dir ./notes/ --recursive`
103
+ `cerefox document ingest-dir ./notes/` (recurses into sub-directories automatically)
104
104
  - **Search from the CLI**: `cerefox search "your query"`
105
105
  - **Discover all commands**: `cerefox --help`
106
106
  - **Run the web UI**: `cerefox web` (TypeScript — Hono backend + React SPA); see [`setup-local.md`](setup-local.md)
@@ -133,7 +133,7 @@ contributions compact. The response size limit then governs the total across all
133
133
  documents.
134
134
 
135
135
  See `docs/guides/configuration.md` → "RPC-level retrieval parameters" to change the
136
- threshold (it is a SQL DEFAULT in `rpcs.sql`, changed via `db_deploy.py`).
136
+ threshold (it is a SQL DEFAULT in `rpcs.sql`, changed via `cerefox server deploy`).
137
137
 
138
138
  ---
139
139
 
@@ -1,5 +1,12 @@
1
1
  # Google Cloud Run Deployment
2
2
 
3
+ > **⚠ Aspirational guidance — not yet tested end-to-end.** This deployment path
4
+ > has not been validated against a live Cloud Run deploy. Treat it as a starting
5
+ > point / design sketch rather than a verified runbook; expect to adapt the
6
+ > `Dockerfile`, ports, and env wiring, and please report back what worked. For
7
+ > paths we actively test, see `setup-supabase.md` (server side) and
8
+ > `setup-local.md`.
9
+
3
10
  Deploy the Cerefox web UI to Google Cloud Run for a lightweight, serverless hosting option. This guide uses Supabase (free tier) for the database.
4
11
 
5
12
  > **Note (v0.9):** The Cerefox web UI is now the TypeScript server (`cerefox web` — Hono
@@ -47,7 +47,7 @@ bun scripts/db_migrate.ts
47
47
  bun scripts/db_deploy.ts
48
48
 
49
49
  # 4. Build the web UI
50
- cd frontend && npm install && npm run build && cd ..
50
+ cd frontend && bun install && bun run build && cd ..
51
51
 
52
52
  # 5. Deploy Edge Functions (if using Supabase-hosted)
53
53
  # Run from the project root (where supabase/ directory is)
@@ -172,10 +172,10 @@ the new code does **not** apply it. After `git pull`, step 4 of the standard
172
172
  checklist (redeploy RPCs) is mandatory, not optional:
173
173
 
174
174
  ```bash
175
- uv run python scripts/db_deploy.py
175
+ bun scripts/db_deploy.ts # or: cerefox server deploy
176
176
  ```
177
177
 
178
- `db_deploy.py` is idempotent (`CREATE OR REPLACE FUNCTION`) and safe to
178
+ `db_deploy.ts` is idempotent (`CREATE OR REPLACE FUNCTION`) and safe to
179
179
  re-run. **If you skip this step, searches for any title containing `-`
180
180
  (e.g. "Job Hunting - Opportunity Index", `setup-supabase`) will continue
181
181
  to return zero results until the RPCs are redeployed.** This is the
@@ -202,7 +202,7 @@ rationale lives in [`docs/solution-design.md` §5.2](../solution-design.md#52-ti
202
202
  - Drops the `GENERATED ALWAYS AS` expression on `cerefox_chunks.fts` (it can't cross-reference `cerefox_documents.title`)
203
203
  - Adds `cerefox_update_chunk_fts(p_document_id, p_new_title)` RPC for title-change FTS refresh
204
204
 
205
- Both are applied automatically by `db_migrate.py` (step 3). After the migration, also run `db_deploy.py` (step 4) to update the RPC definitions.
205
+ Both are applied automatically by `bun scripts/db_migrate.ts` (step 3). After the migration, also run `bun scripts/db_deploy.ts` (step 4) to update the RPC definitions.
206
206
 
207
207
  **Redeploy Edge Functions**: `cerefox-ingest` and `cerefox-mcp` now prepend the document title to chunk embedding inputs. Redeploy both:
208
208
 
@@ -219,14 +219,14 @@ To upgrade existing chunks:
219
219
 
220
220
  ```bash
221
221
  # Preview what would be reindexed (no changes made)
222
- uv run python scripts/reindex_all.py --dry-run
222
+ cerefox server reindex --all --dry-run
223
223
 
224
224
  # Reindex all chunks (re-embeds with title prefix, updates FTS)
225
225
  # Uses 50 chunks per API call by default; lower --batch if you hit rate limits
226
- uv run python scripts/reindex_all.py
227
-
228
- # Or run directly via the CLI (same effect)
229
226
  cerefox server reindex --all
227
+
228
+ # Or run the contributor script directly (same effect)
229
+ bun scripts/reindex_all.ts --all
230
230
  ```
231
231
 
232
232
  The reindex is **resumable**: if interrupted, re-running it skips chunks already embedded with the current model. Archived chunks (historical versions) are not reindexed -- they are not searched.
@@ -240,8 +240,8 @@ Cost estimate: ~$0.01-0.05 for a typical personal knowledge base (a few thousand
240
240
  - `0007_usage_log_requestor.sql` -- renames `reader` column to `requestor` in `cerefox_usage_log`
241
241
  and updates all 3 usage RPCs. Non-destructive (existing data preserved).
242
242
 
243
- Both are applied automatically by `db_migrate.py` (step 3 above). After migrations, also
244
- redeploy RPCs via `db_deploy.py` (step 4) to update the canonical function definitions.
243
+ Both are applied automatically by `bun scripts/db_migrate.ts` (step 3 above). After migrations, also
244
+ redeploy RPCs via `bun scripts/db_deploy.ts` (step 4) to update the canonical function definitions.
245
245
 
246
246
  **New REST API endpoints**: `/api/v1/usage-log`, `/api/v1/usage-log/export.csv`,
247
247
  `/api/v1/usage-log/summary`, `/api/v1/config/{key}`.
@@ -299,7 +299,7 @@ MCP clients pick up new tools automatically on the next connection.
299
299
 
300
300
  ### Upgrading to v0.1.4+ (from v0.1.0-v0.1.3)
301
301
 
302
- **Versioning schema**: Migration `0003_add_document_versions.sql` adds the `cerefox_document_versions` table and `version_id` column on `cerefox_chunks`. This is applied automatically by `db_migrate.py`.
302
+ **Versioning schema**: Migration `0003_add_document_versions.sql` adds the `cerefox_document_versions` table and `version_id` column on `cerefox_chunks`. This is applied automatically by `bun scripts/db_migrate.ts`.
303
303
 
304
304
  ### Upgrading to v0.1.1+ (from v0.1.0)
305
305
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cerefox/memory",
3
- "version": "0.9.2",
3
+ "version": "0.9.3",
4
4
  "description": "Cerefox — user-owned shared memory for AI agents. The local TypeScript runtime: stdio MCP server in v0.4; CLI binary added in v0.5; in-process web server in v0.6; ingestion pipeline in v0.7.",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://github.com/fstamatelopoulos/cerefox",