memex-vault
A template structure for Obsidian to coodinate local knowledge bases with LLMs
memex-vault
A personal template memex for accumulating and connecting knowledge from web articles, videos, academic papers, technical documentation, and meetings. A memex is a memory-extension machine — it ingests, indexes, and recombines knowledge. Inspired by Andrej Karpathy's LLM wiki concept.
This specific name - other than being a cool reference - was adjusted based on some now deleted comments here that rightly pointed out that a core aspect of a "wiki" is community consensus between people. So a mostly LLM derived knowledge graph of notes is decidedly not an interpersonal consensus.
Concept
This vault is a layered knowledge graph, not a flat bookmark list. Sources are never searched directly — instead, they feed upward into concept atoms, which feed upward into topic maps. Search flows top-down:
topics/concepts/ → atoms/ → extracts/ → sources/ → .archive/
(broad domain) (concept) (claim) (document) (raw text)
Every connection between notes is typed (e.g., extends::, supports::, refutes::), making the graph navigable by relationship kind — not just by link existence.
Density rises left to right and curation falls. atoms/ and above are
hand-curated: one concept per file, written by a human. extracts/ is the
evidence layer — what a source actually said, claim by claim, each claim
carrying a verbatim quote that _meta/lint.sh checks against the archived text.
It is optional and selective; a vault with no extracts works exactly as before,
its atoms simply capped at confidence: medium. Nothing is ever promoted from
extracts/ to atoms/ automatically.
Folder Structure
vault/
├── _templates/ # Templater input templates (not indexed)
│ ├── source-digital.md # All digital sources (web, video, paper, docs)
│ ├── source-meeting.md # Meeting notes (no URL; different schema)
│ ├── atom.md
│ ├── glossary.md
│ ├── extract.md
│ ├── topic-concept.md
│ ├── topic-project.md
│ └── topic-research.md
│
├── _meta/ # Infrastructure
│ ├── index.md # Live Dataview catalog of all notes
│ ├── log.md # Append-only ingest history
│ ├── schema.md # Relationship types, naming conventions (authoritative)
│ ├── domain.md # Instance vocabulary — tags, node types (edit on fork)
│ ├── lint.sh # Programmatic health checks
│ └── normalize.sh # Archive text normalizer — every .archive/ write pipes through it
│
├── sources/ # One file per URL or meeting — summary only
│ ├── web/
│ ├── video/
│ ├── paper/
│ ├── docs/
│ └── meeting/
│
├── extracts/ # Evidence layer — one file per deep-extracted source,
│ # quote-grounded claims addressed as [[ext-slug#^c07]]
├── atoms/ # One concept per file (Wikipedia stub granularity)
├── glossary/ # One term definition per file
│
├── topics/
│ ├── concepts/ # Domain-level maps linking atoms
│ ├── projects/ # Project brainstorm workspaces
│ └── research/ # Research synthesis across multiple sources
│
├── canvas/ # Optional visual maps (.canvas files)
├── _exports/ # Gitignored; composed topic export documents
└── .archive/ # Gitignored; optional full-text source backups
Node Types
| Folder | type: | Role | Granularity |
|---|---|---|---|
sources/ | Source | URL + why-saved + short summary. Never full article text. | One per URL or meeting |
extracts/ | Extract | Evidence layer. What one source said, claim by claim, each with a verbatim quote. Never hand-curated. | One per deep-extracted source |
atoms/ | Atom | Concept-level synthesis. Holds claims, links sources, connects to other atoms. | One concept per file |
glossary/ | Glossary Term | Precise term definitions. Lighter than atoms. | One term per file |
topics/concepts/ | Concept Map | Domain map — aggregates atoms, provides broad entry point. | One domain per file |
topics/projects/ | Project | Brainstorm workspace for active work. | One project per file |
topics/research/ | Research Question | Cross-source synthesis for a specific research question. | One question per file |
_exports/ | — | Composed topic export — generated by memex-compose. Gitignored. | One per compose session |
Every curated note carries type: — the one field that survives the folder
layout being flattened, and the only field the Open Knowledge
Format makes
mandatory. medium: is the subtype of a source (web, video, paper,
docs, meeting), so a paper is type: Source + medium: paper.
Workflow position is stage:, not status: — see _meta/schema.md § Stage
Values for why that distinction is load-bearing. Provenance is generated:
(who made this note) and verified: (who has since checked it). verified: is
append-only, written by memex-trust-audit on an explicit human yes and never
inferred — and signing off deliberately does not bump updated:, because
checking a note is not revising it.
Extract filenames carry an ext- prefix (extracts/ext-2026-04-27-lewis-rag.md
for sources/paper/2026-04-27-lewis-rag.md). Obsidian resolves wikilinks by
filename, so without the prefix every cites:: [[2026-04-27-lewis-rag]] already
written on an atom would go ambiguous the moment the extract appeared.
Relationship Taxonomy
Connections are Dataview inline fields written in note bodies, not frontmatter:
extends:: [[Other Atom]]
cites:: [[source-filename]]
Affirmative (source → atom)
| Field | Meaning |
|---|---|
supports:: | Source provides evidence for a claim in this atom |
introduces:: | Source is where this concept first appeared in the vault |
demonstrates:: | Source shows a concrete worked example |
Skeptical (source → atom)
| Field | Meaning |
|---|---|
challenges:: | Source questions or weakens a claim; describe the tension in the atom body |
refutes:: | Source provides direct counter-evidence; stronger than challenges:: |
Any note → source
| Field | Meaning |
|---|---|
cites:: | References a source as evidence (affirmative or neutral) |
rebuts:: | References a source as counter-evidence |
Structural (atom → atom)
| Field | Meaning |
|---|---|
extends:: | Builds on / specializes another concept |
uses:: | Applies or depends on another concept |
part-of:: | Component of a broader concept |
Epistemic (atom → atom)
| Field | Meaning |
|---|---|
contradicts:: | Direct logical conflict; document tension in both atoms |
challenges:: | Weakens or questions without direct contradiction |
supersedes:: | Replaces or obsoletes in modern understanding |
limits:: | Defines where the target breaks down or partially applies |
contrasts-with:: | Alternative approach to the same problem |
Navigational
| Field | Meaning |
|---|---|
related:: | Loosely connected; fallback only — refine monthly |
defines:: | Any note → glossary term |
Topic membership is derived, not written
A topic does not list its atoms. Each atom declares part-of:: [[Topic]], and the
topic surfaces its membership with a Dataview query:
LIST FROM "atoms"
WHERE contains(row["part-of"], this.file.link)
There is one source of truth and nothing to keep in sync. Outside Obsidian, the
same set is recovered with grep -rlE "^part-of::.*\[\[<topic>\]\]" atoms/.
Full taxonomy with decision tree for skeptical relations: _meta/schema.md
Obsidian Plugins
Exactly one plugin is load-bearing. Everything else is convenience: the vault is
readable, writable, and checkable without any of them, because _meta/lint.sh
answers in plain text what _meta/index.md answers in Dataview.
Required
| Plugin | Kind | Why | Install name |
|---|---|---|---|
| Dataview | Community | The only hard dependency. Powers every _meta/index.md catalog and every relationship query. | dataview |
| Canvas | Core | Only if you keep canvas/. Disabling it makes that folder dead. | built-in |
Dataview is not replaceable by Bases. Core Bases reads YAML frontmatter
properties; this vault's typed relations (cites::, part-of::, supports::,
contradicts:: …) are Dataview inline fields in the note body, which Bases
cannot see. The frontmatter-only catalogs in _meta/index.md would port to a
Base; the link-graph queries — orphan detection, topic membership, unpromoted
extracts — would not. Enable Bases if you want it, but not instead of Dataview.
Optional (quality-of-life)
| Plugin | Kind | Why | Install name |
|---|---|---|---|
| Backlinks | Core | Sidebar pane showing what links here. Convenience only — Dataview's file.inlinks reads Obsidian's metadata cache and works whether or not this is enabled | built-in |
| Graph view | Core | Visualize the knowledge graph; see the group colouring below | built-in |
| Properties | Core | Frontmatter sidebar pane. In-document property editing is built into the editor and does not depend on it | built-in |
| Tags | Core | Tag pane. The vault reads tags through Dataview, never through the pane | built-in |
| Templater | Community | Only if you hand-author notes in the Obsidian UI. Core Templates covers everything the shipped templates use — see below | templater-obsidian |
Deliberately not required
Folder Notes and Graph Analysis were listed as requirements through
Phase 4 and have been removed. Nothing in _meta/, _templates/, or any skill
referenced either, and the vault contains no folder notes. Graph Analysis has
additionally had no release since January 2022, and the job it does —
co-citation and link prediction — is covered here by memex-connect and
memex-candidates, which write their results to disk rather than into a pane
that disappears. Install either if you like them; neither is part of the vault
contract.
Obsidian Configuration
1. Templates
The shipped templates in _templates/ use exactly two Templater substitutions:
<% tp.date.now("YYYY-MM-DD") %> and <% tp.file.title %>. Both have core
equivalents, so either plugin will do.
With Templater (Settings → Templater):
- Template folder location:
_templates - Enable Trigger Templater on new file creation (optional but recommended)
- Set a hotkey for Create new note from template (e.g.,
Ctrl+T)
With core Templates instead (Settings → Templates): set the same template
folder, then in your local copies swap <% tp.date.now("YYYY-MM-DD") %> for
{{date:YYYY-MM-DD}} and <% tp.file.title %> for {{title}} — core Templates
does not understand <% %> and will leave it in the note verbatim. You lose
apply-on-creation: create the note first, then run Insert template.
Either way, all digital sources use source-digital.md; set medium: manually
after creation.
Neither plugin is on the skill path. memex-ingest, memex-save,
memex-meeting, memex-topic-init, and memex-deep-extract copy the template
structure and fill the placeholders themselves, so template syntax never
reaches a generated note.
2. Dataview setup
Settings → Dataview:
- Enable Inline queries — required for
extends::,cites::, etc. to be queryable - Enable Dataview JS queries (optional; needed only for advanced index queries)
- Set Refresh interval to
2500msor lower for responsive live tables
3. Exclude archive from indexing
Already configured in .obsidian/app.json. The .archive/ folder will not appear in file explorer, graph, or search results.
4. Graph view coloring (optional but recommended)
Settings → Graph view → Groups:
- Add group:
path:sources/→ color orange - Add group:
path:extracts/→ color grey - Add group:
path:atoms/→ color blue - Add group:
path:glossary/→ color green - Add group:
path:topics/→ color purple
Grey for extracts is deliberate: they are evidence, not curated knowledge, and should read as background in the graph rather than as nodes to navigate by.
Using the Skills
Skills live in skills/ and are invoked by talking to Claude Code naturally — there's no special syntax. Claude reads the skill's description to decide when to load it, then follows the workflow instructions inside.
To trigger a skill: just describe what you want. Examples that work:
- "quick save this: https://..." → capture
- "what do I know about attention mechanisms?" → search
- "reconcile my vault" → reconcile
If Claude doesn't pick up the right skill, name it explicitly: "use memex-ingest to save..."
Skill Lifecycle
The skills follow a natural progression from raw input to composed output:
CAPTURE ─────────────────────────────────────────────────
save URL → fetched title + summary draft; branches on read stage;
optional collaborative summary session
ingest URL → fully processed note + atoms
meeting meeting notes → structured source note
STRUCTURE ───────────────────────────────────────────────
connect inbox notes → enrich metadata + wire connections
deep-extract source → quote-grounded claims (mode A); claims → atoms (mode B)
topic-init create a new topic map (top-down)
topic-emerge discover emerging topic clusters from atoms (bottom-up)
refactor revise / split / merge existing atoms
MAINTAIN ────────────────────────────────────────────────
reconcile fix dangling part-of; promote stale related:: to typed relations
trust-audit audit confidence against the claim rubric; record human sign-off
conflicts surface and document unacknowledged tensions
stale read-only decay audit (unread age, stale atoms, underconfident topics)
COMPOSE ─────────────────────────────────────────────────
compose topic → structured Markdown export in _exports/
NAVIGATE ────────────────────────────────────────────────
search query the graph top-down by topic or concept
review semantic validity audit of one topic map
log-query query ingest history (recency, medium, atom)
SUPPORT ─────────────────────────────────────────────────
glossary scan a note for terms needing glossary definitions
candidates review and apply pending writes from dropped sessions
Run reconcile before trust-audit; run both before compose. The output quality of compose depends directly on graph integrity (reconcile) and trustworthy confidence signals (trust-audit).
deep-extract is the exception to "run it regularly": it is by far the most
expensive skill here, so it is user-invoked, one source at a time, never
automatic and never vault-wide. Reach for it when a source is dense enough that a
document-level summary loses what it said, or when stale / trust-audit names
a specific source as under-extracted. Ingest first, then extract — it does not
replace ingest (which summarizes) or connect (which wires whole sources).
Workflow Patterns
Saving new knowledge
| What you have | What to say | Skill |
|---|---|---|
| A URL to save (read or unread) | "save this: [url]" | save |
| A URL ready to process with atoms | "ingest this: [url]" | ingest |
| Meeting notes | "log this meeting" | meeting |
Building and maintaining the graph
| Task | What to say | Skill |
|---|---|---|
| Process inbox notes into the graph | "process my inbox" | connect |
| Start a new domain area | "create a topic map for [domain]" | topic-init |
| Discover topics from accumulated atoms | "what topics are emerging?" | topic-emerge |
| Update an atom's body | "revise atom [name]" | refactor |
| Atom covers two things | "split [atom] into [A] and [B]" | refactor |
| Merge redundant atoms | "merge [A] and [B]" | refactor |
| Read one dense source claim by claim | "deep extract [paper]" | deep-extract |
| Ground an atom's confidence in real quotes | "promote the claims in [extract]" | deep-extract |
| Fix graph drift after bulk ingest | "reconcile my vault" | reconcile |
| Review confidence levels | "trust audit [topic]" | trust-audit |
| Record that you checked an atom | "sign off on [atom]" | trust-audit |
| Find undocumented tensions | "find conflicts in my vault" | conflicts |
Searching and synthesizing
| Task | What to say | Skill |
|---|---|---|
| Find what you know about X | "what do I know about [topic]?" | search |
| Audit a topic's structure | "review my [topic] concept map" | review |
| Export a topic as a document | "compose [topic]" | compose |
| Check recent ingest activity | "what did I ingest this week?" | log-query |
| Decide what maintenance to do | "what should I run now?" | tend |
Maintenance cadence
Ask memex-tend — "what should I run now?" It runs _meta/lint.sh once,
routes the findings to the skills that can act on them, and proposes them in
dependency order. It reports before it runs anything, and never invokes
memex-deep-extract.
The cadence it encodes, if you would rather drive by hand:
- After each ingest session: run
memex-connectto close any inbox items - Weekly: open
_meta/index.md— scan orphan atoms and stale unread sources - After 5+ new sources in an area: run
trust-auditon that topic - Monthly: run
bash _meta/lint.sh; runmemex-stale; runreconcile; runreviewon one active topic - Before sharing research: run
reconcile→trust-audit→conflicts→compose
Claude Code Skills Reference
| Skill | Phase | Trigger phrases |
|---|---|---|
memex-save | Capture | "quick save", "just bookmark", "save this", "I've read this", "mark as read" |
memex-ingest | Capture | "ingest this", "add to wiki with atoms", "full ingest" |
memex-meeting | Capture | "log this meeting", "save meeting notes", "record this discussion" |
memex-connect | Structure | "process my inbox", "wire up my notes" |
memex-deep-extract | Structure | "deep extract [source]", "what did [paper] actually say", "promote the claims in [extract]" |
memex-topic-init | Structure | "create topic map", "start a new topic", "initialize [domain]" |
memex-topic-emerge | Structure | "what topics are emerging", "discover clusters", "find natural groupings", "suggest topic maps" |
memex-refactor | Structure | "refactor atom", "split [atom]", "merge [A] and [B]", "revise [atom]" |
memex-reconcile | Maintain | "reconcile my vault", "check graph integrity", "fix bidirectional links" |
memex-trust-audit | Maintain | "audit confidence", "trust audit [topic]", "are my atoms overconfident", "sign off on [atom]" |
memex-conflicts | Maintain | "find conflicts", "what's in tension", "surface contradictions" |
memex-stale | Maintain | "find stale notes", "decay check", "what's been sitting unread" |
memex-compose | Compose | "compose [topic]", "write up my notes on", "export my research on" |
memex-search | Navigate | "what do I know about", "find sources on", "search my wiki" |
memex-review | Navigate | "review this topic", "audit my concept map" |
memex-log-query | Navigate | "what did I ingest this week", "show unprocessed sources", "log stats" |
memex-glossary | Support | "scan this note for jargon", "what terms need defining", "build glossary from [atom]" |
memex-candidates | Support | "show pending candidates", "what's waiting to be applied", "recover my session" |
memex-init | Support | "initialize my vault", "set up this vault", "specialize this template", "I just forked this" |
memex-tend | Support | "what should I run now", "tend my vault", "vault health check", "weekly maintenance" |
Specializing This Template
This repo is a template. Forking it for a different subject — law, medicine, a company's internal docs — means editing one file.
Run memex-init and it edits that file for you: five questions, then it
rewrites the vocabulary, scaffolds the folders that vocabulary implies, seeds one
topic to enter at, and leaves the vault passing _meta/lint.sh. Everything below
describes what it writes, and what to change by hand if you would rather.
That file is _meta/domain.md. It holds everything instance-specific:
| Section | What it controls |
|---|---|
| Domain Name | Free-text label used in exports and scaffolding |
| Domain Tags | Subject-matter tags — replaced wholesale on a fork |
| Type Tags | What kind of thing a note is (foundational, survey, …) |
| Stage Tags | Workflow flags for human review (needs-review, stale) |
| Source Types | Valid medium: values; each needs a sources/<medium>/ folder |
| OKF Types | Folder → type: mapping; rename Atom to Note here and nowhere else |
_meta/lint.sh reads all of it from that file, so extending a vocabulary never
means editing a script.
What you keep: _meta/schema.md (relation types, stage values, naming
patterns), all 20 skills, all 8 templates, _meta/lint.sh, and
_meta/normalize.sh. These are the structure every memex-vault shares.
Paths need no editing. Every skill resolves the vault root at run time —
VAULT="${MEMEX_VAULT:-$(git rev-parse --show-toplevel)}" — so a fork works at any
path with no search-and-replace. Set MEMEX_VAULT only if the vault is not a git
repository, or if you run the skills from outside it.
What you should also change, in practice:
topics/concepts/getting-started.md— rewrite the Overview for your domainsources/<medium>/folders — add or remove to match your Source TypesREADME.md— this file
Sanity check after a fork:
bash _meta/lint.sh # must exit 0
A renamed type that lint does not know about fails immediately, so a half-done
rename cannot go quiet. The source-type vocabulary is read from _meta/domain.md
too: add hearing to § Source Types and lint applies every naming and frontmatter
check to sources/hearing/, and warns if the folder is missing — or if a folder
under sources/ was never declared, whose notes would otherwise go unchecked.
Naming Conventions
| Type | Pattern | Example |
|---|---|---|
| Sources (non-meeting) | YYYY-MM-DD-kebab-title.md | 2026-04-27-attention-is-all-you-need.md |
| Meetings | YYYY-MM-DD-kebab-context.md | 2026-04-27-rag-architecture-sync.md |
| Atoms | kebab-concept-name.md | transformer-architecture.md |
| Glossary | term.md | self-attention.md |
| Concept maps | kebab-domain.md | deep-learning.md |
| Projects | proj-kebab-name.md | proj-rag-pipeline.md |
| Research notes | rq-kebab-question.md | rq-scaling-laws-llms.md |
Source Text Archival
Full article/transcript text is not stored in the vault by default. The .archive/ folder provides an opt-in escape hatch:
- Save full text through the normalizer:
<fetch> | bash _meta/normalize.sh > .archive/YYYY-MM-DD-slug.md - Add
raw:: .archive/YYYY-MM-DD-slug.mdto the source note
The archive is gitignored and excluded from Obsidian's indexer.
Always pipe through _meta/normalize.sh. It folds ligatures, smart quotes,
dashes and exotic spaces to ASCII, rejoins words split across line breaks, and
unwraps each paragraph onto one line. memex-deep-extract grounds every claim by
running grep -F for its verbatim quote against this file, and _meta/lint.sh
section 12 FAILs on a miss — raw pdftotext output would fail that check on
almost every multi-line quote and turn the anti-fabrication guarantee into noise.
The script is deterministic and idempotent, so bringing a legacy archive up to
standard is safe:
bash _meta/normalize.sh --in-place .archive/YYYY-MM-DD-slug.md
When to use archival: High-value sources at risk of link rot; long-form
content you expect to re-read in full; papers you need offline. It is also a hard
prerequisite for memex-deep-extract — a claim with no checkable quote is not a
claim, so the skill refuses to run without an archive.
Because .archive/ is gitignored, the grounding guarantee is local-only. On a
fresh clone the archive is simply absent, and both the archive-mismatch check and
the grounding check SKIP rather than fail — unverifiable is not fabricated.
That is stated plainly rather than pretended around: grounding cannot run in CI.
Extract quotes themselves are committed, unlike the archives they come from. They are short attributed excerpts — ordinary citation, and the reason the guarantee is auditable by anyone reading the repo. Keep them that way: quote the sentence that carries the claim, not the paragraph around it.
Optional MCP Integrations
The memex-connect skill can fetch most URLs natively via WebFetch, but two source types benefit from dedicated MCP servers: YouTube transcripts and PDFs.
YouTube Transcripts
The memex-connect skill extracts video title and channel from the YouTube page, but cannot retrieve full transcripts without an API. A transcript MCP enables structured ## Key Points with timestamps.
Option: mcp-youtube — wraps the youtube-transcript Node package; no API key needed for public videos.
To install:
npm install -g @anaisbetts/mcp-youtube
Then add to .claude/settings.local.json:
"mcpServers": {
"youtube": {
"command": "mcp-youtube"
}
}
PDF Text Extraction
PDFs cannot be fetched as text via WebFetch. A PDF MCP lets the connect skill extract title, authors, abstract, and body text from local or remote PDF files.
Option: mcp-pdf or a local wrapper around pdftotext (part of poppler-utils).
A minimal approach using pdftotext (already installed on most Linux/macOS systems):
# Install poppler if needed
apt install poppler-utils # Linux
brew install poppler # macOS
Then add a shell MCP wrapper to .claude/settings.local.json:
"mcpServers": {
"pdf": {
"command": "bash",
"args": ["-c", "pdftotext \"$1\" -", "--", ""]
}
}
Note: test specific MCP server stability before committing to one — the ecosystem is still maturing. The skills degrade gracefully without these integrations (PDFs prompt for manual metadata; videos leave Key Points empty).
Further Reading
- Karpathy's original LLM wiki concept
- Extended memory hierarchy discussion
- llm-atomic-wiki (linting patterns)
- llm-wiki-compiler
- claude-obsidian (Obsidian integration)
_meta/ccm-mapping.md— how this vault's design lines up with PaperGuru's Capital Chunk Memory (CCM) architecture
How to Install
- Download the ZIP or clone the repository
- Open the folder as a vault in Obsidian (File → Open Vault)
- Obsidian will prompt you to install required plugins
Stats
Stars
0
Forks
0
License
MIT
Last updated 2d ago