Skip to main content

PatchRail

Local-first CI failure triage for open-source maintainers. Paste a failing CI log, get the failure class, the reproduction command, and a suggested fix strategy — in seconds, fully offline.

PyPI CI License Python

patchrail ci explain reading a failed CI log and emitting root cause, confidence, and a reproduce command

The recording above is real output from the bundled examples/ci-triage/typescript-import-type-drift.log fixture. No model calls, no network, no telemetry: the classifier is a curated rule engine that runs entirely on your machine.

Why maintainers use it

  • 40 failure classes backed by real log signatures — dependency resolution, flaky network, OOM-killed runners, Docker builds, lint, type checks, docs-site builds, and test failures across Python, Node, TypeScript, Go, Rust, Java, .NET, Ruby, PHP, C++, and Swift/Xcode. Run patchrail ci classes to list them all (add --format json to check coverage from a script).
  • 223 sanitized CI log fixtures keep the classifier honest: every rule is benchmarked against the public fixture zoo in examples/ci-triage/ on every test run.
  • Benchmarked on real failed CI runs, misses included: seven public logs from pandas, deno, svelte, Home Assistant, Prometheus, Grafana and ruff, committed unmodified so you can run them yourself — including the two PatchRail still gets wrong. See docs/real-world-benchmark.md.
  • 24 secret-redaction patterns (GitHub/GitLab/npm/PyPI/AWS tokens, private keys, JWTs, emails, home paths) so logs can be shared safely.
  • Local-first by design: no network access, no billing, no external model, no telemetry. Nothing leaves the machine.
  • Markdown for humans, JSON for automation — pipe the same result into a PR comment or a workflow step.

Quickstart

PatchRail is published on PyPI:

pipx install patchrail

Prefer not to install anything? With uv you can run the same triage straight from PyPI — no install step, and it also reads from stdin:

uvx patchrail ci explain --log failed-ci.log
# or pipe a run that just failed, no download step:
gh run view <run-id> --log-failed --repo <owner/repo> | uvx patchrail ci explain

Confirm which release you have:

patchrail --version   # or: patchrail -V
# patchrail 0.7.6

Classify any failed CI log:

patchrail ci explain --log failed-ci.log

Or try it on a bundled fixture from a clone of this repo:

git clone https://github.com/patchrail/patchrail
cd patchrail
patchrail ci explain --log examples/ci-triage/dependency-failure.log --format markdown

Real output:

# PatchRail CI Report

- Root cause: `python_dependency_resolution`
- Confidence: `0.89`
- Subsystem: Python dependency installation
- Reproduce: `python -m pip install -r requirements.txt`
- Suggested action: Pin or relax the conflicting dependency range, then rerun the same install command and the affected tests.

## Evidence signals

- `Could not find a version that satisfies the requirement`
- `Cannot install .*because these package versions have conflicting dependencies`
- `ResolutionImpossible`

## Safety

PatchRail classified this log locally. It did not create a pull request, post a comment, claim funding, or send data to an external service.

It also reads from stdin, so you can point it straight at the run that just failed. With the GitHub CLI, pipe the failing job's log in directly — no download step:

gh run view <run-id> --log-failed --repo <owner/repo> | patchrail ci explain

Point it at a recent failed run: GitHub expires job logs after a while, and --log-failed on an expired or still-green run pipes nothing in — PatchRail then exits 2 with a hint instead of guessing.

PatchRail normalizes the gh/Actions line prefix (job, step, and timestamp columns), so piping the raw gh output classifies identically to a saved log file. Any log on stdin works the same way:

tail -n 200 failed-ci.log | patchrail ci explain

When no rule matches, PatchRail says unknown rather than guessing — but it still reports any line the CI runner itself annotated as an error (##[error], ::error::), so you get the line you would have scrolled to instead of a shrug. The class stays unknown: an annotation says where the job died, not why.

Every failure class has a step-by-step remediation write-up in docs/fix/.

GitHub Action

Run the same triage on every red CI run with patchrail/ci-triage-action (also on the GitHub Marketplace). It classifies the log locally on the runner — no PR, no comment, nothing leaves the job:

- name: PatchRail CI triage
  if: failure()
  uses: patchrail/ci-triage-action@v1
  with:
    log-path: test.log

The @v1 drop-in exposes failure-class, confidence, and guide-url, plus a run annotation and job summary. See docs/using-the-action.md for its full inputs and outputs, or examples/ci-triage-action for the artifact shapes of both @v1 and the richer in-repo composite.

Features

Feature Status Notes
CI failure triage (ci explain, ci classify, ci classes) Beta 40 failure classes for GitHub Actions-style logs and common toolchains
Secret redaction (redact, ci explain --redact) Beta 23 patterns for tokens, keys, emails, and home paths
Reports Beta Markdown, JSON, and plain text
Fixture benchmark (ci benchmark) Beta Scores the classifier against all 223 public fixtures
GitHub Action Beta Read-only triage artifact on failed workflows
Local queue / control plane (queue) Experimental SQLite-backed work items with human approval states
Funded issue discovery (funded-issues) Experimental (read-only) Safe-only defaults, no claiming or commenting; see docs/funded-issues-ethics.md

Local-first & safety

PatchRail never phones home. The classifier needs no API key, no GitHub App, no repo write permission, and no external model call. Write actions (PRs, comments, claims) are out of scope; anything that could become one sits behind an explicit human approval state.

Secret redaction is a first-class feature, not an afterthought. Redact a log before sharing it anywhere:

patchrail redact --log failed.log > failed.redacted.log
patchrail ci explain --redact --log failed.log

The redaction pass covers GitHub, GitLab, npm, PyPI, AWS, Stripe, Slack, Google, Hugging Face, and SendGrid credentials, private key blocks, JWTs, bearer tokens, URL-embedded credentials, *_TOKEN/*_SECRET environment assignments, email addresses, and user home paths.

See ETHICS.md, SECURITY.md, and docs/threat-model.md.

Roadmap

  • v0.3 — public demo of the local agent control plane: SQLite-backed work queue, approval gates, and audit export.
  • v0.4 — ethical funded-maintenance workflow: read-only discovery with human-gated follow-up, no automated claiming.

Details in docs/roadmap.md.

Documentation

Contributing

The fastest way in is adding a CI fixture — it takes about 10 minutes: grab a failed log, redact it, trim it to the smallest excerpt that still shows the root cause, and add it with its expected classification under examples/ci-triage/. The full path is in CONTRIBUTING.md, and the CI failure fixture issue template works if you are not ready to open a pull request.

Issues labeled good first issue are scoped for first-time contributors.

Run the checks locally before opening a PR:

uv run --extra dev pytest -q
uv run --extra dev ruff check .
uv run --extra dev patchrail ci benchmark examples/ci-triage --format json

License

Apache-2.0.

Metadata

Release files for patchrail 0.7.6

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for patchrail 0.7.6
File Size Uploaded Provenance
patchrail-0.7.6.tar.gz 468.8 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for patchrail 0.7.6
File Interpreter ABI Platform
patchrail-0.7.6-py3-none-any.whl Python 3 none any Details

Total release size: 698.5 kB

Release files / patchrail-0.7.6.tar.gz

Download URL patchrail-0.7.6.tar.gz
Size 468.8 kB
Tags Source
SHA-256 checksum
How to use checksums
87144a905864b30f2c317eb3f64daad6431e76a75f06908e7f2d9464dfce3578
BLAKE2b-256 checksum
How to use checksums
426c7b4cc60f03e0a0b6fa390d3eb9f05d1c7f8cfd9725e921994ab4611e5acd
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 22, 2026.

Transparency log

Release files / patchrail-0.7.6-py3-none-any.whl

Download URL patchrail-0.7.6-py3-none-any.whl
Size 229.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
96795cacd45f6f4a1b5ed1862ab01cf82f69e4951a03e103423ff212867f21c4
BLAKE2b-256 checksum
How to use checksums
0f6dda179f79e20632c1b96107b991815e34bee2f52d5f68e0482b039ff34893
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 22, 2026.

Transparency log

Security for patchrail 0.7.6

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.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for patchrail-0.7.6.tar.gz

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 22, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page