A CLI tool that compiles raw source material (articles, notes, papers) into a structured, interlinked markdown knowledge base browsable in Obsidian. Think make for knowledge — raw sources in, wiki out.
- Incremental compilation — only reprocesses changed files using SHA-256 content hashing
- Automatic cross-linking — title matching, tag overlap, concept detection, and optional LLM-powered semantic linking
- Obsidian-first — generates YAML frontmatter,
[[wikilinks]], and standard markdown - Git versioned — every compile auto-commits so you can track, diff, and rollback
- Zero hosted dependencies — runs fully local with no databases or cloud services required
Requires Go 1.23+.
go install github.com/kaiohenricunha/kortex/cmd/kortex@latestOr build from source:
git clone https://github.com/kaiohenricunha/kortex.git
cd kortex
go build ./cmd/kortex# 1. Create a new vault (also initializes git)
kortex init --path my-vault
# 2. Add source material
cp your-notes/*.md my-vault/raw/
# or use the included sample vault:
cp sample-vault/* my-vault/raw/
# 3. Run the pipeline
kortex ingest --path my-vault
kortex compile --path my-vault
# 4. Open my-vault/ in Obsidian and browse wiki/The compile command automatically runs index first, applies cross-linking, and commits changes to git.
| Command | Description | Key Flags |
|---|---|---|
init |
Create vault directory structure + git repo | --path, --no-git |
doctor |
Check vault health and environment | --path |
ingest |
Scan raw/ and update source manifest |
--path, --force |
status |
Show vault source summary | --path |
index |
Build metadata indexes from manifest | --path |
compile |
Generate wiki pages with cross-linking | --path, --full, --no-link, --no-git |
query |
Search knowledge base, write response | --path, --top N |
lint |
Check wiki pages for issues | --path, --fix |
log |
Show vault git commit history | --path, --count N |
Global flags: --verbose, --debug
Kortex automatically connects wiki pages using four layered strategies:
- Title matching — if "Distributed Systems" is a page title and another page mentions it in body text, it gets wrapped in
[[Distributed Systems]]automatically - Tag-based linking — pages sharing tags appear in each other's
related_pagesfrontmatter - Concept detection — multi-word phrases (e.g., "gradient descent") shared across sources are indexed and used to link pages
- LLM-powered linking (opt-in) — when configured, sends page summaries to Claude or OpenAI for semantic relationship suggestions
Strategies 1-3 are deterministic and zero-config. Strategy 4 requires setting llm.provider in kortex.yaml:
llm:
provider: "anthropic" # "none" | "anthropic" | "openai"
model: "claude-sonnet-4-20250514"
api_key_env: "ANTHROPIC_API_KEY" # env var name, never the key itselfraw/ --> ingest --> index --> compile --> wiki/
|
├── generate pages
├── cross-link (title, tag, concept)
├── LLM link (opt-in)
├── build relationships + backlinks
├── generate global pages
└── git auto-commit
Each stage reads from disk, transforms, and writes back. No in-memory state between commands.
vault/
├── .git/ # version history (auto-managed)
├── raw/ # drop source material here (read-only by pipeline)
├── wiki/ # generated knowledge base (open in Obsidian)
│ ├── sources/ # one summary page per source
│ ├── index.md # master index
│ ├── unresolved-concepts.md
│ └── compilation-backlog.md
├── outputs/ # query results
├── kortex.yaml # project config
└── system/
├── state/
│ ├── manifest.json
│ └── compilation.json
└── indexes/
├── source-index.json
├── title-index.json
├── tag-index.json
├── concept-index.json
└── relationships.json
cmd/kortex/main.go # CLI entry point (Cobra)
internal/
├── config/ # Config structs + loader
├── commands/ # Command handlers
├── manifest/ # Ingestion manifest model
├── hasher/ # SHA-256 file hashing
├── filedetect/ # File type detection
├── extractor/ # Source metadata extraction
├── indexer/ # Index building + concept extraction
├── compilation/ # Compilation state + staleness
├── compiler/ # Wiki page generation + pipeline orchestration
├── markdown/ # Markdown utilities (frontmatter, wikilinks)
├── linker/ # Cross-linking engine (title, tag, concept)
├── llm/ # LLM provider abstraction (Anthropic, OpenAI)
├── search/ # Keyword search engine
├── linter/ # Lint checks + auto-fix
└── gitops/ # Git operations (init, commit, log)
kortex.yaml is created by init with sensible defaults. Key sections:
compile:
auto_index: true # run index before compile
excerpt_length: 200 # chars for excerpts
linking:
title_match: true # inject [[wikilinks]] for title mentions
tag_overlap: true # populate related_pages from shared tags
concept_match: true # populate related_pages from shared concepts
min_title_length: 3 # skip titles shorter than this
max_related_pages: 10 # cap per page
git:
auto_commit: true # commit after compile
author_name: "kortex"
author_email: "kortex@local"
llm:
provider: "none" # "none" | "anthropic" | "openai"go build ./cmd/kortex # build binary
go test ./... -v # run all tests (~170 tests)
go test ./internal/linker/... -v # run single package| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | Error |
| 2 | Lint warnings only (no errors) |
Kortex implements the LLM Wiki pattern described by Andrej Karpathy — a persistent, compounding knowledge artifact maintained by LLMs rather than re-derived on every query.