# Command Reference
## Global Flags
These flags can be used with any command:
| `--verbose`, `-v` | Show skip/restore/cache messages during build |
| `--output-display`, `-O` | What to show for output files (`none`, `basename`, `path`; default: `none`) |
| `--input-display`, `-I` | What to show for input files (`none`, `source`, `all`; default: `source`) |
| `--path-format`, `-P` | Path format for displayed files (`basename`, `path`; default: `path`) |
| `--show-child-processes` | Print each child process command before execution |
| `--show-output` | Show tool output even on success (default: only show on failure) |
| `--json` | Output in JSON Lines format (machine-readable) |
| `--quiet`, `-q` | Suppress all output except errors (useful for CI) |
| `--phases` | Show build phase messages (discover, add_dependencies, etc.) |
Example:
```bash
rsconstruct --phases build # Show phase messages during build
rsconstruct --show-child-processes build # Show each command being executed
rsconstruct --show-output build # Show compiler/linter output even on success
rsconstruct --phases --show-child-processes build # Show both phases and commands
rsconstruct -O path build # Show output file paths in build messages
rsconstruct -I all build # Show all input files (including headers)
```
## `rsconstruct build`
**Requires config.** (no subcommands)
Incremental build — only rebuilds products whose inputs have changed.
```bash
rsconstruct build # Incremental build
rsconstruct build --force # Force full rebuild
rsconstruct build -j4 # Build with 4 parallel jobs
rsconstruct build --dry-run # Show what would be built without executing (honors -p/-x/-t)
rsconstruct build --keep-going # Continue after errors
rsconstruct build --timings # Show per-product and total timing info
rsconstruct build --stop-after discover # Stop after product discovery
rsconstruct build --stop-after add-dependencies # Stop after dependency scanning
rsconstruct build --stop-after resolve # Stop after graph resolution
rsconstruct build --stop-after classify # Stop after classifying products
rsconstruct build --show-output # Show compiler/linter output even on success
rsconstruct build --auto-add-words # Add misspelled words to .zspell-words instead of failing
rsconstruct build --auto-add-words -p processor.checker.zspell # Run only zspell and auto-add words
rsconstruct build -p processor.checker.ruff,processor.checker.pylint # Run only specific processors
rsconstruct build --explain # Show why each product is skipped/restored/rebuilt
rsconstruct build --retry 3 # Retry failed products up to 3 times
rsconstruct build --no-mtime # Disable mtime pre-check, always compute checksums
rsconstruct build --no-summary # Suppress the build summary
rsconstruct build --batch-size 10 # Limit batch size for batch-capable processors
rsconstruct build --verify-tool-versions # Verify tool versions against .tools.versions
rsconstruct build -t "src/*.c" # Only build products matching this glob pattern
rsconstruct build -d src # Only build products under this directory
rsconstruct build --show-all-config-changes # Show all config changes, not just output-affecting
```
By default, tool output (compiler messages, linter output) is only shown when a command fails. Use `--show-output` to see all output.
### Selecting processors (`-p`, `-x`)
`-p` runs the named processors **and the processors that generate their
inputs**, transitively — selecting a checker of generated files also runs
the generator, so the checker has something to check even on a clean
checkout. (`-t`/`-d` do the same for the products they select.)
`-x` excludes a processor, and with it every product that needs its
outputs: those could only run against files nobody is producing. An
excluded processor is never pulled back in, even when a `-p` selection
depends on it.
### Incremental recovery and batch behavior
By default (fail-fast mode), rsconstruct executes each product independently, even for batch-capable processors. Successfully completed products are cached immediately, so if a build fails or is interrupted, the next run only rebuilds what wasn't completed.
With `--keep-going`, batch-capable processors group all their products into a single tool invocation. If the tool fails, all products in the batch are marked failed and must be rebuilt. Use `--batch-size N` to limit batch chunks and improve recovery granularity.
### Processor Shortcuts (`@` aliases)
The `-p` flag supports `@`-prefixed shortcuts that expand to groups of processors:
**By type:**
- `@checker` — all checker processors (ruff, pylint, shellcheck, etc.)
- `@generator` — all generator processors (tera, cc_single_file, etc.)
- `@creator` — all creator processors (pip, npm, cargo, etc.)
- `@explicit` — all explicit processors
- `@mass_generator` — all mass generator processors
- `@lua` — all Lua plugin processors
**By tool or name** — any other `@x` selects both of these:
- every processor that requires tool `x` (`@python3`, `@node`; matched
against each processor's `required_tools()`)
- every processor whose short name is `x`, with all its instances
(`@tera` → `processor.generator.tera` and e.g.
`processor.generator.tera.docs`; `@generic` → the generic processor of
every type)
An `@x` that selects nothing is reported as an unknown processor.
Examples:
```bash
rsconstruct build -p @checker # Run only checker processors
rsconstruct build -p @generator # Run only generator processors
rsconstruct build -p @python3 # Run all Python-based processors
rsconstruct build -p @checker,tera # Mix shortcuts with processor names
```
The `--stop-after` flag allows stopping the build at a specific phase:
- `discover` — stop after discovering products (before dependency scanning)
- `add-dependencies` — stop after adding dependencies (before resolving graph)
- `resolve` — stop after resolving the dependency graph (before execution)
- `classify` — stop after classifying products (show skip/restore/build counts)
- `build` — run the full build (default)
## `rsconstruct clean`
Clean build artifacts. When run without a subcommand, removes build output files (same as `rsconstruct clean outputs`).
| `outputs` | Yes |
| `all` | Yes |
| `git` | Yes |
| `unknown` | Yes |
```bash
rsconstruct clean # Remove build output files (preserves cache) [default]
rsconstruct clean outputs # Remove build output files (preserves cache)
rsconstruct clean outputs -p processor.generator.tera,processor.generator.tags # Only clean outputs from named processors
rsconstruct clean outputs --no-empty-dirs # Skip the empty-directory sweep
rsconstruct clean all # Remove out/ and .rsconstruct/ directories
rsconstruct clean git # Hard clean using git clean -qffxd (requires git repository)
rsconstruct clean unknown # Remove files not tracked by git and not known as build outputs
rsconstruct clean unknown --dry-run # Show what would be removed without deleting
rsconstruct clean unknown --no-gitignore # Include gitignored files as unknown
```
### `rsconstruct clean outputs`
Removes build output files. The cache (`.rsconstruct/`) is preserved.
What gets removed depends on each product's processor type:
- **Checkers** (ruff, cppcheck, shellcheck, terms, …) — produce no outputs, so nothing to delete.
- **Generators** (tera, tags, mako, jinja2, mermaid, pdflatex, pdfunite, …) — declare concrete output files. Each declared output file is removed individually with `fs::remove_file`. **Directories are never recursed into.**
- **Creators** (mdbook, sphinx, jekyll, cargo, npm, gem, cc, …) — invoke an external build that produces an unknown set of files inside a declared output directory (e.g. `book/`, `_site/`, `target/`). The whole declared `output_dir` is removed recursively. This is the only path that recursively deletes a directory, and it only ever affects directories the creator itself declared.
- **Explicit** — declares both `output_files` and `output_dirs` directly in `rsconstruct.toml`. Files are removed individually; declared `output_dirs` are removed recursively (because the user asked for that).
- **Mass generators** — every file the tool's plan predicted is a declared output and is removed individually. The `output_dirs` a mass generator declares only bound where predicted files may live and are never removed.
- **Lua plugins** — call the plugin's own `clean()` function if defined; otherwise fall back to file-only removal.
#### Empty-directory sweep
After every product's `clean()` has run, `clean outputs` walks every directory that previously contained an output file (and the parents of every removed `output_dir`), bottom-up, and removes any that are now empty. The sweep:
- Tries `fs::remove_dir` (non-recursive) — only succeeds when the directory is empty.
- Walks upward through parents until it hits a non-empty directory or the project root.
- Never removes a directory that still contains files — empty dirs only.
- Does not special-case `out/`. Any path ancestor of a cleaned output is eligible.
Pass `--no-empty-dirs` to skip the sweep entirely. Files still get cleaned; empty parent directories are left in place.
#### Filtering by processor
`-p` / `--processor` accepts a comma-separated list of processor instance names (inames), e.g. `-p processor.generator.tera,processor.creator.cargo`. Only products of exactly those instances are cleaned: a named instance is its own iname, so cleaning both `[processor.generator.marp.slides]` and `[processor.generator.marp.docs]` takes `-p processor.generator.marp.slides,processor.generator.marp.docs`.
#### Other clean variants
- `clean all` — removes `out/` and `.rsconstruct/` outright (cache included). Use when you want a full reset.
- `clean git` — runs `git clean -qffxd`. Requires a git repository.
- `clean unknown` — finds files in the working tree that are neither git-tracked nor declared as a build output. Defaults to dry-run unless you pass without `--dry-run`. `--no-gitignore` includes gitignored files in the search.
## `rsconstruct status`
**Requires config.** (no subcommands)
Show product status — whether each product is up-to-date, stale, or restorable from cache.
```bash
rsconstruct status # Show per-processor and total summary
rsconstruct status -v # Show per-product status
rsconstruct status --breakdown # Show source file counts by processor and extension
rsconstruct --json status # Same summary as JSON
```
The per-processor table (and each entry of `--json`'s `processor` array) carries
two flags after the counts: `native`, whether the processor is pure Rust inside
rsconstruct, and `rust`, whether the code that does the work is written in Rust at
all — always so for a native processor, and for an external one only when the tool
it runs is (ruff, taplo, rumdl, clippy, cargo, mdbook, pyrefly, rustc). Processors
that run a user-supplied command (`script`, `explicit`, `generator`, `creator`,
`mass_generator`) report `rust: false`, since the language is unknown.
## `rsconstruct smart auto`
Auto-detect relevant processors and add them to `rsconstruct.toml`. Scans the project for files matching each processor's conventions and checks that the required tools are installed. Only adds new sections — existing processor sections are preserved. **Requires config.**
```bash
rsconstruct smart auto
```
Example output:
```
Added 3 processor(s): pylint, ruff, shellcheck
```
## `rsconstruct init`
**No config needed.** (no subcommands)
Initialize a new rsconstruct project in the current directory.
```bash
rsconstruct init
```
## `rsconstruct watch`
**Requires config.** (no subcommands)
Watch source files and auto-rebuild on changes.
```bash
rsconstruct watch # Watch and rebuild on changes
rsconstruct watch --auto-add-words # Watch with zspell auto-add words
rsconstruct watch -j4 # Watch with 4 parallel jobs
rsconstruct watch -p processor.checker.ruff # Watch and only run the ruff processor
```
The watch command accepts the same build flags as `rsconstruct build` (e.g., `--jobs`, `--keep-going`, `--timings`, `--processor`, `--batch-size`, `--explain`, `--retry`, `--no-mtime`, `--no-summary`).
## `rsconstruct graph`
Display the build dependency graph.
| `show` | Yes |
| `view` | Yes |
| `stats` | Yes |
```bash
rsconstruct graph show # Default SVG format
rsconstruct graph show --format dot # Graphviz DOT format
rsconstruct graph show --format mermaid # Mermaid format
rsconstruct graph show --format json # JSON format
rsconstruct graph show --format text # Plain text hierarchical view
rsconstruct graph show --format svg # SVG format (requires Graphviz dot)
rsconstruct graph view # Open as SVG (default viewer)
rsconstruct graph view --viewer mermaid # Open as HTML with Mermaid in browser
rsconstruct graph view --viewer svg # Generate and open SVG using Graphviz dot
rsconstruct graph stats # Show graph statistics (products, processors, dependencies)
```
## `rsconstruct cache`
Manage the build cache.
| `clear` | No |
| `size` | Yes |
| `trim` | Yes |
| `list` | Yes |
| `stale` | Yes |
| `stats` | Yes |
| `remove-stale` | Yes |
```bash
rsconstruct cache clear # Clear the entire cache
rsconstruct cache size # Show cache size
rsconstruct cache trim # Remove unreferenced objects
rsconstruct cache list # List all cache entries and their status
rsconstruct cache stale # Show which cache entries are stale vs current
rsconstruct cache stats # Show per-processor cache statistics
rsconstruct cache remove-stale # Remove stale index entries not matching any current product
```
## `rsconstruct webcache`
Manage the web request cache. Schemas fetched by `iyamlschema` (and any future processors that fetch URLs) are cached in `.rsconstruct/webcache.redb`.
| `clear` | No |
| `stats` | No |
| `list` | No |
```bash
rsconstruct webcache clear # Clear all cached web responses
rsconstruct webcache stats # Show cache size and entry count
rsconstruct webcache list # List all cached URLs and their sizes
```
## `rsconstruct analyzer`
Manage dependency analyzers and inspect the dependency cache they fill. An analyzer scans source files for dependencies (C/C++ `#include`s, Python imports, Sass `@use`s, Markdown and Tera references) and records them in `.rsconstruct/deps.redb`; see [Dependency Analyzers](analyzers.md). Analyzers are referred to by pname (the type: `cpp`, `icpp`, `markdown`, `python`, `sass`, `tera`) or by iname (the instance as declared in `rsconstruct.toml`, e.g. `cpp` or `cpp.kernel`).
| `add` | Yes (`--dry-run`: no) |
| `build` | Yes |
| `clean` | Yes |
| `config` | Yes |
| `defconfig` | No |
| `delete` | Yes |
| `disable` | Yes |
| `enable` | Yes |
| `list` | No |
| `show` | Yes |
| `stats` | Yes |
| `used` | Yes |
```bash
rsconstruct analyzer list # List all available analyzers
rsconstruct analyzer used # Show which analyzers are enabled and detected
rsconstruct analyzer defconfig cpp # Show the default configuration of an analyzer type
rsconstruct analyzer config # Show the resolved configuration of every declared analyzer
rsconstruct analyzer config cpp # ...of one analyzer instance
rsconstruct analyzer add cpp # Append [analyzer.cpp] to rsconstruct.toml with comments
rsconstruct analyzer add cpp --dry-run # Print the snippet instead of writing it
rsconstruct analyzer enable cpp # Set enabled = true on the stanza
rsconstruct analyzer disable cpp # Set enabled = false on the stanza
rsconstruct analyzer delete cpp # Remove the stanza entirely
rsconstruct analyzer build # Run dependency analysis without building
rsconstruct analyzer show all # Show all cached dependencies
rsconstruct analyzer show files src/main.c # Show dependencies for a specific file
rsconstruct analyzer show files src/a.c src/b.c # ...for several files
rsconstruct analyzer show files --hash-pieces src/main.c # Also show each analyzer's hash pieces
rsconstruct analyzer show analyzers cpp # Show dependencies found by the C/C++ analyzer
rsconstruct analyzer show analyzers cpp python # ...by several analyzers
rsconstruct analyzer stats # Show statistics by analyzer
rsconstruct analyzer clean # Clear the entire dependency cache
rsconstruct analyzer clean --analyzer cpp # Clear only entries from the cpp analyzer
```
Example output for `rsconstruct analyzer show all`:
```
src/main.c: [icpp] (no dependencies)
src/test.c: [icpp]
src/utils.h
src/config.h
```
Example output for `rsconstruct analyzer stats`:
```
╭──────────┬───────┬──────────────╮
│ Analyzer │ Files │ Dependencies │
├──────────┼───────┼──────────────┤
│ icpp │ 2 │ 2 │
├──────────┼───────┼──────────────┤
│ Total │ 2 │ 2 │
╰──────────┴───────┴──────────────╯
```
`show`, `stats` and `clean` read the dependency cache directly. If it is empty, run `rsconstruct analyzer build` (or a build) first to populate it.
These commands are useful for:
- Debugging why a file is being rebuilt
- Understanding the include/import structure of your project
- Verifying that dependency analyzers are finding the right files
- Clearing dependencies for a specific analyzer without affecting others
## `rsconstruct smart`
Smart config manipulation commands for managing processor sections in `rsconstruct.toml`.
| `disable-all` | No |
| `enable-all` | No |
| `enable` | No |
| `disable` | No |
| `only` | No |
| `reset` | No |
| `enable-detected` | Yes |
| `enable-if-available` | Yes |
| `minimal` | Yes |
| `auto` | Yes |
| `remove-no-file-processors` | Yes |
```bash
rsconstruct smart enable pylint # Add [processor.checker.pylint] section
rsconstruct smart disable pylint # Remove [processor.checker.pylint] section
rsconstruct smart enable-all # Add sections for all builtin processors
rsconstruct smart disable-all # Remove all processor sections
rsconstruct smart enable-detected # Add sections for auto-detected processors
rsconstruct smart enable-if-available # Add sections for detected processors with tools installed
rsconstruct smart minimal # Remove all, then add only detected processors
rsconstruct smart only ruff pylint # Remove all, then add only listed processors
rsconstruct smart reset # Remove all processor sections
rsconstruct smart remove-no-file-processors # Remove processors that don't match any files (skips enabled = false)
```
## `rsconstruct processor`
| `add` | Yes (`--dry-run`: no) |
| `allowlist` | Yes |
| `config` | Yes |
| `defconfig` | No |
| `delete` | Yes |
| `disable` | Yes |
| `enable` | Yes |
| `files` | Yes |
| `graph` | Yes |
| `info` | No |
| `list` | No |
| `names` | Yes |
| `recommend` | No |
| `search` | No |
| `types` | No |
| `used` | Yes |
```bash
rsconstruct processor list # List all built-in processors with type and description
rsconstruct processor list --type checker # ...only one processor type
rsconstruct --json processor list # Same list as JSON
rsconstruct processor info processor.checker.ruff # Describe a processor and every config field
rsconstruct processor info # ...every processor
rsconstruct --json processor info # Same as JSON
rsconstruct processor types # List the processor types
rsconstruct processor search yaml # Search processors by name, description or keywords
rsconstruct processor recommend # Show the recommended processor for each file extension
rsconstruct processor used # Show which processors are enabled and detected
rsconstruct processor names # Print the iname of every enabled processor, one per line
rsconstruct processor files # Show source and target files for each declared processor
rsconstruct processor files processor.checker.ruff # Show files for a specific processor
rsconstruct processor config processor.checker.ruff # Show resolved configuration for a processor
rsconstruct processor config --diff # Show only fields that differ from defaults
rsconstruct processor defconfig processor.checker.ruff # Show default configuration for a processor
rsconstruct processor add processor.checker.ruff # Append [processor.checker.ruff] to rsconstruct.toml (fields pre-populated + comments)
rsconstruct processor add processor.checker.ruff --dry-run # Preview the snippet without writing
rsconstruct processor enable processor.checker.ruff # Set enabled = true on the stanza
rsconstruct processor disable processor.checker.ruff # Set enabled = false on the stanza
rsconstruct processor delete processor.checker.ruff # Remove the stanza entirely
rsconstruct processor allowlist # Show the current processor allowlist
rsconstruct processor graph # Show inter-processor dependencies
rsconstruct processor graph --format dot # Graphviz DOT format
rsconstruct processor graph --format mermaid # Mermaid format
rsconstruct processor files --headers # Show files with processor headers
```
`list` prints one row per processor with its type and three flags: `Native`
(pure Rust inside rsconstruct, or `external` when it runs another program),
`Rust` (whether the code that does the work is written in Rust — every native
processor, plus external ones whose tool is Rust: ruff, taplo, rumdl, clippy,
cargo, mdbook, pyrefly, rustc) and `Fix` (has a built-in fixer for
`rsconstruct fix`; currently `false` for every processor, see
[`rsconstruct fix`](#rsconstruct-fix)). The JSON
form carries the same as `native`, `rust` and `fix` booleans. `rust` is what to
read when the question is "how much of this project's toolchain is Rust";
`native` is what to read when the question is "which processors need no tool
installed".
`info` is the long form of one processor (or, without a name, of every
processor): its description, type, keywords, the same flags as `list` plus
batch support, the `max_jobs` cap and the implementation version, then a table
of every config field it accepts — type, default, whether it is required,
whether it is part of the cache key (`Checksum`), and what it does. It is
`defconfig -v` with the processor's own description on top, and reads only
the processors' built-in metadata, so it needs no `rsconstruct.toml`.
## `rsconstruct tool`
List or check external tools required by declared processors. All subcommands use config if available; without config, they operate on all built-in processors.
| `list` | Uses config if available |
| `check` | Uses config if available |
| `lock` | Uses config if available |
| `install` | Uses config if available |
| `install-deps` | Uses config if available |
| `stats` | Uses config if available |
| `graph` | Uses config if available |
```bash
rsconstruct tool list # List all tools known to rsconstruct (from the central registry)
rsconstruct tool list -M # ...with every install method for each tool
rsconstruct tool list-configured # List tools this project's processors require, and which needs them
rsconstruct tool list-configured -a # Include tools from disabled processors
rsconstruct tool check # Verify tool versions against .tools.versions lock file
rsconstruct tool lock # Lock tool versions to .tools.versions
rsconstruct tool install # Install missing external tools for enabled processors
rsconstruct tool install ruff # Install a specific tool by name
rsconstruct tool install --all # Install every tool in the registry, ignoring the config (no config needed)
rsconstruct tool install -i # Ask for confirmation first (default: install without asking)
rsconstruct tool install --no-eatmydata # Don't wrap apt/dnf/pacman with eatmydata
rsconstruct tool install-deps # Install declared [dependencies] (pip set from uv.lock, npm set from package-lock.json by default) in fixed order: system → pip → npm → gem → cargo
rsconstruct tool install-deps -i # Ask for confirmation first (default: install without asking)
rsconstruct tool install-deps --no-eatmydata # Don't wrap apt/dnf/pacman with eatmydata
rsconstruct tool stats # Show tool availability and language runtime breakdown
rsconstruct tool stats --json # Show tool stats in JSON format
rsconstruct tool graph # Show tool-to-processor dependency graph (DOT format)
rsconstruct tool graph --format mermaid # Mermaid format
rsconstruct tool graph --view # Open tool graph in browser
```
`install --all` walks the central registry instead of the project config, so it
needs no `rsconstruct.toml`. It never skips: a tool with no automatable install
method is a hard error, not a warning. This makes it the intended way to
provision CI — one command covers the whole matrix, and a registry entry that
loses its install method fails the provisioning step instead of quietly
shrinking the matrix. `--all` cannot be combined with a tool name.
### Ruby gems without a writable gem dir
Only system package managers (apt/dnf/pacman/snap) are sudo-wrapped; `pip`,
`npm`, `cargo`, and `gem` run unprivileged. With a distro ruby, that would
make `gem install` die on the root-owned system gem dir (`/var/lib/gems` on
Debian/Ubuntu), so when the default gem dir isn't writable, gem installs get
`--user-install` appended automatically. To make the resulting executables
resolvable, every rsconstruct invocation appends the user gem bin dirs that
exist (`$GEM_HOME/bin`, `~/.gem/ruby/*/bin`, `~/.local/share/gem/ruby/*/bin`)
to its own `PATH` at startup — tool probes and spawned processors see them
without any workflow- or shell-level `GEM_HOME`/`PATH` setup.
### Node.js packages from the project's `node_modules`
The same startup step prepends the project's `node_modules/.bin`, when it
exists, so the packages `install-deps` put there from `package.json` (with
`npm ci`, see `[dependencies]` in the configuration reference) resolve ahead
of any global copy. `tool install` therefore finds a locked tool already
installed and does not add a global one on top.
## `rsconstruct tag`
Search and query frontmatter tags from markdown files.
| `list` | Yes |
| `count` | Yes |
| `tree` | Yes |
| `stats` | Yes |
| `files` | Yes |
| `grep` | Yes |
| `for-file` | Yes |
| `frontmatter` | Yes |
| `unused` | Yes |
| `validate` | Yes |
| `matrix` | Yes |
| `coverage` | Yes |
| `orphans` | Yes |
| `check` | Yes |
| `suggest` | Yes |
| `merge` | Yes |
| `collect` | Yes |
```bash
rsconstruct tag list # List all unique tags
rsconstruct tag count # Show each tag with file count, sorted by frequency
rsconstruct tag tree # Show tags grouped by prefix/category
rsconstruct tag stats # Show statistics about the tags database
rsconstruct tag files docker # List files matching a tag (AND semantics)
rsconstruct tag files docker --or k8s # List files matching any tag (OR semantics)
rsconstruct tag files level:advanced # Match key:value tags
rsconstruct tag grep deploy # Search for tags containing a substring
rsconstruct tag grep deploy -i # Case-insensitive tag search
rsconstruct tag for-file src/main.md # List all tags for a specific file
rsconstruct tag frontmatter src/main.md # Show raw frontmatter for a file
rsconstruct tag validate # Validate tags against tags_dir allowlist
rsconstruct tag unused # List tags in tags_dir not used by any file
rsconstruct tag unused --strict # Exit with error if unused tags found (CI)
rsconstruct tag check # Run all tag validations without building
rsconstruct tag suggest src/main.md # Suggest tags for a file based on similarity
rsconstruct tag coverage # Show percentage of files with each tag category
rsconstruct tag matrix # Show coverage matrix of tag categories per file
rsconstruct tag orphans # Find markdown files with no tags
rsconstruct tag merge ../other/tags # Merge tags from another project
rsconstruct tag collect # Add missing tags from source files to tag collection
```
## `rsconstruct complete`
Generate shell completions. No config needed when shell is specified as argument; uses config to read default shells if no argument given.
```bash
rsconstruct complete bash # Generate bash completions
rsconstruct complete zsh # Generate zsh completions
rsconstruct complete fish # Generate fish completions
```
## `rsconstruct term`
Manage term checking and fixing in markdown files.
| `fix` | Yes |
| `merge` | Yes |
| `stats` | Yes |
### `rsconstruct term fix`
Add backticks around terms from the terms directory that appear unquoted in markdown files.
```bash
rsconstruct term fix
rsconstruct term fix --remove-non-terms # also remove backticks from non-terms
```
### `rsconstruct term merge`
Merge terms from another project's terms directory. Unions matching files and copies missing files in both directions.
```bash
rsconstruct term merge ../other-project/terms
```
## `rsconstruct doctor`
**Requires config.** (no subcommands)
Diagnose build environment — checks config, tools, versions, and declared
`[dependencies]` (Python deps declared in `pyproject.toml` are checked too;
see the `[dependencies]` section in Configuration). Tools are probed by
running them; `system` dependencies are
packages, not tools, so they are probed through the platform's package manager
(dpkg-query/rpm/pacman/brew) — a binary-less package like `aspell-en` counts
as installed even though no binary carries its name.
```bash
rsconstruct doctor
```
## `rsconstruct info`
Show project information.
| `source` | Yes |
```bash
rsconstruct info source # Show source file counts by extension
```
## `rsconstruct page`
Query GitHub Pages publishing settings from the [`[pages]`](configuration.md#pages) config section.
| `dir` | Yes |
```bash
rsconstruct page dir # Print the published directory ([pages].dir)
rsconstruct --json page dir # {"configured": true, "dir": "out/web"}
```
`page dir` prints nothing and still exits 0 when `[pages]` is not configured — CI branches on the output being empty, not on exit codes. See [GitHub Actions](github-actions.md#github-pages-deployment) for the workflow pattern this enables.
## `rsconstruct sloc`
**No config needed.** (no subcommands)
Count source lines of code (SLOC) by language, with optional COCOMO effort/cost estimation.
```bash
rsconstruct sloc # Show SLOC by language
rsconstruct sloc --cocomo # Include COCOMO effort/cost estimation
rsconstruct sloc --cocomo --salary 80000 # Custom annual salary for COCOMO
```
## `rsconstruct toml`
```bash
rsconstruct toml check # validate rsconstruct.toml (unknown fields, types, required fields)
rsconstruct toml files # list every config file rsconstruct may read and whether it exists
```
`toml files` needs no config. It prints the merge chain lowest precedence
first — the user config (`$XDG_CONFIG_HOME/rsconstruct/config.toml`, see
[User config](configuration.md#user-config-configrsconstructconfigtoml)),
`rsconstruct.toml` and `rsconstruct.local.toml` — followed by the other
project files rsconstruct reads (`.rsconstructignore`, `.tools.versions`),
each with its resolved path and whether it is present. Use it to find out
which file a setting is coming from, or where the user config lives on a
given machine. With `--json` the same list is emitted as an array of
`{precedence, role, path, exists, note}` objects.
## `rsconstruct error`
**No config needed.** (no subcommands)
List every exit code rsconstruct can return and its name. Errors are printed as `Error [EXIT_...]: ...`, so the name in a message maps back to the code here.
```bash
rsconstruct error
```
| 0 | `EXIT_SUCCESS` |
| 1 | `EXIT_BUILD_ERROR` |
| 2 | `EXIT_CONFIG_ERROR` |
| 3 | `EXIT_TOOL_ERROR` |
| 4 | `EXIT_GRAPH_ERROR` |
| 5 | `EXIT_IO_ERROR` |
| 130 | `EXIT_INTERRUPTED` |
## `rsconstruct fix`
Run fixers (auto-format, auto-fix) on source files, modifying them in place.
| `list` | Yes |
| `run` | Yes |
```bash
rsconstruct fix list # List the fix-capable processors declared in this project
rsconstruct fix run processor.checker.script.format # Run one fixer (by full iname)
rsconstruct fix run processor.checker.script.a,processor.checker.script.b # Run several, comma-separated
```
`fix run` requires at least one processor name. Today the only fix-capable processors are [`script`](processor/checker/script.md) instances that set `fix_command` (and optionally `fix_args`); no built-in processor declares a fixer, so the `Fix` column of `rsconstruct processor list` is `false` for all of them.
## `rsconstruct function`
**No config needed.**
Inspect the built-in functions rsconstruct exposes to Tera templates (`load_python`, `load_lua`, `load_toml`, `toml_get`, ...).
| `list` | No |
```bash
rsconstruct function list # Signature, return value, dependency tracking and an example for each function
```
Example entry:
```
load_toml(path: string)
Parse a TOML file and expose its top-level table to the template.
returns: object (key → value, nested tables preserved)
dep tracking: The file at `path` is added as an input (content-tracked).
example: {% set cfg = load_toml(path="pyproject.toml") %}{{ cfg.project.version }}
```
## `rsconstruct hook`
**No config needed.** (no subcommands)
List the post-config hooks: built-in adjustments applied to the configuration after it is loaded, such as defaults that change when running under CI (`CI=true`).
```bash
rsconstruct hook
```
```
╭──────────────────────┬─────────────────────────────────────────────────────────────────────╮
│ Hook │ Description │
├──────────────────────┼─────────────────────────────────────────────────────────────────────┤
│ eatmydata_ci_default │ When CI=true, enable eatmydata wrapping for apt/dnf/pacman installs │
│ marp_ci_cap │ When CI=true and marp.max_jobs is unset, cap it at 2 │
╰──────────────────────┴─────────────────────────────────────────────────────────────────────╯
```
## `rsconstruct product`
**Requires config.**
Inspect a single product in the build graph: everything that goes into its cache key and whether it would be rebuilt. Use it to answer "why is this file rebuilding?".
| `show` | Yes |
```bash
rsconstruct product show out/processor.generator.cc_single_file/src/main.elf # By output path
rsconstruct product show src/main.c # By primary input
```
The path is looked up as an output first; if no product owns it, products that have it as their primary input are shown. Example output:
```
processor: processor.generator.cc_single_file
outputs:
out/processor.generator.cc_single_file/src/test.elf
inputs:
primary src/test.c
analyzer [icpp]
src/utils.h
src/config.h
cache_key: 7b1eccc2...
config b884aa0c...
tool 2a4d5d7d...
hash_pieces: (none)
input_checksum: 71e9982e...
descriptor_key: 8c2a5920...
cache_state: BUILD (no cache entry)
```
## `rsconstruct symlink-install`
**Requires config.** (no subcommands)
Symlink every file under one or more source folders into target folders, recreating the directory structure. Configure the folder pairs in `rsconstruct.toml`; `sources[i]` is installed into `targets[i]`, so both arrays must have the same length. A leading `~/` in a target is expanded to `$HOME`.
```toml
[command.symlink_install]
sources = ["dotfiles", "bin"]
targets = ["~/", "~/.local/bin"]
```
```bash
rsconstruct symlink-install
```
```
dotfiles → /home/user/
created .bashrc
created .config/git/config
Symlink install: 2 created, 0 updated, 0 unchanged
```
Each link points to the absolute path of the source file. Running it again is safe: links that already point to the right file are left alone (`unchanged`), and links pointing elsewhere are replaced (`updated`). **A regular file at a target path is deleted and replaced by the link**, so make sure the target folders hold nothing you want to keep under the same names.
## `rsconstruct version`
**No config needed.** (no subcommands)
Print version information.
```bash
rsconstruct version
```