Chapter 15: Toolchain Deep Dive

VibeLang ships as a single binary — vibe — that handles every phase of development: checking, building, running, testing, formatting, linting, documentation, language server support, package management, and compiler inspection. This chapter covers every command in depth.


15.1 The vibe CLI

Architecture: One Binary, Many Commands

The vibe binary dispatches to the appropriate compiler crate based on the subcommand:

vibe <command> [flags] [arguments]

Global Flags

FlagShortDescription
--help-hPrint help for the command
--version-VPrint compiler version
--verbose-vIncrease output verbosity
--quiet-qSuppress non-error output
--colorColor output: always, never, auto
--threads-jParallel compilation threads

Every command follows consistent conventions: --help for usage, exit code 0 for success, non-zero for failure.


15.2 Building and Running

vibe check — Verify Without Building

Terminal
vibe check src/main.yb    # Single file
vibe check src/            # All .yb files in directory
vibe check .               # Entire project

Runs the full frontend — lexing, parsing, type checking, effect verification, and contract validation — without generating a binary. This is the fastest feedback loop.

What vibe check verifies:

CheckExample error
SyntaxE0101: expected ')' after parameter list
TypesE0102: type mismatch — expected Int, found Str
EffectsE0401: missing effect declaration — @effect io
ContractsE0402: effectful function in contract expression
ExhaustivenessE0540: non-exhaustive match expression
SendabilityE0801: cannot capture mutable binding in go block

vibe check reports all errors it finds, not just the first one. When run inside a project directory (containing vibe.toml), it automatically discovers all source files.

vibe build — Compile to Native Binary

Terminal
vibe build src/main.yb                    # Debug build
vibe build --release src/main.yb          # Release build
vibe build --profile test src/main.yb     # Test build
vibe build -o myapp src/main.yb           # Custom output name

Compilation flags:

FlagDescription
--releaseRelease profile (optimized)
--profile <name>Select profile: dev, test, release
-o <path>Output binary path
--target <triple>Cross-compilation target
--emit <stage>Emit intermediate representation

Build Profiles

ProfileOptimizationContractsDebug InfoUse Case
devNoneRuntime checksFullDaily development
testNoneRuntime checksFullRunning tests
releaseFullConfigurableStrippedProduction

Release contract behavior is configured in vibe.toml:

TOML
[release]
contracts = "checked"    # "checked", "unchecked", or "removed"
  • checked — contracts compiled as runtime checks (safest, default)
  • unchecked — contracts used for static analysis only, no runtime overhead
  • removed — contracts stripped entirely (smallest binary)

vibe run — Build and Execute

Terminal
vibe run src/main.yb
vibe run src/main.yb -- --flag1 arg1    # Pass arguments to the program
vibe run .                               # Run project entry point

Shorthand for vibe build followed by executing the binary. Arguments after -- are passed to the compiled program. Inside a project directory, uses the entry point from vibe.toml.


15.3 Testing

vibe test — Run Tests

Terminal
vibe test src/main.yb          # Single file
vibe test src/                  # All files in directory
vibe test .                     # Entire project
vibe test . --filter "parse"    # Tests matching "parse"

Discovers and runs two kinds of tests:

1. @examples in contracts:

VibeLang
@examples {
    celsius_to_fahrenheit(0.0) == 32.0
    celsius_to_fahrenheit(100.0) == 212.0
}
celsius_to_fahrenheit(celsius: Float) -> Float {
    celsius * 9.0 / 5.0 + 32.0
}
Testing src/main.yb...
  ✓ celsius_to_fahrenheit: 2 examples passed

2. Test functions (names starting with test_):

VibeLang
pub test_edge_cases() -> Int {
    @effect alloc
    assert(celsius_to_fahrenheit(-273.15) >= -459.67, "absolute zero check")
    0
}

Test Output Format

Testing <file>...
  ✓ <function>: <N> examples passed
  ✗ <function>: example <N> failed
    Expected: <expression> == <expected>
    Got:      <expression> == <actual>

<summary line>

Exit code 0 if all tests pass, 1 if any fail.

Testing Strategies

Unit tests via @examples: Best for pure functions. Zero boilerplate, automatic execution, doubles as documentation.

Integration tests in tests/: Best for effectful code:

myproject/
├── src/
│   └── main.yb
└── tests/
    ├── parser_test.yb
    └── pipeline_test.yb

Concurrent tests: Use channels to synchronize assertions. Test aggregate properties (sums, counts) rather than ordering.


15.4 Code Quality

vibe fmt — Format Code

Terminal
vibe fmt src/main.yb       # Format a file
vibe fmt .                  # Format entire project
vibe fmt --check .          # Check without modifying (CI mode)

VibeLang has one canonical formatting style with no configuration options. This eliminates formatting debates and ensures all VibeLang code looks the same.

Key rules: 4-space indentation, opening braces on same line, contract annotations ordered (@intent, @examples, @require, @ensure, @effect), 100-character soft line limit.

CI integration: vibe fmt --check . exits with code 1 if any file is not formatted, printing the diff.

vibe lint — Static Analysis

Terminal
vibe lint src/main.yb       # Single file
vibe lint .                  # Entire project
vibe lint --intent .         # Include AI-powered intent analysis

Catches patterns that are technically valid but likely incorrect:

WarningDescription
W0101Unused binding
W0102Unused import
W0201Unreachable code
W0301Shadowed binding
W0401Over-declared effect
W0402Redundant contract
W0601Channel created but never used

vibe lint --intent — AI-Powered Intent Verification

Activates the AI sidecar to compare @intent annotations against implementations:

warning[W0501]: intent mismatch
 --> src/math.yb:8:1
  |
1 | @intent "Returns the absolute value of a number"
  ...
8 |     if n < 0 { n } else { -n }
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation negates positive numbers
  |
  = help: did you mean `if n < 0 { -n } else { n }`?

The sidecar is optional and configured in vibe.toml:

TOML
[sidecar]
enabled = true
endpoint = "http://localhost:11434"
model = "codellama"

Use --changed to limit analysis to files modified since the last commit.


15.5 Documentation

vibe doc — Generate API Documentation

Terminal
vibe doc src/                # Generate docs
vibe doc . --open            # Generate and open in browser
vibe doc . --output docs/    # Custom output directory

Extracts function signatures, @intent annotations, @examples as usage examples, contracts as documented pre/postconditions, and @effect declarations.

Documentation comments use /// for functions or //! for modules:

VibeLang
//! The math module provides basic mathematical operations.

/// Compute the greatest common divisor using the Euclidean algorithm.
@intent "Greatest common divisor via Euclidean algorithm"
@examples {
    gcd(12, 8) == 4
    gcd(7, 13) == 1
}
@require a > 0
@require b > 0
pub gcd(a: Int, b: Int) -> Int {
    if b == 0 { a } else { gcd(b, a % b) }
}

15.6 Language Server

vibe lsp — Editor Integration

Terminal
vibe lsp    # Start the language server (editors call this automatically)

Implements the Language Server Protocol (LSP):

  • Diagnostics: Type errors, effect violations, and contract issues appear as you type
  • Completion: Context-aware suggestions for functions, types, and fields
  • Hover: Shows signature, contracts, and effects for any symbol
  • Go-to-definition: Jump to any function, type, or module definition
  • Find references: Locate all uses of a symbol across the project
  • Rename: Rename a symbol with automatic updates to all references
  • Format on save: Runs vibe fmt automatically

Editor Setup

VS Code / Cursor: Install the "VibeLang" extension.

Neovim (nvim-lspconfig):

lua
require('lspconfig').vibelang.setup {
    cmd = { "vibe", "lsp" },
    filetypes = { "vibelang" },
}

15.7 Package Management

vibe pkg — Dependency Management

Terminal
vibe pkg install <package>       # Add a dependency
vibe pkg update                  # Update all dependencies
vibe pkg audit                   # Check for vulnerabilities
vibe pkg list                    # List installed dependencies

Dependencies are declared in vibe.toml:

TOML
[dependencies]
http = "1.2.0"
json = "0.8.3"

Dependency Resolution

Resolves dependencies transitively. Conflicts are reported clearly:

error: dependency conflict
  myapp requires http >= 1.2.0
  logging 2.1.0 requires http < 1.0.0

Lock Files and Reproducibility

vibe pkg writes vibe.lock with exact versions and checksums:

TOML
[[package]]
name = "http"
version = "1.2.3"
checksum = "sha256:a1b2c3d4..."

Commit vibe.lock to version control. This ensures vibe build uses identical dependency versions on every machine.

Security Auditing

Terminal
vibe pkg audit
advisory[VIBE-2025-001]: json < 0.9.0 — denial of service via deeply nested input
  installed: json 0.8.3
  fix: upgrade to json >= 0.9.0

Run in CI to catch vulnerable dependencies before deployment.


15.8 Debugging Tools

vibe ast — Inspect the Abstract Syntax Tree

Terminal
vibe ast src/main.yb              # Print AST
vibe ast --tokens src/main.yb     # Print token stream
vibe ast --json src/main.yb       # Output as JSON

Useful for debugging parsing issues or understanding operator precedence.

vibe hir — Inspect High-Level IR

Terminal
vibe hir src/main.yb

Shows code after desugaring and contract lowering. See how @require becomes runtime checks, how for ... in desugars to iterators, and how ? expands to match-and-return.

vibe mir — Inspect Mid-Level IR

Terminal
vibe mir src/main.yb

Shows the optimized control flow graph. Comparing HIR and MIR reveals which optimizations the compiler applied: dead code elimination, constant folding, inlining, and contract check elimination.

vibe index — Semantic Indexing

Terminal
vibe index src/                   # Build semantic index
vibe index --query "Result" src/  # Search the index

Maps symbols to definitions, references, types, and contracts. The language server uses this index for go-to-definition and find-references.


15.9 Summary

The vibe toolchain provides a complete development environment:

  • vibe check — fastest feedback: types, effects, contracts without building
  • vibe build — native binaries with three profiles: dev, test, release
  • vibe run — build and execute in one step
  • vibe test — automatic @examples and test function discovery
  • vibe fmt — single canonical style, --check for CI
  • vibe lint — static analysis; --intent for AI-powered drift detection
  • vibe doc — HTML documentation from signatures and contracts
  • vibe lsp — real-time editor integration via LSP
  • vibe pkg — dependency management with lock files and security auditing
  • vibe ast/hir/mir — compiler stage inspection for debugging
  • vibe index — semantic indexing for code navigation

Every command follows consistent conventions: --help for usage, --verbose for detail, --quiet for CI, and exit code 0 for success.


Next: Chapter 16 covers production deployment, release engineering, and team adoption strategies.