Skip to main content
Commands

vg build

Build or update the code map incrementally. Maps source code into a graph artifact that powers all downstream queries — vg show, vg ask, vg impact, and more.

Overview

vg build maps your source code into a deterministic graph artifact (.vibgrate/graph.json), enabling all downstream code graph queries. Incremental: only re-processes changed files.


Usage

vg build [paths...]
FlagDefaultDescription
[paths...].Folders or files to map
--only <langs>—Restrict to languages (e.g. ts,py,go)
--exclude <glob>—Extra ignore glob (repeatable)
--jobs <n>autoWorker count (1 = single-threaded)
--scip <file>auto-detectIngest a SCIP index for precise resolution
--no-scip—Ignore any SCIP index
--no-tsc—Skip the TypeScript resolver (heuristic floor only)
--no-html—Do not write graph.html
--no-report—Do not write GRAPH_REPORT.md
--no-warm—Do not warm the semantic index after building
--grammars <dir>—Grammar .wasm directory for offline/air-gapped use
-o, --export <file>—Also write the map to a file (format from extension)
--attest—After the map is written, sign it. See Sign and check the map
--verify—Check an attestation against the map on disk, and run the determinism self-check. Does not sign, and does not replace the map
--attest-key <path>$VG_ATTEST_KEY, else .vibgrate/attest-key.pemEd25519 private key PEM used by --attest
--attestation <file>.vibgrate/attestation.intoto.jsonlWhere --attest writes, and where --verify reads
--pub <path>—Public key PEM that pins the signer for --verify

Examples

# Map current directory
vg build

# Map specific folders only
vg build src/ lib/

# TypeScript only, single-threaded
vg build --only ts --jobs 1

# Export map to JSON as well
vg build -o map.json

Sign and check the map

There is no vg attest-actions command. Signing and checking are flags on vg build. vg attest and vg verify are retired names. Each exits 5 and prints where the flag moved:

error: `vg attest` has moved to `vg build --attest`
error: `vg verify` has moved to `vg build --verify`

--attest builds the map, writes the usual artifacts, then signs that map. --verify does not take that path. If both flags are set, --verify runs and nothing is signed.

The attestation is a signed statement that this map was produced by this vg version, over this corpus, and (when git can say so) at this commit. A later vg build --verify checks that statement against the map already on disk. It does not decide that the source was reviewed, and it does not certify a build environment.

--attest--verify
ReadsThe project tree, then an Ed25519 private keyThe attestation file, the map already on disk, and the project tree (the determinism rebuilds). --pub adds a public key PEM
WritesThe usual map artifacts, then the attestation file. The first run with no key at the default path also writes the key pairNothing. The in-memory rebuilds are not saved over graph.json, and no attestation is written

--attest writes a one-line DSSE envelope at .vibgrate/attestation.intoto.jsonl. --attestation <file> chooses another path. The payload type is application/vnd.in-toto+json. Inside it is an in-toto Statement (https://in-toto.io/Statement/v1) whose predicate type is https://vibgrate.com/attestation/code-graph/v1. The subject is graph.json. Its sha256 is the canonical map with generatedAt left out, so two builds of the same content share a digest. The signature block also carries the signer's public key, so a later check can test that the bytes were not altered without a separate key file. The same graph and the same Ed25519 key produce the same envelope. No timestamp is written. The default .vibgrate/.gitignore does not list attestation.intoto.jsonl. Commit that file. Do not commit the private key.

The key is read in this order: --attest-key <path>, then VG_ATTEST_KEY, then .vibgrate/attest-key.pem. When nothing names a key and the default path is missing, the first run creates an Ed25519 key there, mode 0600, and writes the public key beside it as .vibgrate/attest-key.pem.pub. It prints:

  minted a new Ed25519 signing key at .vibgrate/attest-key.pem (keyid <16 hex chars>) — keep it, add it to .gitignore, and reuse it to re-sign reproducibly

Keep that private key and add it to .gitignore. A key you name with --attest-key or VG_ATTEST_KEY is never created for you.

--verify builds the map in memory to check determinism (two cache-off builds, then one cache-warm build) and does not write those builds over graph.json. The attestation check reads the file and compares it to the map already on disk. It does not rebuild in order to check the signature, and it does not re-read git. --pub <path> pins the signer. Without it, a good signature is integrity only.

JSON status is verified (exit 0), signature-valid (exit 0), or failed (exit 2). verified needs a pinned key, a valid signature, and a statement that was not marked dirty when you signed. The reason signature valid, signer trusted, graph digest matches is the one that compared the map. signature valid, signer trusted means no map was on disk, so the digest was not compared. A missing file at the default path, with no --attestation and no --pub, is not a failure. The command prints the line below, and JSON sets attestation to null.

  attestation: none (sign one with `vg build --attest`)

Signing and checking use local Ed25519 only. Nothing is uploaded. While signing, git records the commit, whether the tree was dirty, and the branch name, when those commands work. They do not fetch or push. vg build --attest is still a build: unless you pass --offline or --local, it can download the Architecture module, and an interactive terminal can start an embedding-model download unless you also pass --no-warm, --json, or --quiet. vg build --verify does not install modules.

Sign the map, then check it against the public key written next to the private key:

vg build --attest
vg build --verify --pub .vibgrate/attest-key.pem.pub

With a clean tree at sign time and a matching map, the reason is signature valid, signer trusted, graph digest matches.

Asking to verify a file that is not there fails. From the project root, before any attestation has been written:

vg build --verify --attestation .vibgrate/attestation.intoto.jsonl
error: no attestation at .vibgrate/attestation.intoto.jsonl — sign one with `vg build --attest`

Exit code 3. The path in the message is the path you named.

Exit 3. You passed --attestation, or you passed --pub, and that file is not there. Sign with vg build --attest, or point --attestation at the file you committed.

error: no attestation at <path> — sign one with `vg build --attest`

Not a failed signature. No file is at the default path, and you did not name one. The exit is 0 when the determinism checks pass, and 4 when they do not.

  attestation: none (sign one with `vg build --attest`)

Exit 5. --attest-key or VG_ATTEST_KEY names a file that is not there. The default path is created only when you do not name a key.

error: signing key not found: <path>

Exit 5. The file is there but is not a PEM private key.

error: could not read an Ed25519 private key from <path>

Exit 5. The PEM is some other algorithm, or unknown. Use an Ed25519 key.

error: attest requires an Ed25519 key, but <path> is <type>

Exit 2. Read the reason on the line above. A digest mismatch means the map on disk changed after signing: run vg build --attest again with the same key. malformed attestation payload (not a valid in-toto statement) means the envelope parsed but the payload is not an in-toto statement.

A file that is not a JSON line never reaches that reason. Parsing it throws, the process exits 1, and the message is the parser text plus a ref line. --pub is read only after an attestation file is found. A public-key path that is not there is the same exit 1. When the attestation file is also missing, you get the exit 3 line above instead.

error: attestation verification failed

Exit 4. The in-memory rebuilds disagreed, or the toolchain fingerprint does not match the committed map. This exit is reported even when the attestation also failed.

error: determinism self-check failed

Global Options

All graph commands accept: --cwd <dir>, --graph <file>, --json, --quiet, --local, --deep, --no-cache.


Related

  • vg show — Inspect a node
  • vg ask — Ask the map a question
  • vg serve — Start local MCP for AI assistants

Example use cases

Expand any use case to watch a live replay of the real @vibgrate/cli running against one of our test repositories. Nothing executes in your browser — these are recordings of actual runs, with the scan time shown as of now.

vg build

Related Documentation

Vibgrate CLI

See a real scan run

A replay of the actual CLI running against our test repositories — live progress, real findings, a genuine DriftScore. Nothing executes in your browser.

Replay
demo@vibgrate — bash
❯ npx @vibgrate/cli scan
 
╭──────────────────────────────────────────╮
│ Vibgrate Drift Report │
╰──────────────────────────────────────────╯
 
── node-turborepo (node) .
Runtime: >=18.0.0 (6 majors behind)
Frameworks:
Turbo: 1.13.4 → 2.11.7 (1 behind)
TypeScript: 5.9.3 → 7.0.2 (2 behind)
Dependencies:
1 current 1 1-behind 3 2+ behind 1 unknown
 
── @repo/admin (node) apps/admin
Frameworks:
TanStack Query: 5.104.1 → 5.104.1 (current)
React: 18.3.1 → 19.3.0 (1 behind)
React DOM: 18.3.1 → 19.3.0 (1 behind)
TypeScript: 5.9.3 → 7.0.2 (2 behind)
Vite: 5.4.21 → 8.3.3 (3 behind)
Dependencies:
3 current 9 1-behind 3 2+ behind 4 unknown
 
── @repo/api (node) apps/api
Frameworks:
Express: 4.22.3 → 5.2.1 (1 behind)
TypeScript: 5.9.3 → 7.0.2 (2 behind)
Vitest: 1.6.1 → 5.0.3 (4 behind)
Dependencies:
7 current 4 1-behind 4 2+ behind 4 unknown
 
── @repo/web (node) apps/web
Frameworks:
Next.js: 14.2.35 → 16.3.8 (2 behind)
React: 18.3.1 → 19.3.0 (1 behind)
React DOM: 18.3.1 → 19.3.0 (1 behind)
TypeScript: 5.9.3 → 7.0.2 (2 behind)
Dependencies:
2 current 6 1-behind 3 2+ behind 5 unknown
 
── @repo/config (node) packages/config
Frameworks:
TypeScript: 5.9.3 → 7.0.2 (2 behind)
Dependencies:
2 current 2 1-behind 5 2+ behind 0 unknown
 
── @repo/database (node) packages/database
Frameworks:
Prisma: 5.22.0 → 7.10.0 (2 behind)
TypeScript: 5.9.3 → 7.0.2 (2 behind)
Dependencies:
1 current 0 1-behind 3 2+ behind 1 unknown
 
── @repo/types (node) packages/types
Frameworks:
TypeScript: 5.9.3 → 7.0.2 (2 behind)
Dependencies:
0 current 0 1-behind 1 2+ behind 1 unknown
 
── @repo/ui (node) packages/ui
Frameworks:
React: 18.3.1 → 19.3.0 (1 behind)
TypeScript: 5.9.3 → 7.0.2 (2 behind)
React: 18.3.1 → 19.3.0 (1 behind)
Dependencies:
1 current 4 1-behind 1 2+ behind 1 unknown
 
── @repo/utils (node) packages/utils
Frameworks:
TypeScript: 5.9.3 → 7.0.2 (2 behind)
Vitest: 1.6.1 → 5.0.3 (4 behind)
Dependencies:
0 current 1 1-behind 2 2+ behind 1 unknown
 
Tech Stack
Frontend: React, React DOM
Meta-frameworks: Next.js
Bundlers: tsx, Turbo, Vite
CSS / UI: Autoprefixer, PostCSS, Tailwind CSS
Backend: Express
ORM / Database: Prisma, Prisma Client
Testing: Vitest
Lint & Format: ESLint, ESLint Prettier, ESLint React, Prettier, typescript-eslint
 
Services & Integrations
Auth: JWT 9.0.3
Databases: Prisma 5.22.0
 
TypeScript
v5.3.3 · strict ✔ · MIXED · target: ES2022
 
Build & Deploy
Package Managers: pnpm
Monorepo: npm-workspaces, pnpm-workspaces, turbo
 
Product Purpose Signals
Frameworks: react, nextjs
Evidence: 177
Top Signals:
- [heading] Dashboard (apps/admin/src/pages/Dashboard.tsx)
- [title] Revenue Overview (apps/admin/src/pages/Dashboard.tsx)
- [copy] workspace:* (packages/ui/package.json)
- [copy] ./dist (packages/ui/tsconfig.json)
- [copy] ./src/index.ts (packages/ui/package.json)
- [copy] @repo/config/tsconfig-base.json (packages/ui/tsconfig.json)
- [copy] @repo/ui (packages/ui/package.json)
- [copy] #3b82f6 (apps/admin/src/pages/Dashboard.tsx)
Unknowns:
- No pricing or billing evidence found.
- No integrations/connectors evidence found.
- No route structure evidence found.
 
Security Posture
Lockfile ✖ · .env ✔ · node_modules ✔
 
Platform
Native modules: turbo
 
Code Quality
Files: 36 · Functions: 183 · Avg complexity: 2.62 · Avg length: 21.13 lines
Max nesting: 2 · Circular deps: 0 · Dead code: 0%
God files: apps/admin/src/pages/Products (448 lines)
 
Database Schema
postgresql · 8 models · 1 enum
Models: Address, CartItem, Category, Order, OrderItem (+3 more)
 
Findings (16 errors, 11 warnings)
✖ Node.js runtime ">=18.0.0" reached end-of-life on 2025-04-30 (latest: 24.0.0).
vibgrate/runtime-eol in .
⚠ TypeScript is 2 major versions behind (current: 5.9.3, latest: 7.0.2).
vibgrate/framework-major-lag in .
✖ 60% of dependencies are 2+ major versions behind in node-turborepo.
vibgrate/dependency-rot in .
✖ @types/node is 6 major versions behind (spec: ^20.11.0, latest: 26.6.4).
vibgrate/dependency-major-lag in .
⚠ TypeScript is 2 major versions behind (current: 5.9.3, latest: 7.0.2).
vibgrate/framework-major-lag in apps/admin
✖ Vite is 3 major versions behind (current: 5.4.21, latest: 8.3.3).
vibgrate/framework-major-lag in apps/admin
✖ vite is 3 major versions behind (spec: ^5.0.12, latest: 8.3.3).
vibgrate/dependency-major-lag in apps/admin
⚠ TypeScript is 2 major versions behind (current: 5.9.3, latest: 7.0.2).
vibgrate/framework-major-lag in apps/api
✖ Vitest is 4 major versions behind (current: 1.6.1, latest: 5.0.3).
vibgrate/framework-major-lag in apps/api
✖ @types/node is 6 major versions behind (spec: ^20.11.0, latest: 26.6.4).
vibgrate/dependency-major-lag in apps/api
✖ vitest is 4 major versions behind (spec: ^1.2.1, latest: 5.0.3).
vibgrate/dependency-major-lag in apps/api
⚠ Next.js is 2 major versions behind (current: 14.2.35, latest: 16.3.8).
vibgrate/framework-major-lag in apps/web
⚠ TypeScript is 2 major versions behind (current: 5.9.3, latest: 7.0.2).
vibgrate/framework-major-lag in apps/web
✖ @types/node is 6 major versions behind (spec: ^20.11.0, latest: 26.6.4).
vibgrate/dependency-major-lag in apps/web
⚠ TypeScript is 2 major versions behind (current: 5.9.3, latest: 7.0.2).
vibgrate/framework-major-lag in packages/config
✖ 56% of dependencies are 2+ major versions behind in @repo/config.
vibgrate/dependency-rot in packages/config
✖ eslint-plugin-react-hooks is 3 major versions behind (spec: ^4.6.0, latest: 7.1.1).
vibgrate/dependency-major-lag in packages/config
⚠ Prisma is 2 major versions behind (current: 5.22.0, latest: 7.10.0).
vibgrate/framework-major-lag in packages/database
⚠ TypeScript is 2 major versions behind (current: 5.9.3, latest: 7.0.2).
vibgrate/framework-major-lag in packages/database
✖ 75% of dependencies are 2+ major versions behind in @repo/database.
vibgrate/dependency-rot in packages/database
⚠ TypeScript is 2 major versions behind (current: 5.9.3, latest: 7.0.2).
vibgrate/framework-major-lag in packages/types
✖ 100% of dependencies are 2+ major versions behind in @repo/types.
vibgrate/dependency-rot in packages/types
⚠ TypeScript is 2 major versions behind (current: 5.9.3, latest: 7.0.2).
vibgrate/framework-major-lag in packages/ui
⚠ TypeScript is 2 major versions behind (current: 5.9.3, latest: 7.0.2).
vibgrate/framework-major-lag in packages/utils
✖ Vitest is 4 major versions behind (current: 1.6.1, latest: 5.0.3).
vibgrate/framework-major-lag in packages/utils
✖ 67% of dependencies are 2+ major versions behind in @repo/utils.
vibgrate/dependency-rot in packages/utils
✖ vitest is 4 major versions behind (spec: ^1.2.1, latest: 5.0.3).
vibgrate/dependency-major-lag in packages/utils
 
╭──────────────────────────────────────────╮
│ Top Priority Actions │
╰──────────────────────────────────────────╯
 
1. Upgrade EOL runtime in node-turborepo
End-of-life runtimes no longer receive security patches and block ecosystem upgrades.
./.
>=18.0.0 → 24.0.0 (6 majors behind)
Impact: −10 drift points (runtime & EOL)
 
2. Fix security posture: no lockfile found
Without a lockfile, installs are non-deterministic. Run the install command to generate one and commit it.
./
Missing: package-lock.json, pnpm-lock.yaml, or yarn.lock
 
3. Upgrade Vitest 1.6.1 → 5.0.3 in @repo/api (+2 more)
4 major versions behind. Major framework drift increases breaking change risk and blocks access to security fixes and performance improvements.
./apps/api
Vitest: 1.6.1 → 5.0.3 (4 majors behind)
./packages/utils
Vitest: 1.6.1 → 5.0.3 (4 majors behind)
./apps/admin
Vite: 5.4.21 → 8.3.3 (3 majors behind)
Impact: −5–15 drift points
 
4. Reduce dependency rot in @repo/types (100% severely outdated)
1 of 1 dependencies are 2+ majors behind. Run `npm outdated` and prioritise packages with known CVEs or breaking API changes.
./packages/types
typescript: 5.9.3 → 7.0.2 (2 majors behind)
Impact: −5–10 drift points
 
5. Reduce dependency rot in @repo/database (75% severely outdated)
3 of 4 dependencies are 2+ majors behind. Run `npm outdated` and prioritise packages with known CVEs or breaking API changes.
./packages/database
@prisma/client: 5.22.0 → 7.10.0 (2 majors behind)
prisma: 5.22.0 → 7.10.0 (2 majors behind)
typescript: 5.9.3 → 7.0.2 (2 majors behind)
Impact: −5–10 drift points
 
╭──────────────────────────────────────────╮
│ Architecture Layers │
╰──────────────────────────────────────────╯
 
Archetype: nextjs (80% confidence)
Files classified: 24 (11 unclassified)
Folders classified: 8
apps/admin/src presentation 100% 4 files
apps/admin/src/pages presentation 100% 2 files
apps/api/src/middleware middleware 100% 2 files
apps/api/src/routes routing 100% 2 files
apps/web/src/app presentation 100% 4 files
apps/web/src/app/products presentation 100% 2 files
apps/web/src/app/products/[id] presentation 100% 1 file
packages/ui/src presentation 100% 6 files
Unclassified source (sample): 11
 
presentation 15 files drift ████████████████████ 100 risk high
routing 4 files drift ████████████████████ 100 risk high
middleware 2 files drift ███████▍░░░░░░░░░░░░ 37 risk moderate
config 2 files drift ░░░░░░░░░░░░░░░░░░░░ 0 risk none
shared 1 file drift ████████████████████ 100 risk high
 
╭──────────────────────────────────────────╮
│ DriftScore Summary │
╰──────────────────────────────────────────╯
 
DriftScore: 70/100
Risk Level: HIGH
Projects: 9
Classified: 8 nano · 1 micro · 0 small · 0 standard
Billable: 0.42 · 9 detected → 0.42 billable projects (micro-project pricing)
0.1 micro · 0.32 nano
These fractions add up across repositories, then round down to whole billable projects.
 
Score Breakdown
Runtime: ████████████████████ 100
Frameworks: ███████████▊░░░░░░░░ 59
Dependencies: ██████▌░░░░░░░░░░░░░ 33
EOL Risk: ████████████████████ 100
 
Scanned at 2026-10-06T11:29:54.082Z · 7.8s · 286 files scanned · 56 workspace files · 27 dirs
❯
Press Run to start.