From an Obsidian folder to a big project
01Many people keep what they teach their coding agent in one folder of Markdown notes, often an Obsidian vault. It holds rules for commits and reviews, notes on what a project must do, prompts that worked, a daily log. This page turns such a folder into a VibeVM project one step at a time, and Obsidian keeps working throughout. At the end, the part worth sharing is a package that your other projects, your other computer and your colleagues install with one command. Plan for about an hour.
What you need
| What | Why | Where to get it |
|---|---|---|
| vibe | makes the folder a project and installs its package | Install vibe |
| a folder of Markdown notes | the thing this page puts in order | your Obsidian vault, or the sample below |
| Git and a private repository on GitHub or another host | carry the folder to your other computer and to your colleagues, in steps 5 and 6 | git-scm.com |
| a coding agent that has the vibevm skill | does each step for you, if you prefer | Give your agent the vibevm skill |
03The sample is the vault this page was tested on: eight notes and the settings folder Obsidian keeps for itself.
04my-vault/
.obsidian/
Daily/2026-09-20.md
Inbox.md
Projects/calculator/decisions.md
Projects/calculator/spec.md
Prompts/release-checklist.md
Skills/code-review.md
Skills/commit-messages.md
Skills/writing-style.md
The folder most people have
05A vault grows the way a desk drawer grows. The rules for commit messages lie beside the specification of a calculator, a release checklist and last Tuesday. A line in CLAUDE.md tells the agent to read the rules, and for one project that is enough.
06The trouble starts with the second project. The rules are useful there too, so you copy them. A week later you improve one copy, and the other stays as it was. A colleague who asks for your review checklist gets a file in a chat, and a third copy begins a life of its own. Nothing in the folder says which notes are rules for an agent and which are only notes, and no other project can depend on them.
Step 1: make the folder a project
07A VibeVM project is a folder with a manifest, vibe.toml, and a tree of its own under vibevm/. Making the vault a project adds these files and moves nothing: your notes and .obsidian/ stay exactly where they were. Give your agent this request:
Turn the Obsidian vault in ./my-vault into a VibeVM project without touching my notes or the .obsidian folder: run vibe init inside it, then vibe check, and list every file it created.
the vibevm skill installed for your agent; no network
the vault holds vibe.toml, vibe.lock, a vibevm/ folder and three instruction files for agents, and vibe check reports that every check passed
vibe check --path my-vault --quiet
09Or do it by hand:
101. Open a terminal in the vault and run vibe init. The project takes the folder's name:
11Initializing project `my-vault` in `.`
✓ created vibevm/vibespecs/boot/00-core.md
✓ created vibevm/vibespecs/boot/90-user.md
✓ created vibe.toml
✓ created vibe.lock
✓ created .vibe/.gitignore
✓ created .gitignore
✓ created vibevm/vibespecs/boot/INDEX.md
✓ created CLAUDE.md
✓ created AGENTS.md
✓ created GEMINI.md
Done. Project `my-vault`: 10 files created, 0 kept.
122. Run vibe check. It answers that every check passed.
13CLAUDE.md, AGENTS.md and GEMINI.md are the files coding agents read first. Each now ends with a short block that points the agent at the boot lane, the reading list for the start of a session.
Step 2: move the notes into vibevm/vibespecs
14vibevm/vibespecs/ is the tree of text you write yourself, and installing a package never edits it. Moving the notes there makes them the project's own text. Obsidian does not mind. A link such as [[spec]] finds a note by its name, wherever the note lies, as long as the name is unique.
15 spec: The owner's hard constraint: installing…
The owner's hard constraint: installing a dependency must never modify any node's authored spec — the C++ rule that you do not paste a header's text into your #include.
In the VibeVM project ./my-vault, move Projects/calculator/*.md to vibevm/vibespecs/modules/calculator/ and Inbox.md, Daily/ and Prompts/ to vibevm/vibespecs/notes/. Then name both folders in vibevm/vibespecs/boot/90-user.md so a session reads them. Run vibe check.
the agent session of step 1, or a new one in my-vault
the notes lie under vibevm/vibespecs/, 90-user.md names both folders, and vibe check passes
test -d my-vault/vibevm/vibespecs/notesgrep -q 'vibespecs/notes' my-vault/vibevm/vibespecs/boot/90-user.mdvibe check --path my-vault --quiet
17By hand:
181. Move the notes. These commands work on macOS, on Linux and in Git Bash on Windows:
19mkdir -p vibevm/vibespecs/modules/calculator vibevm/vibespecs/notes
mv Projects/calculator/*.md vibevm/vibespecs/modules/calculator/
mv Inbox.md Daily Prompts vibevm/vibespecs/notes/
202. Tell the agent where the notes are. Open vibevm/vibespecs/boot/90-user.md, the one file of the boot lane that is yours, and add a section at its end:
21## Where the notes live
- `vibevm/vibespecs/modules/calculator/`: what the calculator must do, and
the decisions behind it. Read these before changing anything about it.
- `vibevm/vibespecs/notes/`: the inbox, the daily notes and the release
checklist. Read a file here only when the task names it.
223. Run vibe check. It passes.
23The second step is the one people skip. A note in vibevm/vibespecs/ is the project's own text. But the boot lane names only its own files, so no session reads the note until something points at it. 90-user.md is that pointer, and no install ever rewrites it. The folder notes/ needs no declaration: vibe accepts any folder under vibevm/vibespecs/.
Step 3: make the shared part a package
24The rules under Skills/ are the part your other projects want. VibeVM shares text as a package: a folder with a manifest, a version and the files it delivers. This one stays inside the vault, in vibevm/vibepacks/, the folder of packages a project writes itself. vibe reads that folder as a registry of the project, so the vault installs its own packages with no publishing at all.
25The package's kind is flow: a way of working, such as commit rules and review conventions. The agent reads a flow at the start of every session.
In ./my-vault create the in-tree flow package org.acme/my-skills with vibe init package --kind flow, move Skills/*.md into its vibevm/vibespecs/flows/my-skills/, give each note a {#root} anchor, rewrite its boot snippet to name the three notes by spec:// address, then install it into the vault.
the agent session of step 2; no network
vibe list shows org.acme/my-skills at 0.1.0, and the boot lane names the package's snippet
vibe list --path my-vault --quiettest -f my-vault/vibevm/vibedeps/org.acme.my-skills/0.1.0/vibevm/vibespecs/flows/my-skills/commit-messages.md
27By hand:
281. Create the package. Pass the kind now, because the command names the package's files after it:
29vibe init package org.acme/my-skills --kind flow
30It creates the package's folder for version 0.1.0, vibevm/vibepacks/org.acme/my-skills/v0.1.0/, with three files in it: the manifest vibe.toml, a README.md and vibevm/vibespecs/boot/10-flow-my-skills.md.
312. Move the rules into the package:
32P=vibevm/vibepacks/org.acme/my-skills/v0.1.0
mkdir -p $P/vibevm/vibespecs/flows/my-skills
mv Skills/*.md $P/vibevm/vibespecs/flows/my-skills/
333. Give each rule file an anchor on its first heading: # Code review {#root}. Replace the Obsidian links between the three files with addresses: [[code-review]] becomes spec://org.acme/my-skills/flows/my-skills/code-review#root. An address works in every project that installs the package; a note's name works only inside the vault.
344. Replace the text of $P/vibevm/vibespecs/boot/10-flow-my-skills.md, the package's boot snippet. Every session of every project that installs the package reads it:
35<!-- vibe:static org.acme/my-skills — boot snippet -->
# my-skills
The working rules of this vault. Read all three documents before the first
change of a session, and follow them over any habit of your own.
- Commit messages —
`spec://org.acme/my-skills/flows/my-skills/commit-messages#root`:
Conventional Commits, imperative summary, one change per commit.
- Code review —
`spec://org.acme/my-skills/flows/my-skills/code-review#root`:
the description first, the tests before the implementation, every
blocking comment marked as blocking.
- Writing style —
`spec://org.acme/my-skills/flows/my-skills/writing-style#root`:
short sentences, no filler, active voice.
Each document states its rules and the reasons for them. Nothing else here.
365. In $P/vibe.toml, fill in the description with one line a stranger understands: description = "The working rules of my vault: commit messages, code review, writing style".
376. Install the package into the vault itself:
38vibe install org.acme/my-skills --assume-yes
39vibe copied the package into vibevm/vibedeps/org.acme.my-skills/0.1.0/, the tree of copies that arrive with packages, and recorded the version in the lock file. The boot lane's reading list, vibevm/vibespecs/boot/INDEX.md, now names the package's snippet between the project's own two files:
40[[entry]]
path = "vibevm/vibespecs/boot/00-core.md"
kind = "static"
[[entry]]
path = "vibevm/vibedeps/org.acme.my-skills/0.1.0/vibevm/vibespecs/boot/10-flow-my-skills.md"
kind = "static"
[[entry]]
path = "vibevm/vibespecs/boot/90-user.md"
kind = "static"
41The vault is now both the author of the package and its first user. When you change a rule later, run vibe install --assume-yes in the vault again. vibe notices that the package comes from a folder that can change, reads it again and copies the new text:
42 → re-resolving — `org.acme/my-skills` resolves from an in-workspace file:// source (a mutable working tree); re-resolving to pick up any source edit (PROP-011 §2.6)
Skills for your agent
43A package can also carry skills: instructions an agent loads when a task calls for them, rather than at every session start. An Obsidian vault often holds exactly such notes. Declare a skill in the package's manifest:
44[[skill]]
name = "vault-rules"
path = "vibevm/vibespecs/skills/vault-rules"
description = "Apply this vault's working rules to a commit, a review or a draft"
45Put the skill's SKILL.md in that folder, with its name and description in the header, the format the agents read. Install the package again, and ask vibe what the project declares:
46 → vault-rules [flow:my-skills] → agents: all — Apply this vault's working rules to a commit, a review or a draft
1 skill(s) declared.
47vibe skill install --scope project --yes then writes the skill where agents look for it in this project: .claude/skills/, .opencode/skills/ and .agents/skills/. Cursor and Claude Desktop have no loader for a project's skills, and vibe says so instead of writing anything for them.
Step 4: use the package in your other projects
48Another project on this computer can install the package straight from the vault's folder. There are two roads: a flag for one install, and an entry in the machine's own list of registries for good.
Make the packages of ~/my-vault installable in every project on this computer: add its vibevm/vibepacks folder as the first [[registry]] in ~/.vibe/registry.toml, named my-vault, then install org.acme/my-skills into the project ~/code/other-project.
the vibevm skill; the vault as step 3 left it; no network
~/.vibe/registry.toml starts with the my-vault entry, and other-project lists the package
vibe list --path ~/code/other-project --quietgrep -q 'org.acme.my-skills' ~/code/other-project/vibevm/vibespecs/boot/INDEX.md
50By hand, for one install, run this in the other project:
51vibe install --registry ~/my-vault/vibevm/vibepacks org.acme/my-skills --assume-yes
52--registry takes the folder's path and reads nothing else, so the install touches no network. In the test run it took a tenth of a second.
53By hand, for good:
541. Open ~/.vibe/registry.toml, the list of registries vibe keeps for the whole machine, and put the vault's folder first:
55[[registry]]
name = "my-vault"
url = "file:///home/me/my-vault/vibevm/vibepacks"
562. On Windows, keep the drive letter and use forward slashes: file:///C:/Users/me/my-vault/vibevm/vibepacks.
573. Leave the entries below it as they are. vibe wrote the two central registries there the first time it ran.
584. In any project on this computer, run vibe install org.acme/my-skills --assume-yes.
59Order matters, because vibe asks the registries in the order the file lists them. With the vault first, a fresh project installed the package in 1.4 seconds. With the vault last, vibe asked both central registries first, and the same install took 5.9 seconds.
60 spec: Decision: Registry settings may also live…
Decision. Registry settings may also live in a per-user file resolved through the settings chokepoint (vibe_core::settings::registry_config_path→~/.vibe/registry.toml, or$VIBE_SETTINGS/registry.toml). It carries the same[[registry]]/[[mirror]]/[[override]]sections as a projectvibe.toml— any registry, not only local ones: a remotehttps:///ssh:///git@org (withauth) is merged and searched exactly like afile:/// path repo. A common motivation is keeping machine-local registries (afile://checkout, a path repo) out of a team-sharedvibe.toml, where a hard-coded local path would differ per teammate; but a whole extra remote registry can be added machine-wide the same way. (Locality matters only to--offline, §2.2.2.1.)
61 spec: Resolution: the solver iterates registries…
Resolution: the solver iterates registries in array order; the first that has a satisfying match for a pkgref wins. Versions of the same pkgref are not unioned across registries — this prevents a lower-trust registry from influencing resolve when a higher-trust one already has a valid answer.
62When a rule changes in the vault, run vibe update org.acme/my-skills --assume-yes in the other project. It reads the package again, copies the new text and records its new fingerprint in the lock file.
Step 5: take it to your other computer
63The road to your other computer is the one your code already takes: a private Git repository. The vault goes there whole, packages included, and the other computer uses its clone exactly as step 4 used the folder.
Prepare ./my-vault for my other computer: add a .gitattributes that keeps text files with LF line endings, ignore .obsidian/workspace.json, then make it a git repository on main and commit everything, including vibevm/vibedeps and vibevm/vibepacks. Do not push.
the agent session of step 3; Git
a Git repository on main with one commit, and a .gitattributes that holds * text=auto eol=lf
grep -q 'eol=lf' my-vault/.gitattributesgit -C my-vault ls-files --error-unmatch vibevm/vibepacks/org.acme/my-skills/v0.1.0/vibe.toml
65By hand:
661. In the vault's root, create .gitattributes with one line:
67* text=auto eol=lf
682. Add .obsidian/workspace.json to .gitignore. Obsidian rewrites that file whenever you move a pane.
693. Make the vault a repository, commit everything, and push it to a private repository:
70git init -b main
git add -A
git commit -m "chore: make the vault a VibeVM project"
git remote add origin git@github.com:<you>/my-vault.git
git push -u origin main
714. On the other computer, clone the repository and add the clone's vibevm/vibepacks folder to that computer's ~/.vibe/registry.toml, as in step 4.
72The first line of this list prevents the surprise the test run met. Git for Windows converts line endings when it checks a file out, and that changes the file's bytes. vibe checks a package by the fingerprint of its bytes, so the same package got another fingerprint in the clone. One rule file was 727 bytes where it was written and 744 on the other computer. With .gitattributes in place, both computers see the same bytes and record the same fingerprint.
73Commit vibevm/vibedeps/ as well. The copies that packages brought are committed on purpose, so an agent that clones the repository can read everything without running anything. vibe init already told Git to ignore .vibe/, where vibe keeps this computer's own state.
Step 6: share it with colleagues, in one repository
74Colleagues need no repository per package. Give them access to the vault's repository; each clones it and points their own machine at their clone, as you did on your other computer. The packages stay where you write them, beside the notes that explain them.
I cloned my team's vault to ./team-vault. Add its vibevm/vibepacks folder as the first [[registry]] in my ~/.vibe/registry.toml, named team-vault, then install org.acme/my-skills into my project ./team-notes and show me its boot lane.
the vibevm skill; a clone of the vault; no network
team-notes lists the package, and its boot lane names the package's snippet
vibe list --path team-notes --quietgrep -q 'org.acme.my-skills' team-notes/vibevm/vibespecs/boot/INDEX.md
76When a rule changes, you commit and push. A colleague runs git pull in their clone, then vibe update org.acme/my-skills --assume-yes in each project that uses the package.
77This is how the VibeVM repository keeps its own packages. The redbook and its neighbours live in the repository's own vibevm/vibepacks/, thirty packages in one group alone. The projects nested inside the repository install them from there with one command, and --offline keeps vibe from asking the central registries anything:
78vibe install --offline --registry <repository>/vibevm/vibepacks <group>/<name> --assume-yes
Step 7: a registry of your own, or the central one
79A clone stops being the right tool when the people who need a package should not see the whole vault, or when you no longer know them all. Then publish the package. A registry of your own is an organisation on GitHub or another Git host, where each package gets a repository of its own and you decide who reads it. Publish a package shows how, including vibe workspace publish, which publishes every package of a repository in one run. To offer a package to everyone, ask for a place in the central registry, as Publish a package to the central registry shows.
What appeared on disk
80The vault, at the end of the test run, without Git's and vibe's own state:
81my-vault/
.gitattributes .gitignore .obsidian/
AGENTS.md CLAUDE.md GEMINI.md vibe.toml vibe.lock
vibevm/
vibespecs/
boot/00-core.md boot/90-user.md boot/INDEX.md
modules/calculator/decisions.md modules/calculator/spec.md
notes/Inbox.md notes/Daily/ notes/Prompts/
vibepacks/org.acme/my-skills/v0.1.0/
vibe.toml README.md
vibevm/vibespecs/boot/10-flow-my-skills.md
vibevm/vibespecs/flows/my-skills/ (the three rules)
vibevm/vibespecs/skills/vault-rules/SKILL.md
vibedeps/org.acme.my-skills/0.1.0/ (the installed copy)
82Three trees sit under vibevm/. vibespecs/ is the text you write for this project. vibepacks/ holds the packages you write for others, this project included. vibedeps/ holds the copies that packages brought; vibe writes it, and you never edit it.
Edge cases and rules
83--registry takes a folder's path, and a url in registry.toml takes a file:/// address. Each refuses the other's form, with an error from the operating system rather than a sentence.
84vibe registry add accepts only a Git host, so a folder goes into registry.toml by hand.
85vibe registry list shows only the project's own list. An entry in ~/.vibe/registry.toml works without appearing there.
86Create the vault project outside any other project. vibe init inside another project nests a second project in the first, with no warning.
87vibe skill install --scope user writes into the agents' folders in your home directory, for every project at once. This page uses --scope project, which writes only into the vault.