@cerefox/memory 0.8.3 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,7 +5,7 @@
5
5
  <link rel="icon" type="image/png" href="/app/cerefox_icon.png" />
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
7
  <title>Cerefox</title>
8
- <script type="module" crossorigin src="/app/assets/index-CAp2_lFX.js"></script>
8
+ <script type="module" crossorigin src="/app/assets/index-De3R6K8J.js"></script>
9
9
  <link rel="stylesheet" crossorigin href="/app/assets/index-DoDJGRih.css">
10
10
  </head>
11
11
  <body>
@@ -18,7 +18,7 @@
18
18
  * doesn't touch `supabase/functions/` leaves it alone).
19
19
  */
20
20
 
21
- export const EF_VERSION = "0.8.0";
21
+ export const EF_VERSION = "0.9.1";
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. From v0.5+ the canonical invocation is plain **`cerefox <subcommand>`** (installed via `npm install -g @cerefox/memory`). The legacy `uv run cerefox <subcommand>` (Python CLI in a Cerefox checkout) still works through v0.7 but emits a deprecation banner.\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 (v0.5+ canonical) |\n|---|---|\n| `cerefox_search` | `cerefox search \"<q>\" --requestor \"<your-name>\"` |\n| `cerefox_ingest` (paste) | `printf '...' \\| cerefox ingest --paste --title \"<t>\" --author \"<your-name>\" --author-type agent` |\n| `cerefox_ingest` (update by ID) | `printf '...' \\| cerefox ingest --paste --title \"<t>\" --document-id \"<uuid>\" --author \"<your-name>\" --author-type agent` |\n| `cerefox_get_document` | `cerefox get-doc <id> --version-id <vid> --requestor \"<your-name>\"` |\n| `cerefox_list_versions` | `cerefox list-versions <id> --requestor \"<your-name>\"` |\n| `cerefox_list_projects` | `cerefox list-projects --requestor \"<your-name>\"` |\n| `cerefox_list_metadata_keys` | `cerefox list-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 get-audit-log --requestor \"<your-name>\"` (add `--json` for scripted access) |\n| `cerefox_get_help` | `cerefox docs agent-quick-reference --print` (or `cerefox docs --list` for the full bundled-docs index) |\n\n**Set identity on every call**, exactly as you would on MCP:\n- Writes (`ingest`, `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`); 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";
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. From v0.5+ the canonical invocation is plain **`cerefox <subcommand>`** (installed via `npm install -g @cerefox/memory`). The legacy `uv run cerefox <subcommand>` (Python CLI in a Cerefox checkout) still works through v0.7 but emits a deprecation banner.\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 (v0.5+ canonical) |\n|---|---|\n| `cerefox_search` | `cerefox search \"<q>\" --requestor \"<your-name>\"` |\n| `cerefox_ingest` (paste) | `printf '...' \\| cerefox ingest --paste --title \"<t>\" --author \"<your-name>\" --author-type agent` |\n| `cerefox_ingest` (update by ID) | `printf '...' \\| cerefox ingest --paste --title \"<t>\" --document-id \"<uuid>\" --author \"<your-name>\" --author-type agent` |\n| `cerefox_get_document` | `cerefox get-doc <id> --version-id <vid> --requestor \"<your-name>\"` |\n| `cerefox_list_versions` | `cerefox list-versions <id> --requestor \"<your-name>\"` |\n| `cerefox_list_projects` | `cerefox list-projects --requestor \"<your-name>\"` |\n| `cerefox_list_metadata_keys` | `cerefox list-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 get-audit-log --requestor \"<your-name>\"` (add `--json` for scripted access) |\n| `cerefox_get_help` | `cerefox docs agent-quick-reference --print` (or `cerefox docs --list` for the full bundled-docs index) |\n\n**Set identity on every call**, exactly as you would on MCP:\n- Writes (`ingest`, `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`); 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.",
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)"];
@@ -5,7 +5,7 @@ configure, what can reach the database, and which path is right for your integra
5
5
 
6
6
  > **A note on Supabase keys (2026):** Cerefox needs two API keys for two different transport
7
7
  > layers. Layer 1 (Edge Functions) uses the **legacy anon JWT** as a Bearer token — the new
8
- > `sb_publishable_…` key is rejected by the Edge Function gateway. Layer 2 (Python REST)
8
+ > `sb_publishable_…` key is rejected by the Edge Function gateway. Layer 2 (web + CLI REST)
9
9
  > uses the new **secret key** (`sb_secret_…`) or the legacy `service_role` JWT — either
10
10
  > works. See [`setup-supabase.md` → Supabase API keys (2026)](setup-supabase.md#supabase-api-keys-2026)
11
11
  > for the full picture and why this asymmetry exists.
@@ -14,7 +14,7 @@ configure, what can reach the database, and which path is right for your integra
14
14
 
15
15
  ## Layer 1 — AI Agents via Edge Functions (HTTPS)
16
16
 
17
- This is the primary integration layer for AI clients. Six Supabase Edge Functions are
17
+ This is the primary integration layer for AI clients. Nine Supabase Edge Functions are
18
18
  deployed on the Supabase platform and are reachable over HTTPS with nothing more than the
19
19
  **legacy anon JWT** (a public-facing JWT, `eyJ…`). The Supabase gateway validates the key
20
20
  before any request reaches a function; individual functions then use the service-role key
@@ -25,7 +25,7 @@ internally to call Postgres RPCs. Your anon key is never elevated to database-le
25
25
  > [`setup-supabase.md` → Supabase API keys (2026)](setup-supabase.md#supabase-api-keys-2026)
26
26
  > for why.
27
27
 
28
- ### The six Edge Functions
28
+ ### The nine Edge Functions
29
29
 
30
30
  | Edge Function | Role |
31
31
  |---|---|
@@ -34,29 +34,28 @@ internally to call Postgres RPCs. Your anon key is never elevated to database-le
34
34
  | `cerefox-metadata` | List metadata keys with document counts and example values |
35
35
  | `cerefox-get-document` | Retrieve full document content (current or archived version) |
36
36
  | `cerefox-list-versions` | List the archived version history for a document |
37
- | `cerefox-mcp` | Streamable HTTP MCP adapter delegates to all five above |
37
+ | `cerefox-get-audit-log` | Query audit log entries with filters |
38
+ | `cerefox-metadata-search` | Query documents by metadata key-value criteria without text search |
39
+ | `cerefox-list-projects` | List all projects with names, IDs, and descriptions |
40
+ | `cerefox-mcp` | Streamable HTTP MCP adapter — calls Postgres RPCs directly |
38
41
 
39
42
  ### How clients connect
40
43
 
41
44
  **MCP clients** (Claude Code, Cursor, Claude Desktop) connect to `cerefox-mcp`. It speaks
42
- the MCP Streamable HTTP protocol and fans out each tool call to the appropriate primitive
43
- Edge Function via an internal `fetch()`. The client only ever talks to one URL.
45
+ the MCP Streamable HTTP protocol and calls the Postgres RPCs directly (no internal fan-out
46
+ to the primitive Edge Functions). The client only ever talks to one URL.
44
47
 
45
48
  ```
46
49
  MCP client (anon key)
47
50
 
48
51
 
49
- cerefox-mcp ──▶ cerefox-search
50
- ──▶ cerefox-ingest
51
- ──▶ cerefox-metadata
52
- ──▶ cerefox-get-document
53
- ──▶ cerefox-list-versions
54
-
55
- ▼ (service-role key, internal)
56
- Postgres RPCs
52
+ cerefox-mcp
53
+
54
+ (service-role key, internal)
55
+ Postgres RPCs
57
56
  ```
58
57
 
59
- **ChatGPT Custom GPT Actions** call the five primitive Edge Functions directly over HTTPS
58
+ **ChatGPT Custom GPT Actions** call the eight primitive Edge Functions directly over HTTPS
60
59
  using an OpenAPI schema. `cerefox-mcp` is not involved (ChatGPT does not support the
61
60
  Streamable HTTP MCP protocol).
62
61
 
@@ -72,14 +71,17 @@ See `docs/guides/connect-agents.md` for step-by-step setup per client.
72
71
 
73
72
  ---
74
73
 
75
- ## Layer 2 — Python Web App and CLI via Supabase REST
74
+ ## Layer 2 — Web UI and CLI via Supabase REST
75
+
76
+ The web UI (TypeScript Hono backend + React/Mantine SPA, served by `cerefox web`) and all
77
+ `cerefox` CLI commands (`document ingest`, `search`, `server reindex`, `backup`, etc.) talk
78
+ to Supabase over its REST API (PostgREST), authenticating with a **service-role-equivalent
79
+ key** rather than the anon key — either the new **secret key** (`sb_secret_…`) or the legacy
80
+ `service_role` JWT. Both are accepted by the Data API gateway.
76
81
 
77
- The FastAPI web app and all `cerefox` CLI commands (`ingest`, `search`, `reindex`,
78
- `backup`, etc.) use `CerefoxClient` (`src/cerefox/db/client.py`), a thin wrapper around
79
- `supabase-py`. This library talks to Supabase over its REST API (PostgREST), but
80
- authenticates with a **service-role-equivalent key** rather than the anon key — either
81
- the new **secret key** (`sb_secret_…`) or the legacy `service_role` JWT. Both are
82
- accepted by the Data API gateway.
82
+ > The legacy Python FastAPI web app and Python CLI are husks slated for removal; only
83
+ > `uv run cerefox mcp` survives as a frozen, unmaintained fallback. The TS `cerefox` CLI
84
+ > and `cerefox web` are the current implementations.
83
85
 
84
86
  The service-role key bypasses Supabase Row Level Security (RLS) policies and grants
85
87
  unrestricted read and write access. This is intentional — the CLI and web app are trusted,
@@ -87,14 +89,14 @@ local tools that need to insert, update, and delete freely. Keep this key out of
87
89
  public-facing configuration.
88
90
 
89
91
  > **Local coding agents (Claude Code, Codex CLI, opencode, OpenClaw, Hermes, …) also reach
90
- > Cerefox through this layer**, when the user authorises the agent to invoke `uv run cerefox …`
92
+ > Cerefox through this layer**, when the user authorises the agent to invoke `cerefox …`
91
93
  > via its Bash tool. This is "Path C" in `connect-agents.md`. The agent runs with the same
92
94
  > service-role privileges as the user — same trust assumption as letting the agent edit
93
95
  > source code in your repo. See `docs/guides/connect-agents.md` → "Path C — Shell CLI for
94
96
  > local coding agents" for the setup and caveats.
95
97
 
96
98
  ```
97
- Python web app / CLI (service-role key)
99
+ Web UI / CLI (service-role key)
98
100
 
99
101
 
100
102
  Supabase REST API (PostgREST)
@@ -103,7 +105,7 @@ Supabase REST API (PostgREST)
103
105
  Postgres RPCs (same cerefox_* functions called by Edge Functions)
104
106
  ```
105
107
 
106
- The Python layer calls the same Postgres RPCs as the Edge Functions — the business logic
108
+ This layer calls the same Postgres RPCs as the Edge Functions — the business logic
107
109
  lives in one place (Postgres) and is shared across all callers.
108
110
 
109
111
  ### Credentials needed
@@ -115,20 +117,24 @@ lives in one place (Postgres) and is shared across all callers.
115
117
 
116
118
  ## Layer 3 — Direct Postgres (Deployment Scripts Only)
117
119
 
118
- The deployment and migration scripts (`scripts/db_deploy.py`, `scripts/db_migrate.py`,
119
- `scripts/backup_restore.py`) connect directly to Postgres over TCP using **psycopg2** and
120
- the database connection string. This is the only path that can run DDL statements (`CREATE
121
- TABLE`, `CREATE FUNCTION`) the REST API does not support them.
120
+ For end users, `cerefox server deploy` (which bundles schema + RPCs + the nine Edge
121
+ Functions from the npm package) handles schema deployment directly. For contributors, the
122
+ canonical deployment and migration scripts (`bun scripts/db_deploy.ts`,
123
+ `bun scripts/db_migrate.ts`, `bun scripts/backup_restore.ts`) connect directly to Postgres
124
+ over TCP using the database connection string. (The legacy `.py` equivalents still exist
125
+ but are deprecated.) This is the only path that can run DDL statements (`CREATE TABLE`,
126
+ `CREATE FUNCTION`) — the REST API does not support them.
122
127
 
123
128
  ```
124
- scripts/db_deploy.py (DB password via DATABASE_URL)
129
+ cerefox server deploy / bun scripts/db_deploy.ts (DB password via DATABASE_URL)
125
130
 
126
131
 
127
132
  Postgres (direct TCP connection)
128
133
  ```
129
134
 
130
- No application code — not the web app, not the CLI uses this path at runtime. It is
131
- exclusively for schema deployment and data restore operations.
135
+ No application code — not the web app, not the CLI's runtime read/write commands uses
136
+ this path at request time. It is exclusively for schema deployment and data restore
137
+ operations.
132
138
 
133
139
  ### Credentials needed
134
140
 
@@ -149,10 +155,10 @@ exclusively for schema deployment and data restore operations.
149
155
  | Claude Desktop | HTTPS → `cerefox-mcp` (via `supergateway`) | Legacy anon JWT | Daily AI assistant access |
150
156
  | ChatGPT Custom GPT | HTTPS → primitive Edge Functions | Legacy anon JWT | AI assistant via GPT Actions |
151
157
  | curl / HTTP scripts | HTTPS → primitive Edge Functions | Legacy anon JWT | Ad-hoc queries, automation |
152
- | Python web app | Supabase REST API | Secret key (or legacy service_role) | Web UI backend |
158
+ | Web UI (`cerefox web`) | Supabase REST API | Secret key (or legacy service_role) | Web UI backend (TS Hono) |
153
159
  | `cerefox` CLI (human) | Supabase REST API | Secret key (or legacy service_role) | Ingestion, search, reindex, backup |
154
160
  | Local coding agent via `cerefox` CLI | Supabase REST API | Secret key (or legacy service_role) | User-authorised agent (Claude Code, Codex CLI, opencode, OpenClaw, Hermes, …) acting on user's behalf via Bash tool |
155
- | Deployment scripts | Direct TCP (psycopg2) | DB password | Schema deploy, data restore |
161
+ | `cerefox server deploy` / deployment scripts | Direct TCP | DB password | Schema deploy, data restore |
156
162
 
157
163
  ### Key security principle
158
164
 
@@ -177,7 +183,7 @@ paths.
177
183
  | Tier | Operations | Reversible? | Where exposed |
178
184
  |---|---|---|---|
179
185
  | 1. Reads + soft mutations | search, get, list-*, ingest (create/update), metadata-search, get-audit-log | n/a (reads) / yes (versioned) | All paths — MCP, Edge Functions, CLI, web UI |
180
- | 2. Soft-destructive | `delete_document` (soft delete to trash), `set_review_status` | yes — restorable via web UI | All paths (CLI: `cerefox delete-doc`; web UI; Python; **not** MCP or Edge Functions today) |
186
+ | 2. Soft-destructive | `delete_document` (soft delete to trash), `set_review_status` | yes — restorable via web UI | All paths (CLI: `cerefox document delete`; web UI; Python; **not** MCP or Edge Functions today) |
181
187
  | 3. **Hard-destructive** | `purge_document` (permanent), `restore_document` (un-trash), `set_version_archived` (toggle version retention) | no (purge) / yes (restore, but recovers from a destructive action) | **Web UI only** |
182
188
 
183
189
  ### Why purge / restore are web-UI-only
@@ -210,7 +216,7 @@ clear before the operation actually runs).
210
216
 
211
217
  If you're building tooling that uses the CLI (Path C) or any MCP/Edge Function path:
212
218
 
213
- - **Use `cerefox delete-doc` freely** to soft-delete agent-authored content. Pair it
219
+ - **Use `cerefox document delete` freely** to soft-delete agent-authored content. Pair it
214
220
  with `--author <name> --author-type agent` so the audit trail is correct.
215
221
  - **Surface the soft-delete to the user.** When your agent decides to delete something,
216
222
  tell the user explicitly: "I soft-deleted X (recoverable from the Cerefox trash in
@@ -221,13 +227,13 @@ If you're building tooling that uses the CLI (Path C) or any MCP/Edge Function p
221
227
 
222
228
  ### CLI delete-doc — interactive vs scripted
223
229
 
224
- `cerefox delete-doc` prompts for confirmation by default (since `click.confirm` requires
230
+ `cerefox document delete` prompts for confirmation by default (since `click.confirm` requires
225
231
  a TTY, an agent's Bash tool will get an abort instead of accidentally deleting). Agents
226
232
  that legitimately need to soft-delete must pass `--yes` *and* set `--author` /
227
233
  `--author-type` so the audit log captures who acted:
228
234
 
229
235
  ```bash
230
- cerefox delete-doc <doc-id> --yes \
236
+ cerefox document delete <doc-id> --yes \
231
237
  --author "claude-code" --author-type "agent"
232
238
  ```
233
239