review-shift
review-shift reviews your local git branches overnight and leaves a report and an apply-able git patch on your desk by morning — instead of the review you keep postponing until after the merge.
Status: v0.1.2 released.
pipx install review-shiftinstalls it from PyPI.
What it does
At night, with nobody present, review-shift:
- finds local branches that moved recently (
refs/heads/, by committer date); - builds each branch's diff against its merge base with the base branch;
- masks secret values before anything is sent to the model;
- runs a read-only code review at the configured depth;
- writes a markdown report, a
findings.json, and two patch files — and validates every patch withgit apply --checkbefore writing it to disk.
In the morning you read one file and apply one patch. review-shift never applies anything
itself, never commits, never pushes, and never touches your working tree.
Requirements
- macOS for the scheduled path (
launchd), on mains power and awake — see Limitations. The CLI itself runs on Linux and macOS, x86 and ARM. - Claude Code CLI 2.1.0 or newer, already authenticated.
- Python 3.11+.
Install
pipx install review-shift
Golden path
# set the repo up: writes .review-shift/config.yml, keeps run artifacts out of git
cd ~/proj/myrepo && review-shift init
# check the environment before trusting it with a night
review-shift doctor
# schedule the nightly run (renders the launchd job, registers the wake-up)
review-shift init launchd
Then, in the morning:
$EDITOR .review-shift/runs/latest/report.md
Configuration
review-shift init writes .review-shift/config.yml, self-documented with inline comments —
that file is the reference. A few fields worth knowing about before you first tune anything:
| Field | Default | |
|---|---|---|
depth |
medium |
low | medium — sets the review prompt, effort and max-findings preset |
discovery.patterns |
[] |
fnmatch globs (or re:-prefixed regex) restricting which branches get discovered; empty means "every recently-moved branch" |
discovery.max_age_hours |
24 |
a branch is eligible only if its last commit is within this window |
runtime.budget_usd |
10.00 |
spend cap for one branch's review |
runtime.total_budget_usd |
50.00 |
spend cap for the whole run; once hit, remaining branches are marked skipped: budget_exhausted, not treated as a failure |
runtime.auth_preflight_budget_usd |
0.01 |
budget for the cheap health check run/doctor do before touching any branch; raise this if it fails with "exhausted its own budget" on a machine with a large cached system prompt (many MCP servers/plugins inflate even the very first call) |
patch.auto_fix_min_severity |
high |
minimum severity that lands in auto_fixed.patch instead of only all.patch |
Any scalar runtime/discovery/patch field (plus depth/base_branch) can also be set via
an env var, REVIEW_SHIFT__<SECTION>__<FIELD> (e.g.
REVIEW_SHIFT__RUNTIME__AUTH_PREFLIGHT_BUDGET_USD=0.10). Precedence is config file → env var →
CLI flag, where a flag exists — run --depth/--model and a few others override both.
Demo
asciinema play demo/review-shift.cast
Findings in the recording are scripted for a fast, free, reproducible playback — init and
the patch/report artifacts you see are real review-shift output, produced by the same
patch.resolve / patch.generate_and_verify / report.render code a real overnight run uses
(the recording skips the live model call review-shift run makes, and doesn't run doctor
either, since its own auth check is a live call too).
In-session review (/review-shift)
review-shift also works from inside a Claude Code session, as a skill that shells out to
the same CLI (ADR-006) — same prompts, same lock, same report. It is capped to one branch and
depth <= medium. Two ways to get it, not alternatives to pick between:
# zero marketplace dependency, exact `/review-shift` command, no auto-update
review-shift init skill
# in a Claude Code session: self-hosted marketplace, auto-updatable, namespaced command
/plugin marketplace add https://github.com/yushman/review-shift
/plugin install review-shift@review-shift
# invoked as /review-shift:review-shift (Claude Code always namespaces plugin skills)
init skill writes .claude/skills/review-shift/SKILL.md in the current repository; re-run
it after upgrading review-shift to pick up a changed skill. Both channels can be installed
at once — Claude Code keeps the original /skill-name and the plugin copy side by side.
Applying a patch
Deliberately manual, and deliberately three steps. The patch is bound to the branch head the review ran against.
# 1. the sha the patch was built against is in the patch header and in run.json
git -C . rev-parse feature/payments-v2
# 2. check applicability
git switch feature/payments-v2
git apply --check .review-shift/runs/latest/patches/auto_fixed.patch
# 3. apply
git apply .review-shift/runs/latest/patches/auto_fixed.patch
If the branch has moved past that sha, the CLI says so and prints an explanation instead of the recipe, rather than pretending the patch still applies.
Output
.review-shift/
├── config.yml # meant to be committed
└── runs/
├── 2026-08-22T03-30-00Z-feature-payments-v2/
│ ├── report.md # what you read in the morning
│ ├── findings.json
│ ├── run.json # branch, shas, depth, cost, timings, counters
│ ├── events.jsonl
│ └── patches/
│ ├── auto_fixed.patch # severity >= patch.auto_fix_min_severity, default high
│ └── all.patch
├── index.json
└── latest -> …
Exit codes
| Code | Meaning |
|---|---|
| 0 | Run finished, no critical findings |
| 1 | Run finished, critical findings present — a signal, not an error |
| 2 | Internal error (config, git, invalid model output, hard timeout) |
| 3 | Another run is already in progress |
| 4 | Authentication failed or quota exhausted |
The scheduler templates pass --exit-zero-on-findings, so a night that honestly finds
problems does not look like a broken job.
Limitations — read these
- A closed laptop on battery will not wake up.
launchddoes not wake the machine; the run would happen at your next wake, which is far too late to be useful. The tool registers apmsetwake-up and wraps the run incaffeinate, but neither helps a machine on battery with the lid shut. - Your code is sent to the model provider. Check your employer's policy and your plan's terms before pointing this at work code.
- Secret masking reduces exposure, it does not guarantee it. Regex heuristics miss custom token formats, and the agent has its own filesystem access. Not for code under regulatory constraints.
- No quality numbers are published yet. Recall and precision are only claimed once the benchmark bench exists (v0.2). What v0.1 measures is patch applicability.
- Run artifacts contain code fragments and live in your working tree.
- v0.1 scope: depths
lowandmedium, local branches only, one repository per run. Diffs above ~2 000 changed lines are skipped with an explicit reason rather than truncated.high, chunking, retention and incremental review are v0.2; remote branches and PR integration are v0.3.
License
MIT — see LICENSE.
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 review_shift-0.1.2.tar.gz.
File metadata
- Download URL: review_shift-0.1.2.tar.gz
- Upload date:
- Size: 76.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
68fed96300bbf83bbb06745c1cba3abc796ec3c99ceba37b607d983c37523c2b
|
|
| MD5 |
52879dc0ef1ec35948223243a090608c
|
|
| BLAKE2b-256 |
fada39752436a4e2052b72be0e8457afc8cf644d47cc846103b2d447dd61049a
|
Provenance
The following attestation bundles were made for review_shift-0.1.2.tar.gz:
Publisher:
release.yml on yushman/review-shift
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
review_shift-0.1.2.tar.gz -
Subject digest:
68fed96300bbf83bbb06745c1cba3abc796ec3c99ceba37b607d983c37523c2b - Sigstore transparency entry: 2417971763
- Sigstore integration time:
-
Permalink:
yushman/review-shift@83abb8dc3325fda516f804107da8b3b3b210171a -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/yushman
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@83abb8dc3325fda516f804107da8b3b3b210171a -
Trigger Event:
push
-
Statement type:
File details
Details for the file review_shift-0.1.2-py3-none-any.whl.
File metadata
- Download URL: review_shift-0.1.2-py3-none-any.whl
- Upload date:
- Size: 53.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2cf3f5bfd420dddc79e0f5c9e107c996b24f320745a3a40abbd080f31685193e
|
|
| MD5 |
b44c095793c470d91930efbbac5d67f2
|
|
| BLAKE2b-256 |
f41bf7cc775778ddf4bb4a33fca6598dedfa2390069c4f4cde0e048ae4b01cf3
|
Provenance
The following attestation bundles were made for review_shift-0.1.2-py3-none-any.whl:
Publisher:
release.yml on yushman/review-shift
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
review_shift-0.1.2-py3-none-any.whl -
Subject digest:
2cf3f5bfd420dddc79e0f5c9e107c996b24f320745a3a40abbd080f31685193e - Sigstore transparency entry: 2417971822
- Sigstore integration time:
-
Permalink:
yushman/review-shift@83abb8dc3325fda516f804107da8b3b3b210171a -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/yushman
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@83abb8dc3325fda516f804107da8b3b3b210171a -
Trigger Event:
push
-
Statement type: