Create your first project
01This page takes you from an empty folder to the first description of a program, written before the program exists. The program is Hello VibeVM, a small calculator for the command line. You give the folder a published set of working rules and look at what arrived. Then you describe the calculator, by hand or by asking your coding agent. Plan for about an hour, most of it the agent's; you install nothing but vibe and an agent.
What you need
| What | Why | Where to get it |
|---|---|---|
vibe |
creates the project and installs the rules | Install vibe |
| git | the rules you install ask for one commit per idea | git-scm.com, or your system's package manager |
| a coding agent | reads the rules and writes with you | Claude Code, Codex, Gemini CLI, or an agent inside your editor |
| the vibevm skill, optional | lets the agent run the first step for you | Give your agent the vibevm skill |
03Pick a short folder for the project. Windows refuses file paths longer than 260 characters, and the deepest installed file sits about 140 characters below the project folder. Keep the project's own path under 120 characters: C:\dev\hello-vibevm works, a folder eight levels down may not.
04The first install needs a network connection. After it, every package you installed stays in the machine store, and a second project reuses it.
Step 1: create the project
Create a VibeVM project named hello-vibevm in the current folder, set spec_format = "xml" in its manifest, make it a git repository on branch main, install org.vibevm.world/redbook into it from the default registry, commit the result, and show me the tree of what an agent reads at session start.
the vibevm skill installed for your agent; git; network access to github.com/vibespecs, or the packages already in the machine store
a folder hello-vibevm with vibe.toml, vibe.lock, a vibevm/ directory, and CLAUDE.md, AGENTS.md and GEMINI.md ending with a <vibevm> block; 27 packages installed and committed on main; vibe check reports no errors
grep -q 'spec_format = "xml"' hello-vibevm/vibe.tomlgrep -q "org.vibevm.world/redbook" hello-vibevm/vibe.locktest -f hello-vibevm/vibevm/vibespecs/boot/STATIC.xmlgit -C hello-vibevm rev-parse --verify maintest -z "$(git -C hello-vibevm status --porcelain)"vibe check --path hello-vibevm --quiet
06A project is a folder with a manifest in it, and everything vibe does, it does to one. Hand the request above to your agent, or take the steps yourself; both roads end in the same folder.
071. Create the project. The name becomes the folder:
vibe init hello-vibevm
Initializing project `hello-vibevm` in `hello-vibevm`
✓ 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 `hello-vibevm`: 10 files created, 0 kept.
Next:
• edit vibevm/vibespecs/boot/00-core.md and vibevm/vibespecs/common as your project takes shape
• install packages with `vibe install <kind>:<name>` (e.g. flow:wal)
092. Open hello-vibevm/vibe.toml, the project's manifest. Add one line under [project]:
10[project]
spec_format = "xml"
name = "hello-vibevm"
113. Make the folder a git repository with a branch named main:
12git init -b main hello-vibevm
13The line in step 2 decides how the rules you install land on disk. A package author may write in XML or in Markdown. With spec_format = "xml", vibe converts every Markdown document of a package to XML as it copies the package in. The installed text then has one form. The files you write yourself are never converted. On this page they stay Markdown.
14 spec: The setting and its home (revised…
The setting and its home (revised by the measure — reproducibility rules). The materialisation format is a REPRODUCIBLE project property, so its canonical home is the project manifest:vibe.toml [project] spec_format = "mixed" | "markdown" | "xml", with the effective value recorded in the slot record defined by PROP-054 §9.2 so two machines materialise identically. The user-config family supplies only the operator DEFAULT for projects that do not pin one ([install] spec_format, besideslot_integrity), per the standing precedence CLI > env > project > user > built-in; vibe-settings is barred from this key by PROP-040's own boundary (app prefs never extend vibe.toml).mixedis the built-in default — for an all-MD world byte-for-byte today's behaviour; the flip of the default to XML is the owner's word, never silent.
Step 2: install the redbook
16The redbook is a collection of working practices for a team of people and agents, taken from a book on AI-native development. Each practice is its own package with its own rules. Two processes, the person's and the agent's, share one task. Files are the only memory they share. Every decision is written down with its reason, and every commit carries one idea. The redbook names 21 practices, and two of them bring 5 more, so one install gives the project 27 packages.
171. Install it. vibe finds the package in the default registry, downloads 27 packages and copies them in; it takes about a minute. Leave off --assume-yes to see the plan first and answer it yourself; the default answer is no:
vibe install org.vibevm.world/redbook --path hello-vibevm --assume-yes --quiet
vibe install: 27 packages materialised
192. Check the project:
vibe check --path hello-vibevm
vibe check: clean — every check passed against `<TMP>/work/hello-vibevm`
213. Commit everything, the installed packages included. The folder vibevm/vibedeps/ is vibe's copy of the packages. You commit it too, so a fresh clone of the project is readable before anyone runs vibe:
22git -C hello-vibevm add -A
git -C hello-vibevm commit -m "chore: create the project and install the redbook"
Step 3: look at what arrived
24Run vibe tree in the project folder. On a terminal it opens an interactive tree of the 27 packages. The arrows move, Space folds a branch, Enter opens a package's card, and Esc leaves. In a script, or with --plain, the same tree prints as text:
vibe tree --plain --path hello-vibevm
project: <TMP>/work/hello-vibevm
STATIC.xml: 37217 bytes, 300 lines, 4 contribution(s)
packages: 27 roots: 1
columns: load T=transitive C=condition S=in STATIC.xml
org.vibevm.world/redbook dynamic . . .
├─ org.vibevm.world/addressable-specs [public-chain] dynamic . . .
├─ org.vibevm.world/campaign-plans [public-chain] dynamic . . .
├─ org.vibevm.world/comparative-research [public-chain] dynamic . . .
├─ org.vibevm.world/conflict-protocol [public-chain] dynamic . . .
├─ org.vibevm.world/decision-records [public-chain] dynamic . . .
├─ org.vibevm.world/dev-runtime-docs [public-chain] dynamic . . .
├─ org.vibevm.world/discovery-prompt [public-chain] dynamic . . .
├─ org.vibevm.world/git-practices [public-chain] dynamic . . .
│ ├─ org.vibevm.world/git-atomic-commits [public-chain] static . . x
│ ├─ org.vibevm.world/git-attribution-policy [public-chain] static . . x
│ ├─ org.vibevm.world/git-autonomy [public-chain] static . . x
│ └─ org.vibevm.world/git-conventional-commits [public-chain] static . . x
├─ org.vibevm.world/health-audit [public-chain] dynamic . . .
├─ org.vibevm.world/licensing [public-chain] dynamic . . .
├─ org.vibevm.world/managed-blocks [public-chain] dynamic . . .
├─ org.vibevm.world/manual-tests [public-chain] dynamic . . .
├─ org.vibevm.world/operating-modes [public-chain] dynamic . . .
├─ org.vibevm.world/qualified-naming [public-chain] dynamic . . .
├─ org.vibevm.world/secrets-hygiene [public-chain] dynamic . . .
├─ org.vibevm.world/source-mirrors [public-chain] dynamic . . .
├─ org.vibevm.world/spec-genres [public-chain] dynamic . . .
├─ org.vibevm.world/sync-from-code [public-chain] dynamic . . .
├─ org.vibevm.world/tool-design-lessons [public-chain] dynamic . . .
├─ org.vibevm.world/two-process-model [public-chain] dynamic . . .
└─ org.vibevm.world/wal-specspaces [public-chain] dynamic . . .
└─ org.vibevm.world/wal [public-chain] dynamic . . .
26Each row is one package and says how its rules reach the agent. The four git practices are static: an agent reads them first and in full at every session start, because they govern every commit. The others are dynamic: the agent reads them next, one file per package, in a fixed order. That reading list is the boot lane. In this project it runs to about 30 files and 190 kilobytes, which an agent reads before its first word.
27 spec: vibe tree answers that algorithmically: it…
vibe tree answers
that algorithmically: it renders the resolved package tree annotated with the
effective load type and the flags that explain it, and emits the same data as
JSON for downstream tools.
28Now open the folder and see the same thing as files:
291. Open hello-vibevm/vibevm/vibedeps/. It holds 27 folders, one per package, each named by the package's group, name and version: org.vibevm.world.two-process-model/1.0.0/. Inside one is the package as its author published it, with every document in XML.
302. Open .vibe-slot.toml in the same folder. It is vibe's record of this copy. It names the format and the converter's recipe, and holds two hashes: one of what the author published, one of what landed here. Then it lists every file with its own hash and one word, copied or converted. A README.md of the package, for example, arrives as README.xml.
313. Open hello-vibevm/vibevm/vibespecs/boot/. STATIC.xml holds the four git practices joined into one file, and INDEX.md lists the rest of the lane in order. Both files are generated. The other two files there, 00-core.md and 90-user.md, are yours to edit, and no install ever touches them.
32 spec: Decision: For every entry-point node, vibe…
Decision. For every entry-point node,vibe installgenerates two artifacts under the node'svibevm/vibespecs/boot/:
33 spec: STATIC obeys the same materialisation rules…
STATIC obeys the same materialisation rules as everything else (owner ruling 2026-08-22, chat, near-verbatim: «при рематериализации у нас STATIC.md в формате Markdown вне зависимости от того, какой формат материализации выбран, это плохо. На STATIC должны действовать те же правила, что и на всю остальную рематериализацию — должен появиться STATIC.xml»). The generated static lane emits in the project's materialisation format:STATIC.xmlunder thexmltarget,STATIC.mdundermarkdown(themixedextension is the STATIC-format wave's open call — PROP-046 ##OPEN-MIXED-STATIC). This owner-revises the extension-stable-STATIC.mdresidue named at the inheritance-parity landing (##INHERITANCE-PARITY): what was lawful residue is now a defect to fix. The wave's perimeter, known in advance: the dynamic-STATIC target path in hybrid emit, the bootgen emitter, the generated CLAUDE.md boot block, INDEX raw-snippet targets, the parity twins that pin the.mdname, and every by-name consumer ofvibevm/vibespecs/boot/STATIC.xml(hooks, docs). Ordered by the owner as the next act after PROP-046's status waves. The compilate-form decision (recorded before the build): STATIC is and stays an AGENT-facing tape of contributions — under thexmltarget each contribution emits through the pivot's to_xml instead of the markdown projection, the<!-- vibe:static … -->provenance separators stay comments, and a single well-formed root is deliberately NOT promised (the compiled lane is not an input to the machine readers today, and wrapping thirty documents under one root would change anchor semantics for no consumer); the extension law isxml → STATIC.xml,markdown → STATIC.md,mixed → STATIC.md(the single canonical compilate for a per-file target, resolving PROP-046 ##OPEN-MIXED-STATIC); exactly one STATIC file may exist — both present is a loud generator error; consumers learn the name from the generated sources (the CLAUDE.md boot block, INDEX, the redirect) or by exactly-one existence, never by guessing. Landed (7d494f53 + 40e67d56): the format module owns both names with the stray deleted on a switch (polygon-pinned across all three targets), contributions cross to_xml once post-qualification with the markdown path byte-identical, every chooser and generated-name exclusion selects through the module, exactly-one resolution replaced guessing in every machine reader (a new one —show effective— was found by the build itself and reads the lane as the tape it is), boot_directory fails loud on both names, and the host lane re-landed as STATIC.xml with 26 contributions.
344. Open hello-vibevm/CLAUDE.md. Its last lines are a block vibe wrote: they send an agent to the two generated files. AGENTS.md and GEMINI.md end with the same block, because different agents look for different file names.
35 spec: Decision: vibe owns exactly one managed…
Decision. vibe owns exactly one managed block inside each agent instruction file — a contiguous region bounded by an opening and a closing marker.
Step 4: open your agent in the project
36Start the agent inside the project folder, not above it: an agent reads the instruction file of the folder it starts in.
| Agent | How to start it | The file it reads first |
|---|---|---|
| Claude Code | cd hello-vibevm, then claude |
CLAUDE.md |
| Codex | cd hello-vibevm, then codex |
AGENTS.md |
| Gemini CLI | cd hello-vibevm, then gemini |
GEMINI.md |
| an agent inside Cursor, VS Code or a JetBrains IDE | open the hello-vibevm folder as the project, then open the agent's panel |
AGENTS.md, or CLAUDE.md for Claude in the editor |
38Before you ask for any work, ask the agent one question: «What rules does this project follow? Name the practices and where you read them.» The first answer takes a few minutes, because the agent reads the whole lane before it says anything. It should list the practices of the redbook, tell the four static git rules from the rest, and say where it read each. A good answer adds that these rules win over its own habits: for example, its commits will carry no line that credits the agent.
39If it names no practice, it did not start in the folder. Close it, cd hello-vibevm, and start it again.
40The agent may also say that some practices assume a bigger project than a calculator. It is right: one practice expects a tool that updates itself, another a history kept on several git hosts. The collection has opinions. A practice that does not fit can go, with Remove a package.
Step 5: write the specification
41In the redbook's way of working, a program starts as a specification: a text that says what the program must do, written before the code. It is the channel between you and the agent. You decide what the calculator is; the agent reads the decision in a file, not in a chat that ends with the session.
42The rules sort such texts into two kinds. A PROP is a contract: the standing rules of one part of the program, changed rarely and never deleted. A FEAT is one slice of work under that contract: its scope and the checks that say it is done. Every rule sits under a heading with an anchor, {#division-by-zero}, so a test, a commit or a message can point at exactly one rule.
43Two roads lead to the same two files. Write them yourself, or ask your agent to write them and answer its questions.
Write it yourself
441. Create the folder hello-vibevm/vibevm/vibespecs/modules/calculator/.
452. In it, create PROP-001.md, the contract:
46# PROP-001: The calculator {#root}
Hello VibeVM is a command-line calculator. This document is its contract:
what the program accepts, what it prints, and how it fails.
## Input {#input}
The program takes one argument, an expression in quotes: two numbers and
one operator, separated by spaces, as in `hello-vibevm "2 + 3"`.
## Numbers {#numbers}
A number is a decimal with an optional sign and fraction: `-4`, `2.5`.
## Operators {#operators}
The operators are `+`, `-`, `*` and `/`, and no others.
## Result {#result}
The program prints the result on one line of standard output and exits
with code 0. A whole result prints without a fraction: `"2 + 3"` prints
`5`, and `"7 / 2"` prints `3.5`.
## Division by zero {#division-by-zero}
Dividing by zero is an error. The program prints `error: division by zero`
on standard error and exits with code 1.
## Bad input {#bad-input}
Any other input is an error: no argument, a word where a number belongs,
or an operator not listed above. The program names the problem on standard
error and exits with code 2.
## Decision: one quoted argument {#decision-one-argument}
- Decision: the expression arrives as one argument in quotes.
- Why: unquoted, a shell reads `*` as a file pattern, and Git Bash on
Windows turns a lone `/` into a path.
- Revisit when: the calculator gets an interactive mode.
## Decision: Rust {#decision-rust}
- Decision: the calculator is written in Rust.
- Why: one binary with no runtime to install, and a compiler that catches
a class of mistakes before the program runs.
- Revisit when: the calculator must run inside a web page.
473. Create FEAT-001.md beside it, the first slice:
48# FEAT-001: Four operations {#root}
The first slice of Hello VibeVM: the four operations on two numbers and the
two errors, as [PROP-001](PROP-001.md) states them.
## Scope {#scope}
Everything PROP-001 states, and nothing more: no longer expressions, no
history, no interactive mode.
## Acceptance {#acceptance}
| Command | Standard output | Standard error | Exit code |
|----------------------------|-----------------|---------------------------|-----------|
| `hello-vibevm "2 + 3"` | `5` | | 0 |
| `hello-vibevm "10 - 4.5"` | `5.5` | | 0 |
| `hello-vibevm "6 * 7"` | `42` | | 0 |
| `hello-vibevm "7 / 2"` | `3.5` | | 0 |
| `hello-vibevm "-4 * 2.5"` | `-10` | | 0 |
| `hello-vibevm "1 / 0"` | | `error: division by zero` | 1 |
| `hello-vibevm "2 ^ 3"` | | names the operator `^` | 2 |
| `hello-vibevm "2 +"` | | names the missing number | 2 |
494. Ask the agent to read the two files and name what is missing or ambiguous. A good review finds real gaps: this contract says nothing about a result too large to print. Decide each point yourself, and let the agent edit the files.
505. Commit the specification:
51git -C hello-vibevm add vibevm/vibespecs/modules
git -C hello-vibevm commit -m "docs(calculator): specify Hello VibeVM"
Ask your agent to write it
Hello VibeVM is a Rust command-line calculator: `hello-vibevm "7 / 2"` prints `3.5`. It takes one quoted expression, two decimal numbers around `+`, `-`, `*` or `/`; dividing by zero exits with code 1. Specify it in Markdown the way this project's rules require: a short contract and its first feature slice. Write no code; list the files.
an agent session started in hello-vibevm after the redbook install
two new Markdown files under vibevm/vibespecs/modules/, a PROP with the contract and a FEAT with the first slice and its acceptance checks, one anchored heading per rule, and a REVIEW marker on every value the agent chose for you; no source code
find vibevm/vibespecs/modules -name 'PROP-*.md' | grep -q .find vibevm/vibespecs/modules -name 'FEAT-*.md' | grep -q .test ! -e Cargo.tomlvibe check --quiet
53The phrase that does the work is «the way this project's rules require». The agent reads the redbook's rule on kinds of documents, decides that the contract is a PROP and the slice a FEAT, and writes both under vibevm/vibespecs/modules/ with an anchor on every rule. When this page was tested, two agents from two vendors, given only this request and the installed rules, put the same two files in the same place.
54Expect more than you asked for. Everything the request left open, the agent settles with a cautious default, writes the decision down with its reason, and marks it REVIEW for you. In the test run a frontier model spent about 25 minutes here, and most of what it wrote was those decisions. That is the practices working as designed: under the two-process practice, what the program means is yours to decide.
55So answer the markers one by one. Read the list the agent gives you, answer the questions you have an opinion on in plain words, «a result keeps at most ten digits after the point», and say that the rest stand. Do not approve the whole file in one sentence. In the test run, one such sentence settled eight decisions its author never read. When every marker has an answer, ask the agent to commit the specification.
What appeared on disk
56Open hello-vibevm/vibe.toml: it names the project, fixes the format of installed text, and lists org.vibevm.world/redbook under its requirements with a version range. Open hello-vibevm/vibe.lock, the project's lock file: it pins all 27 packages to exact versions and content fingerprints. The rest splits into two trees. vibevm/vibedeps/ and the generated boot files belong to vibe, which rewrites them on every install. vibevm/vibespecs/modules/ and your two boot files belong to you, and vibe never writes into them.
57 spec: Decision: A node's authored spec/…
Decision. A node's authoredspec/and its materialised dependencies live in physically separate trees.vibe installnever writes into any node's authoredspec/.
58If the agent wrote the specification, it may also have left vibevm/vibespecs/WAL.xml: a short record of where the work stands, which the next session reads first. One of the installed practices asks for it.
59The specification is the first thing in this project that is yours alone. The advanced tutorial, Build Hello VibeVM in AI-Native Rust, turns it into a program. It installs Rust, asks the agent to build the calculator from these two files, and adds a discipline that keeps the code tied to them.
Edge cases and rules
60A repeated vibe install with no package names installs whatever the manifest requires; that is the command after cloning an existing project.
61If the folder already has a CLAUDE.md, vibe appends its block at the end and leaves your text alone. If it finds two blocks or a broken one, it stops with an error and changes nothing until you fix the file.
62 spec: Malformed: (§2.2) — vibe aborts…
Malformed (§2.2) — vibe aborts the whole operation with an error naming the file and the exact defect, and changes nothing. It does not proceed until the user repairs the file by hand. vibevm never guesses which of two blocks is canonical and never auto-deletes a stray marker — a malformed managed block is always a human's call.
63Declining the install plan is not an error: nothing is written, and the store keeps what was fetched for next time.
64If the agent starts writing code before the specification is settled, stop it and ask which rule it followed. The redbook's practices put the specification first; an agent that skipped them usually started outside the project folder.
65On Windows, git add may print one warning per file: LF will be replaced by CRLF. It comes from Git's core.autocrlf setting and is harmless: the commit keeps the files' LF endings.