AI News HubLIVE
站内改写5 min read

Cortex – Agent-Native Knowledge OS on Markdown (Karpathy's LLM Wiki, via MCP)

PULSE8.ai Cortex is an agent-native knowledge OS built on Markdown, providing a shared vault for AI agents and humans with a typed knowledge graph, full-text search, and a MarkItDown-powered compiler, all accessible via a unified MCP interface. Inspired by Andrej Karpathy's LLM Wiki pattern, it requires no database.

SourceHacker News AIAuthor: jiekepan

Notifications You must be signed in to change notification settings

Fork 1

Star 5

BranchesTags

Open more actions menu

Folders and files

NameName

Last commit message

Last commit date

Latest commit

History

206 Commits

206 Commits

.cursor/skills

.cursor/skills

.github/workflows

.github/workflows

assets

assets

cortex

cortex

docker/qmd

docker/qmd

docs

docs

example_vault

example_vault

roadmap

roadmap

scripts

scripts

tests

tests

.env.example

.env.example

.gitignore

.gitignore

AGENTS.md

AGENTS.md

CHANGELOG.md

CHANGELOG.md

Dockerfile

Dockerfile

LICENSE.md

LICENSE.md

README.md

README.md

claude_desktop_config.example.json

claude_desktop_config.example.json

development_plan.md

development_plan.md

docker-compose.cortex-only.yml

docker-compose.cortex-only.yml

docker-compose.gpu.yml

docker-compose.gpu.yml

docker-compose.yml

docker-compose.yml

pyproject.toml

pyproject.toml

server.json

server.json

uv.lock

uv.lock

Repository files navigation

Agent-native knowledge OS built on Markdown

PULSE8.ai Cortex is an agent-native knowledge OS built on Markdown. It gives AI agents and humans a shared vault backed by a typed knowledge graph, full-text search, and a MarkItDown-powered compiler — all accessible through a unified MCP interface.

Drop files in (PDF, DOCX, PPTX, XLSX, HTML, images, and more), let agents read, write, search, link, and compile knowledge — no database required.

Inspired by Andrej Karpathy's LLM Wiki pattern — a persistent, compounding knowledge base maintained by LLMs instead of re-derived on every query. Search powered by Tobi Lütke's QMD.

Get started

Note

PULSE8.ai Cortex requires Docker. An OpenRouter API key is optional — needed only for LLM-powered cross-referencing between wiki articles. File conversion works out of the box without any API key.

Clone the repository:

git clone https://github.com/synpulse8-opensource/pulse8-ai-cortex-knowledge-vault.git cd cortex-knowledge-vault

Launch PULSE8.ai Cortex:

./scripts/start.sh

This builds and starts both PULSE8.ai Cortex (API + MCP on :8420) and QMD (search on :3100), waits for health checks, and you're ready to go.

Connect your MCP client (e.g. Claude Desktop) to http://localhost:8420/mcp/.

To stop: ./scripts/stop.sh

Cortex-only mode (macOS / native QMD)

If you want QMD to run natively (e.g. on macOS with Metal GPU acceleration), start only the Cortex container:

Terminal 1: Run QMD natively

npm install -g @tobilu/qmd VAULT_PATH=./example_vault node docker/qmd/server.mjs

Terminal 2: Start only Cortex in Docker

./scripts/start.sh --cortex-only

To stop: ./scripts/stop.sh --cortex-only

GPU-accelerated QMD (EC2 / Linux with NVIDIA GPU)

For production deployments with NVIDIA GPU acceleration:

docker compose -f docker-compose.yml -f docker-compose.gpu.yml up --build -d

See docs/ec2-gpu-setup.md for a full guide on instance selection, NVIDIA toolkit installation, and cost estimates.

Features

Knowledge Graph Typed graph engine (NetworkX) — wikilinks, tags, and custom edges, auto-maintained on every file change

Full-Text Search QMD search with hybrid (BM25 + vector + re-ranking) by default; keyword and semantic modes selectable. Results cached with a configurable TTL.

File Compiler Converts raw sources (PDF, DOCX, PPTX, XLSX, HTML, images, etc.) to Markdown via MarkItDown. LLM used only for cross-referencing.

MCP Server Streamable HTTP + stdio transport — works with Claude Desktop, Cursor, and any MCP client

Feedback & Notifications vault_feedback captures quality feedback as notes; optional Microsoft Teams webhook posts an adaptive card per submission

Daily Activity Log Every write/ingest/compile is mirrored into daily/.md as a greppable, wikilinked timeline

Bulk Ingest Ingest dozens or hundreds of files at once from a local directory with SHA-256 dedup and bounded concurrency

REST API FastAPI endpoints mirroring all MCP tools at /api/v1/, including multipart file upload and bulk ingest

Vault Watcher Real-time filesystem monitoring — graph stays in sync automatically

Zero Database Everything persists as Markdown + JSON on your filesystem

MCP tools

Tool Description

vault_read Read a note by path

vault_write Create or update a note

vault_search Search the vault (keyword / semantic / hybrid)

vault_link Create, query, or delete graph edges

vault_context Build a context window: search → graph traversal → ranked subgraph

vault_ingest Ingest raw content or binary files (supports content_base64 for binary)

vault_compile Compile unprocessed raw sources into wiki Markdown via MarkItDown

vault_feedback Submit feedback on vault quality (status: OPEN; optional related_paths of .md notes)

vault_list_feedbacks List feedback note metadata (paths, tags, status; not full body)

Architecture

┌──────────────────────────────────────────────┐ │ MCP Client (Claude Desktop, Cursor, etc.) │ └──────────┬───────────────────────────────────┘ │ MCP (HTTP or stdio) ┌──────────▼───────────────────────────────────┐ │ PULSE8.ai Cortex :8420 │ │ ┌──────────────────────────────────────┐ │ │ │ Auth (API Key or Microsoft Entra ID) │ │ │ └──────────────┬───────────────────────┘ │ │ ┌─────────┐ ┌──┴───────┐ ┌──────────────┐ │ │ │ MCP │ │ REST API │ │ Vault Watcher│ │ │ │ /mcp/ │ │ /api/v1/ │ │ (watchfiles) │ │ │ └────┬────┘ └────┬─────┘ └──────┬───────┘ │ │ └───────────┼──────────────┘ │ │ ┌──────▼──────┐ │ │ │ Graph Engine│ │ │ │ + Compiler │ │ │ └─────────────┘ │ └──────────┬───────────────────────────────────┘ │ ┌──────────▼───────────────────────────────────┐ │ QMD :3100 │ │ BM25 + vector search, auto-indexes on start │ └──────────┬───────────────────────────────────┘ │ ┌──────────▼───────────────────────────────────┐ │ Vault (bind-mounted volume) │ │ wiki/ raw/ agents/ sessions/ daily/ feedback/ │ │ .cortex/ (graph.json, index.md, log.md) │ └──────────────────────────────────────────────┘

Vault layout

The vault is a plain directory of Markdown files organised by purpose. Cortex classifies each file into a typed node (NodeType) used by the graph engine and exposed in REST and MCP responses.

Folder NodeType Purpose

wiki/ note Compiled, interlinked knowledge articles

raw/ raw_source Unprocessed sources (PDF, DOCX, TXT, …) the compiler reads from

agents/ agent_def Agent definitions

sessions/ session Per-session notes / conversation transcripts

daily/ daily Daily notes (Obsidian Daily Notes convention)

feedback/ feedback Feedback on vault quality (status, related_paths)

.cortex/ (skipped) Cortex internals — graph.json, index.md, log.md, manifests

How classification works

Order of precedence (first match wins):

*Frontmatter type:* — explicit override always wins (e.g. type: note in agents/foo.md resolves to NodeType.NOTE)

Folder prefix — files under raw/ agents/ sessions/ daily/ feedback/ inherit the folder's type with no filename suffix needed (e.g. daily/2026-06-10.md → daily)

Filename suffix (backward-compatible) — .agent.md, .session.md, .memory.md are still honored anywhere (e.g. wiki/legacy.agent.md → agent_def)

Default — NodeType.NOTE

In practice this means you can drop YYYY-MM-DD.md straight into daily/, or an unsuffixed planner.md into agents/, and the graph and API will classify them correctly without any renaming.

Daily activity log

Every vault_write, vault_ingest, and successful compile event (MCP and REST paths) is automatically mirrored into today's UTC daily note at daily/YYYY-MM-DD.md. The file is created on first event of the day and each subsequent event appends a ## [HH:MM] event | summary block plus a [[wiki-stem]] wikilink (so the watcher draws a LINKS_TO edge to the affected note). The format follows the Karpathy log.md greppable-prefix pattern — grep "^## \[" daily/2026-06-10.md gives a clean timeline of the day.

Writes targeting daily/, feedback/, or .cortex/ are deliberately not mirrored (would be self-referential noise). The hidden .cortex/log.md audit log is unaffected and continues to receive every operation.

Bulk ingest

For ingesting many files at once (dozens or hundreds of PDFs, papers, docs), use the one-click shell script instead of feeding them one at a time through MCP. It reads directly from a local directory — no wire overhead, no running server required — deduplicates via SHA-256 hashing, compiles with bounded concurrency, and rebuilds the index once at the end.

One-click script (recommended)

Ingest all files from a directory

./scripts/bulk_ingest.sh ./my-papers/

Dry-run to preview what would be ingested

./scripts/bulk_ingest.sh ./my-papers/ --dry-run

Force re-ingest (bypass dedup manifest)

./scripts/bulk_ingest.sh ./my-papers/ --force

Control LLM concurrency (default: 4)

./scripts/bulk_ingest.sh ./my-papers/ --concurrency 8

The script automatically loads your .env for the LLM key and vault path, prints a summary, then runs the full pipeline (copy, compile, reindex). No running Cortex server needed.

Python CLI (direct)

CORTEX_VAULT_PATH=./example_vault uv run cortex-bulk-ingest --source ./my-papers/

Inside Docker

Set INGEST_DIR in .env or export it, then restart

export INGEST_DIR=/path/to/your/papers docker compose up -d

Run bulk ingest inside the container

docker exec pulse8-ai-cortex uv run cortex-bulk-ingest --source /ingest

Via REST API

For programmatic use without MCP (requires running Cortex server):

curl -X POST http://localhost:8420/api/v1/bulk-ingest \ -H "Content-Type: application/json" \ -H "x-api-key: your-secret-api-key" \ -d '{"source_dir": "/ingest", "concurrency": 4}'

Deduplication

The dedup manifest is stored at .cortex/ingest-manifest.json. Files are matched by content hash, not filename — renaming a file won't cause re-ingestion, and the same content under a different name will be skipped.

Configuration

Copy the example and fill in your values:

cp .env.example .env

Variable Required Default Description

LLM_API_KEY No — OpenRouter (or compatible) API key (for cross-referencing only)

COMPILER_MODEL No anthropic/claude-sonnet-4 Model for cross-reference detection

LLM_BASE_URL No https://openrouter.ai/api/v1 LLM API base URL

VAULT_DIR No ./example_vault Path to your vault directory

INGEST_DIR No ./ingest Path to bulk-ingest source directory (mounted as /ingest in Docker)

QMD_REFRESH_INTERVAL_SECONDS No 900 Periodic re-index interval (seconds; 0 to disable)

QMD_SEARCH_MODE No hybrid Default search mode when unspecified: hybrid (BM25 + vector + re-rank), semantic, or keyword

QMD_CACHE_TTL_SECONDS No 30 TTL for the search-result cache; raise it on read-heavy vaults to skip repeat QMD calls

QMD_SEARCH_TIMEOUT_SECONDS No 120 Per-request search timeout (increase for hybrid on CPU-only hosts)

QMD_EMBED_TIMEOUT_MS No 600000 Embed timeout in ms (increase for CPU-only deployments)

QMD_URL No — External QMD URL for cortex-only mode (e.g. http://host.docker.internal:3100)

AUTH_METHOD No none Authentication method: none, apikey, or oidc (see Authentication)

API_KEY No — Static API key for x-api-key header (used when AUTH_METHOD=apikey)

OIDC_TENANT_ID No — Microsoft Entra ID tenant ID (used when AUTH_METHOD=oidc)

OIDC_CLIENT_ID No — Microsoft Entra ID app (client) ID

OIDC_CLIENT_SECRET No — Microsoft Entra ID client secret

OIDC_BASE_URL No http://localhost:8420 Public base URL of the Cortex server (used for OAuth callbacks)

TEAMS_WEBHOOK_URL No — Incoming webhook / Power Automate URL; posts an adaptive card on each new feedback note

TEAMS_APP_BASE_URL No — Optional public Cortex base URL for a "View in Cortex" link on the Teams card

OPENROUTER_API_KEY and CORTEX_LLM_API_KEY are accepted as aliases for LLM_API_KEY. Variables above are set in .env (Docker reads them via Compose) and map to the CORTEX_* settings used by the app.

Authentication

Cortex support

[truncated for AI cost control]