# Cortex — AI Project Memory & Knowledge Graph ## Overview Cortex is a CLI tool and web server for storing, linking, and searching project knowledge as a graph of typed nodes and edges. It supports hybrid search (BM25 + vector similarity + freshness), auto-decay of stale nodes, and a web portal for visualization. Data is stored in `.memory/cortex.db` (SQLite) in the current working directory. --- ## Installation & Building ### Development Mode ```bash # Install dependencies npm install # Build TypeScript npm run build # Run CLI (development) node dist/cli/index.js # Run MCP server (development) node dist/mcp/index.js ``` ### Standalone Executables Build self-contained executables that don't require Node.js: ```bash # Build for Windows (creates cortex.exe and cortex-mcp.exe) npm run package:win # Build for Linux npm run package:linux # Build for macOS npm run package:mac # Build all (CLI + MCP for current platform) npm run package ``` **Output files** (in `build/` directory): - `cortex.exe` / `cortex` — CLI tool - `cortex-mcp.exe` / `cortex-mcp` — MCP server for Claude Code integration ### Running Standalone ```bash # CLI ./build/cortex.exe list ./build/cortex.exe query "authentication" ./build/cortex.exe serve --port 3100 # MCP server (for Claude Code) ./build/cortex-mcp.exe ``` --- ## CLI Reference All commands are invoked as `cortex ` (standalone) or `node dist/cli/index.js ` (dev). ### `cortex add ` Add a node to the knowledge graph. | Argument / Option | Required | Description | |---|---|---| | `` | yes | Node kind: `memory`, `component`, `task`, `decision` | | `-t, --title ` | yes | Node title | | `-c, --content <content>` | no | Node content/description | | `--tags <tags>` | no | Comma-separated tags | | `--status <status>` | no | Status (e.g. `todo`, `doing`, `done`, `active`, `deprecated`) | | `--section <section>` | no | Structured section as `"Label: body"` (repeatable) | ```bash cortex add memory -t "Auth flow design" -c "OAuth2 PKCE flow for SPA" --tags auth,security --status active cortex add memory -t "add command" --section "Arguments: <kind> — memory, component, task, decision" --section "Options: -t title, -c content, --tags, --status" cortex add task -t "Implement login page" --status todo cortex add decision -t "Use PostgreSQL" -c "Chose Postgres over MySQL for JSON support" cortex add component -t "UserService" -c "Handles user CRUD operations" --tags backend ``` ### `cortex query <text>` Search the knowledge graph using natural language. Uses hybrid BM25 + vector + freshness scoring. | Argument / Option | Required | Description | |---|---|---| | `<text>` | yes | Natural language search query | | `--kind <kind>` | no | Filter by node kind | | `--limit <n>` | no | Max results (default: 10) | | `--format <fmt>` | no | Output format: `text` or `json` (default: `text`) | ```bash cortex query "authentication" cortex query "database decisions" --kind decision cortex query "user service" --limit 5 --format json ``` ### `cortex show <id>` Show a node's full details, structured sections, inline children, and connections. The `<id>` can be a full UUID or a unique prefix. Each call to `show` updates the node's `lastAccessedAt` timestamp, which affects freshness scoring. If the node has `metadata.sections`, they render as labeled blocks. If the node has outgoing `contains` edges, children are listed inline before other connections. | Argument / Option | Required | Description | |---|---|---| | `<id>` | yes | Node ID or unique prefix | | `--format <fmt>` | no | Output format: `text` or `json` (default: `text`) | ```bash cortex show abc123 cortex show abc123 --format json ``` ### `cortex list` List nodes in the knowledge graph. | Option | Required | Description | |---|---|---| | `--kind <kind>` | no | Filter by kind | | `--status <status>` | no | Filter by status | | `--tags <tags>` | no | Comma-separated tags to filter | | `--limit <n>` | no | Max results | | `--stale` | no | Include stale/decayed nodes | | `--format <fmt>` | no | Output format: `text` or `json` (default: `text`) | ```bash cortex list cortex list --kind task --status todo cortex list --tags auth,security cortex list --stale cortex list --format json ``` ### `cortex update <id>` Update an existing node's fields. | Argument / Option | Required | Description | |---|---|---| | `<id>` | yes | Node ID or unique prefix | | `-t, --title <title>` | no | New title | | `-c, --content <content>` | no | New content | | `--status <status>` | no | New status | | `--tags <tags>` | no | Replace tags (comma-separated) | | `--stale` | no | Mark as stale | | `--section <section>` | no | Structured section as `"Label: body"` (repeatable, replaces by label) | ```bash cortex update abc123 --status done cortex update abc123 -t "Updated title" -c "New content" cortex update abc123 --tags newtag1,newtag2 cortex update abc123 --section "Notes: Updated implementation notes" ``` ### `cortex remove <id>` Remove a node. Default is soft delete (marks as stale). Use `--hard` for permanent deletion. | Argument / Option | Required | Description | |---|---|---| | `<id>` | yes | Node ID or unique prefix | | `--hard` | no | Permanently delete instead of marking stale | ```bash cortex remove abc123 cortex remove abc123 --hard ``` ### `cortex link <fromId> <toId>` Create a directed edge between two nodes. | Argument / Option | Required | Description | |---|---|---| | `<fromId>` | yes | Source node ID or prefix | | `<toId>` | yes | Target node ID or prefix | | `--type <type>` | yes | Edge type: `depends_on`, `contains`, `implements`, `blocked_by`, `subtask_of`, `relates_to`, `supersedes`, `about` | ```bash cortex link abc123 def456 --type depends_on cortex link abc123 def456 --type contains ``` ### `cortex graph [id]` Visualize the knowledge graph as an ASCII tree. Optionally root at a specific node. | Argument | Required | Description | |---|---|---| | `[id]` | no | Root node ID or prefix. Omit for full graph. | ```bash cortex graph cortex graph abc123 ``` ### `cortex children <id>` List child nodes connected via outgoing `contains` edges from the given node. | Argument / Option | Required | Description | |---|---|---| | `<id>` | yes | Parent node ID or prefix | | `--kind <kind>` | no | Filter children by kind | | `--format <fmt>` | no | Output format: `text` or `json` (default: `text`) | ```bash cortex children abc123 cortex children abc123 --kind task cortex children abc123 --format json ``` ### `cortex decay` Run auto-decay to mark old untouched nodes as stale. Nodes whose `lastAccessedAt` exceeds the threshold are marked stale and hidden from default listings and search. | Option | Required | Description | |---|---|---| | `--days <number>` | no | Max age in days before decay (default: 180) | ```bash cortex decay cortex decay --days 90 cortex decay --days 0 # decay all nodes not accessed today ``` ### `cortex serve` Start the Cortex Portal web server. Auto-decay runs on startup and every 24 hours. | Option | Required | Description | |---|---|---| | `-p, --port <number>` | no | Port number (default: 3100) | ```bash cortex serve cortex serve --port 8080 ``` --- ## Node Kinds | Kind | Purpose | |---|---| | `memory` | General knowledge, notes, context | | `component` | Code components, services, modules | | `task` | Work items, todos | | `decision` | Architectural or design decisions | ## Edge Types | Type | Meaning | |---|---| | `depends_on` | Source depends on target | | `contains` | Source contains target | | `implements` | Source implements target | | `blocked_by` | Source is blocked by target | | `subtask_of` | Source is a subtask of target | | `relates_to` | General relationship | | `supersedes` | Source supersedes/replaces target | | `about` | Source is about target | ## Structured Sections Nodes can have structured content via `metadata.sections`. Each section has a `label` and `body`. Use the `--section "Label: body"` flag on `add` or `update` to create sections. When displayed with `cortex show`, sections render as: ``` ── Arguments ── <kind> — memory, component, task, decision ── Options ── -t title, -c content, --tags, --status ``` The `show` command also displays inline children (nodes linked via `contains` edges). Use `cortex children <id>` to list only children. ## Search Scoring Search combines three signals: - **BM25** (weight 0.25) — text relevance - **Vector similarity** (weight 0.60) — semantic similarity via embeddings (requires Ollama) - **Freshness** (weight 0.15) — exponential decay based on `lastAccessedAt` Freshness multiplier: `e^(-0.01 * ageDays)` — half-life ~69 days. Recently accessed nodes are boosted; old untouched nodes are penalized but not zeroed. ## REST API The web server exposes these endpoints under `/api`: | Method | Path | Description | |---|---|---| | `GET` | `/api/nodes` | List nodes. Query params: `kind`, `status`, `tags`, `limit`, `includeStale` | | `GET` | `/api/nodes/:id` | Get node + connections | | `POST` | `/api/nodes` | Create node. Body: `{ kind, title, content?, status?, tags?, metadata? }` | | `PATCH` | `/api/nodes/:id` | Update node. Body: `{ title?, content?, status?, tags?, metadata?, isStale? }` | | `DELETE` | `/api/nodes/:id` | Delete node. Query param: `hard=true` for permanent delete | | `POST` | `/api/edges` | Create edge. Body: `{ fromId, toId, type, metadata? }` | | `DELETE` | `/api/edges/:id` | Delete edge | | `GET` | `/api/graph` | Get full graph (nodes + edges) for visualization | | `POST` | `/api/search` | Search. Body: `{ text, options?: { kind?, tags?, limit?, includeStale? } }` | --- ## MCP Server (Claude Code Integration) Cortex includes an MCP (Model Context Protocol) server that exposes memory tools directly to Claude Code. ### Setup (Development) 1. Build the project: `npm run build` 2. Ensure `.mcp.json` exists in the project root: ```json { "mcpServers": { "memory": { "command": "node", "args": ["./dist/mcp/index.js"] } } } ``` 3. Restart Claude Code — the memory tools will appear automatically. ### Setup (Standalone Executable) 1. Build the MCP server: `npm run package:win` (or `package:linux`/`package:mac`) 2. Configure `.mcp.json` to use the standalone executable: ```json { "mcpServers": { "memory": { "command": "./build/cortex-mcp.exe" } } } ``` Or with an absolute path for use from any directory: ```json { "mcpServers": { "memory": { "command": "C:/path/to/cortex-mcp.exe" } } } ``` 3. Restart Claude Code — the memory tools will appear automatically. ### MCP Tools | Tool | Description | Parameters | |---|---|---| | `memory_query` | Hybrid search (BM25 + vector + freshness) | `text`, `kind?`, `limit?` | | `memory_show` | Show node by ID or prefix with connections | `id` | | `memory_list` | List nodes with filters | `kind?`, `status?`, `tags?`, `limit?` | | `memory_children` | List children of a node | `id`, `kind?` | | `memory_add` | Add a new node | `kind`, `title`, `content?`, `tags?`, `status?`, `sections?` | | `memory_link` | Create an edge between nodes | `fromId`, `toId`, `type` | | `memory_split` | Break a large node into smaller children | `id`, `pieces`, `summary?` | | `memory_merge` | Merge multiple nodes into one | `nodeIds`, `title`, `content`, `kind?` | | `memory_dedupe` | Find similar/duplicate nodes | `threshold?`, `kind?`, `limit?` | | `memory_prune` | Clean up stale nodes or orphans | `mode`, `maxAgeDays?` | | `memory_reorganize` | Move a node under a new parent | `nodeId`, `newParentId` | | `memory_bulk_tag` | Add/remove tags on multiple nodes | `action`, `tags`, `nodeIds?`, `filter?` | | `memory_stats` | Get graph statistics | — | | `memory_summary` | Get hierarchical summary of the graph | `refresh?` | | `memory_prompt` | Execute natural language instruction | `prompt` | ### Manual Testing ```bash # Development echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"0.1"}}}' | node dist/mcp/index.js # Standalone echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"0.1"}}}' | ./build/cortex-mcp.exe ```