v0.1 • Early
Beginner friendly
Go 1.25 • CMake 3.16+

Rivets Docs

The friendly C++ bootstrapper. This wiki covers installs, commands, project layout and pro tips — written so even if today is your Day 1 in C++, you’ll feel at home.

15+ commands
Convention-based
Hints, not crashes
Compile DB free
Getting Started

Introduction

Rivets (riv) removes the first 30 minutes of C++ pain: CMake boilerplate, folder linking, and “where do I put my files?”. You write src/main.cpp, Rivets generates a clean, standard CMake project in .riv/ and builds it. It’s not a package manager (yet), it’s training wheels — you learn CMake by reading what we generate.

For beginners

Zero config. riv initriv run and you’re coding.

No lock-in

Generated CMake is readable. Outgrow Rivets? Take it with you.

Fast

Parallel builds, incremental compiles, .riv/build stays out of your way.

Installation

Requires Go 1.25+ to install from source, plus a C++ compiler and CMake on your machine.

Option A — Go install (recommended)

Works on Linux, macOS (WSL on Windows)

bash
go install github.com/Akash97p/rivets/cmd/riv@latest
riv --version
riv doctor

Make sure $(go env GOPATH)/bin is in your PATH.

Option B — From source

Clone and build locally

bash
git clone https://github.com/Akash97p/rivets.git
cd rivets
go build -o riv ./cmd/riv
./riv --help
Prerequisites: clang++ ≥10 or g++ ≥9 and cmake ≥3.16 (3.22+ recommended). Run riv doctor to verify. Install hints: sudo apt install build-essential cmake clang-format clang-tidy or brew install llvm cmake.

Quick Start — 60 seconds

bash
# 1) Check your toolchain
riv doctor

# 2) Create a project (full = with sample lib + header)
riv init hello --std c++20
cd hello

# 3) Build & run
riv build
riv run
# Hello from riv!
# 2 + 3 = 5
Tip: riv init --minimal for a tiny hello-world
Tip: riv run -- --args are passed to your program
Edit loop: change src/main.cpp and hit riv run again — incremental build, no CMake touching. Try riv run --watch for auto-rebuild.

Your First Project — Step by Step

1. Make the project

bash
riv init mygame --template full

Creates riv.toml, src/main.cpp, sample lib and a .gitignore already ignoring .riv/.

2. Add your code

cpp
// src/main.cpp
#include <iostream>
int main(){
  std::cout << "My game starts\n";
}

3. Create a library (optional but encouraged)

Each folder in lib/ becomes a static library automatically.

bash
mkdir -p lib/physics/include/physics lib/physics/src
# lib/physics/include/physics/physics.h  -> int update();
# lib/physics/src/physics.cpp            -> implementation
riv build   # links automatically

Why Rivets?

ProblemWithout Rivets 😵With Rivets ✅
Start a projectWrite 40-line CMakeLists by handriv init → ready
Add a libraryEdit CMake, add_subdirectory, target_link…Create lib/mylib/ → auto linked
IDE supportConfigure compile_commands manuallyWe symlink it to root — clangd just works
ErrorsCryptic CMake dumpFriendly Hints: “move .cpp out of include/”

Project Structure

text
mygame/
├── riv.toml              # your manifest
├── src/main.cpp          # entry point (must exist)
├── lib/                  # compiled libs → auto static libs
│  └── physics/
│     ├── include/physics/
│     │  └── physics.h
│     └── src/
│        └── physics.cpp
├── include/              # header-only libs
│  └── utils/utils.h
├── external/             # riv add deps live here
└── .riv/                 # generated CMake + build (gitignored)
   ├── CMakeLists.txt
   └── build/myapp

Folder rules (enforced)

src/main.cpp is mandatory — it’s your executable.
• Each lib/<name> needs both include/ and src/. All .cpp under src/ (recursive) are compiled.
include/ is header-only — no .cpp allowed (we error with a Hint).
• No symlinks — security policy.
• No spaces in lib names.
💡 Pro tip: put shared helpers in include/, heavy modules in lib/.

riv.toml Explained

Tiny, human manifest — alternative to CMake boilerplate.

toml
name = "mygame"
version = "0.1.0"
standard = "c++20"

[build]
warnings = "all"

[dependencies]
stb_image = "2.28"

Fields

name — binary name + project folder.
standardc++17 | c++20 | c++23 (validated).
[build] — for future flags (warnings, sanitize).
[dependencies] — added by riv add; lock details live in riv.lock.
Change standard to c++23 and rebuild — we generate CMAKE_CXX_STANDARD 23 for you.

How It Works

riv build
Scan
Validate
Generate .riv/CMakeLists.txt
cmake configure + build
1. Scan — walks src/, lib/*/src (recursive), include/, external/.
2. Validate — rejects .cpp in include/, spaces/symlinks, missing src/main.cpp with friendly Hints.
3. Generate — renders internal/generator/templates/CMakeLists.txt.tmpl with file lists.
4. Executecmake -S .riv -B .riv/build -DCMAKE_BUILD_TYPE=Release|Debugcmake --build. Binary lands at .riv/build/<name>. We also symlink compile_commands.json to root for clangd.
Commands — your daily toolkit
Each card shows what/why/flags/examples. Copy-paste friendly.

riv doctor
first run
--json

Diagnose your C++ toolchain and get OS-specific install hints.

bash
riv doctor
riv doctor --json | jq
Checks
  • OS: Linux native / macOS experimental / Windows WSL hint
  • Compiler: clang++ → g++ → cl, version ≥ clang 10 / gcc 9
  • CMake: ≥3.16 (warn if <3.22)
  • Build test: compiles a hello.cpp
Pro tips
  • Run this first on a new laptop.
  • --json is great for CI: fails the job if Ready=false.
  • If it says “Not found”, copy the Hint line.

riv init / riv new
scaffold

Create a new project. new is an alias.

bash
riv init myapp --std c++20
riv init myapp --template minimal      # no sample lib
riv init myapp --minimal --no-git
riv new myapp --std c++23                # same as init
FlagDefaultNotes
--stdc++20c++17/20/23 validated, normalized to “20” for CMake
--templatefullfull (with lib/sample + utils) / minimal / lib
--minimalfalseShorthand for --template minimal — tiny hello-world
--no-gitfalseSkip git init
⚠️ Name must be ^[a-zA-Z0-9_-]+$ — no spaces/slashes. Directory must not already exist.

riv build
--release / --clean / -j / -v

Generate CMake and compile. Smart about caching.

bash
riv build
riv build --release -j 8
riv build --clean --verbose
riv build --debug --clean
FlagWhat
-j, --jobsParallel jobs (default: CPU cores)
--releaseCMAKE_BUILD_TYPE=Release (optimized)
--debugDebug (default)
--cleanRemove .riv before build
-v, --verboseShow cmake / build logs
Beginner note: You never edit .riv/CMakeLists.txt — edit your .cpp files and rebuild. Binary goes to .riv/build/<name>. We also symlink compile_commands.json to the root so VS Code / CLion IntelliSense just works.

riv run
build+run
--watch

Builds if needed, then runs your binary and forwards args.

bash
riv run
riv run -- --my-flag hello    # args after -- go to your program
riv run --no-build            # skip build, just run
riv run --release             # build Release then run
riv run --watch               # auto-rebuild on save
Watch mode polls src/, lib/, include/ for .cpp/.h/.hpp changes and re-runs. Great for live tweaking. Ctrl+C to stop.

riv clean

Wipe build artifacts, keep your source.

bash
riv clean
riv build --clean   # clean + build in one go

Deletes .riv/ and the compile_commands.json symlink. Use when CMake cache feels stale.

riv fmt
--check

Format all C++ files with clang-format.

bash
riv fmt              # format in place
riv fmt --check      # CI mode: fail if not formatted

Walks src/, lib/, include/. We ship a default .clang-format (Google, 4 spaces, 100 cols) at riv init. Customize it — we respect yours.

Needs clang-format in PATH. Hint: sudo apt install clang-format.

riv check

Lint without building — validates layout + runs clang-tidy if available.

bash
riv check

Always validates src/main.cpp, lib layout, no .cpp in include/, no symlinks, riv.toml fields. If .riv/build/compile_commands.json exists and clang-tidy is installed, it also lints — otherwise it tells you to run riv build first. Perfect pre-commit.

riv info
--json

Debug helper — see what Rivets discovered.

bash
riv info
riv info --json | jq

Prints project name / version / standard, main entry, every lib with its source count, include dirs and external deps. Use when “it builds on my machine” and you want to see what scan found vs what you expected.

Dependencies — add / remove / list / search

Curated, offline-friendlyRegistry. Dependencies are vendored into external/ and locked in riv.lock with SHA256.

bash
riv search                # list all packages
riv search stb           # filter
riv add stb_image        # -> external/stb_image/ + riv.toml + riv.lock
riv list                 # show what's installed
riv remove stb_image
How it works
  • Finds registry.toml (repo or project root).
  • Clones to ~/.cache/riv/repos/<pkg>, checks out commit.
  • Copies listed include files to external/<pkg>.
  • Writes riv.lock with SHA256 checksums.
Beginner tip
  • We auto-add ../external to your CMake includes — just #include "stb_image.h".
  • riv search without a query lists everything — great to browse.
  • Deps are data, not code execution — no build-script surprises (philosophy).
Registry today: stb_image 2.28 (header-only) from nothings/stb. We keep it tiny on purpose; expansion is roadmapped but deferred while core stabilizes.

riv test

Runs CTest if your build registered tests.

bash
riv test
riv test --verbose
ctest --test-dir .riv/build --output-on-failure   # same thing manually

Needs a build that calls enable_testing() / add_test(). If no tests are registered, we print a helpful hint instead of failing. Perfect for the upcoming “Test runner integration” milestone.

Shell Completion

Autocomplete for bash / zsh / fish / PowerShell — powered by Cobra.

bash
# Bash (add to ~/.bashrc)
source <(riv completion bash)

# Zsh
riv completion zsh > "${fpath[1]}/_riv"

# Fish
riv completion fish | source

# PowerShell
riv completion powershell | Out-String | Invoke-Expression

Guides

Adding a Local Library (the Rivets way)

bash
# 1. Create the folders
mkdir -p lib/net/include/net lib/net/src

# 2. Add header + source
# lib/net/include/net/net.h
# lib/net/src/net.cpp

# 3. Just build — it auto-links
riv build
# CMake got: add_library(net ../lib/net/src/net.cpp)
#            target_include_directories(net PUBLIC ../lib/net/include)
#            target_link_libraries(myapp PRIVATE net)

No riv.toml edits needed. Delete the folder to remove it.

Header-only vs Compiled — which folder?

Header-only → include/

Single .h/.hpp files, no .cpp. Example: include/utils/utils.h with inline funcs. Auto on include path.

Compiled → lib/<name>

include/<name>/ headers + src/ sources → builds a static lib and links to your exe.

Formatting & Linting

Format: riv fmt uses your .clang-format if present, else our default (Google, 100 cols). Add riv fmt --check to CI.
Lint: riv check validates layout always; with compile_commands.json + clang-tidy it lints deeply.

Watch Mode

Want instant feedback while tweaking?

bash
riv run --watch
# edit src/main.cpp → save → auto rebuild + rerun
# Ctrl+C to exit

IDE Setup — VS Code & CLion

VS Code

Install C/C++ (Microsoft) extension.
We symlink .riv/build/compile_commands.json./compile_commands.json — IntelliSense just works after riv build.

CLion

Open the project folder → CLion imports the generated .riv/CMakeLists.txt automatically.
Mark .riv/ as excluded if you like.

Troubleshooting

missing entry point: src/main.cpp
You deleted or renamed src/main.cpp — restore it or run riv init in a fresh dir.
riv.toml: unsupported standard
Use standard = "c++17" / "c++20" / "c++23" (quotes matter, TOML).
found .cpp file in include directory
Move that .cpp to lib/<name>/src/. include/ is header-only by design.
binary not found at .riv/build/...
Run riv build first. If it still fails, check the build log above — likely a compiler error.
clang-format not found
sudo apt install clang-format | brew install clang-format
symlink not allowed
Copy the file instead of symlinking — Rivets blocks symlinks for security.

Philosophy & Roadmap

Security first

Deps are vendored data, not code execution. No build-script surprises.

No lock-in

Generated CMake is standard. Outgrow us? Copy .riv/CMakeLists.txt and go.

Fail loudly

Invalid layout → precise message + Hint. No silent breakage.

Roadmap

✓ init / build / run
✓ doctor / clean / fmt / check / info
✓ add/remove/list/search (curated)
○ Native Windows
○ macOS native
○ Test runner (ctest wired, deeper later)
⏸ Dependency mgmt expansion — deferred
We keep the registry tiny today on purpose while core stabilizes. Follow GitHub for releases.
Built for the next C++ beginner. If Rivets saved you 30 minutes, leave a ⭐ on GitHub.