Compi
A build system written in Rust.
Features
- Clean TOML structure: Simple and declarative task definitions.
- Incremental Builds: Tracks file hashes and modification times to skip unnecessary work.
- Dependencies: Automatic DAG resolution for complex build chains.
- Parallel Execution: Concurrent execution of independent tasks.
Installation
From crates.io
From GitHub
cargo install --git https://github.com/allyedge/compi
From Source
git clone https://github.com/allyedge/compi cd compi cargo install --path .
From GitHub Releases
Download the latest binary for your platform from the GitHub Releases page.
Linux
wget https://github.com/allyedge/compi/releases/latest/download/compi-linux chmod +x compi-linux sudo mv compi-linux /usr/local/bin/compi
macOS
wget https://github.com/allyedge/compi/releases/latest/download/compi-macos chmod +x compi-macos sudo mv compi-macos /usr/local/bin/compi
Windows
Download the executable from the releases page and add it to your PATH.
CLI Usage
| Flag | Description |
|---|---|
-f, --file <FILE> |
Configuration file (default: compi.toml) |
-j, --workers <N> |
Number of parallel workers (default: CPU cores) |
-t, --timeout <DURATION> |
Default timeout (e.g., "30s", "5m") |
--output <MODE> |
Output mode: group (default) or stream |
--dry-run |
Preview execution order without running tasks |
--rm |
Remove output files after successful execution |
-v, --verbose |
Enable verbose logging |
compi
compi build
compi -j 8 build
compi -t 5m test
compi --rm buildConfiguration Reference
Create a compi.toml in your project root.
[config] default = "build" cache_dir = ".compi_cache" workers = 4 default_timeout = "10m" output = "group" [variables] TARGET = "target" SRC = "src/**/*.rs" FLAGS = "--release" [task.prepare] command = "mkdir -p ${TARGET}" outputs = ["${TARGET}/"] aliases = ["p"] [task.build] dependencies = ["prepare"] command = "cargo build ${FLAGS}" inputs = ["${SRC}", "Cargo.toml"] outputs = ["${TARGET}/app"] aliases = ["b"] [task.test] dependencies = ["build"] command = "cargo test" inputs = ["tests/**/*.rs"] always_run = true aliases = ["t"] [task.clean] command = "rm -rf ${TARGET}"
Reference
Task Fields
| Field | Type | Description |
|---|---|---|
command |
String | Required. Shell command to execute. |
dependencies |
[String] | List of task IDs that must complete first. |
inputs |
[String] | List of files/globs to track for changes. |
outputs |
[String] | List of files/globs this task produces. |
aliases |
[String] | Short names for CLI invocation (e.g. ["b"]). |
always_run |
Boolean | If true, ignore cache and always execute. |
auto_remove |
Boolean | If true, delete outputs after success (temp files). |
timeout |
String | Duration string (e.g. "30s") for this specific task. |
Caching & Execution Logic
Compi uses a local cache (compi_cache.json) to skip tasks that are up-to-date.
A task is SKIPPED if:
- All
outputsexist. - The
inputscontent hash matches the previous run. - The
inputsmodification times are older than theoutputs.
A task RUNS if:
- It has no
inputsdefined. always_runis set totrue.- Any output file is missing.
- Input files have changed (content hash mismatch).
- Input files are newer than output files.
Output Cleanup
--rmflag: Deletes files listed inoutputsafter the task succeeds.auto_remove = true: Acts like--rmis always passed for that specific task.