@theronap/cortex-mcp 0.9.72 → 0.9.73

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/README.md CHANGED
@@ -1,10 +1,10 @@
1
1
  # cortex-mcp
2
2
 
3
- Connect your AI assistant to **Cortex** — your org's projects, recent activity, gaps, and directives, scoped to exactly what you're permitted to see.
3
+ Connect your AI assistant to **Agnoclast** — your org's projects, recent activity, gaps, and directives, scoped to exactly what you're permitted to see.
4
4
 
5
5
  ## Setup
6
6
 
7
- 1. Get your personal token from the Cortex console → **Connect your AI**.
7
+ 1. Get your personal token from the Agnoclast console → **Connect your AI**.
8
8
  2. Add this to your Claude Code config (`~/.claude.json`, under `mcpServers`):
9
9
 
10
10
  ```json
@@ -21,7 +21,7 @@ Connect your AI assistant to **Cortex** — your org's projects, recent activity
21
21
 
22
22
  3. Restart Claude Code. Your AI now sees your org context automatically, the managed startup skill
23
23
  will prefer query-centered `session_context` on substantive session opens, and each session start
24
- will log the exact baseline Cortex context to `~/.cortex/context-snapshots/`.
24
+ will log the exact baseline Agnoclast context to `~/.cortex/context-snapshots/`.
25
25
 
26
26
  No clone, no path, no build step — `npx` fetches and runs it.
27
27
 
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * cortex-mcp — connect your AI assistant to Cortex.
3
+ * cortex-mcp — connect your AI assistant to Agnoclast.
4
4
  *
5
5
  * Subcommands:
6
6
  * (none) run the MCP server (stdio) — used by your Claude config
@@ -8,14 +8,14 @@
8
8
  * doctor live health check — is the token actually working? (no restart needed)
9
9
  * capture the Stop-hook capturer (invoked by Claude Code, not by hand)
10
10
  * ingest-folder <path> ingest a local markdown folder as your authored records
11
- * snapshot-context save the exact startup context served by Cortex to a local log file
11
+ * snapshot-context save the exact startup context served by Agnoclast to a local log file
12
12
  * --version | -v
13
13
  * --help | -h
14
14
  *
15
15
  * Zero-install onboarding:
16
16
  * npx -y @theronap/cortex-mcp setup <your-token>
17
17
  *
18
- * Get your token from the Cortex console → Connect your AI.
18
+ * Get your token from the Agnoclast console → Connect your AI.
19
19
  */
20
20
 
21
21
  import { readFileSync } from 'node:fs'
@@ -35,31 +35,31 @@ if (cmd === '--version' || cmd === '-v') {
35
35
 
36
36
  if (cmd === '--help' || cmd === '-h' || cmd === 'help') {
37
37
  process.stdout.write(
38
- `cortex-mcp ${VERSION} — connect your AI assistant to Cortex\n\n` +
38
+ `cortex-mcp ${VERSION} — connect your AI assistant to Agnoclast\n\n` +
39
39
  `Onboard (one command, no token to copy):\n` +
40
40
  ` npx -y @theronap/cortex-mcp login\n\n` +
41
41
  `This opens your browser, you click Approve, and it wires everything up. Restart\n` +
42
- `Claude Code after, and your AI sees your Cortex context while your sessions flow\n` +
42
+ `Claude Code after, and your AI sees your Agnoclast context while your sessions flow\n` +
43
43
  `into the org automatically.\n\n` +
44
44
  `Subcommands:\n` +
45
45
  ` login [--label <name>] browser-approved sign-in — gets a token for you, then runs setup\n` +
46
46
  ` setup <token> wire MCP server + capture hook into ~/.claude config (single editor)\n` +
47
- ` install [<token>] [--editor auto|all|<id,...>] wire Cortex into EVERY detected editor + write the capability manifest\n` +
47
+ ` install [<token>] [--editor auto|all|<id,...>] wire Agnoclast into EVERY detected editor + write the capability manifest\n` +
48
48
  ` repair re-run setup at the latest version using your existing token (no token needed)\n` +
49
- ` uninstall remove ALL Cortex wiring (MCP, hooks, skills, launchd, cron). --dry-run to preview, --purge to also wipe ~/.cortex + npx cache\n` +
49
+ ` uninstall remove ALL Agnoclast wiring (MCP, hooks, skills, launchd, cron). --dry-run to preview, --purge to also wipe ~/.cortex + npx cache\n` +
50
50
  ` doctor live health check — confirm your token works (no restart needed)\n` +
51
51
  ` status one-line connected/not-connected check (used by the SessionStart hook)\n` +
52
- ` skills install/repair the managed Cortex skills — bundled + org-published (also wired by setup)\n` +
52
+ ` skills install/repair the managed Agnoclast skills — bundled + org-published (also wired by setup)\n` +
53
53
  ` skills push <file> publish a SKILL.md to your org (owner/manager/admin)\n` +
54
- ` docs-scan detect new/changed local docs pending Cortex authoring (used by /cortex-author-docs)\n` +
54
+ ` docs-scan detect new/changed local docs pending Agnoclast authoring (used by /cortex-author-docs)\n` +
55
55
  ` graphify-sync [path] rebuild the local code graph (graphify) + log an evidence-tier timeline event\n` +
56
- ` snapshot-context save the exact startup context Cortex served to a local snapshot\n` +
56
+ ` snapshot-context save the exact startup context Agnoclast served to a local snapshot\n` +
57
57
  ` hydrate UserPromptSubmit hook — inject query-centered context on the first substantive turn\n` +
58
58
  ` statusline ambient presence line for the Claude Code statusline (local read only)\n` +
59
59
  ` capture Stop-hook capturer (invoked by Claude Code)\n` +
60
60
  ` ingest-folder <path> ingest a local markdown folder as your authored records\n` +
61
61
  ` (no args) run the MCP server (used by your Claude config)\n\n` +
62
- `Get your token from the Cortex console → Connect your AI.\n`,
62
+ `Get your token from the Agnoclast console → Connect your AI.\n`,
63
63
  )
64
64
  process.exit(0)
65
65
  }
@@ -84,14 +84,14 @@ if (cmd === 'login') {
84
84
  const { closeFetch } = await import('../lib/diagnose.mjs')
85
85
  await closeFetch()
86
86
  } else if (cmd === 'install') {
87
- // The cross-editor hub installer: wire Cortex into every detected editor via the adapter
87
+ // The cross-editor hub installer: wire Agnoclast into every detected editor via the adapter
88
88
  // registry, then write the capability manifest (~/.cortex/editors.json). Superset of `setup`.
89
89
  const { runInstall } = await import('../lib/install.mjs')
90
90
  await runInstall(rest, VERSION)
91
91
  const { closeFetch } = await import('../lib/diagnose.mjs')
92
92
  await closeFetch()
93
93
  } else if (cmd === 'uninstall' || cmd === 'remove') {
94
- // Full reverse of setup: strip every Cortex touch-point (MCP entries, hooks, skills, launchd, cron).
94
+ // Full reverse of setup: strip every Agnoclast touch-point (MCP entries, hooks, skills, launchd, cron).
95
95
  // --dry-run prints the plan and changes nothing; --purge also removes ~/.cortex, the npx cache, and
96
96
  // backups. No network — safe to run even when the token is dead or the server is unreachable.
97
97
  const { runUninstall } = await import('../lib/uninstall.mjs')
@@ -153,7 +153,7 @@ if (cmd === 'login') {
153
153
  const { closeFetch } = await import('../lib/diagnose.mjs')
154
154
  await closeFetch()
155
155
  } else if (cmd === 'hydrate') {
156
- // UserPromptSubmit hook (① discovery): hydrate the model with query-centered Cortex context on the
156
+ // UserPromptSubmit hook (① discovery): hydrate the model with query-centered Agnoclast context on the
157
157
  // FIRST substantive turn, before it answers — then never again this session (topic-shift refresh stays
158
158
  // the cortex-context skill's job). Synchronous by necessity, but once-per-session + 8s + fail-open.
159
159
  const { runHydrate } = await import('../lib/hydrate.mjs')
@@ -166,7 +166,7 @@ if (cmd === 'login') {
166
166
  const { runStatusline } = await import('../lib/statusline.mjs')
167
167
  process.exitCode = runStatusline()
168
168
  } else if (cmd === 'skills') {
169
- // Install / repair the managed Cortex skills — bundled + org-published (`skills push` publishes).
169
+ // Install / repair the managed Agnoclast skills — bundled + org-published (`skills push` publishes).
170
170
  // Org sync is network-fail-soft so the SessionStart hook stays safe offline.
171
171
  const { runSkills } = await import('../lib/skills.mjs')
172
172
  process.exitCode = await runSkills(rest)
package/lib/capture.mjs CHANGED
@@ -35,7 +35,7 @@ export function projectFrom(cwd) {
35
35
  return base ?? 'general'
36
36
  }
37
37
 
38
- // Claude Code Stop hook → POSTs a session digest to Cortex cloud, which
38
+ // Claude Code Stop hook → POSTs a session digest to Agnoclast cloud, which
39
39
  // summarizes server-side and upserts ONE record per session. Node-native
40
40
  // SHR-01/T6 — parse a git remote URL into GitHub 'owner/name', or null.
41
41
  //
@@ -4,7 +4,7 @@ import { join } from 'path'
4
4
 
5
5
  // Thin local wrapper around the `graphify` CLI's read-only query subcommands. Deliberately NOT a
6
6
  // fetchCortex client like grep/read_page: this is LOCAL-MACHINE data (a tree-sitter AST graph of
7
- // whatever repo the session's cwd happens to be in), not org-shared Cortex content, and it never
7
+ // whatever repo the session's cwd happens to be in), not org-shared Agnoclast content, and it never
8
8
  // becomes the wiki graph — see cortex-wiki-primary-spec (structural/extracted data is evidence,
9
9
  // never auto-promoted into authored pages). No LLM, no network call; graphify already built the
10
10
  // graph on disk, this just queries it.
@@ -49,7 +49,7 @@ export async function runSnapshotContext() {
49
49
  const out = (m) => process.stdout.write(m + '\n')
50
50
  const token = resolveToken()
51
51
  if (!token) {
52
- out('Cortex: context snapshot skipped — no token found.')
52
+ out('Agnoclast: context snapshot skipped — no token found.')
53
53
  return 0
54
54
  }
55
55
 
@@ -58,13 +58,13 @@ export async function runSnapshotContext() {
58
58
  try {
59
59
  res = await fetchCortex(`${base}/api/mcp-context`, { headers: { Authorization: `Bearer ${token}` } })
60
60
  } catch (e) {
61
- out(`Cortex: context snapshot failed — ${e?.message ?? String(e)}`)
61
+ out(`Agnoclast: context snapshot failed — ${e?.message ?? String(e)}`)
62
62
  return 0
63
63
  }
64
64
 
65
65
  if (!res.ok) {
66
66
  const body = await res.text()
67
- out(`Cortex: context snapshot failed — ${classify(res.status, res.headers.get('content-type'), body, res.headers.get('x-vercel-id')).message}`)
67
+ out(`Agnoclast: context snapshot failed — ${classify(res.status, res.headers.get('content-type'), body, res.headers.get('x-vercel-id')).message}`)
68
68
  return 0
69
69
  }
70
70
 
@@ -76,7 +76,7 @@ export async function runSnapshotContext() {
76
76
  const capturedAt = new Date().toISOString()
77
77
  const file = join(dir, `${stamp()}.md`)
78
78
  const header = [
79
- '# Cortex startup context snapshot',
79
+ '# Agnoclast startup context snapshot',
80
80
  `- Captured: ${capturedAt}`,
81
81
  `- Source: ${base}/api/mcp-context`,
82
82
  '',
@@ -94,6 +94,6 @@ export async function runSnapshotContext() {
94
94
 
95
95
  pruneSnapshots(dir)
96
96
 
97
- out(`Cortex: logged startup context → ${file}`)
97
+ out(`Agnoclast: logged startup context → ${file}`)
98
98
  return 0
99
99
  }
package/lib/diagnose.mjs CHANGED
@@ -1,12 +1,12 @@
1
1
  // Shared health / diagnosis helpers for the cortex MCP client.
2
2
  //
3
3
  // The whole reason this file exists: a transient infrastructure block (Vercel firewall / bot
4
- // protection / deployment protection) once surfaced as a bare "Cortex API 403: unknown", which
4
+ // protection / deployment protection) once surfaced as a bare "Agnoclast API 403: unknown", which
5
5
  // read like an auth failure and sent everyone chasing token regeneration for hours. The fix is
6
6
  // to tell the truth about WHAT failed.
7
7
  //
8
- // KEY SIGNAL: the Cortex app ALWAYS returns JSON ({ error: ... }). So a NON-JSON body on a
9
- // 4xx/5xx means infrastructure handled the request, not Cortex auth — re-running setup or
8
+ // KEY SIGNAL: the Agnoclast app ALWAYS returns JSON ({ error: ... }). So a NON-JSON body on a
9
+ // 4xx/5xx means infrastructure handled the request, not Agnoclast auth — re-running setup or
10
10
  // regenerating the token will not help; it is usually transient and worth a retry.
11
11
 
12
12
  import { readFileSync } from 'fs'
@@ -85,7 +85,7 @@ const sleep = (ms) => new Promise((r) => setTimeout(r, ms))
85
85
  // A non-OK response → an actionable diagnosis: { kind, retriable, message }.
86
86
  // kind: 'auth' → token bad/revoked/wrong-deployment (NOT retriable)
87
87
  // 'infra' → blocked by infrastructure, non-JSON body (retriable, usually transient)
88
- // 'app' → a real Cortex API error with a JSON message (retriable only if 5xx)
88
+ // 'app' → a real Agnoclast API error with a JSON message (retriable only if 5xx)
89
89
  export function classify(status, contentType, bodyText, requestId) {
90
90
  const isJson = (contentType ?? '').includes('application/json')
91
91
  let appError = null
@@ -109,20 +109,20 @@ export function classify(status, contentType, bodyText, requestId) {
109
109
  kind: 'auth', retriable: false,
110
110
  message: `Token rejected (HTTP ${status}: ${appError ?? 'unauthorized'}). The token is invalid, ` +
111
111
  `revoked, or for a different deployment — not an infrastructure problem. Get a fresh token from ` +
112
- `the Cortex console → Connect your AI, then re-run setup.${rid}`,
112
+ `the Agnoclast console → Connect your AI, then re-run setup.${rid}`,
113
113
  }
114
114
  }
115
115
  if (!isJson) {
116
116
  return {
117
117
  kind: 'infra', retriable: true,
118
- message: `Blocked by infrastructure (HTTP ${status}, non-JSON response) — NOT by Cortex auth. This is ` +
118
+ message: `Blocked by infrastructure (HTTP ${status}, non-JSON response) — NOT by Agnoclast auth. This is ` +
119
119
  `usually a transient firewall / bot-protection hiccup; retrying often clears it. If it persists, check ` +
120
120
  `Vercel firewall / deployment protection on the API route. Re-running setup will not help.${rid}`,
121
121
  }
122
122
  }
123
123
  return {
124
124
  kind: 'app', retriable: status >= 500,
125
- message: `Cortex API ${status}: ${appError ?? 'unknown error'}.${appHint ? ` ${appHint}` : ''}${rid}`,
125
+ message: `Agnoclast API ${status}: ${appError ?? 'unknown error'}.${appHint ? ` ${appHint}` : ''}${rid}`,
126
126
  }
127
127
  }
128
128
 
@@ -176,7 +176,7 @@ export async function fetchCortex(url, opts = {}, { retries = 2, baseDelayMs = 4
176
176
  }
177
177
  }
178
178
  throw new Error(
179
- `Could not reach Cortex at ${url} — ${lastErr?.message ?? 'network error'}. ` +
179
+ `Could not reach Agnoclast at ${url} — ${lastErr?.message ?? 'network error'}. ` +
180
180
  `Check your connection (and CORTEX_URL if you set it).`,
181
181
  )
182
182
  }
@@ -190,7 +190,7 @@ export async function checkToken(token, base) {
190
190
  }
191
191
  if (!isUuid(token)) {
192
192
  return { ok: false, status: 0, diagnosis: { kind: 'config', retriable: false,
193
- message: `Token "${String(token).slice(0, 8)}…" is not a valid Cortex token (expected a UUID). ` +
193
+ message: `Token "${String(token).slice(0, 8)}…" is not a valid Agnoclast token (expected a UUID). ` +
194
194
  `Re-run setup with the token from the console.` } }
195
195
  }
196
196
  const url = `${(base ?? 'https://cortex-console.vercel.app').replace(/\/$/, '')}/api/mcp-context`
package/lib/docs_scan.mjs CHANGED
@@ -6,7 +6,7 @@ import { join, resolve, dirname } from 'path'
6
6
  // Documentation ingestion — detection half (D1 of docs/documentation-ingestion-spec.md).
7
7
  //
8
8
  // Specs/plans/design docs get written to disk (repo docs/, ~/.gstack/projects/…) and never reach
9
- // Cortex as pages. This subcommand DETECTS new/changed markdown under registered roots by content
9
+ // Agnoclast as pages. This subcommand DETECTS new/changed markdown under registered roots by content
10
10
  // hash; the AUTHORING is done by the live session (the cortex-author-docs skill reads each pending
11
11
  // doc and calls the `author` MCP tool) — the agent is the pipe, never a raw-markdown dump.
12
12
  //
@@ -90,7 +90,7 @@ export function markFiles(state, paths, now = new Date().toISOString()) {
90
90
  }
91
91
 
92
92
  // Heuristic soak guardrail (spec D5): the Robin parity experiment forbids re-syncing the local
93
- // brain into Cortex during the window, so warn when a root looks like the brain repo.
93
+ // brain into Agnoclast during the window, so warn when a root looks like the brain repo.
94
94
  const looksLikeBrain = (dir) => /\/Documents\/brain(\/|$)/.test(dir)
95
95
 
96
96
  export async function runDocsScan(argv = []) {
@@ -111,7 +111,7 @@ export async function runDocsScan(argv = []) {
111
111
  const abs = resolve(dir)
112
112
  if (!existsSync(abs)) { process.stderr.write(`Not a directory: ${abs}\n`); return 1 }
113
113
  if (looksLikeBrain(abs)) {
114
- out(`⚠ ${abs} looks like the local brain repo — the Robin parity soak forbids re-syncing it into Cortex.`)
114
+ out(`⚠ ${abs} looks like the local brain repo — the Robin parity soak forbids re-syncing it into Agnoclast.`)
115
115
  out(' Registering anyway is on you; the cortex-author-docs skill will also warn.')
116
116
  }
117
117
  if (!state.roots.includes(abs)) state.roots.push(abs)
@@ -163,7 +163,7 @@ export async function runDocsScan(argv = []) {
163
163
  }
164
164
  if (!pending.length) out(`✓ up to date — ${scanned} doc(s) scanned, nothing pending`)
165
165
  else {
166
- out(`${pending.length} doc(s) pending Cortex authoring (of ${scanned} scanned):`)
166
+ out(`${pending.length} doc(s) pending Agnoclast authoring (of ${scanned} scanned):`)
167
167
  for (const p of pending) out(` ${p.status === 'new' ? '+ ' : '~ '}${p.path}`)
168
168
  out('Author them via the cortex-author-docs skill, then: docs-scan --mark <file>...')
169
169
  }
package/lib/doctor.mjs CHANGED
@@ -6,7 +6,7 @@ import { checkToken, resolveBase } from './diagnose.mjs'
6
6
  // `npx @theronap/cortex-mcp doctor` — a live, one-command health check.
7
7
  //
8
8
  // This is the "is it ACTUALLY working?" tool that was missing: it reads your token, calls the
9
- // real Cortex API, and prints a clear PASS/FAIL with the actual cause. No Claude Code restart
9
+ // real Agnoclast API, and prints a clear PASS/FAIL with the actual cause. No Claude Code restart
10
10
  // needed — so onboarding can confirm the connection independently of "did the server load."
11
11
 
12
12
  // Token resolution: env first, then the Claude config the setup command wrote (so `doctor`
@@ -24,7 +24,7 @@ function resolveToken() {
24
24
  return { token: null, source: null }
25
25
  }
26
26
 
27
- // `status` — the one-line SessionStart variant of doctor: a visible "is Cortex capturing?"
27
+ // `status` — the one-line SessionStart variant of doctor: a visible "is Agnoclast capturing?"
28
28
  // signal inside Claude Code itself (three-machine dry-run finding 2026-06-09: with no
29
29
  // indicator, a user can't tell whether their sessions are flowing to the org).
30
30
  // Always returns 0 — a status line must never break a session start.
@@ -33,19 +33,19 @@ export async function runStatus() {
33
33
  const out = (m) => process.stdout.write(m + '\n')
34
34
  const { token } = resolveToken()
35
35
  if (!token) {
36
- out('Cortex: NOT connected — no token found. Run: npx -y @theronap/cortex-mcp setup <token>')
36
+ out('Agnoclast: NOT connected — no token found. Run: npx -y @theronap/cortex-mcp setup <token>')
37
37
  return 0
38
38
  }
39
39
  try {
40
40
  const r = await checkToken(token, base)
41
41
  if (r.ok) {
42
42
  const n = typeof r.projectCount === 'number' ? ` · ${r.projectCount} project${r.projectCount === 1 ? '' : 's'} visible` : ''
43
- out(`Cortex: connected — sessions on this machine are captured to your org${n}.`)
43
+ out(`Agnoclast: connected — sessions on this machine are captured to your org${n}.`)
44
44
  } else {
45
- out(`Cortex: NOT connected — ${r.diagnosis?.message ?? 'check failed'}. Run: npx -y @theronap/cortex-mcp doctor`)
45
+ out(`Agnoclast: NOT connected — ${r.diagnosis?.message ?? 'check failed'}. Run: npx -y @theronap/cortex-mcp doctor`)
46
46
  }
47
47
  } catch (e) {
48
- out(`Cortex: status check failed (${e?.message ?? String(e)}) — run doctor.`)
48
+ out(`Agnoclast: status check failed (${e?.message ?? String(e)}) — run doctor.`)
49
49
  }
50
50
  return 0
51
51
  }
@@ -55,7 +55,7 @@ export async function runDoctor() {
55
55
  const out = (m) => process.stdout.write(m + '\n')
56
56
 
57
57
  out('')
58
- out('Cortex doctor — checking your connection…')
58
+ out('Agnoclast doctor — checking your connection…')
59
59
  const { token, source } = resolveToken()
60
60
  out(` token source: ${source ?? 'NONE FOUND'}`)
61
61
  out(` endpoint: ${base}`)
@@ -64,11 +64,11 @@ export async function runDoctor() {
64
64
  const r = await checkToken(token, base)
65
65
 
66
66
  if (r.ok) {
67
- out(' ✓ PASS — your token authenticates and Cortex returned your context.')
67
+ out(' ✓ PASS — your token authenticates and Agnoclast returned your context.')
68
68
  if (typeof r.projectCount === 'number') out(` You can currently see ${r.projectCount} project(s).`)
69
69
  if (r.requestId) out(` (request id: ${r.requestId})`)
70
70
  out('')
71
- out(' If your AI still does not see Cortex, the server just is not loaded yet —')
71
+ out(' If your AI still does not see Agnoclast, the server just is not loaded yet —')
72
72
  out(' fully quit and reopen Claude Code (the MCP server starts on launch).')
73
73
  out('')
74
74
  return 0
@@ -55,7 +55,7 @@ export function renderAntigravityPlist({ home = homedir() } = {}) {
55
55
  * NOTE the AGENT_DIR line is the portability blocker documented above. */
56
56
  export function renderAntigravitySyncSh() {
57
57
  return `#!/bin/bash
58
- # Cortex ⇄ Antigravity one-shot sync, triggered by launchd WatchPaths on the Antigravity
58
+ # Agnoclast ⇄ Antigravity one-shot sync, triggered by launchd WatchPaths on the Antigravity
59
59
  # trajectory store. There is no resident daemon — launchd wakes this on change and it exits.
60
60
  # Token is resolved from the wired MCP config at runtime (never stored in plist/script).
61
61
  # ⚠ AGENT_DIR points at a local dev checkout — see antigravity.mjs BLOCKER note (not coworker-portable).
@@ -6,7 +6,7 @@ import { existsSync } from 'node:fs'
6
6
  import { join } from 'node:path'
7
7
  import { readJson, backupFile, ensureDir, writeJson } from './_fsutil.mjs'
8
8
 
9
- /** Merge the Cortex MCP server into a ~/.claude.json object. Pure + idempotent: sets only the
9
+ /** Merge the Agnoclast MCP server into a ~/.claude.json object. Pure + idempotent: sets only the
10
10
  * `cortex` entry (type:'stdio'), preserves every other server. `spec` = the package@dist-tag string. */
11
11
  export function mergeClaudeMcp(existing, spec, token) {
12
12
  const cfg = existing && typeof existing === 'object' ? { ...existing } : {}
@@ -15,7 +15,7 @@ export function mergeClaudeMcp(existing, spec, token) {
15
15
  return cfg
16
16
  }
17
17
 
18
- /** The Cortex tools every seat may run WITHOUT a permission prompt: the read surface, the live
18
+ /** The Agnoclast tools every seat may run WITHOUT a permission prompt: the read surface, the live
19
19
  * authoring core, and trivially-reversible maintenance. The contract this enforces: authoring is
20
20
  * EXPECTED agent behavior — a page update must never stall on a yes/no dialog the user won't read
21
21
  * (the ask-permission failure mode is how pages go stale). Safe because every page edit is
@@ -38,7 +38,7 @@ export const CORTEX_ALLOWED_TOOLS = [
38
38
  'set_page_validity', 'snooze_red_link', 'attribute_thread',
39
39
  ].map((t) => `mcp__cortex__${t}`)
40
40
 
41
- /** Merge Cortex's Claude Code hooks into a ~/.claude/settings.json object. Pure + idempotent: drops
41
+ /** Merge Agnoclast's Claude Code hooks into a ~/.claude/settings.json object. Pure + idempotent: drops
42
42
  * any prior cortex entry (old token/path/version) from each hook array before appending the current
43
43
  * one — capture (Stop), status + skills-repair + snapshot-context (SessionStart), hydrate
44
44
  * (UserPromptSubmit), precompact (PreCompact). Commands carry NO inline token (each subcommand
@@ -6,7 +6,7 @@ import { existsSync, readFileSync, writeFileSync } from 'node:fs'
6
6
  import { join } from 'node:path'
7
7
  import { readJson, backupFile, ensureDir, writeJson } from './_fsutil.mjs'
8
8
 
9
- /** Merge the Cortex MCP server into a Codex config.toml. Pure + idempotent: strips any existing
9
+ /** Merge the Agnoclast MCP server into a Codex config.toml. Pure + idempotent: strips any existing
10
10
  * [mcp_servers.cortex] / [mcp_servers.cortex.env] tables (so re-runs update in place rather than
11
11
  * duplicating — a duplicate TOML table would break Codex's parser), preserves every other table,
12
12
  * and appends a fresh block. Only touches the cortex tables; never rewrites the user's config. */
@@ -6,7 +6,7 @@ import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs'
6
6
  import { join } from 'node:path'
7
7
  import { backupFile } from './_fsutil.mjs'
8
8
 
9
- /** Merge the Cortex MCP server into a Cursor mcp.json object. Pure + idempotent: sets only the
9
+ /** Merge the Agnoclast MCP server into a Cursor mcp.json object. Pure + idempotent: sets only the
10
10
  * `cortex` entry, preserves every other server. `spec` is the package@dist-tag STRING — the same
11
11
  * convention claude/codex/setup.mjs use, so one install driver can pass a single spec to every adapter. */
12
12
  export function mergeCursorMcp(existing, spec, token) {
@@ -1,4 +1,4 @@
1
- // Editor adapter registry (P0-b task 1). One place that knows every editor Cortex can wire.
1
+ // Editor adapter registry (P0-b task 1). One place that knows every editor Agnoclast can wire.
2
2
  // Adding an editor = add a module here; the install driver + capability manifest fall out of it.
3
3
  //
4
4
  // EditorAdapter shape (see the four modules):
@@ -82,7 +82,7 @@ export async function runGraphifySync(argv = []) {
82
82
  }
83
83
  const payload = await res.json()
84
84
  process.stdout.write(
85
- `Logged to Cortex timeline: ${repo}@${commitSha.slice(0, 7)} (${nodeCount} nodes, ${edgeCount} edges, ${communityCount} communities)` +
85
+ `Logged to Agnoclast timeline: ${repo}@${commitSha.slice(0, 7)} (${nodeCount} nodes, ${edgeCount} edges, ${communityCount} communities)` +
86
86
  `${payload.inserted ? '' : ' (already logged)'}\n`,
87
87
  )
88
88
  return 0
package/lib/grep_cli.mjs CHANGED
@@ -56,7 +56,7 @@ export async function runGrep(rest = []) {
56
56
  const TOKEN = process.env.CORTEX_TOKEN
57
57
  const BASE = resolveBase(process.env.CORTEX_URL)
58
58
  if (!TOKEN) {
59
- process.stderr.write('cortex grep: CORTEX_TOKEN is required (get yours from the Cortex console).\n')
59
+ process.stderr.write('cortex grep: CORTEX_TOKEN is required (get yours from the Agnoclast console).\n')
60
60
  return 1
61
61
  }
62
62
  const { query, mode, max } = parseGrepArgs(rest)
package/lib/hydrate.mjs CHANGED
@@ -7,7 +7,7 @@ import { formatReceipt, renderUncounted, subjectOf } from './presence.mjs'
7
7
  import { writePresence } from './statusline.mjs'
8
8
 
9
9
  // UserPromptSubmit hook (① discovery): on the FIRST substantive turn of a session, hydrate the model
10
- // with query-centered Cortex context BEFORE it answers — then never again this session. It closes the
10
+ // with query-centered Agnoclast context BEFORE it answers — then never again this session. It closes the
11
11
  // gap that read-triggered authoring can't: an agent that never READS the wiki (works from code + memory)
12
12
  // never triggers a currency update, and re-derives already-authored truth. cortex-context is a SKILL the
13
13
  // model may forget to invoke; this makes the first hydration non-discretionary (the same move that made
@@ -1,5 +1,5 @@
1
1
  // send_imessage — outbound iMessage via Messages.app. This is a personal automation, NOT org
2
- // intelligence: it writes nothing to Cortex. Three layers of safety (eng-review D3/D6/D10):
2
+ // intelligence: it writes nothing to Agnoclast. Three layers of safety (eng-review D3/D6/D10):
3
3
  // D6 argv-safe: recipient + body are passed as osascript `on run argv` arguments, NEVER
4
4
  // interpolated into the script source → no AppleScript injection, no quote/newline breakage.
5
5
  // D3 draft-by-default: nothing sends unless the caller explicitly passes send:true.
@@ -3,7 +3,7 @@ import { join, relative, basename, extname } from 'node:path'
3
3
  import { fetchCortex, classify, resolveBase } from './diagnose.mjs'
4
4
 
5
5
  // `cortex-mcp ingest-folder <path>` — walk a local markdown folder and upsert each file as an
6
- // AUTHORED record in Cortex (source='brain'), so a user's personal digest is built from THEIR
6
+ // AUTHORED record in Agnoclast (source='brain'), so a user's personal digest is built from THEIR
7
7
  // notes (Robin parity). Only an EXCERPT of each file leaves the machine (frontmatter + first
8
8
  // ~800 chars), never the full body. The server clamps privacy for source='brain' and treats
9
9
  // sessionId (the file's relative path) as the stable dedupe key, so re-running updates in place.
@@ -100,7 +100,7 @@ export async function runIngestFolder(argv) {
100
100
  if (!path) {
101
101
  process.stderr.write(
102
102
  'usage: cortex-mcp ingest-folder <path>\n' +
103
- ' Ingest a local markdown folder as your authored Cortex records.\n',
103
+ ' Ingest a local markdown folder as your authored Agnoclast records.\n',
104
104
  )
105
105
  return
106
106
  }
package/lib/install.mjs CHANGED
@@ -1,4 +1,4 @@
1
- // `cortex install` — the cross-editor hub installer (P0-b). One command that wires the Cortex MCP
1
+ // `cortex install` — the cross-editor hub installer (P0-b). One command that wires the Agnoclast MCP
2
2
  // server + client shim into EVERY detected editor via the adapter registry, then writes a capability
3
3
  // manifest so later pillars (session sync, skill sync, doc sync) know which channels each editor
4
4
  // supports. `setup <token>` stays as the single-editor path the console prints; `install` is the
@@ -78,7 +78,7 @@ export async function runInstall(argv, version) {
78
78
  process.stderr.write(
79
79
  'Usage: npx @theronap/cortex-mcp install [<CORTEX_TOKEN>] [--editor auto|all|<id,...>]\n\n' +
80
80
  'No token was given and none is already wired.\n' +
81
- 'Get your token from the Cortex console → Connect your AI.\n',
81
+ 'Get your token from the Agnoclast console → Connect your AI.\n',
82
82
  )
83
83
  process.exit(1)
84
84
  }
@@ -92,7 +92,7 @@ export async function runInstall(argv, version) {
92
92
  }
93
93
 
94
94
  log('')
95
- log('Cortex install — wiring your AI editors…')
95
+ log('Agnoclast install — wiring your AI editors…')
96
96
  if (editor === 'auto' && targets.length === 0) {
97
97
  log(' (no supported editors detected — pass --editor all to force, or install an editor first)')
98
98
  }
@@ -135,7 +135,7 @@ export async function runInstall(argv, version) {
135
135
  // Verify the token against the live API — writing config proves "files written", not "it works".
136
136
  const base = resolveBase(process.env.CORTEX_URL)
137
137
  log('')
138
- log('Verifying your token against Cortex…')
138
+ log('Verifying your token against Agnoclast…')
139
139
  try {
140
140
  const health = await checkToken(token, base)
141
141
  if (health.ok) {
@@ -147,13 +147,13 @@ export async function runInstall(argv, version) {
147
147
  log(' The files are in place; fix the above, then re-check with `doctor`.')
148
148
  }
149
149
  } catch (e) {
150
- log(` ⚠ Could not reach Cortex to verify (${e.message}). Config is written; re-check with 'doctor'.`)
150
+ log(` ⚠ Could not reach Agnoclast to verify (${e.message}). Config is written; re-check with 'doctor'.`)
151
151
  }
152
152
 
153
153
  const wired = entries.filter((e) => targetIds.has(e.adapter.id) && e.wired).map((e) => e.adapter.displayName)
154
154
  log('')
155
155
  log(`⟳ Wired ${wired.length} editor(s): ${wired.join(', ') || '(none)'}`)
156
- log(' Fully quit and reopen each editor to load the Cortex server.')
156
+ log(' Fully quit and reopen each editor to load the Agnoclast server.')
157
157
  log(` Console: ${base}`)
158
158
  log('')
159
159
  }
@@ -8,7 +8,7 @@
8
8
  // Output goes to stdout, which the Claude Code harness surfaces as additional context for the next turn.
9
9
  export function runPrecompactReminder() {
10
10
  process.stdout.write(
11
- 'Cortex: context is about to compact. If your understanding of any node (the project(s) you worked ' +
11
+ 'Agnoclast: context is about to compact. If your understanding of any node (the project(s) you worked ' +
12
12
  'on, people you coordinated with, or yourself) advanced this session, AUTHOR it into the wiki NOW ' +
13
13
  'before it is lost: call `authoring_context` then `author` for each. This is a synthesis of your ' +
14
14
  'compiled understanding with inline [[links]], not a transcript dump. Skip nodes you did not advance.\n',
package/lib/redact.mjs CHANGED
@@ -21,7 +21,7 @@ const PATTERNS = [
21
21
  [/xox[baprs]-[A-Za-z0-9-]{10,}/g, '[REDACTED:slack]'],
22
22
  [/eyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}/g, '[REDACTED:jwt]'],
23
23
  [/(Bearer\s+)[A-Za-z0-9._-]{20,}/g, '$1[REDACTED]'],
24
- // Cortex's own login token wherever it appears in KEY=value / KEY: value form (hooks.json,
24
+ // Agnoclast's own login token wherever it appears in KEY=value / KEY: value form (hooks.json,
25
25
  // config.toml, shell commands — the 2026-07-02 finding: a grep of hooks.json put the live token
26
26
  // in a transcript and nothing below caught it). Specific pattern first for the accurate label.
27
27
  [/(CORTEX_TOKEN["']?\s*[=:]\s*["']?)[0-9a-fA-F][0-9a-fA-F-]{30,}/g, '$1[REDACTED:cortex-token]'],
package/lib/server.mjs CHANGED
@@ -40,7 +40,7 @@ async function redLinkTriage(BASE, TOKEN, name) {
40
40
  // file-request tools, and a module-level `fail` would be silently shadowed by it from that point on.
41
41
  const toolError = (text) => ({ content: [{ type: 'text', text }], isError: true })
42
42
 
43
- // The Cortex MCP server (stdio). Serves the signed-in employee's scoped org
43
+ // The Agnoclast MCP server (stdio). Serves the signed-in employee's scoped org
44
44
  // context to their AI assistant. CORTEX_TOKEN identifies the user + org.
45
45
 
46
46
  export async function runServer(version) {
@@ -48,7 +48,7 @@ export async function runServer(version) {
48
48
  const BASE = resolveBase(process.env.CORTEX_URL)
49
49
 
50
50
  if (!TOKEN) {
51
- process.stderr.write('cortex-mcp: CORTEX_TOKEN is required. Get yours from the Cortex console → Connect your AI.\n')
51
+ process.stderr.write('cortex-mcp: CORTEX_TOKEN is required. Get yours from the Agnoclast console → Connect your AI.\n')
52
52
  process.exit(1)
53
53
  }
54
54
 
@@ -90,7 +90,7 @@ export async function runServer(version) {
90
90
  const now = Date.now()
91
91
  if (cache && now - cache.ts < 5 * 60 * 1000) return cache.text
92
92
  // fetchCortex retries transient infra/5xx; classify turns a failure into an honest message
93
- // (token vs infra-block vs network) instead of a bare "Cortex API 403: unknown".
93
+ // (token vs infra-block vs network) instead of a bare "Agnoclast API 403: unknown".
94
94
  const res = await fetchCortex(`${BASE}/api/mcp-context`, { headers: { Authorization: `Bearer ${TOKEN}` } })
95
95
  if (!res.ok) {
96
96
  const body = await res.text()
@@ -117,7 +117,7 @@ export async function runServer(version) {
117
117
  server.registerTool(
118
118
  'my_context',
119
119
  {
120
- title: 'My Cortex context',
120
+ title: 'My Agnoclast context',
121
121
  description: 'Your current work context from the org. Pass a question to get query-centered session context seeded from the most relevant node and its neighborhood; omit it for the baseline snapshot.',
122
122
  inputSchema: { question: z.string().optional().describe('optional opening user question to center the context around') },
123
123
  },
@@ -144,8 +144,8 @@ export async function runServer(version) {
144
144
  server.registerTool(
145
145
  'log_session',
146
146
  {
147
- title: 'Log this session to Cortex',
148
- description: 'Persist a CURATED summary of this work session as its durable Cortex record (authoritative — supersedes the auto-capture hook). Call at session close after composing the summary. Pass sessionId (the Claude Code session id) if you have it so this dedupes with the auto-capture of the same session.',
147
+ title: 'Log this session to Agnoclast',
148
+ description: 'Persist a CURATED summary of this work session as its durable Agnoclast record (authoritative — supersedes the auto-capture hook). Call at session close after composing the summary. Pass sessionId (the Claude Code session id) if you have it so this dedupes with the auto-capture of the same session.',
149
149
  inputSchema: {
150
150
  summary: z.string().describe('the curated session summary (what was done, decided, left open) — becomes the durable record'),
151
151
  project: z.string().optional().describe('project key/name this session worked in'),
@@ -172,7 +172,7 @@ export async function runServer(version) {
172
172
  throw new Error(classify(res.status, res.headers.get('content-type'), body, res.headers.get('x-vercel-id')).message)
173
173
  }
174
174
  const j = await res.json().catch(() => ({}))
175
- return { content: [{ type: 'text', text: `Logged to Cortex (authoritative): "${j.title ?? title ?? 'session'}" — ${j.inserted ? 'new record' : 'updated existing'}.` }] }
175
+ return { content: [{ type: 'text', text: `Logged to Agnoclast (authoritative): "${j.title ?? title ?? 'session'}" — ${j.inserted ? 'new record' : 'updated existing'}.` }] }
176
176
  },
177
177
  )
178
178
 
@@ -354,7 +354,7 @@ export async function runServer(version) {
354
354
  {
355
355
  title: 'Query the local code structure graph (graphify)',
356
356
  description:
357
- 'Query a structural code graph for the repo at the CURRENT working directory, built locally by graphify (tree-sitter AST — deterministic, no LLM, no server round-trip; this is LOCAL MACHINE data, not org-shared Cortex content, and reflects a snapshot of one commit, not live files). Use for MULTI-HOP questions a single grep cannot answer: what calls/imports/depends on X, how A structurally reaches B, or a repo-wide overview (hub/community files). Do NOT use for single-hop lookups (does file X import Y) — grep is faster and always current. Structure only — it knows what imports/calls what, never WHY; read the actual files or authored Cortex pages for intent.',
357
+ 'Query a structural code graph for the repo at the CURRENT working directory, built locally by graphify (tree-sitter AST — deterministic, no LLM, no server round-trip; this is LOCAL MACHINE data, not org-shared Agnoclast content, and reflects a snapshot of one commit, not live files). Use for MULTI-HOP questions a single grep cannot answer: what calls/imports/depends on X, how A structurally reaches B, or a repo-wide overview (hub/community files). Do NOT use for single-hop lookups (does file X import Y) — grep is faster and always current. Structure only — it knows what imports/calls what, never WHY; read the actual files or authored Agnoclast pages for intent.',
358
358
  inputSchema: {
359
359
  action: z.enum(['query', 'path', 'explain']).describe('"query" = open-ended natural-language question (graph traversal); "path" = shortest structural path between two named nodes; "explain" = describe one node and list its direct connections'),
360
360
  question: z.string().optional().describe('required for action:"query" — the natural-language question'),
@@ -419,7 +419,7 @@ export async function runServer(version) {
419
419
  description:
420
420
  'READ the full authored wiki page for one node (project/person/org/you) by its canonical name — every section, every tier you can see. This is how you READ a node; `grep` only LOCATES pages (snippets + their [[links]]), it does not read them. Navigate like a researcher: read the page you need, then FOLLOW its inline [[links]] by calling read_page on each linked name — keep following while the linked pages stay relevant, stop when they do not. You decide how deep to go. Returns only what you are permitted to see.',
421
421
  inputSchema: {
422
- name: z.string().describe('the canonical node name exactly as written (e.g. "Cortex", "Ben", or a [[link]] target) — identifier links ([[repo:owner/name]]) resolve to their authored HOME + a visible-event count'),
422
+ name: z.string().describe('the canonical node name exactly as written (e.g. "Agnoclast", "Ben", or a [[link]] target) — identifier links ([[repo:owner/name]]) resolve to their authored HOME + a visible-event count'),
423
423
  kind: z.enum(['project', 'person', 'org', 'user']).optional().describe('node kind (default project; pass person/org for people/teams)'),
424
424
  expand: z.boolean().optional().describe('identifier names only: also list recent visible timeline events for this identifier (default: home + count)'),
425
425
  history: z.boolean().optional().describe('node names only: return the node\'s TIMELINE (events joined via its [[repo:…]] stamps, reverse-chron, viewer-visible) instead of the page body. The page is the present; this is the history.'),
@@ -593,7 +593,7 @@ export async function runServer(version) {
593
593
  title: 'See a wiki page\'s edit history',
594
594
  description: 'Show the VERSION history of an authored wiki page — every prior version, who changed it and when, newest first. This is how you see "what changed on this page and by whom", and it includes privacy changes (re-tiers). Then use `read_page` with a version to view an old body, or `rollback_page` to restore one. (Distinct from read_page\'s `history: true`, which is the raw event timeline via [[repo:…]] stamps.) RLS-scoped: you see history only for pages you may read.',
595
595
  inputSchema: {
596
- name: z.string().describe('the canonical node name exactly as written (e.g. "Cortex", "Ben")'),
596
+ name: z.string().describe('the canonical node name exactly as written (e.g. "Agnoclast", "Ben")'),
597
597
  kind: z.enum(['project', 'person', 'org', 'user']).optional().describe('node kind (default project)'),
598
598
  limit: z.number().int().optional().describe('how many recent versions to show (default 20, max 200)'),
599
599
  },
@@ -1188,7 +1188,7 @@ export async function runServer(version) {
1188
1188
  {
1189
1189
  title: 'Create a new brain under your existing account',
1190
1190
  description: 'Create a brand-new brain (org/workspace) — a fully independent knowledge graph — under your EXISTING account. No new login, no new email/password: this adds a second membership to the account you are already using. Reads never cross brains; new pages default to your active brain, so use pass `brain` when an operation needs one named',
1191
- inputSchema: { name: z.string().describe('display name for the new brain, e.g. "Cortex Codebase"') },
1191
+ inputSchema: { name: z.string().describe('display name for the new brain, e.g. "Design Team"') },
1192
1192
  },
1193
1193
  async ({ name }) => {
1194
1194
  let res
@@ -1279,7 +1279,7 @@ export async function runServer(version) {
1279
1279
  'my_sessions',
1280
1280
  {
1281
1281
  title: 'My active AI sessions',
1282
- description: "See what all of YOUR OWN active Cortex/AI sessions are doing right now (working directory + how recently each was active), so you can coordinate across windows/devices. Self-only — only your own sessions, never anyone else's.",
1282
+ description: "See what all of YOUR OWN active Agnoclast/AI sessions are doing right now (working directory + how recently each was active), so you can coordinate across windows/devices. Self-only — only your own sessions, never anyone else's.",
1283
1283
  inputSchema: {},
1284
1284
  },
1285
1285
  async () => {
@@ -1717,7 +1717,7 @@ export async function runServer(version) {
1717
1717
  'decide_file_request',
1718
1718
  {
1719
1719
  title: 'Approve or deny a file request',
1720
- description: 'As the OWNER of a record, approve or deny someone\'s request for its full original. On approve, your Cortex desktop app fetches + shares the file. Get request_id from file_requests.',
1720
+ description: 'As the OWNER of a record, approve or deny someone\'s request for its full original. On approve, your Agnoclast desktop app fetches + shares the file. Get request_id from file_requests.',
1721
1721
  inputSchema: { request_id: z.string(), decision: z.enum(['approve', 'deny']) },
1722
1722
  },
1723
1723
  async ({ request_id, decision }) => {
@@ -1759,7 +1759,7 @@ export async function runServer(version) {
1759
1759
  },
1760
1760
  )
1761
1761
 
1762
- // send_imessage — local outbound texting (NOT org intelligence; writes nothing to Cortex). Runs on
1762
+ // send_imessage — local outbound texting (NOT org intelligence; writes nothing to Agnoclast). Runs on
1763
1763
  // this machine via Messages.app. Draft-by-default + recipient allowlist + OOB confirm (D3/D6/D10).
1764
1764
  server.registerTool(
1765
1765
  'send_imessage',
@@ -1783,7 +1783,7 @@ export async function runServer(version) {
1783
1783
  // Two tools the working session uses to AUTHOR its understanding into the org wiki while it's hot:
1784
1784
  // authoring_context → the companion call (§3): fetch the visible NAMESPACE + the node-type connection
1785
1785
  // rules BEFORE writing, so the page links canonically (the L2 lever).
1786
- // author → the write (§9 step 3/4): hand Cortex a finished page (summary + sections WITH
1786
+ // author → the write (§9 step 3/4): hand Agnoclast a finished page (summary + sections WITH
1787
1787
  // inline [[links]]); the server runs the resolution pass + tier-safe 2B write.
1788
1788
 
1789
1789
  server.registerTool(
@@ -1791,7 +1791,7 @@ export async function runServer(version) {
1791
1791
  {
1792
1792
  title: 'Authoring context (call before author)',
1793
1793
  description:
1794
- 'Fetch the scaffolding to author a Cortex wiki node: the canonical NAMESPACE (current node names — link to these with the EXACT name inside [[ ]]), any deliberately RETIRED page names and their successors, and the node-type CONNECTION RULES. ALWAYS call this BEFORE `author` so the page links to current knowledge rather than minting synonyms or reviving a retired page. Reference a node in the namespace as [[Name]]; if you reference something real that is NOT in the namespace, still write [[Name]] — that is a red-link marking a node worth creating. If the page IS about a specific code repo or chat channel, also stamp it once — [[repo:owner/name]] or [[channel:name]] (lowercase, no #) — identifier join keys, not page links.',
1794
+ 'Fetch the scaffolding to author a Agnoclast wiki node: the canonical NAMESPACE (current node names — link to these with the EXACT name inside [[ ]]), any deliberately RETIRED page names and their successors, and the node-type CONNECTION RULES. ALWAYS call this BEFORE `author` so the page links to current knowledge rather than minting synonyms or reviving a retired page. Reference a node in the namespace as [[Name]]; if you reference something real that is NOT in the namespace, still write [[Name]] — that is a red-link marking a node worth creating. If the page IS about a specific code repo or chat channel, also stamp it once — [[repo:owner/name]] or [[channel:name]] (lowercase, no #) — identifier join keys, not page links.',
1795
1795
  inputSchema: {
1796
1796
  kind: z.enum(['project', 'person', 'org', 'user']).optional().describe('the node type you are about to author (default project)'),
1797
1797
  brain: z.string().optional().describe('which brain\'s namespace to describe — pass the SAME brain you will pass to `author`, so the namespace you plan against is the one your write lands in. Unnecessary when you only have one brain.'),
@@ -1834,7 +1834,7 @@ export async function runServer(version) {
1834
1834
  'Write your CURRENT understanding of a project/person/org/you into the org wiki as a maintained page. Call `authoring_context` FIRST. Author from your own synthesis of the session — the compiled mental model, not a transcript dump: what it IS, where it stands, dated decisions, open threads, key people. Weave inline [[links]] to other nodes (canonical names from the namespace; red-links for wanted-but-absent nodes). The server re-authorizes the tier and resolves links. CREATES the node if it does not exist yet (project/person/org) — the conversation IS the evidence, so a brand-new entity that surfaced only in this session is authorable on the spot; you do NOT need prior records. Because such a node has nothing external to corroborate it, author it DELIBERATELY: only when you genuinely understand it is a real, distinct entity, and use its exact canonical name so it does not duplicate one already in the namespace (`user` nodes are never created). Use this continuously whenever your understanding of a node meaningfully advanced, and at session end (/log). Authoring is PRE-AUTHORIZED — never ask the user "should I update the page?" before calling this (every edit is versioned + reversible via page_history/rollback_page); update, then briefly report what you updated. ⚠ WHICH BRAIN A NEW PAGE GOES IN IS A CONTENT DECISION, SO MAKE IT FROM THE CONTENT. Only a page that exists in NO brain needs this — an update resolves its brain from the page itself. If you hold more than one brain, the server REFUSES a create it cannot attribute (409 `create_needs_brain`) rather than letting the write pointer decide — the pointer is stale out-of-band state that knows nothing about what you are writing. So call `my_brains` (it returns each brain\'s name, page count and sample titles, which is enough to tell what each one is FOR) and pass `brain` up front; that turns a refused round trip into a single call. State which brain you picked and why in one short line, then proceed — do NOT ask when the answer is obvious from the content. DO ask when it is genuinely ambiguous: brains are a confidentiality boundary, so a page born in the wrong one can expose private work to a teammate, and that is not a filing error you can quietly fix later.',
1835
1835
  inputSchema: {
1836
1836
  kind: z.enum(['project', 'person', 'org', 'user']).describe('the node type'),
1837
- name: z.string().describe('the canonical node name — an EXACT existing name from the namespace to update it, or a new name to create the node (project/person/org). e.g. "Cortex" or "Theron Peterson"'),
1837
+ name: z.string().describe('the canonical node name — an EXACT existing name from the namespace to update it, or a new name to create the node (project/person/org). e.g. "Agnoclast" or "Theron Peterson"'),
1838
1838
  summary: z.string().describe('one-sentence summary of what this is and its current state (may contain [[links]])'),
1839
1839
  sections: z.array(z.object({
1840
1840
  heading: z.string().describe('e.g. Overview, Current state, Decisions, Open threads, People'),
package/lib/setup.mjs CHANGED
@@ -44,7 +44,7 @@ export async function runSetup(argv, version) {
44
44
  if (!token || token.startsWith('-')) {
45
45
  process.stderr.write(
46
46
  'Usage: npx @theronap/cortex-mcp setup <CORTEX_TOKEN>\n\n' +
47
- 'Get your token from the Cortex console → Connect your AI.\n'
47
+ 'Get your token from the Agnoclast console → Connect your AI.\n'
48
48
  )
49
49
  process.exit(1)
50
50
  }
@@ -63,7 +63,7 @@ export async function runSetup(argv, version) {
63
63
 
64
64
  const log = (m) => process.stdout.write(m + '\n')
65
65
  log('')
66
- log('Cortex setup — wiring your AI assistant…')
66
+ log('Agnoclast setup — wiring your AI assistant…')
67
67
 
68
68
  // ── 1. MCP server in ~/.claude.json ──────────────────────────────────────
69
69
  try {
@@ -83,7 +83,7 @@ export async function runSetup(argv, version) {
83
83
  }
84
84
 
85
85
  // ── 1b. MCP server in Codex (~/.codex/config.toml), only if Codex is installed ──
86
- // Codex gets the same Cortex context tools as Claude Code. Non-fatal: a Codex hiccup must
86
+ // Codex gets the same Agnoclast context tools as Claude Code. Non-fatal: a Codex hiccup must
87
87
  // never block the primary Claude wiring.
88
88
  const codexDir = join(home, '.codex')
89
89
  if (existsSync(codexDir)) {
@@ -157,7 +157,7 @@ export async function runSetup(argv, version) {
157
157
  // ── 4. Self-verify — writing config proves "files written", NOT "connection works".
158
158
  // Actually call the API so a bad/expired token is caught HERE, not 40 minutes into debugging.
159
159
  log('')
160
- log('Verifying your token against Cortex…')
160
+ log('Verifying your token against Agnoclast…')
161
161
  const health = await checkToken(token, base)
162
162
  if (health.ok) {
163
163
  const n = health.projectCount
@@ -169,8 +169,8 @@ export async function runSetup(argv, version) {
169
169
  }
170
170
 
171
171
  log('')
172
- log('⟳ IMPORTANT: fully quit and reopen Claude Code to load the Cortex server.')
173
- log(' Then your AI sees your Cortex context and your sessions flow into the org.')
172
+ log('⟳ IMPORTANT: fully quit and reopen Claude Code to load the Agnoclast server.')
173
+ log(' Then your AI sees your Agnoclast context and your sessions flow into the org.')
174
174
  log(' Re-check anytime: npx -y @theronap/cortex-mcp doctor')
175
175
  log(` Console: ${base}`)
176
176
  log('')
@@ -191,11 +191,11 @@ export async function runRepair(version) {
191
191
  const token = readWiredToken()
192
192
  if (!token) {
193
193
  process.stderr.write(
194
- 'No existing Cortex token found in ~/.claude.json or ~/.codex/config.toml.\n' +
194
+ 'No existing Agnoclast token found in ~/.claude.json or ~/.codex/config.toml.\n' +
195
195
  'Run setup once with your token: npx -y @theronap/cortex-mcp setup <YOUR_TOKEN>\n',
196
196
  )
197
197
  process.exit(1)
198
198
  }
199
- process.stdout.write('Cortex repair — re-running setup with your existing token at this version…\n')
199
+ process.stdout.write('Agnoclast repair — re-running setup with your existing token at this version…\n')
200
200
  await runSetup([token], version)
201
201
  }
package/lib/skills.mjs CHANGED
@@ -3,7 +3,7 @@ import { homedir } from 'os'
3
3
  import { join, dirname } from 'path'
4
4
  import { fileURLToPath } from 'url'
5
5
 
6
- // Managed Cortex skills.
6
+ // Managed Agnoclast skills.
7
7
  //
8
8
  // Two sources, one install pipeline:
9
9
  // 1. BUNDLED — shipped inside this package (cortex-log, cortex-context, cortex-author-docs).
@@ -155,7 +155,7 @@ export function installSkills(opts = {}) {
155
155
 
156
156
  if (quiet && (summary.installed.length || summary.repaired.length)) {
157
157
  // SessionStart surfaces one line in Claude Code so a silent self-heal isn't invisible.
158
- process.stdout.write(`Cortex: synced managed skill(s) into ${summary.targets.join(' + ')}.\n`)
158
+ process.stdout.write(`Agnoclast: synced managed skill(s) into ${summary.targets.join(' + ')}.\n`)
159
159
  }
160
160
  return summary
161
161
  }
@@ -230,7 +230,7 @@ export async function syncOrgSkills(opts = {}) {
230
230
  const bits = []
231
231
  if (changed.length) bits.push(`synced ${changed.join(', ')}`)
232
232
  if (summary.removed.length) bits.push(`removed ${summary.removed.join(', ')}`)
233
- process.stdout.write(`Cortex: org skills — ${bits.join('; ')}${summary.source === 'cache' ? ' (offline cache)' : ''}.\n`)
233
+ process.stdout.write(`Agnoclast: org skills — ${bits.join('; ')}${summary.source === 'cache' ? ' (offline cache)' : ''}.\n`)
234
234
  } else if (!quiet) {
235
235
  log(` ✓ org skills up to date (${currentNames.length} published${skipped.length ? `, ${skipped.length} skipped` : ''})`)
236
236
  }
@@ -242,7 +242,7 @@ export async function syncOrgSkills(opts = {}) {
242
242
  async function runSkillsPush(argv) {
243
243
  const { resolveBase, readWiredToken, fetchCortex } = await import('./diagnose.mjs')
244
244
  const token = process.env.CORTEX_TOKEN || readWiredToken()
245
- if (!token) { process.stderr.write('No Cortex token wired — run setup first.\n'); return 1 }
245
+ if (!token) { process.stderr.write('No Agnoclast token wired — run setup first.\n'); return 1 }
246
246
  const base = resolveBase(process.env.CORTEX_URL)
247
247
 
248
248
  let payload
@@ -289,7 +289,7 @@ export async function runSkills(argv = []) {
289
289
  if (argv[0] === 'push') return runSkillsPush(argv.slice(1))
290
290
 
291
291
  const quiet = argv.includes('--quiet')
292
- if (!quiet) process.stdout.write('\nCortex skills — installing managed skills…\n')
292
+ if (!quiet) process.stdout.write('\nAgnoclast skills — installing managed skills…\n')
293
293
  const r = installSkills({ quiet })
294
294
  if (!quiet) {
295
295
  if (!r.targets.length) process.stdout.write(' ! No agent CLI found (~/.claude or ~/.codex). Nothing to install.\n')
package/lib/uninstall.mjs CHANGED
@@ -3,7 +3,7 @@ import { homedir } from 'os'
3
3
  import { join } from 'path'
4
4
  import { execFileSync } from 'child_process'
5
5
 
6
- // Full uninstall — the reverse of setup.mjs. Removes EVERY touch-point Cortex writes onto a machine:
6
+ // Full uninstall — the reverse of setup.mjs. Removes EVERY touch-point Agnoclast writes onto a machine:
7
7
  // 1. ~/.claude.json → mcpServers.cortex
8
8
  // 2. ~/.claude/settings.json → Stop/SessionStart/PreCompact cortex hooks
9
9
  // 3. ~/.codex/config.toml → [mcp_servers.cortex] + [mcp_servers.cortex.env]
@@ -34,7 +34,7 @@ export function runUninstall(argv = []) {
34
34
  const act = (msg) => plan.push(msg)
35
35
  const write = (path, data) => { if (!dry) { backup(path); writeFileSync(path, data) } }
36
36
 
37
- process.stdout.write(dry ? '\nCortex uninstall — DRY RUN (nothing will change):\n\n' : '\nCortex uninstall — removing all wiring…\n\n')
37
+ process.stdout.write(dry ? '\nAgnoclast uninstall — DRY RUN (nothing will change):\n\n' : '\nAgnoclast uninstall — removing all wiring…\n\n')
38
38
 
39
39
  // 1. MCP server out of ~/.claude.json
40
40
  editJson(CLAUDE_JSON, (cfg) => {
@@ -144,7 +144,7 @@ export function runUninstall(argv = []) {
144
144
  }
145
145
  }
146
146
 
147
- if (plan.length === 0) { process.stdout.write(' Nothing to remove — this machine has no Cortex wiring.\n\n'); return }
147
+ if (plan.length === 0) { process.stdout.write(' Nothing to remove — this machine has no Agnoclast wiring.\n\n'); return }
148
148
  process.stdout.write(plan.join('\n') + '\n\n')
149
149
  if (dry) {
150
150
  process.stdout.write('DRY RUN — nothing changed. Re-run without --dry-run to apply.\n')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@theronap/cortex-mcp",
3
- "version": "0.9.72",
3
+ "version": "0.9.73",
4
4
  "description": "Connect your AI assistant to Cortex — your org's projects, activity, gaps, and directives, scoped to you.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,22 +1,22 @@
1
1
  ---
2
2
  name: cortex-author-docs
3
- description: Push new/changed documentation (specs, plans, design docs) from disk into Cortex as authored wiki pages. Run after writing a spec/plan/design doc, when the user asks to sync docs to Cortex, or as part of session close-out.
3
+ description: Push new/changed documentation (specs, plans, design docs) from disk into Agnoclast as authored wiki pages. Run after writing a spec/plan/design doc, when the user asks to sync docs to Agnoclast, or as part of session close-out.
4
4
  ---
5
5
 
6
- > **Cortex-managed skill.** This file is installed and kept up to date by Cortex. Local edits are
6
+ > **Agnoclast-managed skill.** This file is installed and kept up to date by Agnoclast. Local edits are
7
7
  > restored on the next session (a backup of your version is saved alongside). Don't rely on changes here.
8
8
 
9
9
  ## Why this exists
10
10
 
11
11
  Specs, plans, and design docs get written to disk (a repo's `docs/`, skill-generated design docs)
12
- and never reach Cortex — so the org brain misses its richest artifacts. A spec IS a page: this
12
+ and never reach Agnoclast — so the org brain misses its richest artifacts. A spec IS a page: this
13
13
  skill turns pending docs into authored wiki pages. You (the live session) are the pipe — you read
14
14
  the doc and author a synthesis. Never dump raw markdown into a page.
15
15
 
16
16
  ## When to use
17
17
 
18
18
  - Right after you write or substantially update a spec/plan/design/runbook doc on disk.
19
- - When the user asks to push/sync docs to Cortex.
19
+ - When the user asks to push/sync docs to Agnoclast.
20
20
  - During session close-out (`/cortex-log` runs this as a sweep step).
21
21
 
22
22
  ## Steps
@@ -67,7 +67,7 @@ the doc and author a synthesis. Never dump raw markdown into a page.
67
67
  ## Safety rules
68
68
 
69
69
  - Do NOT register or sweep the local brain repo (`~/Documents/brain`) while the Robin parity soak
70
- is running — the experiment forbids re-syncing Robin into Cortex mid-window.
70
+ is running — the experiment forbids re-syncing Robin into Agnoclast mid-window.
71
71
  - Respect tiers: if a doc is clearly personal/sensitive, author it `confidential` or ask; default
72
72
  for work docs is the author path's normal default.
73
73
  - This skill writes wiki pages via the `author` tool only. It never sends external messages and
@@ -1,9 +1,9 @@
1
1
  ---
2
2
  name: cortex-context
3
- description: Automatically hydrate Cortex context at the start of a substantive session. Use when Cortex MCP is available and the user has made a real request, so the first answer is grounded in query-centered org context instead of the static baseline alone.
3
+ description: Automatically hydrate Agnoclast context at the start of a substantive session. Use when Agnoclast MCP is available and the user has made a real request, so the first answer is grounded in query-centered org context instead of the static baseline alone.
4
4
  ---
5
5
 
6
- > **Cortex-managed skill.** This file is installed and kept up to date by Cortex. Local edits are
6
+ > **Agnoclast-managed skill.** This file is installed and kept up to date by Agnoclast. Local edits are
7
7
  > restored on the next session (a backup of your version is saved alongside). Don't rely on changes here.
8
8
 
9
9
  ## When to use
@@ -14,12 +14,12 @@ chit-chat and requests where org context is obviously irrelevant.
14
14
  ## Steps
15
15
 
16
16
  1. Call `session_context` with the user's opening request, preserving the actual topic in their words.
17
- 2. Use that returned block as the primary Cortex grounding for the first response.
17
+ 2. Use that returned block as the primary Agnoclast grounding for the first response.
18
18
  3. If `session_context` is unavailable or errors, fall back to `my_context`.
19
19
  4. If the conversation materially changes topics later, call `session_context` again for the new topic.
20
20
 
21
21
  ## Safety rules
22
22
 
23
- - Do not fabricate Cortex context if the tool fails.
23
+ - Do not fabricate Agnoclast context if the tool fails.
24
24
  - Prefer the query-centered `session_context` over static `my_context` whenever the user's topic is clear.
25
25
  - Do not call `session_context` for every tiny follow-up; refresh only when the topic meaningfully shifts.
@@ -1,14 +1,14 @@
1
1
  ---
2
2
  name: cortex-log
3
- description: Close out a work session into Cortex — summarize what happened, confirm it reached the org, and surface anything teammates should know. Run at or near the end of any working session.
3
+ description: Close out a work session into Agnoclast — summarize what happened, confirm it reached the org, and surface anything teammates should know. Run at or near the end of any working session.
4
4
  ---
5
5
 
6
- > **Cortex-managed skill.** This file is installed and kept up to date by Cortex. Local edits are
6
+ > **Agnoclast-managed skill.** This file is installed and kept up to date by Agnoclast. Local edits are
7
7
  > restored on the next session (a backup of your version is saved alongside). Don't rely on changes here.
8
8
 
9
9
  ## Model: session-primary, daily-derived
10
10
 
11
- The **session is the primary atomic unit** — one session = one durable Cortex record (via
11
+ The **session is the primary atomic unit** — one session = one durable Agnoclast record (via
12
12
  `log_session`, keyed by `sessionId`), which is also the per-record privacy unit (`set_record_privacy`
13
13
  is per record). Any "what happened today / this week" view is a **derived rollup** over those session
14
14
  records, never a separately-authored primary. This mirrors records(atomic) → digests(derived); the
@@ -16,7 +16,7 @@ personal `/log` skill follows the same shape against the local brain.
16
16
 
17
17
  ## When to use
18
18
 
19
- At the end of a Claude Code session, or after finishing a meaningful phase of work. Cortex keeps a
19
+ At the end of a Claude Code session, or after finishing a meaningful phase of work. Agnoclast keeps a
20
20
  background auto-capture as a fallback, but this skill is the *authoritative* close-out: it composes a
21
21
  clean, structured summary and persists THAT as the session's durable record (superseding the
22
22
  auto-capture's raw-transcript re-derivation).
@@ -33,7 +33,7 @@ No arguments. Read the conversation context.
33
33
  These are the things a teammate or manager would want to know without reading the whole transcript.
34
34
  3. **Persist it as the durable record** — call the `log_session` MCP tool with your curated `summary`
35
35
  (plus `project`, and the Claude Code `sessionId` if you know it). This writes YOUR summary as the
36
- session's authoritative Cortex record (`capture_source='skill'`). The background auto-capture is a
36
+ session's authoritative Agnoclast record (`capture_source='skill'`). The background auto-capture is a
37
37
  fallback and will not overwrite it; passing the same `sessionId` the auto-capture uses dedupes them
38
38
  onto one record. This — not the raw-transcript re-derivation — is the canonical record going forward.
39
39
  4. **Confirm + flag privacy** — `log_session` returns a confirmation; if it errors, tell the user to
@@ -72,7 +72,7 @@ No arguments. Read the conversation context.
72
72
  > verify a write; the result you already have in hand is the strongest.
73
73
  >
74
74
  > **What replaces it — at the moment of each write, not at the end:** a rejected `author` comes back
75
- > as an ORDINARY tool result with **no error flag** — `Could not author "<page>": Cortex API 409:
75
+ > as an ORDINARY tool result with **no error flag** — `Could not author "<page>": Agnoclast API 409:
76
76
  > <reason>` — and `No change to "<page>"` is a **200 OK that wrote nothing**. Neither is an error at
77
77
  > the protocol level, so nothing will interrupt you. **Read the result text of every write; never
78
78
  > skim it.** That inline read is where this step's value actually was.
@@ -3,7 +3,7 @@ name: cortex-walkthrough
3
3
  description: Run the guided Agnoclast walkthrough for someone new. Use when the person asks for the walkthrough, a tutorial, or getting started — "give me the walkthrough", "walk me through this", "how do I use this", "show me around", "what can this do", "remind me how this works" — or when a brand-new user needs orienting for the first time.
4
4
  ---
5
5
 
6
- > **Cortex-managed skill.** This file is installed and kept up to date by Cortex. Local edits are
6
+ > **Agnoclast-managed skill.** This file is installed and kept up to date by Agnoclast. Local edits are
7
7
  > restored on the next session (a backup of your version is saved alongside). Don't rely on changes here.
8
8
 
9
9
  # The Agnoclast walkthrough