Add --section flag to add/update commands for structured node content, render sections and inline children in show, and add memory children command.
8.3 KiB
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.
CLI Reference
All commands are invoked as memory <command>.
memory add <kind>
Add a node to the knowledge graph.
| Argument / Option | Required | Description |
|---|---|---|
<kind> |
yes | Node kind: memory, component, task, decision |
-t, --title <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) |
memory add memory -t "Auth flow design" -c "OAuth2 PKCE flow for SPA" --tags auth,security --status active
memory add memory -t "add command" --section "Arguments: <kind> — memory, component, task, decision" --section "Options: -t title, -c content, --tags, --status"
memory add task -t "Implement login page" --status todo
memory add decision -t "Use PostgreSQL" -c "Chose Postgres over MySQL for JSON support"
memory add component -t "UserService" -c "Handles user CRUD operations" --tags backend
memory 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) |
memory query "authentication"
memory query "database decisions" --kind decision
memory query "user service" --limit 5 --format json
memory show <id>
Show a node's full details and its 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.
| Argument / Option | Required | Description |
|---|---|---|
<id> |
yes | Node ID or unique prefix |
--format <fmt> |
no | Output format: text or json (default: text) |
memory show abc123
memory show abc123 --format json
memory 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) |
memory list
memory list --kind task --status todo
memory list --tags auth,security
memory list --stale
memory list --format json
memory 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) |
memory update abc123 --status done
memory update abc123 -t "Updated title" -c "New content"
memory update abc123 --tags newtag1,newtag2
memory 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 |
memory remove abc123
memory remove abc123 --hard
memory 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 |
memory link abc123 def456 --type depends_on
memory link abc123 def456 --type contains
memory 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. |
memory graph
memory graph abc123
memory 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) |
memory children abc123
memory children abc123 --kind task
memory children abc123 --format json
memory 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) |
memory decay
memory decay --days 90
memory decay --days 0 # decay all nodes not accessed today
memory 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) |
memory serve
memory 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 memory 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 memory 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? } } |