forgewatch
A single-binary, local-first CI runner. Define a pipeline in YAML, run it from your terminal, or watch it re-run on every save — with a live web dashboard that streams logs as they happen. No Docker, no cloud, no daemon fleet. One Rust binary, one SQLite file, zero external services.
Think of it as the CI you actually run on your machine: the same pipeline that runs in the cloud, but fast, offline, and observable — great for tightening the edit → build → test loop before you ever push.
┌──────────────────────────────────────────────────────────────┐
│ forgewatch serve --watch │
│ • parses forgewatch.yml │
│ • schedules jobs as a DAG (needs:) │
│ • runs steps as subprocesses, streams stdout/stderr │
│ • caches unchanged jobs by content hash │
│ • serves a live dashboard at http://127.0.0.1:7878 │
└──────────────────────────────────────────────────────────────┘
Features
- DAG scheduling — jobs declare
needs:; independent jobs run concurrently, dependents wait, cycles are rejected up front. - Content-addressed cache — a job's
cache_keyglobs are hashed; on a match the job is skipped and itscacheoutputs restored. Rebuild only what changed. - Live dashboard — a self-contained web UI (zero external requests) streams logs over Server-Sent Events, with per-job status cards and full run history.
- Watch mode — edits matching
watch:globs re-trigger the pipeline, debounced, so saving a file kicks off a build automatically. - Full history — every run, job, and log line is persisted in a WAL-mode SQLite database, so you can replay any past build in the dashboard.
- Single binary — Rust + Tokio + axum. Copy it anywhere and go.
Install
cargo install --path .
# or
cargo build --release # -> target/release/forgewatch
Quickstart
forgewatch init # writes a starter forgewatch.yml
forgewatch run # run once, stream logs to the terminal
forgewatch serve --watch # dashboard at http://127.0.0.1:7878, auto-rerun
Pipeline format
name: demo-ci
# Files that re-trigger the pipeline in `serve --watch`.
watch:
- "src/**/*"
# Environment inherited by every job and step.
env:
APP: forgewatch
jobs:
- name: lint
steps:
- name: check
run: cargo clippy --all-targets
- name: build
needs: [lint] # runs after lint succeeds
cache_key: # hash these inputs...
- "src/**/*"
- "Cargo.toml"
cache: # ...restore these outputs on a cache hit
- "target/release"
steps:
- name: compile
run: cargo build --release
- name: test
needs: [build]
steps:
- name: unit
run: cargo test
- name: bench
continue_on_error: true # a non-zero exit here won't fail the job
run: cargo bench
Step fields
| field | meaning |
|---|---|
run |
command line to execute (required) |
shell |
shell override, e.g. bash -c (default: cmd /C on Windows, sh -c elsewhere) |
workdir |
working directory, relative to the pipeline file |
env |
step-level environment (overrides job/pipeline) |
continue_on_error |
if true, a non-zero exit does not fail the job |
Shell note: variable expansion follows the shell.
$VARworks undersh/bash; on the Windows default (cmd) use%VAR%, or setshell: bash -cfor a step.
Commands
| command | description |
|---|---|
forgewatch init |
scaffold a starter forgewatch.yml |
forgewatch run [-f file] |
run once; exit code is non-zero if any job fails |
forgewatch serve [-f file] [-p port] [-w] |
serve the dashboard; -w enables watch mode |
State lives in .forgewatch/ next to your pipeline (runs.db + cache/).
Examples
Runnable pipelines live in examples/:
| example | shows |
|---|---|
demo |
DAG deps, job caching, continue_on_error |
parallel |
fan-out / fan-in — concurrent jobs in one wave |
rust-ci |
real-world Rust CI template (fmt → clippy/build → test) |
forgewatch run --file examples/parallel/forgewatch.yml
How it fits together
main.rs CLI (init / run / serve)
config YAML pipeline schema ......... model.rs
engine DAG scheduler + streaming steps engine.rs
store SQLite run/job/log history ..... store.rs
cache content-addressed job cache .... cache.rs
watch debounced filesystem trigger ... watch.rs
server axum API + SSE + embedded UI ... server.rs + web/index.html
License
MIT — see LICENSE.
Metadata
Release files for forgewatch-ci 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| forgewatch_ci-0.1.1.tar.gz | 36.7 kB | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| forgewatch_ci-0.1.1-py3-none-win_amd64.whl | Python 3 | none | Windows x86-64 | Details |
| forgewatch_ci-0.1.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl | Python 3 | none | Linux glibc 2.17+ x86-64 | Details |
| forgewatch_ci-0.1.1-py3-none-macosx_11_0_arm64.whl | Python 3 | none | macOS 11.0+ ARM64 | Details |
| forgewatch_ci-0.1.1-py3-none-macosx_10_12_x86_64.whl | Python 3 | none | macOS 10.12+ x86-64 | Details |
Total release size: 9.0 MB
Release files / forgewatch_ci-0.1.1.tar.gz
| Download URL | forgewatch_ci-0.1.1.tar.gz |
|---|---|
| Size | 36.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
37b85273f5216fca218d7bc19f72803991aa25a0ddabb63162a2341e3c7b669a
|
|
BLAKE2b-256 checksum How to use checksums |
bc98807ce50d01a51a37f36215775fe6d5e807bf7ed7f33e6181721fa76cf451
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 23, 2026.
Transparency logRelease files / forgewatch_ci-0.1.1-py3-none-win_amd64.whl
| Download URL | forgewatch_ci-0.1.1-py3-none-win_amd64.whl |
|---|---|
| Size | 2.3 MB |
| Tags | Python 3 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
4d691888a52cc6dcec1cfe17fb794f7a56bfcf1120e1c0f1916ee5e5643975f2
|
|
BLAKE2b-256 checksum How to use checksums |
b7ee63588d984e7bcd63debfea1186b25e681f3d7fa8bdbcefe61c0ac24c79eb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 23, 2026.
Transparency logRelease files / forgewatch_ci-0.1.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | forgewatch_ci-0.1.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 2.4 MB |
| Tags | Linux glibc 2.17+ x86-64 Python 3 |
|
SHA-256 checksum How to use checksums |
73aa8b1e7b87dc3313fcf987eb9c059a9690b693fcd849a6cdce8c56e28903a5
|
|
BLAKE2b-256 checksum How to use checksums |
11a835e270a07f4bc11e6389513927414fa24378ed0f0766e5ab09eedd883106
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 23, 2026.
Transparency logRelease files / forgewatch_ci-0.1.1-py3-none-macosx_11_0_arm64.whl
| Download URL | forgewatch_ci-0.1.1-py3-none-macosx_11_0_arm64.whl |
|---|---|
| Size | 2.1 MB |
| Tags | Python 3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
8f26aebe907bcc4b17cc26d744b497e4a5bd1b36f006dbea608adac4f01a408e
|
|
BLAKE2b-256 checksum How to use checksums |
b1828dbea165d5415afeda8f866b554152ce68ed52af11c50c7dac90b104a4a2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 23, 2026.
Transparency logRelease files / forgewatch_ci-0.1.1-py3-none-macosx_10_12_x86_64.whl
| Download URL | forgewatch_ci-0.1.1-py3-none-macosx_10_12_x86_64.whl |
|---|---|
| Size | 2.2 MB |
| Tags | Python 3 macOS 10.12+ x86-64 |
|
SHA-256 checksum How to use checksums |
726366ec28ae1ccfd6ea686fb46df57ccbab2eb536c158a55653c12900a9e49c
|
|
BLAKE2b-256 checksum How to use checksums |
b0553612f3c724049333a70723754f49e5666f9fdd29b01ab69366869254fa3b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 23, 2026.
Transparency log