llm-wiki
LLM wiki kit
Created by Mehmet Goekce
Published in MehmetGoekce/llm-wiki. Publisher page
168 GitHub stars
What it is
Build Karpathy's LLM Wiki with Claude Code. L1/L2 cache architecture. Logseq + Obsidian support.
Summary from the brain’s metadata
Build Karpathy's LLM Wiki with Claude Code. L1/L2 cache architecture. Logseq + Obsidian support. Build Karpathy's LLM Wiki with Claude Code. Two-layer cache architecture (L1/L2). Supports Logseq and Obsidian.
How it works
Memory model: LLM wiki
AutoGineer overview, from the brain’s own files
Memory model: LLM wiki. Folders: .github (agent config, 5 files); docs (docs, 7 files); examples (examples, 2 files); templates (templates, 8 files).
| Folder | Role | Files |
|---|---|---|
| .github | agent-config | 5 |
| docs | docs | 7 |
| examples | examples | 2 |
| templates | templates | 8 |
| .claude-plugin | folder | 3 |
| openspec | folder | 23 |
Requirements
Works with: Claude Code
Set it up
Clone the repository at the commit AutoGineer scanned:
git clone https://github.com/MehmetGoekce/llm-wiki.git && cd llm-wiki && git checkout 5fa5ee7d49a4346eeb1d92c1de7bf649e7654e91Point Claude Code at .claude-plugin/icon.png: it does not read that file on its own.
cd llm-wiki && claude
AutoGineer scanned these files at commit 5fa5ee7.
- Not scanned by AutoGineerThe author’s README also describes installing it as a Claude Code plugin marketplace. Read its install section: AutoGineer did not scan that path. https://github.com/MehmetGoekce/llm-wiki/blob/5fa5ee7d49a4346eeb1d92c1de7bf649e7654e91/README.md#quick-start
- Not scanned by AutoGineerThe author’s README also describes installing it from a clone of its repository. Read its install section: AutoGineer did not scan that path. https://github.com/MehmetGoekce/llm-wiki/blob/5fa5ee7d49a4346eeb1d92c1de7bf649e7654e91/README.md#quick-start
Created by Mehmet Goekce. Published in MehmetGoekce/llm-wiki. Licence: MIT License.
Usage
From the brain’s own files
- ${user_config.wiki_path} (the "Wiki root:" line): your Logseq graph or Obsidian vault
- ${CLAUDE_PLUGIN_ROOT} (the setup workflow): the clone, so that setup finds templates/
Documentation by Mehmet Goekce
llm-wiki
Image: License: MIT Image: Release Image: Stars Image: Top Language Image: Last Commit
Build Karpathy's LLM Wiki with Claude Code. Two-layer cache architecture (L1/L2). Supports Logseq and Obsidian.
graph TB
subgraph "Every Session — Auto-loaded"
L1[L1: Claude Memory]
L1R[Rules & Gotchas]
L1I[Identity & Preferences]
L1C[Credentials]
L1 --> L1R
L1 --> L1I
L1 --> L1C
end
subgraph "On Demand — /llm-wiki query"
L2[L2: Wiki]
L2P[Projects & History]
L2W[Workflows & Processes]
L2K[Research & Learning]
L2 --> L2P
L2 --> L2W
L2 --> L2K
end
NEW[New Knowledge] --> ROUTE{Quick rule?}
ROUTE -->|Yes| L1
ROUTE -->|No| L2
USER[User Query] --> CLAUDE[Claude Code]
CLAUDE --> L1
CLAUDE -->|Deep question| L2What is this?
Image: Wiki graph view after setup Your wiki after a few ingests — interconnected knowledge pages in Logseq's graph view.
In April 2026, Andrej Karpathy published a gist called "LLM Wiki" that got 5,000+ stars in days. The idea: let an LLM maintain a structured, cross-referenced wiki for you. Feed it raw sources, it extracts facts, links them together, and keeps everything consistent. The wiki becomes a persistent, compounding artifact instead of a graveyard of stale notes.
Everyone loved the concept. Almost nobody built one. The gist describes what to build, not how to wire it up with real tools, real files, and real workflows. llm-wiki is the implementation. It uses Claude Code as the LLM brain and either Logseq or Obsidian as the wiki UI, with a two-layer cache architecture that turned out to be the key insight Karpathy's gist does not mention.
Why use this?
5-minute setup. Install the plugin, run
/llm-wiki setup, and you have a schema, namespaces, and git tracking. No manual design needed.Claude becomes your wiki maintainer.
/llm-wiki ingestupdates 5-15 pages with cross-references from a single source.L1/L2 architecture. Auto-loaded rules in memory (L1) + deep knowledge in the wiki (L2). No other tool has this.
Built-in quality checks.
/llm-wiki lintfinds orphan pages, stale content, broken refs, and credential leaks.Logseq + Obsidian. Use whichever you already have. No tool switch required.
Quick Start
As a Claude Code plugin (recommended)
claude plugin marketplace add MehmetGoekce/llm-wiki
claude plugin install llm-wiki@mehmetgoekceOn Claude Code 2.1.275 or later, one line inside a session does the same:
/plugin install llm-wiki --marketplace MehmetGoekce/llm-wikiClaude Code asks for one value, the Wiki root: your Logseq graph or Obsidian vault. The directory may be empty or not exist yet. Then, in any project:
/llm-wiki setup
/llm-wiki ingest "your first source"
/llm-wiki query "what do I know about X?"
/llm-wiki lint/llm-wiki setup asks which tool you use and which namespaces you want, then creates the Schema,
Dashboard, hub pages, Access-Log and llm-wiki.yml. The wiki starts sparse and gets denser with
every ingest. New releases reach you through the plugin; nothing to copy.
Tested with Claude Code 2.1.296.
Without the plugin
Clone the repository and copy the skill into the project that should use it:
git clone https://github.com/MehmetGoekce/llm-wiki.git ~/llm-wiki
mkdir -p ~/myproject/.claude/commands
cp ~/llm-wiki/SKILL.md ~/myproject/.claude/commands/wiki.mdIn the copy, replace two placeholders with absolute paths:
${user_config.wiki_path}(the "Wiki root:" line): your Logseq graph or Obsidian vault${CLAUDE_PLUGIN_ROOT}(the setup workflow): the clone, so that setup findstemplates/
On Linux (on macOS, write sed -i '' instead of sed -i):
sed -i -e 's|\${user_config.wiki_path}|/home/you/notes/wiki|g' \
-e 's|\${CLAUDE_PLUGIN_ROOT}|/home/you/llm-wiki|g' \
~/myproject/.claude/commands/wiki.mdThen run /wiki setup in that project. The copy is invoked as /wiki <command>, stays at the
version you copied, and needs the clone to stay where it is. The plugin is the recommended path.
The rest of this README writes /llm-wiki <command>. With a copied skill, type /wiki <command>.
Moving from a copied skill to the plugin
Install the plugin, enter your existing wiki directory as Wiki root, and delete the copied
.claude/commands/wiki.md from your project. The wiki itself needs no change.
Coming from v1.6.0
The plugin's commands lost their second part: /llm-wiki:wiki ingest is now /llm-wiki ingest, and
/llm-wiki:setup is now /llm-wiki setup. Update the plugin and use the new names.
The L1/L2 Architecture
This is the part not in Karpathy's gist, and it turned out to be the most important design decision.
When you start building a wiki, the instinct is to put everything in one place. That is wrong. Some knowledge must be available in every session, before you even ask a question -- things like "max 2-3 SSH calls to the VPS, never 10+" or "always use ISO 8601 dates." If the LLM has to query the wiki to learn these rules, it has already made the mistake.
Other knowledge only matters in specific contexts. The full history of a project. A detailed API workflow. Loading all of this into every session wastes the context window.
The solution maps to a concept every engineer knows: CPU cache hierarchy.
| Layer | What | Size | Loading | Contains |
|---|---|---|---|---|
| L1 | Claude Code Memory | ~10-20 files | Auto-loaded every session | Rules, gotchas, identity, credentials |
| L2 | Wiki (Logseq/Obsidian) | ~50-200 pages | On-demand via /llm-wiki query | Projects, workflows, research, deep knowledge |
graph TB
subgraph "Every Session — Auto-loaded"
L1[L1: Claude Memory]
L1R[Rules & Gotchas]
L1I[Identity & Preferences]
L1C[Credentials]
L1 --> L1R
L1 --> L1I
L1 --> L1C
end
subgraph "On Demand — /llm-wiki query"
L2[L2: Wiki]
L2P[Projects & History]
L2W[Workflows & Processes]
L2K[Research & Learning]
L2 --> L2P
L2 --> L2W
L2 --> L2K
end
NEW[New Knowledge] --> ROUTE{Quick rule<br/>or gotcha?}
ROUTE -->|Yes| L1
ROUTE -->|No| L2
USER[User Query] --> CLAUDE[Claude Code]
CLAUDE --> L1
CLAUDE -->|Deep question| L2The routing rule is simple: Would the LLM making a mistake without this knowledge be dangerous or embarrassing? Then it belongs in L1. Would the mistake be merely inconvenient? Then L2.
Credentials are a special case -- they must live in L1 because the wiki is typically git-tracked. The L1 memory directory is excluded from git, making it the only safe place for secrets.
For the full deep-dive, see docs/l1-l2-architecture.md.
Commands
| Command | Description |
|---|---|
/llm-wiki ingest <source> | Process a source (URL, file, text), update 5-15 wiki pages |
/llm-wiki query <question> | Two-stage search via hub index, synthesize answer with source attribution |
/llm-wiki prune [--months N] | LRU-Demote: evict cold pages from the live index (default 6 months) |
/llm-wiki prune --l1 | L1-Verification: classify L1 rules, check due behavior claims against local evidence, re-verify / demote / delete |
/llm-wiki lint [--fix] | Health check: orphans, stale pages, broken refs, index drift, credential leaks, due L1 claims |
/llm-wiki status | Metrics dashboard: page count, health, hot/cold profile, recent changes |
Ingest Flow
Ingest is the core operation. When you run /llm-wiki ingest "deployed v2.0 to production", here is what happens:
graph LR
SRC[Source<br/>URL / File / Text] --> A[Phase 1<br/>Analyze & Extract]
A --> B[Phase 2<br/>Scan Wiki<br/>Find affected pages]
B --> C[Phase 3<br/>Update Pages<br/>Create new / Append]
C --> D[Phase 4<br/>Quality Gate<br/>Properties? Cross-refs?<br/>No credentials?]
D --> E[Phase 5<br/>Report<br/>Pages touched / Warnings]
E --> GIT[git commit]Phase 1 -- Analyze & Extract. Claude reads the source and extracts entities, facts, relationships, and dates. It classifies each piece by domain (business, technical, content, etc.) and checks whether it belongs in L1 (quick rule) or L2 (deep knowledge).
Phase 2 -- Scan Wiki. Claude reads the schema, then scans existing pages to find which ones the new information affects. If you mention a tool that already has an entity page, it knows to update that page too.
Phase 3 -- Update Pages. New pages get all required properties from the schema. Existing pages get new facts appended; when a fact supersedes a stated state (a status, a deadline, a decision), the block is rewritten and the old wording moves into a collapsed History -- nothing is deleted, and the current state stays on top. Target: 5-15 page touches per ingest.
Phase 4 -- Quality Gate. Before committing: Do all pages have required properties? Does every page have at least one cross-reference? Are there credential patterns in the content?
Phase 5 -- Report. Summary of pages created, updated, cross-references added, and any warnings.
Query
Query is two-stage, the way a CPU resolves an address before touching memory. Stage 1 (routing): Claude reads only the hub ### Index pages of the candidate namespaces — a cheap list of routing lines ([[page]] -- description #tags) — and picks the 3 most relevant pages by description. This is the wiki's page table. Stage 2 (read): it opens only those full pages and synthesizes an answer with source attribution. A full-text grep over every page is the L3 fallback, used only when routing finds nothing. Each full-page read is logged to an append-only Access-Log together with the routing reason it was picked (the matched index description or grep term) — so the log records not just what loaded but why, and it feeds prune. If the query reveals a gap, it offers to create a new page.
Prune
Prune is the eviction layer that keeps routing precise as the wiki grows. It reads the Access-Log, finds cold pages (no read in N months, default 6), and evicts them from the live index — the routing line moves from the hub ### Index to ### Archive and the page is marked archived::. This is demotion, not deletion: the file stays in place, every incoming [[link]] stays valid, and the page is still found by the L3 grep fallback (and re-promoted automatically if queried again). Crucially, prune never renames or moves a file — the wiki tool links by page name, so a move would break every backlink. Run it on a schedule (the command does not self-schedule).
--l1 is the L1 counterpart. Access frequency cannot find stale L1 rules — every L1 file loads every session, so a stale rule never looks cold; it shows up as the agent confidently acting on an outdated assumption. So L1 files carry a claim class: asserts-current-behavior: true for claims about a system's current state (a path, flag, version, quirk) and false for decisions and preferences, which never go stale. Behavior claims carry a verified date. /llm-wiki prune --l1 classifies unclassified files (it proposes, you confirm), checks due claims against read-only local evidence, and lets you re-verify, demote the rule to L2 as history, or delete it. It does not warn mid-session when a stale rule is about to justify an action — Claude Code loads L1, so there is no hook for that; it is on the roadmap.
Lint
Lint is the automated health check. It scans every wiki page and checks 13 rules: orphan pages (no incoming links), stale content (last updated 90+ days ago but still marked high-confidence), missing required properties, broken references, hub completeness, index drift (an active page with no routing line, or a routing line with no page), archived-in-live-index (a demoted page still routed), empty pages, weak cross-referencing, credential patterns, L1/L2 duplicates, due L1 claims (behavior claims whose verified date is missing or older than l1_verify_days), and block bloat (a block grown past 600 characters of prose, or an updated:: value used as a change log). Run with --fix and Claude auto-repairs what it can — including backfilling missing routing lines into hub indexes.
The Schema
The schema is the contract between you and the LLM. Without it, the LLM creates inconsistent pages -- one uses status: active, another state:: running, a third has no status field at all. With a schema, every page follows the same structure and automated quality checks become possible.
The schema defines:
8 namespaces (Business, Tech, Content, Projects, People, Learning, Reference, Careers)
5 page types (Entity, Project, Knowledge, Feedback, Hub) with required properties
Lint rules for automated health checks
L1/L2 boundary so the system knows where new knowledge should be routed
For the complete schema reference, see docs/schema-reference.md.
Logseq vs. Obsidian
Both wiki apps are supported. Choose based on your preference:
| Logseq | Obsidian | |
|---|---|---|
| Properties | property:: value (inline) | YAML frontmatter |
| Format | Outliner (- prefix on every line) | Flat markdown |
| File names | Wiki___Tech___Strapi.md | Wiki/Tech/Strapi.md |
| Links | [[Wiki/Tech/Strapi]] | [[Wiki/Tech/Strapi]] |
| Backlinks | Automatic (graph-native) | Via plugin or core feature |
| Block addressing | Every line is a block | Paragraph-level |
| License | AGPL-3.0 (open source) | Proprietary (free for personal use) |
Logseq shines when the LLM is doing the writing -- its outliner format means every block is independently addressable, so appending new content never disrupts existing structure.
Obsidian is better if you do a lot of manual editing -- flat markdown is more natural to write by hand, and the plugin ecosystem is massive.
For a detailed comparison with migration paths, see docs/logseq-vs-obsidian.md.
Before & After
The difference between a dead wiki and a living one is page quality.
Before -- a placeholder created when the page was first made:
- type:: knowledge
- domain:: content
- ## Newsletter
- To be filled via /llm-wiki ingest.After -- synthesized from multiple sources over several ingest operations:
- type:: knowledge
- domain:: content
- confidence:: high
- created:: 2026-03-15
- updated:: 2026-04-07
- ## Company Newsletter
- Monthly newsletter targeting existing clients and prospects.
- ### Metrics
- | Metric | Value | As of |
|--------|-------|-------|
| Subscribers | ~240 | 2026-04-01 |
| Open rate | 38% | 2026-04-01 |
| Cadence | monthly | -- |
- ### Content Strategy
- 1 technical deep-dive + 1 business insight per issue
- Always include a CTA to the latest blog post
- Subject lines: question format performs 2x better
- ### Open Questions
- Segment list by industry vertical?
- A/B test send time (Tuesday AM vs Thursday AM)?
- ### Cross-References
- [[Wiki/Content/Blog]] -- Source content
- [[Wiki/Content/LinkedIn]] -- Promotion channel
- [[Wiki/Reference/Workflows]] -- Publishing workflowEvery number has a date. Decisions have rationale. Open questions are explicit. Cross-references connect to related pages.
Configuration
Setup creates llm-wiki.yml in your wiki root. You can also create it manually:
# llm-wiki.yml
tool: logseq # or "obsidian"
wiki_path: ~/Documents/MyWiki/
pages_dir: pages # relative to wiki_path
memory_path: ~/.claude/projects/my-project/memory/
l1_verify_days: 90 # optional: re-verify L1 behavior claims after N days
namespaces:
- Business
- Tech
- Content
- Projects
- People
- Learning
- Reference
- Careers
# Lint settings
lint:
stale_threshold_days: 90
min_cross_refs: 1
credential_patterns:
- "token::"
- "password::"
- "secret::"
- "api.key::"
# Ingest settings
ingest:
target_page_touches: [5, 15] # min, max pages per ingest
append_only: true # never delete content; superseded state moves to a collapsed History
# Language (for multilingual wikis)
language:
business: en # Language for business content
tech: en # Language for technical contentTrade-offs
No system is perfect. Some things to know:
The schema feels overengineered at first. With 10 pages, defining 5 page types and 8 lint rules seems like overkill. Past 50 pages, you will be grateful for the consistency. Define the schema early -- it is much harder to retrofit one later.
Two systems means you need a clear boundary. Having both L1 and L2 means you could accidentally put the same information in both places. The lint rule for L1/L2 duplicates exists precisely for this reason.
Parallel agents can conflict. If you have multiple Claude sessions writing to wiki files simultaneously, concurrent edits can cause conflicts. Treat wiki files as a shared resource.
Start with fewer hub pages. Let them emerge organically from ingest operations rather than creating empty hubs upfront.
Documentation
FAQ — Common questions before you install
Troubleshooting — Setup, integration, and runtime issues
L1/L2 Architecture — Why two layers, how to route knowledge
Schema Reference — Page types, properties, lint rules
Logseq vs. Obsidian — Detailed comparison and migration notes
Privacy
llm-wiki has no backend and collects nothing. It is a skill and a few shell scripts that run inside your own Claude Code session.
Wiki pages, the access log and
llm-wiki.ymlare written to your local Logseq graph or Obsidian vault and stay there. Whatever you ingest ends up in those files, including names or contact details if the source contains them.If you set
memory_path, the skill also reads your local Claude Code memory directory:querymay consult it,lintreports rules that are due for a check, andprune --l1classifies, updates, moves or deletes memory files, each one only after you confirm it.lintnever prints the content of a memory file. Withoutmemory_paththe skill does not touch that directory.The skill and the scripts send nothing to the author or to any third party. There is no telemetry.
The only network access is the page fetch that
ingestmakes when you pass a URL as the source.Commits are local. Nothing is pushed unless you push your wiki yourself.
Claude reads the content you work with in order to do the work. That processing is covered by your own Claude plan and Anthropic's terms, not by this plugin.
Credits
Inspired by Andrej Karpathy's LLM Wiki gist
Built with Claude Code
License
MIT -- see LICENSE for details.
docs/schema-reference.md
Schema Reference
The schema is the single most important file in the system. It is the contract between you and the LLM that governs how every wiki page gets created and maintained.
Without a schema, the LLM creates inconsistent pages. One page might use status: active, another state:: running, a third has no status field at all. With a schema, every page follows the same contract, and automated quality checks become possible. It is the difference between a wiki and a pile of notes.
Schema Location
| Wiki App | File |
|---|---|
| Logseq | Wiki___Schema.md (in your pages directory) |
| Obsidian | Wiki/Schema.md (in your vault) |
The /llm-wiki skill reads this file before every operation.
Page Types
The schema defines five page types. Every wiki page must declare exactly one type via the type:: property.
1. Entity
Represents a person, client, tool, service, or technology. Anything that has identity and persistence.
Required Properties:
| Property | Values | Description |
|---|---|---|
type:: | entity | Page type identifier |
entity-type:: | person | client | tool | service | technology | What kind of entity |
created:: | YYYY-MM-DD | When the page was created |
updated:: | YYYY-MM-DD | Last modification date |
status:: | active | inactive | archived | Current state |
source:: | memory-migration | ingest | manual | How the page was created |
Example (Logseq format):
- type:: entity
- entity-type:: tool
- created:: 2026-03-15
- updated:: 2026-04-07
- status:: active
- source:: ingest
- ## Strapi
- Headless CMS used for blog and content management.
- Version: 5.39.0
- ### Deployment
- Runs on VPS port 1338
- Build locally, upload dist/ to server
- ### Cross-References
- [[Wiki/Tech/Next-js]] -- Frontend consumer
- [[Wiki/Reference/Workflows]] -- Publishing workflowExample (Obsidian format):
---
type: entity
entity-type: tool
created: 2026-03-15
updated: 2026-04-07
status: active
source: ingest
---
## Strapi
Headless CMS used for blog and content management.
Version: 5.39.0
### Deployment
- Runs on VPS port 1338
- Build locally, upload dist/ to server
### Cross-References
- [[Wiki/Tech/Next-js]] -- Frontend consumer
- [[Wiki/Reference/Workflows]] -- Publishing workflow2. Project
Tracks a project with timeline, status, and outcomes.
Required Properties:
| Property | Values | Description |
|---|---|---|
type:: | project | Page type identifier |
status:: | active | completed | on-hold | cancelled | Project state |
created:: | YYYY-MM-DD | When the page was created |
updated:: | YYYY-MM-DD | Last modification date |
started:: | YYYY-MM-DD | When the project began |
Optional Properties:
| Property | Values | Description |
|---|---|---|
completed:: | YYYY-MM-DD | When the project finished (if applicable) |
Example (Logseq format):
- type:: project
- status:: active
- created:: 2026-03-01
- updated:: 2026-04-07
- started:: 2026-02-15
- ## Blog Series
- Technical blog series on distributed systems.
- ### Parts
- Part 1: Introduction (published 2026-03-01)
- Part 2: Architecture (published 2026-03-15)
- Part 3: Implementation (drafting)
- ### Metrics
- | Part | Views | Published |
|------|-------|-----------|
| Part 1 | 1,200 | 2026-03-01 |
| Part 2 | 890 | 2026-03-15 |
- ### Cross-References
- [[Wiki/Content/Blog]] -- Publishing channel
- [[Wiki/Content/Newsletter]] -- Promotion3. Knowledge
Stores synthesized knowledge on a topic. The most common page type.
Required Properties:
| Property | Values | Description |
|---|---|---|
type:: | knowledge | Page type identifier |
domain:: | tech | business | content | ops | Knowledge domain |
created:: | YYYY-MM-DD | When the page was created |
updated:: | YYYY-MM-DD | Last modification date |
confidence:: | high | medium | low | stale | How reliable the content is |
Confidence levels explained:
| Level | Meaning | Action |
|---|---|---|
high | Verified, up-to-date, reliable | None |
medium | Probably correct, not recently verified | Verify on next ingest |
low | Uncertain, incomplete, or based on limited sources | Flag for review |
stale | Was high/medium but updated:: is 90+ days old | Re-verify or downgrade |
Example (Logseq format):
- type:: knowledge
- domain:: tech
- confidence:: high
- created:: 2026-02-01
- updated:: 2026-04-07
- ## Deployment Pipeline
- CI/CD workflow for production deployments.
- ### Pre-deploy Checklist
- 1. Ensure clean git state (no uncommitted changes)
- 2. Run test suite
- 3. Check server RAM (stop non-essential services if needed)
- ### Known Gotchas
- PM2 reload does not work for npm-started processes
- Environment variables baked in at build time, not runtime
- ### Cross-References
- [[Wiki/Tech/PM2]] -- Process manager
- [[Wiki/Tech/Nginx]] -- Reverse proxy4. Feedback
Captures lessons learned, gotchas, and operational rules. Often promoted to L1 if critical enough.
Required Properties:
| Property | Values | Description |
|---|---|---|
type:: | feedback | Page type identifier |
severity:: | critical | important | nice-to-know | How serious the lesson is |
created:: | YYYY-MM-DD | When the feedback was captured |
verified:: | YYYY-MM-DD | When the lesson was last confirmed |
applies-to:: | Page references | Which systems/pages this affects |
Severity guidelines:
| Level | Meaning | L1 Candidate? |
|---|---|---|
critical | Causes data loss, downtime, or security issues | Almost always yes |
important | Causes significant wasted time or incorrect output | Sometimes |
nice-to-know | Minor inconvenience if forgotten | Rarely |
Example (Logseq format):
- type:: feedback
- severity:: critical
- created:: 2026-03-10
- verified:: 2026-04-01
- applies-to:: [[Wiki/Tech/PM2]], [[Wiki/Tech/Deployment]]
- ## PM2 Reload Gotcha
- `pm2 reload` does NOT work for processes started with
`pm2 start npm --name X -- start`.
- Must use `pm2 delete + pm2 start` instead.
- ### Context
- Discovered during production deploy on 2026-03-10.
- Process appeared to reload but was serving stale code.
- ### Cross-References
- [[Wiki/Tech/PM2]] -- Process manager details
- [[Wiki/Tech/Deployment]] -- Full deploy workflow5. Hub
A namespace index page that lists all child pages within its namespace. Hub pages are structural -- they organize the wiki rather than holding knowledge.
Required Properties:
| Property | Values | Description |
|---|---|---|
type:: | hub | Page type identifier |
namespace:: | Namespace path | The namespace this hub indexes |
A hub carries an ### Index block: one routing line per child page, formatted
[[link]] -- description #tags. This is the wiki's "page table" — /llm-wiki query reads the index
first (cheap) and only then opens the 1-3 pages whose description matches. Cold pages demoted by
/llm-wiki prune move to the ### Archive block (see Hub-Index-Routing & LRU-Demote).
Example (Logseq format):
- type:: hub
- namespace:: Wiki/Tech
- ## Tech
- ### Index
- [[Wiki/Tech/Strapi]] -- Headless CMS, ports, deploy + migration gotchas #strapi #deploy
- [[Wiki/Tech/Next-js]] -- Frontend framework, SSR/ISR config #nextjs
- [[Wiki/Tech/PM2]] -- Process manager, cwd/reload bug #pm2 #deploy
- [[Wiki/Tech/Nginx]] -- Reverse proxy, TLS, upstream ports #nginx
- ### Archive
- [[Wiki/Tech/Legacy-Foo]] -- (demoted 2026-06-07) old Foo stack, replaced by Bar #archived
- ### Related Hubs
- [[Wiki/Projects]] -- Project-specific tech decisions
- [[Wiki/Reference]] -- Workflow documentationNamespace Conventions
Top-Level Namespaces
The default schema defines 8 top-level namespaces. Customize these to match your domain.
| Namespace | Purpose | Typical Page Types |
|---|---|---|
Wiki/Business | Clients, services, business strategy | Entity, Knowledge |
Wiki/Tech | Tools, frameworks, infrastructure | Entity, Knowledge, Feedback |
Wiki/Content | Blog, newsletter, social media | Knowledge, Project |
Wiki/Projects | Active and completed projects | Project |
Wiki/People | People you work with | Entity |
Wiki/Learning | Courses, books, research | Knowledge |
Wiki/Reference | Workflows, templates, checklists | Knowledge |
Wiki/Careers | Job applications, opportunities | Project |
Naming Rules
| Rule | Example |
|---|---|
| Title Case | Wiki/Tech/Strapi (not Wiki/tech/strapi) |
| Hyphens for multi-word | Wiki/Projects/Blog-Series (not Blog_Series) |
| Max depth: 3 levels | Wiki/Business/Clients/Acme is the deepest allowed |
| Hub at each level | Wiki/Tech is the hub for all Wiki/Tech/* pages |
File Names on Disk
| Wiki App | Convention | Example |
|---|---|---|
| Logseq | Triple-underscore separator | Wiki___Tech___Strapi.md |
| Obsidian | Directory structure | Wiki/Tech/Strapi.md |
Cross-Reference Rules
Cross-references are what make a wiki a wiki, not just a folder of notes.
Requirements
Every page must have at least 1 outgoing link. A page with zero
[[Wiki/...]]links is isolated and will be flagged by lint.Hub pages must list ALL child pages. If
Wiki/Tech/Strapiexists, it must appear in theWiki/Techhub page.Mention an entity with a page? Link to it. If you reference Strapi in a deployment page, use
[[Wiki/Tech/Strapi]], not just "Strapi".Backlinks are automatic in both Logseq and Obsidian. You only need to create links in one direction.
Link Syntax
| Type | Syntax | When to use |
|---|---|---|
| Wiki internal | [[Wiki/Tech/Strapi]] | Referencing another wiki page |
| Tag | #strapi | Lightweight categorization |
| External | [Strapi Docs](https://docs.strapi.io) | URLs outside the wiki |
Cross-Reference Section
Every non-hub page should end with a ### Cross-References section listing its most important links. This makes the page's relationships explicit and scannable.
- ### Cross-References
- [[Wiki/Tech/Strapi]] -- CMS backend
- [[Wiki/Tech/Next-js]] -- Frontend framework
- [[Wiki/Reference/Workflows]] -- Publishing processLint Rules
The /llm-wiki lint command checks these rules automatically. Run with --fix to auto-repair where possible.
1. Orphan Detection
What: Pages with 0 incoming [[links]] from other pages.
Why: An orphan page is invisible -- nobody will find it by browsing the wiki. It suggests the page is either misplaced, miscategorized, or missing from its hub.
Exception: Hub pages are exempt. They are entry points by definition.
Auto-fix: Add the orphan to its namespace's hub page.
2. Stale Detection
What: Pages where updated:: is older than 90 days AND confidence:: is still high.
Why: Knowledge decays. A page marked "high confidence" but untouched for 3 months is probably overdue for review. The confidence level should be downgraded to stale to signal that it needs verification.
Auto-fix: Downgrade confidence:: from high to stale.
3. Missing Properties
What: Pages that lack one or more required properties for their declared type::.
Why: Missing properties break consistency. A project page without status:: cannot be filtered by status. A knowledge page without confidence:: cannot be assessed for reliability.
Auto-fix: None -- requires human judgment to fill in correct values. Lint reports the missing properties.
4. Broken References
What: [[Wiki/...]] links that point to pages that do not exist.
Why: Broken links are false promises. They suggest knowledge exists when it does not. They also indicate that a page was deleted or renamed without updating references.
Auto-fix: Create stub pages for broken links with the appropriate type and a "To be filled via /llm-wiki ingest" placeholder.
5. Hub Completeness
What: Hub pages that are missing child pages from their namespace.
Why: Hubs are the navigational backbone. If a page exists in Wiki/Tech/ but is not listed in the Wiki/Tech hub, it is effectively hidden from browsing.
Auto-fix: Add missing children to the hub page.
6. Credential Leak
What: Wiki pages containing patterns that look like credentials: token::, password::, secret::, api-key::, or long base64 strings.
Why: Wiki pages are typically git-tracked. Credentials in git history are a security incident. They belong in L1 memory, which is git-excluded.
Auto-fix: None -- credentials must be manually moved to L1. Lint flags the page and pattern.
Severity: Always critical.
7. Empty Pages
What: Pages that have properties but no actual content below the properties.
Why: A page with only type:: knowledge and domain:: tech has no value. It was probably created as a stub and forgotten.
Auto-fix: None -- but lint flags them as candidates for either filling via ingest or deletion.
8. Cross-Reference Minimum
What: Pages with fewer than 1 outgoing [[Wiki/...]] link.
Why: An isolated page is a disconnected thought. The power of a wiki comes from connections. Even a stub page should link to its namespace hub.
Auto-fix: Add a link to the namespace hub page.
9. L1/L2 Duplicates
What: Information that appears in both L1 memory files and L2 wiki pages.
Why: Duplicates mean one copy will eventually go stale, leading to contradictory knowledge. The LLM might get one version from L1 and a different version from L2.
Auto-fix: None -- requires human decision on which location is authoritative. Lint reports the overlap.
10. Index Drift
What: A routing line in a hub ### Index whose page does not exist, an active page without a routing line, or a routing line without a description.
Why: Query routes through the hub index. An unroutable page is only found by the L3 grep fallback.
Auto-fix: Backfill missing routing lines; remove orphaned ones.
11. Archived-in-Live-Index
What: A page marked archived:: whose routing line is still in ### Index instead of ### Archive.
Why: An interrupted prune leaves demoted pages routable.
Auto-fix: Move the routing line to ### Archive. Never rename or move the page file.
12. L1 Verification Due
What: L1 memory files with asserts-current-behavior: true whose verified date is missing or older than l1_verify_days (default 90). Also reports the number of unclassified L1 files (no asserts-current-behavior key) as one info line. Runs only when memory_path is set; the L1 index file is skipped.
Why: Every L1 file loads every session, so access frequency cannot reveal a stale rule. Behavior claims (paths, commands, flags, versions, quirks) go stale silently; decisions and preferences (asserts-current-behavior: false) never do and are never flagged.
Auto-fix: None -- not even with --fix. L1 is not git-tracked. Lint never writes to L1 and never prints L1 file bodies. Use /llm-wiki prune --l1 to classify, check evidence, and re-verify, demote, or delete (see L1 Frontmatter).
13. Block Bloat
What: A block (Obsidian: paragraph) with more than 600 characters of prose outside a History child or ## Change log section (code blocks, tables, and the Access-Log page don't count). Also any updated:: value that is more than an ISO date.
Why: Append-only updates turn a task into a paragraph of dated addenda, and updated:: into a change log. The current state ends up in the last sentence. See State + History.
Auto-fix: Only for updated:: -- cut to the date, move the notes verbatim into a collapsed ## Change log. Oversized blocks are never auto-restructured: deciding what the current state is needs judgment.
L1/L2 Boundary Rules
The schema explicitly defines what belongs where:
L1 (Claude Code Memory) -- Auto-loaded
Operational rules and gotchas (things that prevent mistakes)
User identity and preferences (name, address, communication style)
Credentials and secrets (API tokens, passwords)
Tool-specific quirks that apply every session
L2 (Wiki) -- On-demand
Project details and timelines
Workflow documentation
Research and learning notes
Business intelligence and strategy
Historical decisions and rationale
The Routing Test
Ask: "If the LLM does not know this right now, what happens?"
| Answer | Layer |
|---|---|
| Data loss, security issue, or production incident | L1 (critical) |
| Embarrassing output (wrong name, wrong address) | L1 (important) |
| Incorrect but easily correctable answer | L2 |
| Missing context, needs to ask a follow-up | L2 |
Content Format Rules
Logseq Format
- Every line is a block, prefixed with "- "
- Indentation creates hierarchy (2-space or tab)
- Like this child block
- Properties use inline syntax: property:: value
- Headings go inside blocks: - ## Section Name
- Code blocks use fenced syntax inside blocks:
- ```bash
echo "hello"
```
- Tables work inside blocks:
- | Column 1 | Column 2 |
|----------|----------|
| Value 1 | Value 2 |Obsidian Format
---
type: knowledge
domain: tech
confidence: high
created: 2026-03-15
updated: 2026-04-07
---
## Section Name
Regular markdown paragraphs.
- Bullet points as needed
- No "- " prefix requirement on every line
### Subsection
Code blocks, tables, and all standard markdown features work as expected.
| Column 1 | Column 2 |
|----------|----------|
| Value 1 | Value 2 |Key Differences
| Feature | Logseq | Obsidian |
|---|---|---|
| Properties | property:: value (inline) | YAML frontmatter |
| Every line prefixed | Yes (- ) | No |
| Headings | Inside blocks (- ## Heading) | Standard markdown (## Heading) |
| Hierarchy | Indentation-based | Heading-based |
| Tables | Inside block context | Standard markdown |
Universal Rules (Both Formats)
Dates: ISO 8601 (
YYYY-MM-DD)Links:
[[Wiki/Namespace/Page]]syntaxExternal links:
[Text](URL)syntaxTags:
#tagfor lightweight categorizationNo credentials in wiki content (ever)
Delete nothing during ingest -- new facts are appended; a fact that supersedes a stated state rewrites the block and moves the old wording into a collapsed
History(see below)updated::holds the date only -- change notes go to the commit message or a collapsed## Change log
State + History
A block that changes over time -- a task, a decision, a host's status -- shows the current state on top and, collapsed below it, how it got there. Without this, every update appends a "Status <date>: ..." sentence and the block grows into a paragraph where the valid state sits in the last line.
- 🔴 Decommission staging VM — due [[2026-09-29]]
status:: open
ticket:: OPS-195
- **Next step:** run B1, otherwise default A (check volumes, delete)
- Cost: trial credit until 09-30, ~$1/day after
- History
collapsed:: true
- 2026-09-12 decided B1 only; host unchanged
- 2026-09-07 fact check: trial ends 09-30, VM is emptyHeadline: one line with status marker, task, due date
Properties: only queryable fields (status, due, ticket, decision, blocker)
"Next step": first child, the only bold text
History: last child, collapsed, one line per date, newest first. Obsidian uses a folded callout (> [!note]- History)On update: overwrite headline, properties and next step; the old wording becomes a history line
Hub-Index-Routing & LRU-Demote
L1 (Claude Memory) has an index — the auto-loaded MEMORY.md pointer list. L2 (the wiki) had none.
As the wiki grows, a grep-over-every-page retrieval gets imprecise and expensive. These two mechanisms
keep L2 precise while it scales — the CPU-cache analogy, carried through to the index and eviction layers.
Hub-Index-Routing (two-stage query)
Each hub page carries an ### Index block: one routing line per active child page, formatted
[[Wiki/NS/Page]] -- <one-sentence description, <=120 chars> #tag #tag.
Stage 1 —
/llm-wiki queryreads only the hub### Indexblocks of the candidate namespaces and picks the 3 (max 5) most relevant pages by description. This is the wiki's page table / TLB.Stage 2 — it then reads only those full pages. Grep-over-everything is just the L3 fallback when routing finds nothing.
/llm-wiki ingestmaintains the routing line for every page it creates or updates (required, else the page is unroutable). The description is the routing key: terse, distinctive, no filler.
LRU-Demote (/llm-wiki prune, default 6 months)
/llm-wiki queryappends every full-page hit to the Access-Log page (append-only, non-structural, no per-query commit)./llm-wiki prunecomputes the last access per page (never logged ->created::proxy). Cold = no access in N months.Demote = eviction from the index, not deletion or rename: the routing line moves from
### Indexto### Archive, and the page is markedarchived:: <date>(the canonical demote marker, valid on any type; entity pages also getstatus:: archived). The file stays in place,[[links]]stay intact, and it is still greppable as L3.Exempt: hub pages, Schema, Dashboard, the Access-Log, and
status:: activeprojects.Re-promote: if an L3 grep hits an archived page again, its routing line returns to
### Indexand the archived properties are removed.Critical: the wiki tool links by page name, so a file rename/move would break every incoming
[[link]]. Never move a demoted page — only evict it from the index.
L1 Frontmatter
LRU-Demote cannot see L1: every L1 file is loaded every session. L1 files therefore carry a claim
class instead. Both keys are optional and live either at the top level of the frontmatter or inside an
existing metadata: block.
| Key | Values | Meaning |
|---|---|---|
asserts-current-behavior | true | false | true = claim about a system's current state (path, command, flag, version, port, quirk). false = decision, preference, identity, rationale — never stale |
verified | YYYY-MM-DD | Last evidence check. Only on true rules; set only by re-verify in /llm-wiki prune --l1 |
---
name: pm2-reload-npm-start
description: PM2 reload breaks when the app was started via npm start
asserts-current-behavior: true
verified: 2026-06-15
---No
asserts-current-behaviorkey = unclassified: counted by lint, never flagged as due.Due =
trueAND (verifiedmissing OR older thanl1_verify_days, default 90).Writes never reorder or remove other frontmatter keys. The L1 index file (e.g.
MEMORY.md) carries neither key./llm-wiki prune --l1: classify (propose, confirm) -> read-only local evidence (supports / contradicts / inconclusive) -> per rule: re-verify, demote to L2 (history block withsource:: l1-demotion, then the L1 file is removed), or delete. Credential rules are never demoted.
Access-Log page
Wiki/Reference/Access-Log (access-log:: true, type:: reference) holds an append-only ## Log
block. It is exempt from the orphan, stale, and demote lint rules and is machine-appended — do not
hand-edit it. Each line carries a matched: routing reason (... -- query -- matched: "<reason>") —
the index description or grep term that selected the page — so the log records not just WHICH page
loaded but WHY (routing transparency, surfaced by /llm-wiki status). Legacy lines without matched:
remain valid; the suffix does not affect prune/status parsing.
Related lint rules
Index Drift — a routing line with no matching page (orphaned), or an active page with no routing line in its namespace hub (unroutable).
lint --fixremoves orphans and backfills missing lines.Archived-in-Live-Index — an archived page (
archived::set) still in### Indexinstead of### Archive(an unclean prune).lint --fixmoves it.
58 files · 2 not served here
- .claude-plugin/icon.png (not served here)
- .claude-plugin/marketplace.json
- .claude-plugin/plugin.json
- .github/ISSUE_TEMPLATE/bug_report.md
- .github/ISSUE_TEMPLATE/config.yml
- .github/ISSUE_TEMPLATE/feature_request.md
- .github/PULL_REQUEST_TEMPLATE.md
- .github/SECURITY.md
- .gitignore
- ATTRIBUTION.md
- CHANGELOG.md
- CONTRIBUTING.md
- LICENSE
- README.md
- SECURITY.md
- SKILL.md
- config.example.yml
- docs/diagrams.md
- docs/faq.md
- docs/graph-view.png (not served here)
- docs/l1-l2-architecture.md
- docs/logseq-vs-obsidian.md
- docs/schema-reference.md
- docs/troubleshooting.md
- examples/before-after.md
- examples/l1-memory-examples.md
- openspec/AGENTS.md
- openspec/changes/archive/2026-10-11-add-plugin-packaging/design.md
- openspec/changes/archive/2026-10-11-add-plugin-packaging/proposal.md
- openspec/changes/archive/2026-10-11-add-plugin-packaging/specs/config.md
- openspec/changes/archive/2026-10-11-add-plugin-packaging/specs/plugin.md
- openspec/changes/archive/2026-10-11-add-plugin-packaging/specs/setup.md
- openspec/changes/archive/2026-10-11-add-plugin-packaging/tasks.md
- openspec/changes/remove-shell-scripts/design.md
- openspec/changes/remove-shell-scripts/proposal.md
- openspec/changes/remove-shell-scripts/specs/config.md
- openspec/changes/remove-shell-scripts/specs/plugin.md
- openspec/changes/remove-shell-scripts/specs/setup.md
- openspec/changes/remove-shell-scripts/tasks.md
- openspec/project.md
- openspec/specs/config.md
- openspec/specs/ingest.md
- openspec/specs/l1-l2-routing.md
- openspec/specs/lint.md
- openspec/specs/plugin.md
- openspec/specs/prune.md
- openspec/specs/query.md
- openspec/specs/schema.md
- openspec/specs/setup.md
- templates/logseq/Access-Log.md
- templates/logseq/Dashboard.md
- templates/logseq/Hub.md
- templates/logseq/Schema.md
- templates/obsidian/Access-Log.md
- templates/obsidian/Dashboard.md
- templates/obsidian/Hub.md
- templates/obsidian/Schema.md
- wiki.md
Advantages
- 5-minute setup. Install the plugin, run /llm-wiki setup, and you have a schema, namespaces, and git tracking. No manual design needed. evidence: README.md
- Claude becomes your wiki maintainer. /llm-wiki ingest updates 5-15 pages with cross-references from a single source. evidence: README.md
- L1/L2 architecture. Auto-loaded rules in memory (L1) + deep knowledge in the wiki (L2). No other tool has this. evidence: README.md
- Built-in quality checks. /llm-wiki lint finds orphan pages, stale content, broken refs, and credential leaks. evidence: README.md
- Logseq + Obsidian. Use whichever you already have. No tool switch required. evidence: README.md
Limitations
- The schema feels overengineered at first. With 10 pages, defining 5 page types and 8 lint rules seems like overkill. Past 50 pages, you will be grateful for the consistency. Define the schema early -- it is much harder to retrofit one later. evidence: README.md
- Two systems means you need a clear boundary. Having both L1 and L2 means you could accidentally put the same information in both places. The lint rule for L1/L2 duplicates exists precisely for this reason. evidence: README.md
- Parallel agents can conflict. If you have multiple Claude sessions writing to wiki files simultaneously, concurrent edits can cause conflicts. Treat wiki files as a shared resource. evidence: README.md
- Start with fewer hub pages. Let them emerge organically from ingest operations rather than creating empty hubs upfront. evidence: README.md
Security
Risk level: No risk found
This brain runs
Agent instructions that run or fetch something (18)
SKILL.md:Run /llm-wiki setup to create one." If its `wiki_path` names a different directory than the wiki root above, warn once, naming both paths, and continue with the wiki root above.SKILL.md:Meant as a periodic run (default cadence N = 6 months) — wire it via your scheduler;SKILL.md:READ-ONLY and LOCAL: check existence, read files, search contents, read dependency manifests, run commands only with `--version` / `--help`.SKILL.md:Evidence basis per claim: `executed` (read-only command), `source` (read the implementing code, not run), or `file` (existence/content).SKILL.md:Skip -> file untouched, stays due for the next runSKILL.md:Timestamp the lint runSKILL.md:Last prune run (newest archived:: date) + a recommendation when the cold-page count is highSKILL.md:Comparison to last status run (if Dashboard page exists)SKILL.md:git: if the user wants git init or the root is a repository, check `git --version`.SKILL.md:Run `date +%Y-%m-%d` once.SKILL.md:Git init, only if the user agreed and the root has no `.git`: `git -C "<root>" init`.SKILL.md:Commit, only if the root is a git repository and this run created at least one file.SKILL.md:Run lint on imported pagesSKILL.md:decision:: run benchmark B1 first, then delete (2026-09-12)SKILL.md:- **Next step:** run B1, otherwise default A (check volumes, delete)SKILL.md:status: open · ticket: OPS-195 · decision: run benchmark B1 first, then delete (2026-09-12)SKILL.md:**Next step:** run B1, otherwise default A (check volumes, delete)openspec/AGENTS.md:git is optional.
Attribution and licence
- Created by
- Mehmet Goekce
- Declared authors
- Mehmet Goekce (declared in .claude-plugin/plugin.json)
- Publisher
- Mehmet Gökçe (Community)
- Source
- MehmetGoekce/llm-wiki · commit 5fa5ee7
- Licence
- MIT License (files served here)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
AutoGineer is not affiliated with or endorsed by Mehmet Goekce.
Install from source
2 of its files are not served here, so there is no ZIP. MehmetGoekce/llm-wiki at 5fa5ee7