Git time-travel for AI coding agents. Wrap Claude Code, Codex, aider, or
any command; StepBack checkpoints every settled edit burst and rewinds the
working tree exactly—with best-effort conversation rewind—without touching
your branch, HEAD, index, staging area, or commit history.
pip install stepback
stepback run -- codex # also: claude, aider, or any command
AI coding agents are useful until they aren't. One bad turn and your working
tree is full of half-broken edits and a junk file or two. git stash doesn't
help (the agent never committed), and your editor's undo won't unwind a
multi-file change. stepback sits beside your agent, snapshots your files as it
works, and lets you rewind to any point exactly.
$ stepback run -- claude # or: -- codex / -- aider / any agent
... let the agent work ...
$ stepback list
#7 2m ago 3 file(s) [~3] +conv:claude-code
#6 5m ago 1 file(s) [+1] +conv:claude-code
$ stepback rewind 6 # preview the diff, confirm, done
restored to checkpoint #6. (`stepback redo` to undo this rewind)
resume conversation: claude --resume 9f3c...
$ stepback restore 6 --path src/ # restore only one subtree; leave other edits intact
Restore and recovery path
Every restore is previewed from content hashes, journalled before mutation, and either completed, resumed, or rolled back while preserving HEAD, the index, and unselected files.
Why this exists (and how it's different)
A handful of "undo my AI agent" tools already exist (walkback, doover, bashback,
and others). They share two limits that stepback is built to beat:
-
They're tied to one agent. Most hook into a single tool's lifecycle.
stepback's file layer is filesystem-based, so it works with any agent that edits files on disk: Claude Code, Codex, aider, Cursor's CLI, a plainbashscript, whatever comes next. -
They only rewind the files.
stepbackoptionally also rewinds the conversation state (the agent's on-disk session transcript), so after a rewind you can resume the agent from that point in the chat, not just reset the code.
It does all of that without ever touching your real git history. Checkpoints
live in an isolated ref namespace, written with a private index, so your branch,
HEAD, staging area, and commits are never modified. Run it inside a repo
you're actively working in and it stays out of your way.
Two layers
Layer 1: file checkpoint/rewind (solid, the core)
A debounced file watcher snapshots your working directory each time an edit
burst settles. Snapshots are content-addressed git objects stored under
refs/checkpoints/<session>/<n>:
- Never touches your work. Uses git plumbing (
hash-object,write-tree,commit-tree,update-ref) with a separate index viaGIT_INDEX_FILE. Your branch,HEAD, index, staging, and history are untouched, verified by tests under detached-HEAD, mid-merge, and staged-changes conditions. - Exact restores. Rewinding reproduces the tree byte-for-byte: edits
reverted, added files removed, deleted files brought back. Handles binary
files, symlinks, unicode/space/leading-dash names,
.gitignore, and large trees (it is git). - Atomic. A restore stages the wanted file versions first, then moves them
into place with same-filesystem renames, so a crash can never leave a
half-written file. A write-ahead journal records the operation and a
ref-protected pre-operation tree before anything destructive happens, so an
interrupted restore can be explicitly recovered with
stepback recover. Successful rewinds remain reversible withstepback redo. - Safe. Rewind shows a diff preview and asks for confirmation before
changing anything, and pushes your current state onto a redo stack so a rewind
is itself reversible.
--dry-runshows the plan without touching the tree. - Selective.
stepback restore <id> --path FILErestores one or more files or subtrees from a checkpoint, verifies that unselected paths did not move, and keeps the operation redo-able. Conversation state is intentionally not rewound for a file-only selection. - Concurrency-safe. Mutating operations take an OS-owned cross-process
advisory lock (
flockon POSIX andLockFileExon Windows), and a rewind tells a running watcher to ignore restore events for the full operation, so a watcher and a manualrewindin another terminal never corrupt state. - Works without git too. Outside a git repo, stepback creates a private
object store at
.stepback/shadow.gitand uses the identical machinery.
Layer 2: conversation rewind (the wedge, best-effort)
When an agent is detected, stepback also snapshots its on-disk session state with each checkpoint and restores it on rewind, then prints a resume hint. This is what lets you rewind the conversation, not just the code.
Honesty note. Layer 2 depends on private, undocumented, version-unstable session formats that each agent vendor can change at any time. It is deliberately best-effort and isolated behind a clean adapter interface: if the agent isn't detected or its format isn't recognized, stepback silently degrades to file-only rewind. It never crashes, and it never blocks Layer 1.
| Agent | Adapter | State captured | Resume hint | Status |
|---|---|---|---|---|
| Claude Code | claude-code |
active transcript ~/.claude/projects/<slug>/<uuid>.jsonl |
claude --resume <uuid> |
best-effort |
| Codex CLI | codex |
one recognized session whose metadata matches this work tree | codex resume |
best-effort |
| others | none | none | none | file-only rewind |
Adding an agent is one small class implementing detect / session_files / snapshot / restore / resume_hint (see ARCHITECTURE.md).
What works / what's best-effort
- Works, tested, solid: file snapshot and exact rewind (binary, symlinks,
additions, deletions, nested dirs, unusual names), git-history isolation under
awkward repo states, atomic/recoverable restore,
.gitignorerespect, redo that survivesgit gc, diff preview, checkpoint dedup, cross-process locking. - Best-effort: conversation snapshot/restore for Claude Code and Codex (private formats, may break on agent updates, degrades to file-only).
- Degrades gracefully: if the OS file-watch limit is hit, stepback falls back to a polling watcher, then to start/end-only checkpoints. Checkpoint failures remain contained from the agent but are reported by the CLI. It never takes down the agent it's watching.
Install
pip install stepback
# or, from source:
pip install .
# for development (tests, ruff, mypy):
pip install -e ".[dev]"
Requires Python 3.11+ and git on PATH. Depends only on typer and
watchdog.
Quickstart
# Wrap any agent. stepback watches, checkpoints, and stays out of git's way.
stepback run -- claude
stepback run -- codex
stepback run -- aider
stepback run -- bash -c 'your script that edits files'
stepback status # storage mode, session, watcher state, adapters
stepback list # checkpoints, newest first
stepback diff <id> # what a checkpoint changed (add -w to diff vs working tree)
stepback rewind [id] # preview + restore (defaults to the most recent checkpoint)
stepback rewind <id> -n # dry run: show the plan, change nothing
stepback rewind <id> -y # skip the confirmation
stepback restore [id] -p src/app.py -p tests/ # restore selected paths only
stepback restore [id] -n -p src/ # preview selected restore
stepback redo # reverse the last rewind
stepback recover # recover an interrupted file restore
Exit codes: 0 success, 1 expected failure (no such checkpoint, nothing to
redo, aborted), 2 bad invocation, 127 agent command not found.
Limitations (read these)
- Snapshots respect
.gitignore. Ignored files (build artifacts,.env,node_modules) are not captured or restored. This is usually what you want. It's called out here so it's never a surprise. - Layer 2 conversation formats are private to each agent and can break on any update. Codex capture requires recognized session metadata with an exact work-tree match; unsupported or ambiguous sessions deliberately degrade to file-only rewind. Treat conversation rewind as a bonus, not a guarantee.
- Restoring overwrites the current working tree for tracked/non-ignored files (after the diff preview and your confirmation).
- A restore is not one filesystem-wide atomic syscall. Individual files are
replaced atomically, the final tree is verified, and a write-ahead journal
makes interrupted file restores explicitly recoverable with
stepback recover. Successful rewinds are still reversible withstepback redo. Conversation adapters and external services are outside this file transaction. - Any stepback command resolves storage for the current directory, so running
one outside a git repo creates a
.stepback/directory there.
Development
pip install -e ".[dev]"
ruff check .
mypy
pytest -q
See CONTRIBUTING.md for the layout and ARCHITECTURE.md for how it works.
If StepBack saves an agent session, star the repository so the next developer can find it.
License
MIT (c) 2026 Krishi Attri
Current release status
The current release includes selective file/subtree restore, write-ahead journalling, fresh-process recovery, untouched-path verification, atomic promotion and durable redo. The suite passes 86 tests with 1 platform-gated skip on Linux (85 passed, 2 skipped on Windows); ruff and mypy are clean on both targets. Conversation-layer rewind remains adapter/platform dependent.
Metadata
Release files for stepback 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| stepback-0.2.0.tar.gz | 52.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| stepback-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 92.2 kB
Release files / stepback-0.2.0.tar.gz
| Download URL | stepback-0.2.0.tar.gz |
|---|---|
| Size | 52.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c03f89a2f3bfab24e622201537af3c880286a4ae514836559ccc521eac2accc1
|
|
BLAKE2b-256 checksum How to use checksums |
d5e6e6eeaf4fb7892903665d453163869a4ab7d7cd11892be20db13425ca803b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.3
|
Release files / stepback-0.2.0-py3-none-any.whl
| Download URL | stepback-0.2.0-py3-none-any.whl |
|---|---|
| Size | 40.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2bb896126aded68bf9295ef7440dc2724eda9562006251323306acfe2f0f89e3
|
|
BLAKE2b-256 checksum How to use checksums |
c34bfcde7c7b8b89072abe458e66ccca51296a3d532d5d47d923bf50fc0846f5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.3
|