Vaultkit
Obsidian wiki management β create, connect, and destroy vaults with GitHub Pages and Claude Code MCP.
Ask AI about Vaultkit
Powered by Claude Β· Grounded in docs
I know everything about Vaultkit. Ask me about installation, configuration, usage, or troubleshooting.
0/500
Reviews
Documentation
vaultkit
Make an Obsidian wiki searchable by Claude Code β yours, your team's, or someone else's.
Obsidian is a free Markdown note-taking app where a "vault" is just a folder of .md files on your disk. vaultkit takes that vault, backs it with a GitHub repo, and registers it as a Claude Code MCP server β so every Claude Code session in every project can full-text search and read your notes, with no per-project setup. Connect as many vaults as you want; each lives under its own MCP namespace and stays in sync with upstream automatically.
npm install -g @aleburrascano/vaultkit
vaultkit setup # REQUIRED: bootstraps prerequisites β see below
vaultkit help
[!IMPORTANT] You must run
vaultkit setuponce after installing. Every other command (init,connect,pull,visibility, β¦) refuses to run withError: vaultkit isn't set up yetuntil setup verifies the prerequisites. The two exceptions arevaultkit setupitself (obviously) andvaultkit doctor(so you can diagnose without being blocked).
vaultkit setup walks through every prerequisite in one go (node 22+, gh CLI, gh auth with repo + workflow scopes, git config, claude CLI). It's idempotent β re-run any time. The delete_repo scope is requested separately on the first vaultkit destroy so you're never asked up front to authorize a destructive permission you may never use.
Each vault registers as one MCP server backed by vaultkit's own mcp-server daemon (see ADR-0011) β six tools tuned for Claude (vk_search, vk_list_notes, vk_get_note, vk_get_tags, vk_search_by_tag, vk_recent_notes). vk_search uses SQLite FTS5 + BM25 with title hits weighted 5x, so a query like "token optimization" against a note titled "Token Efficiency" finds it even when the body never says "optimization". Pass vault: "*" to any tool for cross-vault scope. The search engine is Node 22.13+'s built-in node:sqlite β zero npm dependency for the search story.
Updating: npm update -g @aleburrascano/vaultkit to pull a new release; re-run vaultkit setup after major versions to re-check prerequisites and vaultkit doctor to flag any vault whose pinned launcher hash has drifted.
What you'd use this for
- Personal knowledge base. A vault of research notes, papers, books you've read, recurring ideas. Open Claude Code on any project and your notes are queryable mid-conversation β no copy-paste, no "let me find that link."
- Team wiki. A shared decision log, runbook collection, or product knowledge base lives in one GitHub repo. Every teammate's Claude Code can answer from it without anyone manually pasting context, and PRs gate every change.
- Public reference. Publish a curated wiki for a domain you know well; others run
vaultkit connect owner/repoand their Claude Code now has access too β like a knowledge graph anyone can subscribe to. Optional public Quartz site so non-Claude users can read it in a browser. - Reading notebook. Drop source PDFs/articles into
raw/, write synthesis pages inwiki/, ask Claude to surface contradictions between sources or pull every quote on a topic.
Quick Start
A 60-second path from install to "Claude knows my notes":
-
Install + onboard (one-time):
npm install -g @aleburrascano/vaultkit vaultkit setup -
Create a vault (interactive β choose
nfor private notes-only):vaultkit init my-wiki -
Drop in a note:
echo "# Mitochondria" > ~/vaults/my-wiki/wiki/concepts/mitochondria.md echo "Powerhouse of the cell." >> ~/vaults/my-wiki/wiki/concepts/mitochondria.md -
Open Claude Code in any project and ask: "What do I know about mitochondria?" β Claude calls
mcp__my-wiki__vk_search, finds your note via BM25, answers.
That's it. Push to GitHub when you want teammates' Claude Code sessions to see the same content (cd ~/vaults/my-wiki && git add -A && git commit -m "first note" && git push).
Commands
FIRST-TIME SETUP
vaultkit setup Verify + install every prerequisite (run once after install)
CREATE & CONNECT
vaultkit init <name> Create a new vault from scratch
vaultkit connect <owner/repo> Clone someone else's vault and register it
EVERYDAY USE
vaultkit list [name] List vaults + git state (or detail for one)
vaultkit sync Sync all vaults from their upstream
vaultkit refresh [name] Check sources for upstream changes and write a freshness report
Need a snapshot? Every vault is a git repo, so:
git clone --mirror <repo-url> <dest> # full history snapshot
git log -- <path/to/file.md> # historical content for one file
WHEN SOMETHING'S WRONG
vaultkit doctor [name] Diagnose vault + environment health
vaultkit doctor [name] --fix Same as above, but also offer to repair
vaultkit doctor --fix --all Repair every registered vault (e.g. after a vaultkit upgrade)
CHANGE OR REMOVE
vaultkit visibility <name> <mode> Toggle public / private / auth-gated
vaultkit remove <name> Stop using locally + remove from MCP (keeps GitHub repo)
vaultkit remove <name> --delete-repo Also delete the GitHub repo (you must own it)
vaultkit help Show this reference
Every command supports --help / -h for detailed usage. Pass --verbose (or -v) before the args to get trace output. Pass --version to print the installed version + runtime info.
The ecosystem in three steps: someone publishes a vault (vaultkit init), you connect to it (vaultkit connect owner/repo), then every Claude Code session in any project can query its contents β always against the latest merged content upstream.
Anatomy of a vault
Each vault is an Obsidian wiki backed by a GitHub repo. On disk it looks like this:
my-wiki/
βββ raw/ β source material β immutable, never edit
β βββ articles/
β βββ books/
β βββ notes/
β βββ papers/
β βββ transcripts/
β βββ assets/
βββ wiki/ β your authored pages
β βββ concepts/
β βββ topics/
β βββ people/
β βββ sources/
βββ index.md β one-line entry per page
βββ log.md β append-only operation log
βββ CLAUDE.md β instructions for your AI assistant
βββ .mcp-start.js β MCP server launcher (SHA-pinned, see Security)
βββ .quartz/ β Quartz static site generator (only when publishing)
The subfolders are conventions, not requirements β vaultkit creates them but won't complain if you ignore some, delete what you don't use, or add new ones:
raw/holds material you didn't author: PDFs inpapers/, saved articles inarticles/, scanned books inbooks/, audio transcripts intranscripts/, images and screenshots inassets/. CI's duplicate-check workflow blocks PRs that add a file whose name already exists anywhere underraw/.wiki/holds pages you wrote: synthesis notes inconcepts/, broader subject pages intopics/, biographies inpeople/, per-source pages (one wiki page perraw/source) insources/.
If you don't write biographies, leave wiki/people/ empty or delete it. The structure is for you, not the tool.
And each vault ships with these capabilities:
| Site (optional) | https://your-username.github.io/<name> β public, auth-gated, or none |
| PR gating | main is branch-protected β all changes go through pull requests |
| Duplicate check | CI blocks PRs that add a source file whose name already exists in raw/ |
| MCP server | The vault is registered as a Claude Code MCP server so you can query it from any project |
Vaults live in ~/vaults/ by default (override with VAULTKIT_HOME β see Configuration).
Prerequisites
You'll need:
- A GitHub account. Every vault is backed by a GitHub repo β there's no GitLab, self-hosted-git, or local-only mode. If you don't want a GitHub repo, vaultkit isn't for you.
- Node.js 22+ β nodejs.org
- Git (+ Git Bash on Windows) β git-scm.com
Everything else β GitHub CLI, GitHub authentication, git user config, Claude Code β is handled interactively the first time you run vaultkit init.
Usage
Create a vault
vaultkit init my-wiki
init asks how you want to publish:
Publish this vault as a public knowledge site?
(y) Public repo + public Quartz site at https://<user>.github.io/my-wiki
(n) Private repo, notes-only β no Pages, no deploy workflow, no public URL [default]
(a) Private repo + auth-gated Pages site (requires GitHub Pro+)
ypublishes a public Quartz site on GitHub Pages. (Quartz is an Obsidian-aware static-site generator that renders yourwiki/andraw/markdown into a browsable web wiki.)n(default) creates a private repo with no Pages workflow at all β fully hidden, even by URL.acreates a private repo with auth-gated Pages so only authorized GitHub users can view the site. Requires GitHub Pro or higher.
Why not
--private? A private GitHub repo with Pages enabled defaults to a publicly-accessible site on Pro plans β repo visibility and Pages visibility are decoupled. Option(n)skips Pages entirely so there's no site to discover; option(a)explicitly locks Pages visibility down via the GitHub API.
On first run, vaultkit init will:
- Install GitHub CLI if missing (via winget / brew / apt / dnf)
- Open a browser for GitHub authentication if not logged in
- Prompt for your git name and email if not configured
- Ask whether to install Claude Code CLI (required for MCP registration)
After that, every subsequent vaultkit init runs through the same prompts but skips the install steps.
Connect to someone else's vault
vaultkit connect owner/repo
vaultkit connect https://github.com/owner/repo
vaultkit connect git@github.com:owner/repo
Clones the vault and registers it as an MCP server. The MCP server auto-pulls vault content (raw/, wiki/) on every Claude Code session start, so you always query the latest merged content without any manual git pull. The launcher script itself (.mcp-start.js) is never auto-pulled β see Security & Trust.
Remove a vault
vaultkit disconnect my-wiki # removes local + MCP, keeps the GitHub repo
vaultkit destroy my-wiki # deletes local + GitHub repo (if you own it) + MCP
destroy checks ownership via gh api repos/.../permissions.admin first. If you're a collaborator and don't have admin rights, only the local clone and MCP registration are removed (effectively a disconnect).
Using with Claude Code
Open any project in Claude Code and your wiki is already there β full-text searchable, always synced to upstream, no per-project setup. The wiki shows up as a set of MCP tools:
search_notes full-text search across all wiki pages
get_note read a specific page
get_backlinks find pages that link to a given page
get_tags browse by tag
Multiple wikis are available simultaneously under their own MCP namespaces:
mcp__my-wiki__search_notes, mcp__cooking-wiki__get_note, etc. Ask Claude "what do I know about quartz?" in any project and it'll search your obsidian vault, your cooking-wiki, and any other vaults you've connected β all at once.
Contributing to a wiki
- Fork the repo on GitHub
- Add a source file to
raw/and create wiki pages inwiki/ - Open a pull request β CI automatically checks for duplicate source filenames
- The maintainer reviews and merges
Security & Trust
vaultkit connect clones a vault and registers its .mcp-start.js as a Claude Code MCP server. That script runs automatically with your full user permissions on every Claude Code session start β equivalent to adding the vault author to your system PATH.
The launcher itself is small (~70 lines β see lib/mcp-start.js.tmpl for the canonical bytes). On startup it does a SHA-256 self-check, runs a guarded git fetch, and then spawns vaultkit mcp-server --vault-dir <path> β vaultkit's own MCP daemon (src/commands/mcp-server.ts) which exposes the vk_search / vk_get_note / vk_list_notes / vk_get_tags / vk_search_by_tag / vk_recent_notes tools to Claude Code (see ADR-0011 for the engine and tool decisions). Trust thus extends to: vaultkit itself, the per-vault launcher (SHA-pinned), and the vault's git history.
The trust chain on every Claude Code session start, end-to-end:
~/.claude.json ββ pins H = SHA-256 of <vault>/.mcp-start.js
β (set at registration time -- TOFU prompt; layer 1)
β spawn
βΌ
<vault>/.mcp-start.js (~70 lines, byte-pinned via H; layer 2)
β 1. recompute SHA-256 of self -- abort if != H
β 2. `git fetch` -- abort if upstream changed .mcp-start.js
β 3. `git merge --ff-only` to pull raw/, wiki/ from upstream
β 4. spawn the actual MCP server via `npx`
βΌ
obsidian-mcp-pro
β exposes (per-vault namespaced):
β mcp__my-wiki__search_notes
β mcp__my-wiki__get_note
β mcp__my-wiki__get_backlinks
β mcp__my-wiki__get_tags
βΌ
Claude Code -- uses those tools to answer queries about your notes
Two-layer protection
Layer 1 β TOFU at registration. Before registering, vaultkit shows the SHA-256 of .mcp-start.js and asks for explicit confirmation:
File: /home/you/vaults/my-vault/.mcp-start.js
SHA-256: a3f2c1...
Register as MCP server? [y/N]
The hash you confirm is pinned in the MCP registration via --expected-sha256=....
Layer 2 β self-verification on every session start. Each time Claude Code launches the vault's MCP server, the launcher:
- Recomputes its own SHA-256 and aborts if it doesn't match the pinned value (catches in-place tampering).
- Runs
git fetchand aborts if upstream introduced a different.mcp-start.js(catches malicious upstream commits). - Only fast-forwards when the launcher itself is unchanged. Vault content (
raw/,wiki/) updates normally.
If the launcher has changed upstream, you'll see:
[vaultkit] Vault "my-vault" has a new .mcp-start.js upstream β refusing to auto-update.
[vaultkit] Inspect: cd "/home/you/vaults/my-vault" && git diff HEAD..@{u} -- .mcp-start.js
[vaultkit] Re-trust: vaultkit verify my-vault
Run vaultkit doctor periodically β it surfaces hash drift and missing pins across all vaults.
Trust rule: only connect vaults from authors you trust, the same way you'd only npm install -g packages from trusted publishers. See SECURITY.md for the full threat model.
Configuration
| Variable | Default | Description |
|---|---|---|
VAULTKIT_HOME | ~/vaults | Root directory where vaultkit init and vaultkit connect create vaults |
VAULTKIT_LOG | (unset) | If set, every vaultkit invocation appends a tab-separated audit line: timestamp\tcommand\targs\texit=N\t<duration>ms |
VAULTKIT_PULL_TIMEOUT | 30000 | Per-vault timeout in milliseconds for vaultkit sync |
VAULTKIT_VERBOSE | (unset) | Set automatically by the --verbose flag β scripts emit trace output to stderr when it's 1 |
VAULTKIT_NO_UPDATE_CHECK | (unset) | If set to 1, suppresses the once-per-24h "newer version available" notification. Useful in CI or for scripted callers that parse stderr |
Set in your shell profile to override the default:
# ~/.bashrc or ~/.zshrc
export VAULTKIT_HOME=~/Documents/vaults
export VAULTKIT_LOG=~/.vaultkit.log
Platform support
| Platform | Status |
|---|---|
| Windows (Git Bash) | Supported |
| macOS | Supported |
| Linux (apt / dnf / brew) | Supported |
FAQ
Common questions β can I use this without GitHub, does it cost money, where does my data go, can I plug it into MCP clients other than Claude Code, what's the difference between disconnect and destroy β are answered in docs/faq.md.
Troubleshooting
If vaultkit doctor doesn't catch your problem, docs/troubleshooting.md covers the recurring ones with the exact error string each time: launcher SHA-256 mismatch, "Vault has a new .mcp-start.js upstream", gh: command not found on Windows, the first-destroy browser flow, branch-protection push rejections during update, and init failing to enable GitHub Pages.
Contributing to vaultkit
See CONTRIBUTING.md. The repo is intentionally small β TypeScript source under bin/, src/, and tests/, compiled to dist/ at publish time. Three runtime dependencies (commander, execa, @inquirer/prompts) plus typescript and vitest for development.
License
MIT Β© Alessandro Burrascano
