Run CI pipelines locally in Docker with interactive pause/resume debugging
Project description
ciwalk
Run your CI pipeline locally, pause at any step, drop into a live shell to inspect or fix state, then retry / continue — no more commit-push-pray.
uv tool install ciwalk # or: pipx install ciwalk
ciwalk run examples/broken-ci.yml --pause-on-fail
Why
CI feedback is still mostly blind: edit YAML → commit → push → wait → read logs → guess. Tools like act run Actions locally but are still all-or-nothing. ciwalk keeps the container alive, opens a shell at the failure point, and lets you resume.
Install
Requires: Python 3.11+ and Docker (daemon running).
From PyPI (recommended, after release)
uv tool install ciwalk
# or
pipx install ciwalk
# or
pip install ciwalk
From GitHub (no wait for PyPI)
uv tool install git+https://github.com/kiwi-07/ciwalk.git
# or
pipx install git+https://github.com/kiwi-07/ciwalk.git
From a clone (dev)
git clone https://github.com/kiwi-07/ciwalk.git && cd ciwalk
pip install -e ".[dev]"
Standalone binary
GitHub Releases (starting with v0.1.0) attach a platform binary you can download and run without installing Python packages — still needs Docker on the machine.
chmod +x ./ciwalk
./ciwalk run examples/hello.yml
Usage
ciwalk run <workflow.yml> [OPTIONS]
| Flag | Meaning |
|---|---|
--job / -j NAME |
Job id (required if the workflow has multiple jobs) |
--pause-on-fail |
On failure, open a shell then ask retry / continue / abort |
--breakpoint / -b NAME |
Pause before a step (exact step name) |
--image IMAGE |
Override runner image (default: catthehacker/ubuntu:act-latest) |
--workdir / -C PATH |
Host path mounted as /github/workspace (default: cwd) |
--keep |
Leave the container running after the job ends |
--input / -i KEY=VALUE |
Set ${{ inputs.* }} (repeatable; overrides workflow defaults) |
ciwalk cleanup # remove leftover ciwalk containers (e.g. after kill -9)
ciwalk cleanup --dry-run # list matching containers without removing them
Pause flow
- A step fails (with
--pause-on-fail) or you hit--breakpoint. ciwalkattaches an interactive shell inside the same container (same bash flags, env, and working-directory as the step).- Inspect / fix (mounted workspace is live on the host too).
exit(or Ctrl+D) → chooseretry|continue|abort.continueafter a failure still exits non-zero (the failed step stays failed).
Demo
ciwalk run examples/broken-ci.yml --pause-on-fail
Matches examples/broken-ci.yml: checkout + Prepare workspace pass; Require marker file fails (build/MARKER missing). In the shell:
touch build/MARKER
exit
Then choose retry. The step passes, Finish runs, and the job completes.
Recording source: docs/demo.cast (replay with asciinema play docs/demo.cast).
Supported GitHub Actions subset (MVP)
- Single job per run (
--jobif needed) runs-on: ubuntu-latest(or omit)- Steps:
run,name,env,working-directory uses: actions/checkout@*→ bind-mount workspace (no network clone)${{ inputs.* }}/${{ env.* }}string substitution (--input KEY=VALUE)- Any other
${{ }}(or unknowninputs.*/env.*key) → error, not empty-string rewrite - Jobs that are reusable workflow calls, or use job-level
needs:/if:→ SKIPPED (loud, non-zero exit — never silent pass)
Not yet: matrix/parallel jobs, secrets, full expression language (github.*, secrets.*, …), arbitrary marketplace actions, GitLab/Circle/Jenkins, caching.
Roadmap / want to help?
Gaps above are intentional MVP cuts, not forever. Prefer contributions around expression support (github.*), matrix builds, and broader uses: allowlisting — file an issue or PR on develop. Good first issues welcome once labeled.
Development
pip install -e ".[dev]"
pytest
Linux smoke (T1–T4)
Native Linux Docker bind-mount behavior can differ from Docker Desktop on Mac. CI runs this on ubuntu-latest:
scripts/linux-smoke.sh
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ciwalk-0.1.0.tar.gz.
File metadata
- Download URL: ciwalk-0.1.0.tar.gz
- Upload date:
- Size: 18.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b21b7f24f737833b3e66fd2aced5644425ca5977e1252ccb00cb52a41086cd55
|
|
| MD5 |
ba0e47d1634ed054f46828fcd13abfa1
|
|
| BLAKE2b-256 |
f98da6f5bc8ac19b4520314292798329b7ba03349a2b1a2c633f3f99dc6e7b9e
|
File details
Details for the file ciwalk-0.1.0-py3-none-any.whl.
File metadata
- Download URL: ciwalk-0.1.0-py3-none-any.whl
- Upload date:
- Size: 19.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a23efe93fa432e6452f0d4bd8343213902d070912818e10893bfce103c501f0d
|
|
| MD5 |
4e9b66cc503b978506f12861e6497b95
|
|
| BLAKE2b-256 |
b2dafa4ae1fcc195412036045ff0062099cde2002f9a8fabb734d41a644d0b71
|