Skip to content

Getting started

This page walks through installing the CLI, scaffolding a project, writing your first node, and adopting the tool on an existing codebase.

Install

SpexCode runs on Node 22. Install the CLI, which provides the spex command:

npm install -g spexcode

spex init

Run init inside an existing git repository. It needs a git work tree and will not create one for you — if the directory is not a repo, it stops and points you at git init before writing anything.

spex init

init is additive and never overwrites existing files. It scaffolds three things:

  • a starter .spec/ tree with a root node;
  • the git hooks (a pre-commit check and a commit-message stamp), copied into the repository's hooks directory;
  • a spexcode.json at the repository root. Its lint.governedRoots ships pointing at src — set it to your project's source directories, or spex lint will report it is governing nothing.

Your first spec node

A node is a directory under .spec/ containing a spec.md. The directory name is the node id; nesting one directory inside another makes it a child.

Create one for a piece of code you want governed:

mkdir -p .spec/project/auth

Then write .spec/project/auth/spec.md:

---
title: auth
desc: How a session token is issued and checked.
code:
  - src/auth/session.ts
  - src/auth/verify.ts
---
# auth

Tokens are issued on login and expire after 24 hours. Verification
rejects an expired or malformed token before any handler runs.
Refresh is explicit; there is no silent renewal.

The body states present intent, not a changelog — you rewrite it in place as the intent changes, and version history comes from git. The code: list is the edge the linter checks.

Run the linter

spex lint

Two checks are errors and block: every path in a code: list must exist, and a body must not carry a ## vN changelog heading. The rest are advisory warnings — coverage (a tracked source file no node claims), drift (a governed file changed after its spec's last version), and a few size and ownership signals. Coverage and drift stay warnings so a partially adopted repository still passes on its errors.

Every project-shaped value — governed roots, file extensions, budgets, limits — is read from spexcode.json under the lint key, so you tune it to your layout rather than forking the tool.

Adopting an existing codebase

You do not need to restructure anything. Add nodes for the parts you want governed, each with a code: list pointing at existing files, and use the coverage warnings as your worklist: each one names a tracked source file no node claims yet. Work the list down until the graph is complete.

Because the git hooks are per-clone and bypassable, treat them as fast local feedback and make CI the real gate: run spex lint on every push and pull request, and give CI the full git history, since the version timeline and drift are derived from it.

If your layout differs from the default — main at the repository root, worktrees under .worktrees/, node/<id> branches — describe your structure in spexcode.json rather than changing the repository. An explicit mainBranch is respected; otherwise the source-of-truth branch is detected from the main checkout, falling back to main.