@cerefox/memory 0.8.3 → 0.9.0
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/dist/bin/cerefox.js +183 -68
- package/docs/guides/access-paths.md +4 -4
- package/docs/guides/cli.md +55 -55
- package/docs/guides/configuration.md +11 -11
- package/docs/guides/connect-agents.md +14 -14
- package/docs/guides/operational-cost.md +1 -1
- package/docs/guides/ops-scripts.md +9 -9
- package/docs/guides/quickstart.md +2 -2
- package/docs/guides/setup-local.md +2 -2
- package/docs/guides/setup-supabase.md +2 -2
- package/docs/guides/upgrading.md +3 -3
- package/package.json +1 -1
package/dist/bin/cerefox.js
CHANGED
|
@@ -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.
|
|
7187
|
+
var PKG_VERSION = "0.9.0";
|
|
7188
7188
|
var init_meta = () => {};
|
|
7189
7189
|
|
|
7190
7190
|
// ../../node_modules/.bun/tslib@2.8.1/node_modules/tslib/tslib.js
|
|
@@ -26819,11 +26819,11 @@ async function runSyncSelfDocs(options = {}) {
|
|
|
26819
26819
|
printTable(outcomes.filter((o) => o.status === "error").map((o) => ({ topic: o.topic, error: o.detail.slice(0, 100) })));
|
|
26820
26820
|
}
|
|
26821
26821
|
}
|
|
26822
|
-
async function
|
|
26822
|
+
async function action16(options) {
|
|
26823
26823
|
await runSyncSelfDocs(options);
|
|
26824
26824
|
}
|
|
26825
26825
|
function registerSyncSelfDocs(program2) {
|
|
26826
|
-
program2.command("sync-self-docs").description("Ingest bundled Cerefox docs under the _cerefox-self-docs project.").option("--dry-run", "List what would be ingested without writing.").option("--project <name>", "Override the target project name.", "_cerefox-self-docs").action(
|
|
26826
|
+
program2.command("sync-self-docs").description("Ingest bundled Cerefox docs under the _cerefox-self-docs project.").option("--dry-run", "List what would be ingested without writing.").option("--project <name>", "Override the target project name.", "_cerefox-self-docs").action(action16);
|
|
26827
26827
|
}
|
|
26828
26828
|
var init_sync_self_docs = __esm(() => {
|
|
26829
26829
|
init_cli_core();
|
|
@@ -39930,6 +39930,7 @@ var {
|
|
|
39930
39930
|
|
|
39931
39931
|
// src/cli/program.ts
|
|
39932
39932
|
init_meta();
|
|
39933
|
+
init_cli_core();
|
|
39933
39934
|
|
|
39934
39935
|
// src/cli/commands/backup.ts
|
|
39935
39936
|
init_cli_core();
|
|
@@ -42001,6 +42002,64 @@ function registerDeployServer(program2) {
|
|
|
42001
42002
|
program2.command("deploy-server").description("Deploy/update the Cerefox server side (schema + RPCs + Edge Functions) on Supabase.").option("--dry-run", "Print the plan + pre-flight without deploying.").option("--schema-only", "Deploy/update only the schema + RPCs (skip Edge Functions).").option("--functions-only", "Deploy only the Edge Functions (skip the schema/RPCs).").option("--project-ref <ref>", "Supabase project ref for Edge Function deploys (default: derived from CEREFOX_SUPABASE_URL).").action(action8);
|
|
42002
42003
|
}
|
|
42003
42004
|
|
|
42005
|
+
// src/cli/commands/document-restore.ts
|
|
42006
|
+
init_cli_core();
|
|
42007
|
+
init_client();
|
|
42008
|
+
async function action9(documentId, options) {
|
|
42009
|
+
const client = getClient();
|
|
42010
|
+
const { data: doc, error } = await client.raw.from("cerefox_documents").select("id, title, deleted_at").eq("id", documentId).maybeSingle();
|
|
42011
|
+
if (error)
|
|
42012
|
+
throw systemError(`Lookup failed: ${error.message}`);
|
|
42013
|
+
if (!doc)
|
|
42014
|
+
throw notFound(`Document ${documentId} not found.`);
|
|
42015
|
+
if (!doc.deleted_at) {
|
|
42016
|
+
println(c.dim(`Document ${documentId} ("${doc.title}") is not soft-deleted — nothing to restore.`));
|
|
42017
|
+
return;
|
|
42018
|
+
}
|
|
42019
|
+
const author = resolveAuthor(options.author);
|
|
42020
|
+
const authorType = resolveAuthorType(options.authorType);
|
|
42021
|
+
if (author === "unknown") {
|
|
42022
|
+
warn("No --author / CEREFOX_AUTHOR_NAME set — audit log will record this restore as 'unknown'.");
|
|
42023
|
+
}
|
|
42024
|
+
await client.rpc("cerefox_restore_document", {
|
|
42025
|
+
p_document_id: documentId,
|
|
42026
|
+
p_author: author,
|
|
42027
|
+
p_author_type: authorType
|
|
42028
|
+
});
|
|
42029
|
+
println(c.green(`✓ Restored "${doc.title}" (id: ${documentId}) from the trash.`));
|
|
42030
|
+
}
|
|
42031
|
+
function registerDocumentRestore(parent) {
|
|
42032
|
+
parent.command("restore").description("Restore a soft-deleted document from the trash (inverse of `document delete`).").argument("<document-id>", "UUID of the soft-deleted document.").option("-a, --author <name>", "Caller identity (audit log).").option("--author-type <type>", "'user' or 'agent' (default: user).", "user").action(action9);
|
|
42033
|
+
}
|
|
42034
|
+
|
|
42035
|
+
// src/cli/commands/version-archive.ts
|
|
42036
|
+
init_cli_core();
|
|
42037
|
+
init_client();
|
|
42038
|
+
async function setArchived(versionId, archived, options) {
|
|
42039
|
+
const client = getClient();
|
|
42040
|
+
const { data, error } = await client.raw.from("cerefox_document_versions").update({ archived }).eq("id", versionId).select("document_id, version_number").maybeSingle();
|
|
42041
|
+
if (error)
|
|
42042
|
+
throw systemError(`Update failed: ${error.message}`);
|
|
42043
|
+
if (!data)
|
|
42044
|
+
throw notFound(`Version ${versionId} not found.`);
|
|
42045
|
+
const author = resolveAuthor(options.author);
|
|
42046
|
+
const authorType = resolveAuthorType(options.authorType);
|
|
42047
|
+
const op = archived ? "archive" : "unarchive";
|
|
42048
|
+
await client.raw.rpc("cerefox_create_audit_entry", {
|
|
42049
|
+
p_document_id: data.document_id,
|
|
42050
|
+
p_version_id: versionId,
|
|
42051
|
+
p_operation: op,
|
|
42052
|
+
p_author: author,
|
|
42053
|
+
p_author_type: authorType,
|
|
42054
|
+
p_description: `Version ${data.version_number} ${op}d`
|
|
42055
|
+
});
|
|
42056
|
+
println(c.green(`✓ Version ${data.version_number} (${versionId}) ${op}d.`));
|
|
42057
|
+
}
|
|
42058
|
+
function registerVersionArchive(parent) {
|
|
42059
|
+
parent.command("archive").description("Archive a document version (protect it from version cleanup).").argument("<version-id>", "UUID of the version (from `cerefox version list`).").option("-a, --author <name>", "Caller identity (audit log).").option("--author-type <type>", "'user' or 'agent' (default: user).", "user").action((versionId, options) => setArchived(versionId, true, options));
|
|
42060
|
+
parent.command("unarchive").description("Unarchive a document version (allow version cleanup again).").argument("<version-id>", "UUID of the version (from `cerefox version list`).").option("-a, --author <name>", "Caller identity (audit log).").option("--author-type <type>", "'user' or 'agent' (default: user).", "user").action((versionId, options) => setArchived(versionId, false, options));
|
|
42061
|
+
}
|
|
42062
|
+
|
|
42004
42063
|
// src/cli/commands/docs.ts
|
|
42005
42064
|
init_cli_core();
|
|
42006
42065
|
init_bundled_docs();
|
|
@@ -42012,7 +42071,7 @@ function openInBrowser(path) {
|
|
|
42012
42071
|
println(c.dim(`(could not auto-open; the file is at: ${path})`));
|
|
42013
42072
|
}
|
|
42014
42073
|
}
|
|
42015
|
-
function
|
|
42074
|
+
function action10(topic, options) {
|
|
42016
42075
|
const docs = listBundledDocs();
|
|
42017
42076
|
if (options.list || !topic && !options.print) {
|
|
42018
42077
|
if (docs.length === 0) {
|
|
@@ -42041,7 +42100,7 @@ function action9(topic, options) {
|
|
|
42041
42100
|
openInBrowser(doc.path);
|
|
42042
42101
|
}
|
|
42043
42102
|
function registerDocs(program2) {
|
|
42044
|
-
program2.command("docs").description("Open bundled Cerefox docs in your browser (or print to stdout).").argument("[topic]", "Doc topic (e.g. quickstart, connect-agents). Omit for the index.").option("--print", "Print to stdout instead of opening a browser.").option("--list", "List available topics.").action(
|
|
42103
|
+
program2.command("docs").description("Open bundled Cerefox docs in your browser (or print to stdout).").argument("[topic]", "Doc topic (e.g. quickstart, connect-agents). Omit for the index.").option("--print", "Print to stdout instead of opening a browser.").option("--list", "List available topics.").action(action10);
|
|
42045
42104
|
}
|
|
42046
42105
|
|
|
42047
42106
|
// ../../node_modules/.bun/ora@9.4.0/node_modules/ora/index.js
|
|
@@ -46001,7 +46060,7 @@ function symbol(status) {
|
|
|
46001
46060
|
return cErr.dim("ℹ");
|
|
46002
46061
|
}
|
|
46003
46062
|
}
|
|
46004
|
-
async function
|
|
46063
|
+
async function action11(options) {
|
|
46005
46064
|
const useSpinner = !options.json && process.stderr.isTTY;
|
|
46006
46065
|
const spinner = useSpinner ? ora({ text: "Starting checks…", spinner: "dots", stream: process.stderr }).start() : null;
|
|
46007
46066
|
const results = await runAllChecks({
|
|
@@ -46058,13 +46117,13 @@ async function action10(options) {
|
|
|
46058
46117
|
}
|
|
46059
46118
|
}
|
|
46060
46119
|
function registerDoctor(program2) {
|
|
46061
|
-
program2.command("doctor").description("Run diagnostic checks against the installed Cerefox.").option("--json", "Emit machine-readable JSON (no colours, structured output).").action(
|
|
46120
|
+
program2.command("doctor").description("Run diagnostic checks against the installed Cerefox.").option("--json", "Emit machine-readable JSON (no colours, structured output).").action(action11);
|
|
46062
46121
|
}
|
|
46063
46122
|
|
|
46064
46123
|
// src/cli/commands/get-audit-log.ts
|
|
46065
46124
|
init_cli_core();
|
|
46066
46125
|
init_client();
|
|
46067
|
-
async function
|
|
46126
|
+
async function action12(options) {
|
|
46068
46127
|
const limit = parsePositiveInt(options.limit, "--limit", 50);
|
|
46069
46128
|
const client = getClient();
|
|
46070
46129
|
const data = await client.rpc("cerefox_list_audit_entries", {
|
|
@@ -46102,14 +46161,14 @@ async function action11(options) {
|
|
|
46102
46161
|
})));
|
|
46103
46162
|
}
|
|
46104
46163
|
function registerGetAuditLog(program2) {
|
|
46105
|
-
program2.command("get-audit-log").description("Query the audit log with optional filters.").option("-d, --document-id <uuid>", "Filter by document.").option("-a, --author <name>", "Filter by author.").option("-o, --operation <type>", "Filter by operation: create, update-content, update-metadata, delete, restore.").option("--since <iso>", "Lower-bound ISO timestamp.").option("--until <iso>", "Upper-bound ISO timestamp.").option("-l, --limit <n>", "Maximum entries (max 200).", "50").option("-r, --requestor <name>", "Agent / user name (usage log).").option("--json", "Emit machine-readable JSON.").action(
|
|
46164
|
+
program2.command("get-audit-log").description("Query the audit log with optional filters.").option("-d, --document-id <uuid>", "Filter by document.").option("-a, --author <name>", "Filter by author.").option("-o, --operation <type>", "Filter by operation: create, update-content, update-metadata, delete, restore.").option("--since <iso>", "Lower-bound ISO timestamp.").option("--until <iso>", "Upper-bound ISO timestamp.").option("-l, --limit <n>", "Maximum entries (max 200).", "50").option("-r, --requestor <name>", "Agent / user name (usage log).").option("--json", "Emit machine-readable JSON.").action(action12);
|
|
46106
46165
|
}
|
|
46107
46166
|
|
|
46108
46167
|
// src/cli/commands/get-doc.ts
|
|
46109
46168
|
init_cli_core();
|
|
46110
46169
|
init_cli_core();
|
|
46111
46170
|
init_client();
|
|
46112
|
-
async function
|
|
46171
|
+
async function action13(documentId, options) {
|
|
46113
46172
|
const client = getClient();
|
|
46114
46173
|
const rows = await client.rpc("cerefox_get_document", {
|
|
46115
46174
|
p_document_id: documentId,
|
|
@@ -46139,7 +46198,7 @@ async function action12(documentId, options) {
|
|
|
46139
46198
|
println(doc.full_content);
|
|
46140
46199
|
}
|
|
46141
46200
|
function registerGetDoc(program2) {
|
|
46142
|
-
program2.command("get-doc").description("Retrieve the full content of a document by ID.").argument("<document-id>", "UUID of the document.").option("--version-id <uuid>", "Specific archived version (default: current).").option("-r, --requestor <name>", "Agent / user name (usage log).").option("--json", "Emit machine-readable JSON.").action(
|
|
46201
|
+
program2.command("get-doc").description("Retrieve the full content of a document by ID.").argument("<document-id>", "UUID of the document.").option("--version-id <uuid>", "Specific archived version (default: current).").option("-r, --requestor <name>", "Agent / user name (usage log).").option("--json", "Emit machine-readable JSON.").action(action13);
|
|
46143
46202
|
}
|
|
46144
46203
|
|
|
46145
46204
|
// src/cli/commands/ingest.ts
|
|
@@ -46876,7 +46935,7 @@ async function readContent(path, paste) {
|
|
|
46876
46935
|
const titleFromPath = basename2(path, extname2(path));
|
|
46877
46936
|
return { content, titleFromPath };
|
|
46878
46937
|
}
|
|
46879
|
-
async function
|
|
46938
|
+
async function action14(path, options) {
|
|
46880
46939
|
const { content, titleFromPath } = await readContent(path, Boolean(options.paste));
|
|
46881
46940
|
const title = options.title ?? titleFromPath;
|
|
46882
46941
|
if (!title || title.trim() === "") {
|
|
@@ -46948,7 +47007,7 @@ async function action13(path, options) {
|
|
|
46948
47007
|
}
|
|
46949
47008
|
}
|
|
46950
47009
|
function registerIngest(program2) {
|
|
46951
|
-
program2.command("ingest").description("Ingest a file (or stdin paste) into the knowledge base.").argument("[path]", "Path to the file to ingest. Omit when using --paste.").option("--paste", "Read content from stdin instead of a file.").option("-t, --title <title>", "Document title (required with --paste; defaults to filename without extension).").option("-p, --project-name <name>", "Single project membership (non-destructive on update).").option("-P, --project-names <names>", "Comma-separated full project membership set (destructive replace on update).").option("-m, --metadata <json>", "JSON metadata object.").option("--source <label>", "Origin label (default: cli).", "cli").option("-u, --update-if-exists", "Update an existing doc with the same title.").option("-i, --document-id <uuid>", "Update a specific document by UUID (overrides --update-if-exists).").option("-a, --author <name>", "Caller identity (audit log).").option("--author-type <type>", "'user' or 'agent' (default: user).", "user").action(
|
|
47010
|
+
program2.command("ingest").description("Ingest a file (or stdin paste) into the knowledge base.").argument("[path]", "Path to the file to ingest. Omit when using --paste.").option("--paste", "Read content from stdin instead of a file.").option("-t, --title <title>", "Document title (required with --paste; defaults to filename without extension).").option("-p, --project-name <name>", "Single project membership (non-destructive on update).").option("-P, --project-names <names>", "Comma-separated full project membership set (destructive replace on update).").option("-m, --metadata <json>", "JSON metadata object.").option("--source <label>", "Origin label (default: cli).", "cli").option("-u, --update-if-exists", "Update an existing doc with the same title.").option("-i, --document-id <uuid>", "Update a specific document by UUID (overrides --update-if-exists).").option("-a, --author <name>", "Caller identity (audit log).").option("--author-type <type>", "'user' or 'agent' (default: user).", "user").action(action14);
|
|
46952
47011
|
}
|
|
46953
47012
|
|
|
46954
47013
|
// src/cli/commands/ingest-dir.ts
|
|
@@ -46984,7 +47043,7 @@ function walk(dir, extensions) {
|
|
|
46984
47043
|
}
|
|
46985
47044
|
return files;
|
|
46986
47045
|
}
|
|
46987
|
-
async function
|
|
47046
|
+
async function action15(dir, options) {
|
|
46988
47047
|
const extensions = new Set((options.extensions ?? ".md,.txt").split(",").map((e) => e.trim().toLowerCase()).map((e) => e.startsWith(".") ? e : "." + e).filter((e) => e.length > 0));
|
|
46989
47048
|
const files = walk(dir, extensions);
|
|
46990
47049
|
if (files.length === 0) {
|
|
@@ -47057,7 +47116,7 @@ async function action14(dir, options) {
|
|
|
47057
47116
|
}
|
|
47058
47117
|
}
|
|
47059
47118
|
function registerIngestDir(program2) {
|
|
47060
|
-
program2.command("ingest-dir").description("Recursively ingest a directory of markdown / text files.").argument("<dir>", "Root directory to walk.").option("-p, --project-name <name>", "Project membership for all ingested docs.").option("-m, --metadata <json>", "JSON metadata applied to every doc.").option("--source <label>", "Origin label (default: cli).", "cli").option("-u, --update-if-exists", "Update an existing doc with the same title.").option("-a, --author <name>", "Caller identity (audit log).").option("--author-type <type>", "'user' or 'agent' (default: user).", "user").option("-e, --extensions <list>", "Comma-separated file extensions to ingest.", ".md,.txt").action(
|
|
47119
|
+
program2.command("ingest-dir").description("Recursively ingest a directory of markdown / text files.").argument("<dir>", "Root directory to walk.").option("-p, --project-name <name>", "Project membership for all ingested docs.").option("-m, --metadata <json>", "JSON metadata applied to every doc.").option("--source <label>", "Origin label (default: cli).", "cli").option("-u, --update-if-exists", "Update an existing doc with the same title.").option("-a, --author <name>", "Caller identity (audit log).").option("--author-type <type>", "'user' or 'agent' (default: user).", "user").option("-e, --extensions <list>", "Comma-separated file extensions to ingest.", ".md,.txt").action(action15);
|
|
47061
47120
|
}
|
|
47062
47121
|
|
|
47063
47122
|
// src/cli/commands/init.ts
|
|
@@ -47387,7 +47446,7 @@ function writeAnswersTo(target, answers) {
|
|
|
47387
47446
|
}
|
|
47388
47447
|
}
|
|
47389
47448
|
}
|
|
47390
|
-
async function
|
|
47449
|
+
async function action17(options) {
|
|
47391
47450
|
const homeEnv = join9(homedir5(), USER_STATE_DIR_NAME, ".env");
|
|
47392
47451
|
const cwdEnv = join9(process.cwd(), ".env");
|
|
47393
47452
|
const explicitDir = (process.env.CEREFOX_CONFIG_DIR ?? "").trim();
|
|
@@ -47496,13 +47555,13 @@ async function action16(options) {
|
|
|
47496
47555
|
await postWriteLifecycle(target, options);
|
|
47497
47556
|
}
|
|
47498
47557
|
function registerInit(program2) {
|
|
47499
|
-
program2.command("init").description("Interactive first-run setup (config, schema deploy stub, optional MCP wiring).").option("-c, --config <file>", "Non-interactive mode: read answers from a JSON file.").option("--force", "Overwrite existing configuration without prompting.").option("--skip-schema", "Skip the schema deploy step.").option("--skip-self-docs", "Skip the bundled self-doc ingest.").option("--skip-agent-config", "Skip the optional MCP agent wiring.").action(
|
|
47558
|
+
program2.command("init").description("Interactive first-run setup (config, schema deploy stub, optional MCP wiring).").option("-c, --config <file>", "Non-interactive mode: read answers from a JSON file.").option("--force", "Overwrite existing configuration without prompting.").option("--skip-schema", "Skip the schema deploy step.").option("--skip-self-docs", "Skip the bundled self-doc ingest.").option("--skip-agent-config", "Skip the optional MCP agent wiring.").action(action17);
|
|
47500
47559
|
}
|
|
47501
47560
|
|
|
47502
47561
|
// src/cli/commands/list-docs.ts
|
|
47503
47562
|
init_cli_core();
|
|
47504
47563
|
init_client();
|
|
47505
|
-
async function
|
|
47564
|
+
async function action18(options) {
|
|
47506
47565
|
const limit = parsePositiveInt(options.limit, "--limit", 100);
|
|
47507
47566
|
const client = getClient();
|
|
47508
47567
|
let projectId;
|
|
@@ -47557,13 +47616,13 @@ async function action17(options) {
|
|
|
47557
47616
|
})));
|
|
47558
47617
|
}
|
|
47559
47618
|
function registerListDocs(program2) {
|
|
47560
|
-
program2.command("list-docs").description("List documents in the knowledge base.").option("-p, --project <name>", "Filter to a specific project.").option("-l, --limit <n>", "Maximum docs to return.", "100").option("--json", "Emit machine-readable JSON.").action(
|
|
47619
|
+
program2.command("list-docs").description("List documents in the knowledge base.").option("-p, --project <name>", "Filter to a specific project.").option("-l, --limit <n>", "Maximum docs to return.", "100").option("--json", "Emit machine-readable JSON.").action(action18);
|
|
47561
47620
|
}
|
|
47562
47621
|
|
|
47563
47622
|
// src/cli/commands/list-metadata-keys.ts
|
|
47564
47623
|
init_cli_core();
|
|
47565
47624
|
init_client();
|
|
47566
|
-
async function
|
|
47625
|
+
async function action19(options) {
|
|
47567
47626
|
const client = getClient();
|
|
47568
47627
|
const data = await client.rpc("cerefox_list_metadata_keys");
|
|
47569
47628
|
if (data === null) {
|
|
@@ -47591,13 +47650,13 @@ async function action18(options) {
|
|
|
47591
47650
|
})));
|
|
47592
47651
|
}
|
|
47593
47652
|
function registerListMetadataKeys(program2) {
|
|
47594
|
-
program2.command("list-metadata-keys").description("List all metadata keys with document counts and example values.").option("-r, --requestor <name>", "Agent / user name (usage log).").option("--json", "Emit machine-readable JSON.").action(
|
|
47653
|
+
program2.command("list-metadata-keys").description("List all metadata keys with document counts and example values.").option("-r, --requestor <name>", "Agent / user name (usage log).").option("--json", "Emit machine-readable JSON.").action(action19);
|
|
47595
47654
|
}
|
|
47596
47655
|
|
|
47597
47656
|
// src/cli/commands/list-projects.ts
|
|
47598
47657
|
init_cli_core();
|
|
47599
47658
|
init_client();
|
|
47600
|
-
async function
|
|
47659
|
+
async function action20(options) {
|
|
47601
47660
|
const client = getClient();
|
|
47602
47661
|
const { data, error: error2 } = await client.raw.from("cerefox_projects").select("id, name, description, created_at").order("name", { ascending: true });
|
|
47603
47662
|
if (error2) {
|
|
@@ -47626,13 +47685,13 @@ async function action19(options) {
|
|
|
47626
47685
|
})), "(no projects)");
|
|
47627
47686
|
}
|
|
47628
47687
|
function registerListProjects(program2) {
|
|
47629
|
-
program2.command("list-projects").description("List all projects in the knowledge base.").option("-r, --requestor <name>", "Agent / user name (usage log).").option("--json", "Emit machine-readable JSON.").action(
|
|
47688
|
+
program2.command("list-projects").description("List all projects in the knowledge base.").option("-r, --requestor <name>", "Agent / user name (usage log).").option("--json", "Emit machine-readable JSON.").action(action20);
|
|
47630
47689
|
}
|
|
47631
47690
|
|
|
47632
47691
|
// src/cli/commands/list-versions.ts
|
|
47633
47692
|
init_cli_core();
|
|
47634
47693
|
init_client();
|
|
47635
|
-
async function
|
|
47694
|
+
async function action21(documentId, options) {
|
|
47636
47695
|
const client = getClient();
|
|
47637
47696
|
const data = await client.rpc("cerefox_list_document_versions", {
|
|
47638
47697
|
p_document_id: documentId
|
|
@@ -47673,7 +47732,7 @@ async function action20(documentId, options) {
|
|
|
47673
47732
|
})));
|
|
47674
47733
|
}
|
|
47675
47734
|
function registerListVersions(program2) {
|
|
47676
|
-
program2.command("list-versions").description("List archived versions of a document.").argument("<document-id>", "UUID of the document.").option("-r, --requestor <name>", "Agent / user name (usage log).").option("--json", "Emit machine-readable JSON.").action(
|
|
47735
|
+
program2.command("list-versions").description("List archived versions of a document.").argument("<document-id>", "UUID of the document.").option("-r, --requestor <name>", "Agent / user name (usage log).").option("--json", "Emit machine-readable JSON.").action(action21);
|
|
47677
47736
|
}
|
|
47678
47737
|
|
|
47679
47738
|
// src/cli/commands/mcp.ts
|
|
@@ -47688,7 +47747,7 @@ function registerMcp(program2) {
|
|
|
47688
47747
|
// src/cli/commands/metadata-search.ts
|
|
47689
47748
|
init_cli_core();
|
|
47690
47749
|
init_client();
|
|
47691
|
-
async function
|
|
47750
|
+
async function action22(options) {
|
|
47692
47751
|
const metadataFilter = parseJsonObjectArg(options.metadataFilter, "--metadata-filter");
|
|
47693
47752
|
if (!metadataFilter || Object.keys(metadataFilter).length === 0) {
|
|
47694
47753
|
throw userError("--metadata-filter is required and must be a non-empty JSON object.", `Example: --metadata-filter '{"type":"decision-log"}'.`);
|
|
@@ -47751,7 +47810,7 @@ async function action21(options) {
|
|
|
47751
47810
|
}
|
|
47752
47811
|
}
|
|
47753
47812
|
function registerMetadataSearch(program2) {
|
|
47754
|
-
program2.command("metadata-search").description("Find documents by metadata criteria (no text query).").requiredOption("-f, --metadata-filter <json>", "JSON object; only docs whose metadata contains ALL pairs are returned.").option("-p, --project-name <name>", "Filter to a specific project.").option("--updated-since <iso>", "Only docs updated on/after this ISO timestamp.").option("--created-since <iso>", "Only docs created on/after this ISO timestamp.").option("--include-content", "Include full document text in results.").option("-l, --limit <n>", "Maximum docs to return.", "10").option("--max-bytes <n>", "Response size budget in bytes (with --include-content).", "200000").option("-r, --requestor <name>", "Agent / user name (usage log).").option("--json", "Emit machine-readable JSON.").action(
|
|
47813
|
+
program2.command("metadata-search").description("Find documents by metadata criteria (no text query).").requiredOption("-f, --metadata-filter <json>", "JSON object; only docs whose metadata contains ALL pairs are returned.").option("-p, --project-name <name>", "Filter to a specific project.").option("--updated-since <iso>", "Only docs updated on/after this ISO timestamp.").option("--created-since <iso>", "Only docs created on/after this ISO timestamp.").option("--include-content", "Include full document text in results.").option("-l, --limit <n>", "Maximum docs to return.", "10").option("--max-bytes <n>", "Response size budget in bytes (with --include-content).", "200000").option("-r, --requestor <name>", "Agent / user name (usage log).").option("--json", "Emit machine-readable JSON.").action(action22);
|
|
47755
47814
|
}
|
|
47756
47815
|
|
|
47757
47816
|
// src/cli/commands/reindex.ts
|
|
@@ -47759,7 +47818,7 @@ init_dist4();
|
|
|
47759
47818
|
init_cli_core();
|
|
47760
47819
|
init_config();
|
|
47761
47820
|
var DEFAULT_MODEL = "text-embedding-3-small";
|
|
47762
|
-
async function
|
|
47821
|
+
async function action23(options) {
|
|
47763
47822
|
const settings = loadSettings();
|
|
47764
47823
|
if (!settings.supabaseUrl || !settings.supabaseKey) {
|
|
47765
47824
|
throw userError("Supabase credentials not configured — run `cerefox init` first.");
|
|
@@ -47838,7 +47897,7 @@ ${c2.content}`;
|
|
|
47838
47897
|
}
|
|
47839
47898
|
}
|
|
47840
47899
|
function registerReindex(program2) {
|
|
47841
|
-
program2.command("reindex").description("Re-embed existing document chunks (v0.7+).").option("--all", "Reindex every chunk regardless of embedder.").option("--batch <n>", "Chunks per OpenAI batch call. Capped at 96 internally.", "32").option("--dry-run", "Show counts without re-embedding.").option("-i, --document-id <uuid>", "Limit reindex to a single document.").action(
|
|
47900
|
+
program2.command("reindex").description("Re-embed existing document chunks (v0.7+).").option("--all", "Reindex every chunk regardless of embedder.").option("--batch <n>", "Chunks per OpenAI batch call. Capped at 96 internally.", "32").option("--dry-run", "Show counts without re-embedding.").option("-i, --document-id <uuid>", "Limit reindex to a single document.").action(action23);
|
|
47842
47901
|
}
|
|
47843
47902
|
|
|
47844
47903
|
// src/cli/commands/restore.ts
|
|
@@ -47868,7 +47927,7 @@ function resolveBackupFile(target) {
|
|
|
47868
47927
|
}
|
|
47869
47928
|
return join10(path, candidates[0].name);
|
|
47870
47929
|
}
|
|
47871
|
-
async function
|
|
47930
|
+
async function action24(target, options) {
|
|
47872
47931
|
const file = resolveBackupFile(target);
|
|
47873
47932
|
let payload;
|
|
47874
47933
|
try {
|
|
@@ -47924,7 +47983,7 @@ async function action23(target, options) {
|
|
|
47924
47983
|
}
|
|
47925
47984
|
}
|
|
47926
47985
|
function registerRestore(program2) {
|
|
47927
|
-
program2.command("restore").description("Restore a JSON-snapshot backup into the knowledge base.").argument("<snapshot>", "Backup file (or directory; most recent is picked) produced by `cerefox backup`.").option("--dry-run", "Print what would be restored without writing.").option("-p, --project-name <name>", "Reserved for future use; currently ignored (project memberships ride along with each doc's metadata).").action(
|
|
47986
|
+
program2.command("restore").description("Restore a JSON-snapshot backup into the knowledge base.").argument("<snapshot>", "Backup file (or directory; most recent is picked) produced by `cerefox backup`.").option("--dry-run", "Print what would be restored without writing.").option("-p, --project-name <name>", "Reserved for future use; currently ignored (project memberships ride along with each doc's metadata).").action(action24);
|
|
47928
47987
|
}
|
|
47929
47988
|
|
|
47930
47989
|
// src/cli/commands/search.ts
|
|
@@ -47949,7 +48008,7 @@ async function embedQuery(query) {
|
|
|
47949
48008
|
}
|
|
47950
48009
|
|
|
47951
48010
|
// src/cli/commands/search.ts
|
|
47952
|
-
async function
|
|
48011
|
+
async function action25(query, options) {
|
|
47953
48012
|
if (!query || query.trim() === "") {
|
|
47954
48013
|
throw userError("Empty query.");
|
|
47955
48014
|
}
|
|
@@ -48083,7 +48142,7 @@ async function action24(query, options) {
|
|
|
48083
48142
|
}
|
|
48084
48143
|
}
|
|
48085
48144
|
function registerSearch(program2) {
|
|
48086
|
-
program2.command("search").description("Search the knowledge base (hybrid FTS + semantic).").argument("<query>", "Natural-language search query.").option("-c, --match-count <n>", "Maximum number of documents to return.", "5").option("-p, --project-name <name>", "Filter results to a specific project.").option("-f, --metadata-filter <json>", "JSON containment filter; only docs whose metadata contains ALL pairs are returned.").option("--mode <mode>", "Search mode: docs (default), hybrid, fts.", "docs").option("--alpha <float>", "Semantic weight 0..1 (default: 0.7).", "0.7").option("--min-score <float>", "Minimum cosine similarity threshold.", "0.5").option("--max-bytes <n>", "Response size budget in bytes.", "200000").option("-r, --requestor <name>", "Agent / user name (recorded in usage log).").option("--json", "Emit machine-readable JSON instead of the default text.").action(
|
|
48145
|
+
program2.command("search").description("Search the knowledge base (hybrid FTS + semantic).").argument("<query>", "Natural-language search query.").option("-c, --match-count <n>", "Maximum number of documents to return.", "5").option("-p, --project-name <name>", "Filter results to a specific project.").option("-f, --metadata-filter <json>", "JSON containment filter; only docs whose metadata contains ALL pairs are returned.").option("--mode <mode>", "Search mode: docs (default), hybrid, fts.", "docs").option("--alpha <float>", "Semantic weight 0..1 (default: 0.7).", "0.7").option("--min-score <float>", "Minimum cosine similarity threshold.", "0.5").option("--max-bytes <n>", "Response size budget in bytes.", "200000").option("-r, --requestor <name>", "Agent / user name (recorded in usage log).").option("--json", "Emit machine-readable JSON instead of the default text.").action(action25);
|
|
48087
48146
|
}
|
|
48088
48147
|
|
|
48089
48148
|
// src/cli/commands/self-update.ts
|
|
@@ -48130,7 +48189,7 @@ async function fetchLatestVersion() {
|
|
|
48130
48189
|
}
|
|
48131
48190
|
return body.version;
|
|
48132
48191
|
}
|
|
48133
|
-
async function
|
|
48192
|
+
async function action26(options) {
|
|
48134
48193
|
let target;
|
|
48135
48194
|
try {
|
|
48136
48195
|
target = options.version ?? await fetchLatestVersion();
|
|
@@ -48182,7 +48241,7 @@ async function action25(options) {
|
|
|
48182
48241
|
}
|
|
48183
48242
|
function registerSelfUpdate(program2) {
|
|
48184
48243
|
const desc = "Upgrade Cerefox in place. Alias: `cerefox upgrade`.";
|
|
48185
|
-
const declaration = (cmd) => cmd.description(desc).option("--check", "Print current vs latest; do nothing.").option("--yes", "Non-interactive (skip confirmation).").option("--version <version>", "Pin a specific version (e.g. 0.5.1 or 0.6.0-rc.1).").action(
|
|
48244
|
+
const declaration = (cmd) => cmd.description(desc).option("--check", "Print current vs latest; do nothing.").option("--yes", "Non-interactive (skip confirmation).").option("--version <version>", "Pin a specific version (e.g. 0.5.1 or 0.6.0-rc.1).").action(action26);
|
|
48186
48245
|
declaration(program2.command("self-update"));
|
|
48187
48246
|
declaration(program2.command("upgrade"));
|
|
48188
48247
|
}
|
|
@@ -48201,7 +48260,7 @@ function symbol2(status) {
|
|
|
48201
48260
|
return cErr.dim("ℹ");
|
|
48202
48261
|
}
|
|
48203
48262
|
}
|
|
48204
|
-
async function
|
|
48263
|
+
async function action27(options) {
|
|
48205
48264
|
const useSpinner = !options.json && process.stderr.isTTY;
|
|
48206
48265
|
const spinner = useSpinner ? ora({ text: "Starting checks…", spinner: "dots", stream: process.stderr }).start() : null;
|
|
48207
48266
|
const results = await runFastChecks({
|
|
@@ -48222,7 +48281,7 @@ async function action26(options) {
|
|
|
48222
48281
|
}
|
|
48223
48282
|
}
|
|
48224
48283
|
function registerStatus(program2) {
|
|
48225
|
-
program2.command("status").description("Quick sanity check (fast subset of `cerefox doctor`).").option("--json", "Emit machine-readable JSON.").action(
|
|
48284
|
+
program2.command("status").description("Quick sanity check (fast subset of `cerefox doctor`).").option("--json", "Emit machine-readable JSON.").action(action27);
|
|
48226
48285
|
}
|
|
48227
48286
|
|
|
48228
48287
|
// src/cli/commands/sync-docs.ts
|
|
@@ -48258,7 +48317,7 @@ function walkMarkdown(dir) {
|
|
|
48258
48317
|
}
|
|
48259
48318
|
return out;
|
|
48260
48319
|
}
|
|
48261
|
-
async function
|
|
48320
|
+
async function action28(options) {
|
|
48262
48321
|
const cwd = process.cwd();
|
|
48263
48322
|
const project = options.project ?? "cerefox";
|
|
48264
48323
|
const targets = [];
|
|
@@ -48320,7 +48379,7 @@ async function action27(options) {
|
|
|
48320
48379
|
}
|
|
48321
48380
|
}
|
|
48322
48381
|
function registerSyncDocs(program2) {
|
|
48323
|
-
program2.command("sync-docs").description("Sync repo docs (README, AGENT_*, docs/) into a Cerefox project.").option("--dry-run", "Print what would be synced without writing.").option("-p, --project <name>", "Target project for the sync.", "cerefox").action(
|
|
48382
|
+
program2.command("sync-docs").description("Sync repo docs (README, AGENT_*, docs/) into a Cerefox project.").option("--dry-run", "Print what would be synced without writing.").option("-p, --project <name>", "Target project for the sync.", "cerefox").action(action28);
|
|
48324
48383
|
}
|
|
48325
48384
|
|
|
48326
48385
|
// src/cli/program.ts
|
|
@@ -53313,15 +53372,56 @@ function registerWeb(program2) {
|
|
|
53313
53372
|
}
|
|
53314
53373
|
|
|
53315
53374
|
// src/cli/program.ts
|
|
53375
|
+
function moveInto(parent, register, newName) {
|
|
53376
|
+
register(parent);
|
|
53377
|
+
const cmd = parent.commands[parent.commands.length - 1];
|
|
53378
|
+
cmd.name(newName);
|
|
53379
|
+
return cmd;
|
|
53380
|
+
}
|
|
53381
|
+
var RENAMED_VERBS = [
|
|
53382
|
+
["get-doc", "document get"],
|
|
53383
|
+
["list-docs", "document list"],
|
|
53384
|
+
["delete-doc", "document delete"],
|
|
53385
|
+
["ingest", "document ingest"],
|
|
53386
|
+
["ingest-dir", "document ingest-dir"],
|
|
53387
|
+
["list-projects", "project list"],
|
|
53388
|
+
["delete-project", "project delete"],
|
|
53389
|
+
["list-versions", "version list"],
|
|
53390
|
+
["get-audit-log", "audit list"],
|
|
53391
|
+
["list-metadata-keys", "metadata keys"],
|
|
53392
|
+
["metadata-search", "metadata search"],
|
|
53393
|
+
["config-get", "config get"],
|
|
53394
|
+
["config-set", "config set"],
|
|
53395
|
+
["restore", "backup restore"],
|
|
53396
|
+
["deploy-server", "server deploy"],
|
|
53397
|
+
["reindex", "server reindex"]
|
|
53398
|
+
];
|
|
53399
|
+
function registerRenameHusks(program2) {
|
|
53400
|
+
for (const [oldName, newForm] of RENAMED_VERBS) {
|
|
53401
|
+
program2.command(oldName, { hidden: true }).allowUnknownOption(true).allowExcessArguments(true).argument("[args...]", "(renamed)").action(() => {
|
|
53402
|
+
eprintln(c.yellow(`✗ \`cerefox ${oldName}\` was renamed in v0.9.0.`));
|
|
53403
|
+
eprintln(` Use \`cerefox ${newForm}\` instead (run \`cerefox ${newForm.split(" ")[0]} --help\`).`);
|
|
53404
|
+
process.exit(1);
|
|
53405
|
+
});
|
|
53406
|
+
}
|
|
53407
|
+
}
|
|
53316
53408
|
function buildProgram() {
|
|
53317
|
-
const program2 = new Command("cerefox").description("Cerefox — user-owned shared memory for AI agents.").version(PKG_VERSION, "-v, --version", "Print the cerefox version and exit.").addOption(new Option("--json", "Emit machine-readable JSON on stdout instead of the default human text. " + "Available on read commands; ignored on commands without a JSON shape.").hideHelp()).showHelpAfterError("(run `cerefox --help` for usage)").enablePositionalOptions().addHelpText("after", `
|
|
53318
|
-
|
|
53319
|
-
` + `
|
|
53320
|
-
` + `
|
|
53321
|
-
` + `
|
|
53322
|
-
` + `
|
|
53323
|
-
` + `
|
|
53324
|
-
` + `
|
|
53409
|
+
const program2 = new Command("cerefox").description("Cerefox — user-owned shared memory for AI agents.").version(PKG_VERSION, "-v, --version", "Print the cerefox version and exit.").addOption(new Option("--json", "Emit machine-readable JSON on stdout instead of the default human text. " + "Available on read commands; ignored on commands without a JSON shape.").hideHelp()).showHelpAfterError("(run `cerefox --help` for usage)").enablePositionalOptions().addHelpText("after", "\nResource groups (run `cerefox <group> --help`):\n" + ` document get · list · delete · ingest · ingest-dir
|
|
53410
|
+
` + ` project list · delete
|
|
53411
|
+
` + ` version list
|
|
53412
|
+
` + ` metadata keys · search
|
|
53413
|
+
` + ` audit list
|
|
53414
|
+
` + ` config get · set
|
|
53415
|
+
` + ` backup create · restore
|
|
53416
|
+
` + ` server deploy · reindex
|
|
53417
|
+
` + `
|
|
53418
|
+
Top-level commands:
|
|
53419
|
+
` + ` search · init · doctor · status · configure-agent · self-update
|
|
53420
|
+
` + ` mcp · web · docs · completion · sync-docs · sync-self-docs
|
|
53421
|
+
` + `
|
|
53422
|
+
Renamed in v0.9.0: the old flat verbs (get-doc, list-docs, ingest, …)
|
|
53423
|
+
` + ` now live under the groups above. The old names still run but exit with
|
|
53424
|
+
` + ` a pointer to the new form. They are removed in v1.0.
|
|
53325
53425
|
` + `
|
|
53326
53426
|
Exit codes:
|
|
53327
53427
|
` + ` 0 success 2 system error (unreachable Supabase, RPC failure, …)
|
|
@@ -53333,34 +53433,49 @@ Learn more:
|
|
|
53333
53433
|
` + ` https://github.com/fstamatelopoulos/cerefox
|
|
53334
53434
|
`);
|
|
53335
53435
|
registerSearch(program2);
|
|
53336
|
-
registerGetDoc(program2);
|
|
53337
|
-
registerListDocs(program2);
|
|
53338
|
-
registerListVersions(program2);
|
|
53339
|
-
registerListProjects(program2);
|
|
53340
|
-
registerListMetadataKeys(program2);
|
|
53341
|
-
registerMetadataSearch(program2);
|
|
53342
|
-
registerGetAuditLog(program2);
|
|
53343
|
-
registerIngest(program2);
|
|
53344
|
-
registerIngestDir(program2);
|
|
53345
|
-
registerDeleteDoc(program2);
|
|
53346
|
-
registerDeleteProject(program2);
|
|
53347
|
-
registerMcp(program2);
|
|
53348
|
-
registerWeb(program2);
|
|
53349
53436
|
registerInit(program2);
|
|
53350
53437
|
registerDoctor(program2);
|
|
53351
53438
|
registerStatus(program2);
|
|
53352
53439
|
registerConfigureAgent(program2);
|
|
53353
53440
|
registerSelfUpdate(program2);
|
|
53354
|
-
|
|
53355
|
-
|
|
53356
|
-
registerBackup(program2);
|
|
53357
|
-
registerRestore(program2);
|
|
53358
|
-
registerSyncDocs(program2);
|
|
53441
|
+
registerMcp(program2);
|
|
53442
|
+
registerWeb(program2);
|
|
53359
53443
|
registerDocs(program2);
|
|
53360
|
-
registerReindex(program2);
|
|
53361
|
-
registerConfigGet(program2);
|
|
53362
|
-
registerConfigSet(program2);
|
|
53363
53444
|
registerCompletion(program2);
|
|
53445
|
+
registerSyncDocs(program2);
|
|
53446
|
+
registerSyncSelfDocs(program2);
|
|
53447
|
+
const document2 = program2.command("document").description("Documents: get, list, delete, ingest.");
|
|
53448
|
+
moveInto(document2, registerGetDoc, "get");
|
|
53449
|
+
moveInto(document2, registerListDocs, "list");
|
|
53450
|
+
moveInto(document2, registerDeleteDoc, "delete");
|
|
53451
|
+
registerDocumentRestore(document2);
|
|
53452
|
+
moveInto(document2, registerIngest, "ingest");
|
|
53453
|
+
moveInto(document2, registerIngestDir, "ingest-dir");
|
|
53454
|
+
const project = program2.command("project").description("Projects: list, delete.");
|
|
53455
|
+
moveInto(project, registerListProjects, "list");
|
|
53456
|
+
moveInto(project, registerDeleteProject, "delete");
|
|
53457
|
+
const version4 = program2.command("version").description("Document version history: list, archive, unarchive.");
|
|
53458
|
+
moveInto(version4, registerListVersions, "list");
|
|
53459
|
+
registerVersionArchive(version4);
|
|
53460
|
+
const metadata = program2.command("metadata").description("Metadata: keys, search.");
|
|
53461
|
+
moveInto(metadata, registerListMetadataKeys, "keys");
|
|
53462
|
+
moveInto(metadata, registerMetadataSearch, "search");
|
|
53463
|
+
const audit = program2.command("audit").description("Audit log: list.");
|
|
53464
|
+
moveInto(audit, registerGetAuditLog, "list");
|
|
53465
|
+
const config2 = program2.command("config").description("Runtime config: get, set.");
|
|
53466
|
+
moveInto(config2, registerConfigGet, "get");
|
|
53467
|
+
moveInto(config2, registerConfigSet, "set");
|
|
53468
|
+
const backup = program2.command("backup").description("Backup + restore the knowledge base: create, restore.").action(() => {
|
|
53469
|
+
eprintln(c.yellow("`cerefox backup` needs a subcommand."));
|
|
53470
|
+
eprintln(" Use `cerefox backup create` or `cerefox backup restore`.");
|
|
53471
|
+
process.exit(1);
|
|
53472
|
+
});
|
|
53473
|
+
moveInto(backup, registerBackup, "create");
|
|
53474
|
+
moveInto(backup, registerRestore, "restore");
|
|
53475
|
+
const server = program2.command("server").description("Server side: deploy, reindex.");
|
|
53476
|
+
moveInto(server, registerDeployServer, "deploy");
|
|
53477
|
+
moveInto(server, registerReindex, "reindex");
|
|
53478
|
+
registerRenameHusks(program2);
|
|
53364
53479
|
return program2;
|
|
53365
53480
|
}
|
|
53366
53481
|
|
|
@@ -177,7 +177,7 @@ paths.
|
|
|
177
177
|
| Tier | Operations | Reversible? | Where exposed |
|
|
178
178
|
|---|---|---|---|
|
|
179
179
|
| 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
|
|
180
|
+
| 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
181
|
| 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
182
|
|
|
183
183
|
### Why purge / restore are web-UI-only
|
|
@@ -210,7 +210,7 @@ clear before the operation actually runs).
|
|
|
210
210
|
|
|
211
211
|
If you're building tooling that uses the CLI (Path C) or any MCP/Edge Function path:
|
|
212
212
|
|
|
213
|
-
- **Use `cerefox delete
|
|
213
|
+
- **Use `cerefox document delete` freely** to soft-delete agent-authored content. Pair it
|
|
214
214
|
with `--author <name> --author-type agent` so the audit trail is correct.
|
|
215
215
|
- **Surface the soft-delete to the user.** When your agent decides to delete something,
|
|
216
216
|
tell the user explicitly: "I soft-deleted X (recoverable from the Cerefox trash in
|
|
@@ -221,13 +221,13 @@ If you're building tooling that uses the CLI (Path C) or any MCP/Edge Function p
|
|
|
221
221
|
|
|
222
222
|
### CLI delete-doc — interactive vs scripted
|
|
223
223
|
|
|
224
|
-
`cerefox delete
|
|
224
|
+
`cerefox document delete` prompts for confirmation by default (since `click.confirm` requires
|
|
225
225
|
a TTY, an agent's Bash tool will get an abort instead of accidentally deleting). Agents
|
|
226
226
|
that legitimately need to soft-delete must pass `--yes` *and* set `--author` /
|
|
227
227
|
`--author-type` so the audit log captures who acted:
|
|
228
228
|
|
|
229
229
|
```bash
|
|
230
|
-
cerefox delete
|
|
230
|
+
cerefox document delete <doc-id> --yes \
|
|
231
231
|
--author "claude-code" --author-type "agent"
|
|
232
232
|
```
|
|
233
233
|
|
package/docs/guides/cli.md
CHANGED
|
@@ -16,14 +16,14 @@ Invoke any command with `uv run cerefox <subcommand>`. Inside an activated venv,
|
|
|
16
16
|
|
|
17
17
|
## Commands
|
|
18
18
|
|
|
19
|
-
### `cerefox ingest`
|
|
19
|
+
### `cerefox document ingest`
|
|
20
20
|
|
|
21
21
|
**Purpose**: ingest a markdown / PDF / DOCX file (or stdin) into the knowledge base.
|
|
22
22
|
|
|
23
23
|
**Synopsis**:
|
|
24
24
|
```
|
|
25
|
-
cerefox ingest [OPTIONS] [PATH]
|
|
26
|
-
cerefox ingest --paste --title "<title>" [OPTIONS] # stdin
|
|
25
|
+
cerefox document ingest [OPTIONS] [PATH]
|
|
26
|
+
cerefox document ingest --paste --title "<title>" [OPTIONS] # stdin
|
|
27
27
|
```
|
|
28
28
|
|
|
29
29
|
**Options**:
|
|
@@ -45,18 +45,18 @@ cerefox ingest --paste --title "<title>" [OPTIONS] # stdin
|
|
|
45
45
|
**Examples**:
|
|
46
46
|
```bash
|
|
47
47
|
# Minimal: ingest a file
|
|
48
|
-
cerefox ingest notes.md
|
|
48
|
+
cerefox document ingest notes.md
|
|
49
49
|
|
|
50
50
|
# Paste from stdin
|
|
51
|
-
printf '# Title\n\nbody' | cerefox ingest --paste --title "Title"
|
|
51
|
+
printf '# Title\n\nbody' | cerefox document ingest --paste --title "Title"
|
|
52
52
|
|
|
53
53
|
# Agent ingestion with full attribution
|
|
54
|
-
cerefox ingest notes.md \
|
|
54
|
+
cerefox document ingest notes.md \
|
|
55
55
|
--author "claude-code" --author-type "agent" \
|
|
56
56
|
--project-name "research" --metadata '{"type":"design-doc"}'
|
|
57
57
|
|
|
58
58
|
# Deterministic update (preferred — agents should search → grab ID → ingest)
|
|
59
|
-
cerefox ingest --paste --title "Same Title" \
|
|
59
|
+
cerefox document ingest --paste --title "Same Title" \
|
|
60
60
|
--document-id "abc12345-..." \
|
|
61
61
|
--author "claude-code" --author-type "agent"
|
|
62
62
|
```
|
|
@@ -69,13 +69,13 @@ cerefox ingest --paste --title "Same Title" \
|
|
|
69
69
|
|
|
70
70
|
---
|
|
71
71
|
|
|
72
|
-
### `cerefox ingest-dir`
|
|
72
|
+
### `cerefox document ingest-dir`
|
|
73
73
|
|
|
74
74
|
**Purpose**: bulk-ingest every matching file in a directory.
|
|
75
75
|
|
|
76
76
|
**Synopsis**:
|
|
77
77
|
```
|
|
78
|
-
cerefox ingest-dir [OPTIONS] DIRECTORY
|
|
78
|
+
cerefox document ingest-dir [OPTIONS] DIRECTORY
|
|
79
79
|
```
|
|
80
80
|
|
|
81
81
|
**Options**:
|
|
@@ -94,11 +94,11 @@ cerefox ingest-dir [OPTIONS] DIRECTORY
|
|
|
94
94
|
**Examples**:
|
|
95
95
|
```bash
|
|
96
96
|
# Bulk import research notes with shared metadata
|
|
97
|
-
cerefox ingest-dir ./research-notes --recursive \
|
|
97
|
+
cerefox document ingest-dir ./research-notes --recursive \
|
|
98
98
|
--project-name "research" --metadata '{"type":"research","status":"active"}'
|
|
99
99
|
|
|
100
100
|
# Re-ingest after editing files
|
|
101
|
-
cerefox ingest-dir ./notes --update-if-exists
|
|
101
|
+
cerefox document ingest-dir ./notes --update-if-exists
|
|
102
102
|
```
|
|
103
103
|
|
|
104
104
|
**Output**: one line per file showing `✓` (ingested), `↑` (updated), `⏭` (skipped: hash match), or `❌` (error); summary at the end.
|
|
@@ -143,27 +143,27 @@ cerefox search "what we tried" --mode semantic --requestor "claude-code"
|
|
|
143
143
|
|
|
144
144
|
---
|
|
145
145
|
|
|
146
|
-
### `cerefox get
|
|
146
|
+
### `cerefox document get`
|
|
147
147
|
|
|
148
148
|
**Purpose**: print the full markdown content of a document to stdout.
|
|
149
149
|
|
|
150
150
|
**Synopsis**:
|
|
151
151
|
```
|
|
152
|
-
cerefox get
|
|
152
|
+
cerefox document get [OPTIONS] DOCUMENT_ID
|
|
153
153
|
```
|
|
154
154
|
|
|
155
155
|
**Options**:
|
|
156
156
|
|
|
157
157
|
| Flag | Type | Default | Description |
|
|
158
158
|
|---|---|---|---|
|
|
159
|
-
| `--version-id TEXT` (alias: `--version`) | UUID | _none_ (current) | Archived version UUID — get from `cerefox list
|
|
159
|
+
| `--version-id TEXT` (alias: `--version`) | UUID | _none_ (current) | Archived version UUID — get from `cerefox version list`. |
|
|
160
160
|
| `--requestor TEXT` | str | `CEREFOX_REQUESTOR_NAME` or `user` | Identity recorded in the usage log. |
|
|
161
161
|
|
|
162
162
|
**Examples**:
|
|
163
163
|
```bash
|
|
164
|
-
cerefox get
|
|
165
|
-
cerefox get
|
|
166
|
-
cerefox get
|
|
164
|
+
cerefox document get abc12345-...
|
|
165
|
+
cerefox document get abc12345-... --version-id <version-uuid> # archived
|
|
166
|
+
cerefox document get abc12345-... | bat -l md # pipe to viewer
|
|
167
167
|
```
|
|
168
168
|
|
|
169
169
|
**Output**: title + metadata line, blank line, then raw markdown.
|
|
@@ -172,13 +172,13 @@ cerefox get-doc abc12345-... | bat -l md # pipe to viewer
|
|
|
172
172
|
|
|
173
173
|
---
|
|
174
174
|
|
|
175
|
-
### `cerefox list
|
|
175
|
+
### `cerefox document list`
|
|
176
176
|
|
|
177
177
|
**Purpose**: list documents in the knowledge base.
|
|
178
178
|
|
|
179
179
|
**Synopsis**:
|
|
180
180
|
```
|
|
181
|
-
cerefox list
|
|
181
|
+
cerefox document list [OPTIONS]
|
|
182
182
|
```
|
|
183
183
|
|
|
184
184
|
**Options**:
|
|
@@ -192,13 +192,13 @@ cerefox list-docs [OPTIONS]
|
|
|
192
192
|
|
|
193
193
|
---
|
|
194
194
|
|
|
195
|
-
### `cerefox list
|
|
195
|
+
### `cerefox version list`
|
|
196
196
|
|
|
197
197
|
**Purpose**: list all archived versions of a document.
|
|
198
198
|
|
|
199
199
|
**Synopsis**:
|
|
200
200
|
```
|
|
201
|
-
cerefox list
|
|
201
|
+
cerefox version list [OPTIONS] DOCUMENT_ID
|
|
202
202
|
```
|
|
203
203
|
|
|
204
204
|
**Options**:
|
|
@@ -207,19 +207,19 @@ cerefox list-versions [OPTIONS] DOCUMENT_ID
|
|
|
207
207
|
|---|---|---|---|
|
|
208
208
|
| `--requestor TEXT` | str | `CEREFOX_REQUESTOR_NAME` or `user` | Identity recorded in the usage log. |
|
|
209
209
|
|
|
210
|
-
**Output**: table with version number, created timestamp, source, chunk/char counts, and version UUID. Pass the UUID to `cerefox get
|
|
210
|
+
**Output**: table with version number, created timestamp, source, chunk/char counts, and version UUID. Pass the UUID to `cerefox document get --version-id <uuid>` to retrieve the archived content.
|
|
211
211
|
|
|
212
212
|
**MCP equivalent**: [`cerefox_list_versions`](../../AGENT_GUIDE.md).
|
|
213
213
|
|
|
214
214
|
---
|
|
215
215
|
|
|
216
|
-
### `cerefox list
|
|
216
|
+
### `cerefox project list`
|
|
217
217
|
|
|
218
218
|
**Purpose**: list all projects.
|
|
219
219
|
|
|
220
220
|
**Synopsis**:
|
|
221
221
|
```
|
|
222
|
-
cerefox list
|
|
222
|
+
cerefox project list [OPTIONS]
|
|
223
223
|
```
|
|
224
224
|
|
|
225
225
|
**Options**:
|
|
@@ -232,23 +232,23 @@ cerefox list-projects [OPTIONS]
|
|
|
232
232
|
|
|
233
233
|
---
|
|
234
234
|
|
|
235
|
-
### `cerefox
|
|
235
|
+
### `cerefox metadata keys`
|
|
236
236
|
|
|
237
237
|
**Purpose**: discover metadata keys used across all documents (with example values and document counts).
|
|
238
238
|
|
|
239
|
-
**Synopsis**: `cerefox
|
|
239
|
+
**Synopsis**: `cerefox metadata keys`
|
|
240
240
|
|
|
241
241
|
**MCP equivalent**: [`cerefox_list_metadata_keys`](../../AGENT_GUIDE.md).
|
|
242
242
|
|
|
243
243
|
---
|
|
244
244
|
|
|
245
|
-
### `cerefox metadata
|
|
245
|
+
### `cerefox metadata search`
|
|
246
246
|
|
|
247
247
|
**Purpose**: find documents by metadata key-value criteria (no text query needed).
|
|
248
248
|
|
|
249
249
|
**Synopsis**:
|
|
250
250
|
```
|
|
251
|
-
cerefox metadata
|
|
251
|
+
cerefox metadata search --metadata-filter '<json>' [OPTIONS]
|
|
252
252
|
```
|
|
253
253
|
|
|
254
254
|
**Options**:
|
|
@@ -265,21 +265,21 @@ cerefox metadata-search --metadata-filter '<json>' [OPTIONS]
|
|
|
265
265
|
|
|
266
266
|
**Examples**:
|
|
267
267
|
```bash
|
|
268
|
-
cerefox metadata
|
|
269
|
-
cerefox metadata
|
|
268
|
+
cerefox metadata search --metadata-filter '{"type":"decision-log"}' --updated-since 2026-05-01
|
|
269
|
+
cerefox metadata search --metadata-filter '{"status":"active"}' --project-name "research" --include-content
|
|
270
270
|
```
|
|
271
271
|
|
|
272
272
|
**MCP equivalent**: [`cerefox_metadata_search`](../../AGENT_GUIDE.md).
|
|
273
273
|
|
|
274
274
|
---
|
|
275
275
|
|
|
276
|
-
### `cerefox
|
|
276
|
+
### `cerefox audit list`
|
|
277
277
|
|
|
278
278
|
**Purpose**: query the immutable audit log (who changed what, when).
|
|
279
279
|
|
|
280
280
|
**Synopsis**:
|
|
281
281
|
```
|
|
282
|
-
cerefox
|
|
282
|
+
cerefox audit list [OPTIONS]
|
|
283
283
|
```
|
|
284
284
|
|
|
285
285
|
**Options**:
|
|
@@ -298,24 +298,24 @@ cerefox get-audit-log [OPTIONS]
|
|
|
298
298
|
**Examples**:
|
|
299
299
|
```bash
|
|
300
300
|
# All audit entries in the last week
|
|
301
|
-
cerefox
|
|
301
|
+
cerefox audit list --since 2026-05-11
|
|
302
302
|
|
|
303
303
|
# All edits by a specific agent
|
|
304
|
-
cerefox
|
|
304
|
+
cerefox audit list --author "claude-code" --operation update-content
|
|
305
305
|
|
|
306
306
|
# JSON output, piped to jq
|
|
307
|
-
cerefox
|
|
307
|
+
cerefox audit list --json --limit 1000 | jq 'select(.author_type == "agent")'
|
|
308
308
|
```
|
|
309
309
|
|
|
310
310
|
**MCP equivalent**: [`cerefox_get_audit_log`](../../AGENT_GUIDE.md).
|
|
311
311
|
|
|
312
312
|
---
|
|
313
313
|
|
|
314
|
-
### `cerefox delete
|
|
314
|
+
### `cerefox document delete`
|
|
315
315
|
|
|
316
316
|
**Purpose**: **soft-delete** a document — moves it to trash, recoverable. The CLI cannot permanently delete or restore; see [Destructive operations and the trust model](access-paths.md#destructive-operations-and-the-trust-model) for the rationale.
|
|
317
317
|
|
|
318
|
-
**Synopsis**: `cerefox delete
|
|
318
|
+
**Synopsis**: `cerefox document delete [OPTIONS] DOCUMENT_ID`
|
|
319
319
|
|
|
320
320
|
**Options**:
|
|
321
321
|
|
|
@@ -327,7 +327,7 @@ cerefox get-audit-log --json --limit 1000 | jq 'select(.author_type == "agent")'
|
|
|
327
327
|
|
|
328
328
|
**What this command does:**
|
|
329
329
|
- Sets `deleted_at` on the document row. The document stays in the database.
|
|
330
|
-
- Excludes the document from search and from `cerefox list
|
|
330
|
+
- Excludes the document from search and from `cerefox document list`.
|
|
331
331
|
- Writes an immutable `delete` audit-log entry with the resolved author / author_type and timestamp.
|
|
332
332
|
|
|
333
333
|
**What this command does NOT do:**
|
|
@@ -340,7 +340,7 @@ cerefox get-audit-log --json --limit 1000 | jq 'select(.author_type == "agent")'
|
|
|
340
340
|
**Agent usage**:
|
|
341
341
|
```bash
|
|
342
342
|
# Required: --yes (no TTY for confirmation) + identity flags
|
|
343
|
-
cerefox delete
|
|
343
|
+
cerefox document delete <doc-id> --yes \
|
|
344
344
|
--author "claude-code" --author-type "agent"
|
|
345
345
|
```
|
|
346
346
|
The success message echoes the resolved author / author_type back so you can surface it to the user in your response.
|
|
@@ -349,11 +349,11 @@ The success message echoes the resolved author / author_type back so you can sur
|
|
|
349
349
|
|
|
350
350
|
---
|
|
351
351
|
|
|
352
|
-
### `cerefox reindex`
|
|
352
|
+
### `cerefox server reindex`
|
|
353
353
|
|
|
354
354
|
**Purpose**: re-embed chunks (e.g. after switching embedding models or pulling a schema change like title-boosting).
|
|
355
355
|
|
|
356
|
-
**Synopsis**: `cerefox reindex [OPTIONS]`
|
|
356
|
+
**Synopsis**: `cerefox server reindex [OPTIONS]`
|
|
357
357
|
|
|
358
358
|
**Options**:
|
|
359
359
|
|
|
@@ -365,14 +365,14 @@ The success message echoes the resolved author / author_type back so you can sur
|
|
|
365
365
|
|
|
366
366
|
---
|
|
367
367
|
|
|
368
|
-
### `cerefox config
|
|
368
|
+
### `cerefox config get` / `cerefox config set`
|
|
369
369
|
|
|
370
370
|
**Purpose**: read/write runtime config in `cerefox_config` (e.g. `usage_tracking_enabled`).
|
|
371
371
|
|
|
372
372
|
**Synopsis**:
|
|
373
373
|
```
|
|
374
|
-
cerefox config
|
|
375
|
-
cerefox config
|
|
374
|
+
cerefox config get KEY
|
|
375
|
+
cerefox config set KEY VALUE
|
|
376
376
|
```
|
|
377
377
|
|
|
378
378
|
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.
|
|
@@ -436,14 +436,14 @@ Every MCP parameter has an exact-name CLI flag (kebab-cased). Short forms exist
|
|
|
436
436
|
| MCP tool | CLI command |
|
|
437
437
|
|---|---|
|
|
438
438
|
| `cerefox_search(query, match_count, project_name, metadata_filter, requestor)` | `cerefox search "<q>" --match-count N --project-name <name> --metadata-filter '<json>' --requestor <name>` |
|
|
439
|
-
| `cerefox_ingest(title, content, project_name, metadata, update_if_exists, document_id, source, author, author_type)` (file) | `cerefox ingest <path> --title <t> --project-name <n> --metadata '<json>' --update-if-exists\|--document-id <uuid> --source <s> --author <a> --author-type <t>` |
|
|
440
|
-
| `cerefox_ingest(...)` (paste) | `printf '...' \| cerefox ingest --paste --title "<t>"` (same flags) |
|
|
441
|
-
| `cerefox_get_document(document_id, version_id, requestor)` | `cerefox get
|
|
442
|
-
| `cerefox_list_versions(document_id, requestor)` | `cerefox list
|
|
443
|
-
| `cerefox_list_projects(requestor)` | `cerefox list
|
|
444
|
-
| `cerefox_list_metadata_keys()` | `cerefox
|
|
445
|
-
| `cerefox_metadata_search(metadata_filter, project_name, updated_since, created_since, limit, include_content, requestor)` | `cerefox metadata
|
|
446
|
-
| `cerefox_get_audit_log(document_id, author, operation, since, until, limit, requestor)` | `cerefox
|
|
439
|
+
| `cerefox_ingest(title, content, project_name, metadata, update_if_exists, document_id, source, author, author_type)` (file) | `cerefox document ingest <path> --title <t> --project-name <n> --metadata '<json>' --update-if-exists\|--document-id <uuid> --source <s> --author <a> --author-type <t>` |
|
|
440
|
+
| `cerefox_ingest(...)` (paste) | `printf '...' \| cerefox document ingest --paste --title "<t>"` (same flags) |
|
|
441
|
+
| `cerefox_get_document(document_id, version_id, requestor)` | `cerefox document get <id> --version-id <vid> --requestor <name>` |
|
|
442
|
+
| `cerefox_list_versions(document_id, requestor)` | `cerefox version list <id> --requestor <name>` |
|
|
443
|
+
| `cerefox_list_projects(requestor)` | `cerefox project list --requestor <name>` |
|
|
444
|
+
| `cerefox_list_metadata_keys()` | `cerefox metadata keys` |
|
|
445
|
+
| `cerefox_metadata_search(metadata_filter, project_name, updated_since, created_since, limit, include_content, requestor)` | `cerefox metadata search --metadata-filter '<json>' --project-name <n> --updated-since <iso> --created-since <iso> --limit N --include-content --requestor <name>` |
|
|
446
|
+
| `cerefox_get_audit_log(document_id, author, operation, since, until, limit, requestor)` | `cerefox audit list --document-id <id> --author <a> --operation <op> --since <iso> --until <iso> --limit N --requestor <name>` |
|
|
447
447
|
|
|
448
448
|
## Known issues
|
|
449
449
|
|
|
@@ -453,7 +453,7 @@ None outstanding as of v0.1.17 (cerefox#27 — the `cerefox search` NameError
|
|
|
453
453
|
|
|
454
454
|
### Bulk-import a directory with shared metadata
|
|
455
455
|
```bash
|
|
456
|
-
cerefox ingest-dir ./papers --recursive --pattern '*.pdf' \
|
|
456
|
+
cerefox document ingest-dir ./papers --recursive --pattern '*.pdf' \
|
|
457
457
|
--project-name "literature" \
|
|
458
458
|
--metadata '{"type":"paper","status":"reviewed"}'
|
|
459
459
|
```
|
|
@@ -465,7 +465,7 @@ cerefox search "the OAuth design doc" --match-count 1
|
|
|
465
465
|
|
|
466
466
|
# Step 2: copy the id from `Doc: ... (id: <uuid>)` line
|
|
467
467
|
# Step 3: update in place
|
|
468
|
-
printf '%s' "$NEW_CONTENT" | cerefox ingest --paste \
|
|
468
|
+
printf '%s' "$NEW_CONTENT" | cerefox document ingest --paste \
|
|
469
469
|
--title "OAuth 2.1 Design Document" \
|
|
470
470
|
--document-id "<uuid>" \
|
|
471
471
|
--author "claude-code" --author-type "agent"
|
|
@@ -474,7 +474,7 @@ printf '%s' "$NEW_CONTENT" | cerefox ingest --paste \
|
|
|
474
474
|
### Unattended sync job
|
|
475
475
|
```bash
|
|
476
476
|
# In a cron job / launchd plist. Set CEREFOX_AUTHOR_NAME=sync-script in env.
|
|
477
|
-
cd /path/to/cerefox && uv run cerefox ingest-dir ~/notes --recursive --update-if-exists
|
|
477
|
+
cd /path/to/cerefox && uv run cerefox document ingest-dir ~/notes --recursive --update-if-exists
|
|
478
478
|
```
|
|
479
479
|
|
|
480
480
|
### Use the CLI from an agent's Bash tool
|
|
@@ -121,7 +121,7 @@ The `metadata_filter` search parameter (available in all search modes, all acces
|
|
|
121
121
|
- All key-value pairs must match (AND semantics via PostgreSQL `@>` operator)
|
|
122
122
|
- Uses the existing GIN index on `cerefox_documents.metadata` — no additional schema changes needed
|
|
123
123
|
- `NULL` filter = no restriction (backwards-compatible default)
|
|
124
|
-
- Discover available keys via `cerefox_list_metadata_keys` MCP tool or `cerefox
|
|
124
|
+
- Discover available keys via `cerefox_list_metadata_keys` MCP tool or `cerefox metadata keys` CLI
|
|
125
125
|
|
|
126
126
|
Access paths:
|
|
127
127
|
- **MCP tool**: `metadata_filter` argument on `cerefox_search`
|
|
@@ -209,8 +209,8 @@ Metadata-only updates (same content, different title or project) do **not** crea
|
|
|
209
209
|
|
|
210
210
|
To view and retrieve previous versions:
|
|
211
211
|
```bash
|
|
212
|
-
uv run cerefox list
|
|
213
|
-
uv run cerefox get
|
|
212
|
+
uv run cerefox version list <document-id>
|
|
213
|
+
uv run cerefox document get <document-id> --version <version-id>
|
|
214
214
|
```
|
|
215
215
|
|
|
216
216
|
---
|
|
@@ -281,7 +281,7 @@ Change `CEREFOX_OPENAI_EMBEDDING_MODEL` and `CEREFOX_OPENAI_EMBEDDING_DIMENSIONS
|
|
|
281
281
|
### Step 2 — Re-embed all stored chunks
|
|
282
282
|
|
|
283
283
|
```bash
|
|
284
|
-
uv run cerefox reindex
|
|
284
|
+
uv run cerefox server reindex
|
|
285
285
|
```
|
|
286
286
|
|
|
287
287
|
This re-embeds every chunk in the database using the model now configured in `.env`.
|
|
@@ -351,13 +351,13 @@ This means:
|
|
|
351
351
|
**Via CLI:**
|
|
352
352
|
```bash
|
|
353
353
|
# Enable
|
|
354
|
-
cerefox config
|
|
354
|
+
cerefox config set usage_tracking_enabled true
|
|
355
355
|
|
|
356
356
|
# Disable
|
|
357
|
-
cerefox config
|
|
357
|
+
cerefox config set usage_tracking_enabled false
|
|
358
358
|
|
|
359
359
|
# Check current state
|
|
360
|
-
cerefox config
|
|
360
|
+
cerefox config get usage_tracking_enabled
|
|
361
361
|
```
|
|
362
362
|
|
|
363
363
|
**Via REST API:**
|
|
@@ -401,7 +401,7 @@ The `access_path` is set by the caller layer (not the end user):
|
|
|
401
401
|
|
|
402
402
|
**CLI:**
|
|
403
403
|
```bash
|
|
404
|
-
cerefox config
|
|
404
|
+
cerefox config get usage_tracking_enabled
|
|
405
405
|
```
|
|
406
406
|
|
|
407
407
|
---
|
|
@@ -421,11 +421,11 @@ with a helpful message telling the agent what to provide.
|
|
|
421
421
|
|
|
422
422
|
```bash
|
|
423
423
|
# Require all MCP tool calls to include requestor/author
|
|
424
|
-
cerefox config
|
|
424
|
+
cerefox config set require_requestor_identity true
|
|
425
425
|
|
|
426
426
|
# Optionally override the default naming format (regex)
|
|
427
427
|
# Default: ^[a-zA-Z0-9_:.\- ]+$ (letters, numbers, underscores, colons, dots, hyphens, spaces)
|
|
428
|
-
cerefox config
|
|
428
|
+
cerefox config set requestor_identity_format "^[a-z]+:[a-z]+$"
|
|
429
429
|
```
|
|
430
430
|
|
|
431
431
|
### Format examples
|
|
@@ -441,7 +441,7 @@ The format is applied to both `requestor` (read tools) and `author` (ingest).
|
|
|
441
441
|
### Disabling enforcement
|
|
442
442
|
|
|
443
443
|
```bash
|
|
444
|
-
cerefox config
|
|
444
|
+
cerefox config set require_requestor_identity false
|
|
445
445
|
```
|
|
446
446
|
|
|
447
447
|
When disabled, the requestor parameter remains optional with the `"mcp-agent"` default.
|
|
@@ -65,7 +65,7 @@ Three top-level paths plus a few special cases:
|
|
|
65
65
|
|
|
66
66
|
**For all paths:**
|
|
67
67
|
- Supabase project set up and schema deployed (see `setup-supabase.md`)
|
|
68
|
-
- Some content ingested (`cerefox ingest my-notes.md`)
|
|
68
|
+
- Some content ingested (`cerefox document ingest my-notes.md`)
|
|
69
69
|
|
|
70
70
|
**For Path A-Local only:**
|
|
71
71
|
- **Recommended (v0.4.0+):** [Node.js ≥20](https://nodejs.org) (for `npx --package=@cerefox/memory cerefox mcp`)
|
|
@@ -1177,7 +1177,7 @@ Quick sanity check before pointing an agent at it:
|
|
|
1177
1177
|
```bash
|
|
1178
1178
|
cd /path/to/cerefox
|
|
1179
1179
|
uv run cerefox search "any query"
|
|
1180
|
-
uv run cerefox list
|
|
1180
|
+
uv run cerefox project list
|
|
1181
1181
|
```
|
|
1182
1182
|
|
|
1183
1183
|
If both work for you, they'll work for the agent.
|
|
@@ -1218,14 +1218,14 @@ The agent docs are written around MCP tool names. **CLI flag names match MCP par
|
|
|
1218
1218
|
| MCP tool | CLI command |
|
|
1219
1219
|
|---|---|
|
|
1220
1220
|
| `cerefox_search` | `uv run cerefox search "<query>" --match-count N --project-name <n> --metadata-filter '<json>' --requestor <name>` (CLI-only: `--mode`, `--alpha`, `--min-score`) |
|
|
1221
|
-
| `cerefox_ingest` (file) | `uv run cerefox ingest <path> --title <t> --project-name <n> --metadata '<json>' --update-if-exists\|--document-id <uuid> --source <s> --author <a> --author-type user\|agent` |
|
|
1222
|
-
| `cerefox_ingest` (paste) | `printf '...' \| uv run cerefox ingest --paste --title "<title>"` (same flags) |
|
|
1223
|
-
| `cerefox_get_document` | `uv run cerefox get
|
|
1224
|
-
| `cerefox_list_versions` | `uv run cerefox list
|
|
1225
|
-
| `cerefox_list_projects` | `uv run cerefox list
|
|
1226
|
-
| `cerefox_list_metadata_keys` | `uv run cerefox
|
|
1227
|
-
| `cerefox_metadata_search` | `uv run cerefox metadata
|
|
1228
|
-
| `cerefox_get_audit_log` | `uv run cerefox
|
|
1221
|
+
| `cerefox_ingest` (file) | `uv run cerefox document ingest <path> --title <t> --project-name <n> --metadata '<json>' --update-if-exists\|--document-id <uuid> --source <s> --author <a> --author-type user\|agent` |
|
|
1222
|
+
| `cerefox_ingest` (paste) | `printf '...' \| uv run cerefox document ingest --paste --title "<title>"` (same flags) |
|
|
1223
|
+
| `cerefox_get_document` | `uv run cerefox document get <document-id> --version-id <vid> --requestor <name>` |
|
|
1224
|
+
| `cerefox_list_versions` | `uv run cerefox version list <document-id> --requestor <name>` |
|
|
1225
|
+
| `cerefox_list_projects` | `uv run cerefox project list --requestor <name>` |
|
|
1226
|
+
| `cerefox_list_metadata_keys` | `uv run cerefox metadata keys` |
|
|
1227
|
+
| `cerefox_metadata_search` | `uv run cerefox metadata search --metadata-filter '<json>' --project-name <n> --requestor <name>` |
|
|
1228
|
+
| `cerefox_get_audit_log` | `uv run cerefox audit list --document-id <id> --author <a> --operation <op> --since <iso> --until <iso> --limit N --json --requestor <name>` |
|
|
1229
1229
|
|
|
1230
1230
|
### Path C verification prompts
|
|
1231
1231
|
|
|
@@ -1235,16 +1235,16 @@ After pointing your agent at the repo, ask it:
|
|
|
1235
1235
|
> Expected: agent runs `uv run cerefox search "second brain"` via its Bash tool and reports results.
|
|
1236
1236
|
|
|
1237
1237
|
> "Save a note titled 'Test Note' to Cerefox with the content '# Test\nThis is a Path C test.'"
|
|
1238
|
-
> Expected: agent runs `cerefox ingest --paste --title "Test Note"` (or equivalent) and reports the new document ID.
|
|
1238
|
+
> Expected: agent runs `cerefox document ingest --paste --title "Test Note"` (or equivalent) and reports the new document ID.
|
|
1239
1239
|
|
|
1240
1240
|
> "List my Cerefox projects."
|
|
1241
|
-
> Expected: agent runs `uv run cerefox list
|
|
1241
|
+
> Expected: agent runs `uv run cerefox project list`.
|
|
1242
1242
|
|
|
1243
1243
|
### Caveats
|
|
1244
1244
|
|
|
1245
1245
|
- **Privilege level**: the CLI uses the **service-role key** (`CEREFOX_SUPABASE_KEY`), which bypasses Row Level Security. An agent with Bash access has the same full read/write power you do. Only enable Path C for agents you trust to act on your behalf — the same trust level you'd grant Cursor/Claude Code for editing your source code.
|
|
1246
1246
|
- **Audit attribution**: Path C records `access_path = "cli"` in usage logs, distinct from `"local-mcp"` / `"remote-mcp"`. **Agents must set `--author <name> --author-type agent` on writes and `--requestor <name>` on reads** (or rely on `CEREFOX_AUTHOR_NAME` / `CEREFOX_AUTHOR_TYPE` / `CEREFOX_REQUESTOR_NAME` env vars). Without these flags, writes attribute to `"unknown"` / `"user"`, which under-reports agent activity. See the 2026-05-18 Decision Log Q2 entry for the design rationale (`author_type` is caller-declared on ambiguous channels — CLI and Edge Functions — but `access_path` is always derived from the code layer).
|
|
1247
|
-
- **Soft-delete is reachable; purge and restore are not** — by design. `cerefox delete
|
|
1247
|
+
- **Soft-delete is reachable; purge and restore are not** — by design. `cerefox document delete` is exposed on the CLI and sends documents to trash with an audit entry. **Permanent purge** (irreversible) and **restore from trash** (un-doing a destructive action) are intentionally web-UI-only and require human-in-the-loop confirmation. If an agent on Path C decides to delete content, it should surface that to the user explicitly so they can review and either restore or commit. See [`access-paths.md` → Destructive operations and the trust model](access-paths.md#destructive-operations-and-the-trust-model) for the full rationale and contributor guidance.
|
|
1248
1248
|
- **Cross-doc links in content you ingest** become clickable when the user views them in the Cerefox web UI. Author them as `[Text](uuid)` (most stable), `[Text](docs/path.md)` (repo files), or `[Text](<Title With Spaces>)` (angle-bracket form — bare spaces break markdown). See [`AGENT_GUIDE.md` → "Writing linkable content"](../../AGENT_GUIDE.md#writing-linkable-content) for the full set of rules.
|
|
1249
1249
|
- **One repo per machine**: the agent needs your checkout — there's no "Path C without a local clone". If you skip the local install entirely, Path A-Remote or Path B is the only option.
|
|
1250
1250
|
- **No sandboxing beyond the agent's existing Bash sandbox**: the CLI is just shell. If your agent's tool framework restricts which commands run, allowlist `uv run cerefox …` explicitly.
|
|
@@ -1295,7 +1295,7 @@ for hit in resp.results:
|
|
|
1295
1295
|
Both paths use the same Postgres RPCs and the same stored embeddings, but embed queries
|
|
1296
1296
|
independently. If you change the embedding model, **update both paths** before searching:
|
|
1297
1297
|
|
|
1298
|
-
1. Update `.env` + run `cerefox reindex` (re-embeds stored chunks via Python)
|
|
1298
|
+
1. Update `.env` + run `cerefox server reindex` (re-embeds stored chunks via Python)
|
|
1299
1299
|
2. Update the TypeScript constants in `supabase/functions/*/index.ts` + redeploy Edge Functions
|
|
1300
1300
|
|
|
1301
1301
|
See `docs/guides/configuration.md` → "Changing the embedding model" for the full procedure.
|
|
@@ -100,7 +100,7 @@ If you want to keep costs as low as possible:
|
|
|
100
100
|
See `docs/guides/configuration.md` for how to switch.
|
|
101
101
|
- **Batch ingest, don't re-ingest**: Cerefox deduplicates by content hash — re-ingesting the
|
|
102
102
|
same file twice costs nothing. Only new or changed content triggers embedding calls.
|
|
103
|
-
- **`cerefox reindex`**: Re-embeds all existing chunks if you switch embedders. Run this once
|
|
103
|
+
- **`cerefox server reindex`**: Re-embeds all existing chunks if you switch embedders. Run this once
|
|
104
104
|
after switching, not repeatedly.
|
|
105
105
|
|
|
106
106
|
---
|
|
@@ -200,7 +200,7 @@ Backups are JSON files with the following structure:
|
|
|
200
200
|
}
|
|
201
201
|
```
|
|
202
202
|
|
|
203
|
-
**Embeddings are included** in backups. This means a restored database is immediately searchable — no `cerefox reindex` required after restore.
|
|
203
|
+
**Embeddings are included** in backups. This means a restored database is immediately searchable — no `cerefox server reindex` required after restore.
|
|
204
204
|
|
|
205
205
|
The backup directory (`./backup-data/` by default) is gitignored. Back up the backup files separately if you want off-site copies (e.g. copy to cloud storage).
|
|
206
206
|
|
|
@@ -257,15 +257,15 @@ The `cerefox` CLI also provides data management commands:
|
|
|
257
257
|
|
|
258
258
|
| Command | Description |
|
|
259
259
|
|---------|-------------|
|
|
260
|
-
| `uv run cerefox ingest FILE` | Ingest a markdown file |
|
|
261
|
-
| `uv run cerefox ingest --paste --title TITLE` | Ingest text from stdin |
|
|
260
|
+
| `uv run cerefox document ingest FILE` | Ingest a markdown file |
|
|
261
|
+
| `uv run cerefox document ingest --paste --title TITLE` | Ingest text from stdin |
|
|
262
262
|
| `uv run cerefox search QUERY` | Search the knowledge base |
|
|
263
|
-
| `uv run cerefox list
|
|
264
|
-
| `uv run cerefox delete
|
|
265
|
-
| `uv run cerefox list
|
|
266
|
-
| `uv run cerefox list
|
|
267
|
-
| `uv run cerefox get
|
|
268
|
-
| `uv run cerefox get
|
|
263
|
+
| `uv run cerefox document list` | List all documents |
|
|
264
|
+
| `uv run cerefox document delete ID` | Delete a document by ID |
|
|
265
|
+
| `uv run cerefox project list` | List all projects |
|
|
266
|
+
| `uv run cerefox version list ID` | List all archived versions of a document |
|
|
267
|
+
| `uv run cerefox document get ID` | Retrieve current content of a document |
|
|
268
|
+
| `uv run cerefox document get ID --version VERSION_ID` | Retrieve a specific archived version |
|
|
269
269
|
| `uv run cerefox web` | Start the web UI |
|
|
270
270
|
|
|
271
271
|
Run `uv run cerefox --help` or `uv run cerefox COMMAND --help` for details.
|
|
@@ -93,8 +93,8 @@ After v0.6.0, `cerefox init` will offer to do this for you.
|
|
|
93
93
|
|
|
94
94
|
## What's next
|
|
95
95
|
|
|
96
|
-
- **Ingest your notes**: `cerefox ingest my-notes.md`, or
|
|
97
|
-
`cerefox ingest-dir ./notes/ --recursive`
|
|
96
|
+
- **Ingest your notes**: `cerefox document ingest my-notes.md`, or
|
|
97
|
+
`cerefox document ingest-dir ./notes/ --recursive`
|
|
98
98
|
- **Search from the CLI**: `cerefox search "your query"`
|
|
99
99
|
- **Discover all commands**: `cerefox --help`
|
|
100
100
|
- **Run the web UI** (Python-only until v0.6): [`setup-local.md`](setup-local.md)
|
|
@@ -95,10 +95,10 @@ You should see all tables (cerefox_documents, cerefox_chunks, cerefox_projects)
|
|
|
95
95
|
|
|
96
96
|
```bash
|
|
97
97
|
# Ingest a markdown file
|
|
98
|
-
cerefox ingest my-notes.md --project-name "personal"
|
|
98
|
+
cerefox document ingest my-notes.md --project-name "personal"
|
|
99
99
|
|
|
100
100
|
# Or paste content from stdin
|
|
101
|
-
echo "# Quick Note\n\nThis is a quick note." | cerefox ingest --paste --title "Quick Note"
|
|
101
|
+
echo "# Quick Note\n\nThis is a quick note." | cerefox document ingest --paste --title "Quick Note"
|
|
102
102
|
```
|
|
103
103
|
|
|
104
104
|
Each ingest calls the OpenAI embedding API once per batch of chunks (fast, typically under a second).
|
|
@@ -227,10 +227,10 @@ appear with a green "Active" status.
|
|
|
227
227
|
> Supabase compiles them in the cloud. **Docker is not a prerequisite for deploying Cerefox's
|
|
228
228
|
> Edge Functions.** A deploy succeeded as long as each function ends with
|
|
229
229
|
> `Deployed Functions on project …`. This applies to both the manual commands here and
|
|
230
|
-
> `cerefox
|
|
230
|
+
> `cerefox server deploy --functions-only`.
|
|
231
231
|
|
|
232
232
|
> **Re-deploying after updates**: run the same `npx supabase functions deploy` commands
|
|
233
|
-
> again from the project root, or just `cerefox
|
|
233
|
+
> again from the project root, or just `cerefox server deploy --functions-only` (it deploys
|
|
234
234
|
> all 9 from the bundled assets). `npx supabase login` only needs to be run once per machine.
|
|
235
235
|
|
|
236
236
|
---
|
package/docs/guides/upgrading.md
CHANGED
|
@@ -213,7 +213,7 @@ uv run python scripts/reindex_all.py --dry-run
|
|
|
213
213
|
uv run python scripts/reindex_all.py
|
|
214
214
|
|
|
215
215
|
# Or run directly via the CLI (same effect)
|
|
216
|
-
uv run cerefox reindex --all
|
|
216
|
+
uv run cerefox server reindex --all
|
|
217
217
|
```
|
|
218
218
|
|
|
219
219
|
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.
|
|
@@ -238,7 +238,7 @@ redeploy RPCs via `db_deploy.py` (step 4) to update the canonical function defin
|
|
|
238
238
|
|
|
239
239
|
**Usage tracking is opt-in**: disabled by default. Enable via CLI:
|
|
240
240
|
```bash
|
|
241
|
-
cerefox config
|
|
241
|
+
cerefox config set usage_tracking_enabled true
|
|
242
242
|
```
|
|
243
243
|
Or via the toggle on the Analytics page. When enabled, **all operations** (both reads
|
|
244
244
|
and writes) are logged with operation type, access path, requestor identity, query text,
|
|
@@ -290,7 +290,7 @@ MCP clients pick up new tools automatically on the next connection.
|
|
|
290
290
|
|
|
291
291
|
### Upgrading to v0.1.1+ (from v0.1.0)
|
|
292
292
|
|
|
293
|
-
**Cloud-only embeddings**: Local embedders (mpnet, Ollama) were removed. If you were using a local embedder, switch to OpenAI or Fireworks AI and run `uv run cerefox reindex` to re-embed all chunks.
|
|
293
|
+
**Cloud-only embeddings**: Local embedders (mpnet, Ollama) were removed. If you were using a local embedder, switch to OpenAI or Fireworks AI and run `uv run cerefox server reindex` to re-embed all chunks.
|
|
294
294
|
|
|
295
295
|
## AI Agent Integration After Upgrade
|
|
296
296
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cerefox/memory",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
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",
|