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

Foldertype:RoleGranularity
sources/SourceURL + why-saved + short summary. Never full article text.One per URL or meeting
extracts/ExtractEvidence layer. What one source said, claim by claim, each with a verbatim quote. Never hand-curated.One per deep-extracted source
atoms/AtomConcept-level synthesis. Holds claims, links sources, connects to other atoms.One concept per file
glossary/Glossary TermPrecise term definitions. Lighter than atoms.One term per file
topics/concepts/Concept MapDomain map — aggregates atoms, provides broad entry point.One domain per file
topics/projects/ProjectBrainstorm workspace for active work.One project per file
topics/research/Research QuestionCross-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)

FieldMeaning
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)

FieldMeaning
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

FieldMeaning
cites::References a source as evidence (affirmative or neutral)
rebuts::References a source as counter-evidence

Structural (atom → atom)

FieldMeaning
extends::Builds on / specializes another concept
uses::Applies or depends on another concept
part-of::Component of a broader concept

Epistemic (atom → atom)

FieldMeaning
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

FieldMeaning
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

PluginKindWhyInstall name
DataviewCommunityThe only hard dependency. Powers every _meta/index.md catalog and every relationship query.dataview
CanvasCoreOnly 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)

PluginKindWhyInstall name
BacklinksCoreSidebar pane showing what links here. Convenience only — Dataview's file.inlinks reads Obsidian's metadata cache and works whether or not this is enabledbuilt-in
Graph viewCoreVisualize the knowledge graph; see the group colouring belowbuilt-in
PropertiesCoreFrontmatter sidebar pane. In-document property editing is built into the editor and does not depend on itbuilt-in
TagsCoreTag pane. The vault reads tags through Dataview, never through the panebuilt-in
TemplaterCommunityOnly if you hand-author notes in the Obsidian UI. Core Templates covers everything the shipped templates use — see belowtemplater-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 2500ms or 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 haveWhat to saySkill
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

TaskWhat to saySkill
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

TaskWhat to saySkill
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-connect to 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-audit on that topic
  • Monthly: run bash _meta/lint.sh; run memex-stale; run reconcile; run review on one active topic
  • Before sharing research: run reconciletrust-auditconflictscompose

Claude Code Skills Reference

SkillPhaseTrigger phrases
memex-saveCapture"quick save", "just bookmark", "save this", "I've read this", "mark as read"
memex-ingestCapture"ingest this", "add to wiki with atoms", "full ingest"
memex-meetingCapture"log this meeting", "save meeting notes", "record this discussion"
memex-connectStructure"process my inbox", "wire up my notes"
memex-deep-extractStructure"deep extract [source]", "what did [paper] actually say", "promote the claims in [extract]"
memex-topic-initStructure"create topic map", "start a new topic", "initialize [domain]"
memex-topic-emergeStructure"what topics are emerging", "discover clusters", "find natural groupings", "suggest topic maps"
memex-refactorStructure"refactor atom", "split [atom]", "merge [A] and [B]", "revise [atom]"
memex-reconcileMaintain"reconcile my vault", "check graph integrity", "fix bidirectional links"
memex-trust-auditMaintain"audit confidence", "trust audit [topic]", "are my atoms overconfident", "sign off on [atom]"
memex-conflictsMaintain"find conflicts", "what's in tension", "surface contradictions"
memex-staleMaintain"find stale notes", "decay check", "what's been sitting unread"
memex-composeCompose"compose [topic]", "write up my notes on", "export my research on"
memex-searchNavigate"what do I know about", "find sources on", "search my wiki"
memex-reviewNavigate"review this topic", "audit my concept map"
memex-log-queryNavigate"what did I ingest this week", "show unprocessed sources", "log stats"
memex-glossarySupport"scan this note for jargon", "what terms need defining", "build glossary from [atom]"
memex-candidatesSupport"show pending candidates", "what's waiting to be applied", "recover my session"
memex-initSupport"initialize my vault", "set up this vault", "specialize this template", "I just forked this"
memex-tendSupport"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:

SectionWhat it controls
Domain NameFree-text label used in exports and scaffolding
Domain TagsSubject-matter tags — replaced wholesale on a fork
Type TagsWhat kind of thing a note is (foundational, survey, …)
Stage TagsWorkflow flags for human review (needs-review, stale)
Source TypesValid medium: values; each needs a sources/<medium>/ folder
OKF TypesFolder → 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 domain
  • sources/<medium>/ folders — add or remove to match your Source Types
  • README.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

TypePatternExample
Sources (non-meeting)YYYY-MM-DD-kebab-title.md2026-04-27-attention-is-all-you-need.md
MeetingsYYYY-MM-DD-kebab-context.md2026-04-27-rag-architecture-sync.md
Atomskebab-concept-name.mdtransformer-architecture.md
Glossaryterm.mdself-attention.md
Concept mapskebab-domain.mddeep-learning.md
Projectsproj-kebab-name.mdproj-rag-pipeline.md
Research notesrq-kebab-question.mdrq-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:

  1. Save full text through the normalizer:
    <fetch> | bash _meta/normalize.sh > .archive/YYYY-MM-DD-slug.md
    
  2. Add raw:: .archive/YYYY-MM-DD-slug.md to 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

How to Install

  1. Download the ZIP or clone the repository
  2. Open the folder as a vault in Obsidian (File → Open Vault)
  3. Obsidian will prompt you to install required plugins

Stats

Stars

0

Forks

0

License

MIT

Last updated 2d ago