DGC v0.48.4 is out
Navigate
Install DGC
DGC v0.48.4Edit on GitHub ↗
Using DGC/Checkpoints & rewind

what a recovery point holds, /rewind, the editor's Undo, and what cannot come back

Checkpoints & rewind

#

Every turn DGC runs itself opens a recovery point. /rewind takes the code and the conversation back to one of them.

When DGC takes one

#
  • One per turn, before the model sees your message. A standing goal that runs several work cycles from one prompt opens one per cycle. A follow-up typed while a turn is running joins that turn and does not open one of its own.
  • Sub-agents do not open their own. Their edits are captured into the parent turn's point — as they happen in a shared checkout, or when an isolated worktree is integrated. /tasks apply opens a point of its own.
  • Turns delegated to a subscription CLI open none. Claude Code, Codex, Qwen, Kimi and Copilot edit files outside DGC's file tools, so there is nothing for DGC to snapshot.
  • If the point cannot be saved, the turn does not start. DGC refuses the prompt rather than run a turn it could not take back.

What a point holds

#
  • The exact conversation up to just before that prompt — not a summary, and not a message count that compaction can shift.
  • Each file's pre-edit state, taken the first time the turn's file tools (write_file, edit_file, multi_edit, apply_patch) touch it: the exact bytes, the permission bits, a symlink's target, or the fact that the file did not exist yet.
  • Capture comes first. The snapshot is saved to the session before the tool runs. If it cannot be — the file changed while being read, the snapshot budget is spent, the turn has already captured 4,096 files, the path is not a regular file, or the session could not be re-saved — the edit is refused and the file is untouched.
  • What the turn's own commands changed. Around each command the chat runs — bash, the Python code-action, and a tool hook such as a formatter — DGC asks Git what is changed or untracked before and after. A file Git called clean before the command goes into the point as Git's own copy of it, so Undo puts it back, a file the command deleted included; a file the command created is removed again. This needs a Git project, and Git's copy is used only when nothing converts it (no autocrlf, eol, text or filter setting for it, not marked skip-worktree). A file the turn's own tools already wrote stays DGC's work when a later command or formatter changes it.
  • Your uncommitted work. Before each of those commands DGC also copies every file with uncommitted changes — tracked files Git sees as changed or deleted, and untracked files it does not ignore — so a git checkout ., git reset --hard, git clean -fd, git stash or rm over them is undone: Undo puts back each file the command changed exactly as it was just before it (its bytes, its permissions, or the fact that it was deleted). A file whose bytes have not changed since the last command is only re-read, not copied again, and only the copies a command's change needs are kept, in the turn's point, saved and checked like every other snapshot. A file over 5 MB, past 500 in one command, or past the session's 128 MB of snapshots is not copied: the card lists it as Changed by a command — Undo leaves it, and its tooltip says which limit applied.
  • Undo never touches Git itself. It rewrites file contents and nothing else: not the staging area, HEAD, a branch, a stash or a commit. When one of the undone turns' commands committed, reset, checked out a branch or stashed, Undo's question says Your files are put back; Git's commits, branches, stashes and staging are left as they are., and so does its last line.
  • Your own saves are yours. Which change is the command's is told by when it happened: during the command. In VS Code or Cursor with DGC running, DGC also hears every file you save in the chat's folders, so a file you save while a command runs (a long test run, say) is never taken for the command's: it is not put in the point and not listed as the command's, and Undo leaves your edit alone — even when your save reaches DGC a moment after the command ended. That window's DGC passes each save on to every other DGC working in the same folder, a terminal dgc included, through a private inbox in DGC's home folder (only your user can read it, each message carries that DGC's own token, and nothing listens on the network), so a terminal user who edits in VS Code or Cursor is covered too.
  • What no editor reports is told by time. A file you save from an editor DGC can't hear (vim, a JetBrains IDE, or VS Code with DGC not running) while a command runs counts as the command's, and Undo would put it back. So Undo's question names those files — Also puts back 2 files changed while a command ran: rates.py, README.md. (five at most, then and N more) — and offers Restore all or Keep the ones I edited…, a list where you tick the ones you edited yourself: those are left as they are and the rest are put back. In the editor's Undo question it is the same choice, then a checklist.

Rewind in the terminal

#

/rewind lists every point, oldest first: the opening 70 characters of the prompt as DGC received it (a point opened by /tasks apply reads apply retained task ID) and how many files it captured. Pick one and confirm — Reverts N file(s) and truncates the conversation. This cannot be undone., N being the files the rewind restores now across that turn and every later one. Files touched at that turn or any later one return to their earliest saved state (a file the turn created is deleted, and a folder DGC's own write created goes too once it is empty again), the conversation returns to just before that prompt, and that point and every later one are consumed. If any step fails, the files and the point are rolled back and kept, and DGC says which file and why (Undo stopped: couldn't write ro/b.py (Permission denied). Nothing was changed, and the recovery point was kept.).

Your edits after DGC's are merged

#

Undo never writes over somebody else's work without asking. A file you (or another program, or another chat) changed after DGC wrote it — after its last write, or between two of its writes, in a later turn or later in the same one — is merged: your edits stay and DGC's are taken out. For that each point keeps what DGC left in each text file at the end of each run of its writes, up to 1 MiB a file and counted in the session's 128 MB of snapshots, saved with the point and checked like the rest; Undo merges three ways (what DGC left, the file as it is now, the version from before), as helper integration does. Undo's question says what it does with each file:

  • a.py: your later edits are kept and DGC's are taken out;
  • a.py: your edits overlap DGC's; it is left as it is — the rest is undone and that file stays exactly as you left it. Undo anyway puts it back too and loses your edits there.

And its last line says how many were merged: ↩ Undone; DGC restored 2 files and merged 1 with your edits.

When Undo stops instead

#

A file it can't merge stops it: one that changed after DGC wrote it and is binary, over 1 MiB, a link, deleted, or changed only in its permissions, or one from a session saved before DGC kept its writes. It restores nothing and names the files: Undo stopped: a.py changed after DGC wrote it, by you or another program. Nothing was restored, so those changes are intact. Then it asks: These files changed after DGC wrote them, by you or another program: a.py. Undo anyway puts back the version from before this turn and loses those changes. Keep my changes is the default; Undo anyway goes ahead for exactly those files, and stops again if another file has changed by then; Undo the rest, offered for a file whose edits came to overlap DGC's since the question, leaves it as it is. A file DGC has no record of writing (a session saved by a much older DGC) is not taken as a change: that is not evidence.

A background helper that one of the undone turns started and that is still running is stopped, and Undo says so (1 background helper from those turns was stopped.): its work is kept aside in /tasks, never written into your files after you undid the turn that asked for it.

It always restores both — there is no code-only or conversation-only rewind, and no redo. It is refused while a turn is running: stop the turn (Esc) or let it finish, then run /rewind again. dgc --classic skips the confirmation unless there is a choice to make (a file it holds back, or files that changed while a command ran). The standing goal, the todos and Context Notes stay as they were.

Undo in the editor

#

Undo, on the files-changed card under an answer that edited files, finds the recovery point by the prompt that opened it, asks once, and performs the same rewind. The card lists exactly the files that rewind puts back, with the lines added and removed, counted from the state each file was in before the turn: DGC's own edits and a helper's integrated files alike, however the helper changed them, and the files the turn's commands changed that Undo can put back. A file a command changed that Undo can't put back is listed too, as Changed by a command — Undo leaves it, and after an Undo the line says how many: ↩ Undone; DGC restored 2 files. 1 file changed by a command was left as it is. A file edited and then put back as it was is not listed, and Undo's question names the same number of files as the card. A helper that finishes in the background while the chat is idle lands in the recovery point of the turn that last ended, and that turn's card shows it; the changes bar counts it too. Undo on an older turn's card also takes back every turn after it, and its question says so: how many later turns, and how many files the rewind restores across all of them. A file outside the project can be put back only by the session that changed it (its earlier version is never saved); a reopened card marks it "Can't undo" and Undo's count leaves it out. A turn that changed no files shows no card — use /rewind. If no remaining point was opened by that prompt, Undo declines rather than guess; if the same prompt opened more than one point, it takes the most recent one — /rewind lets you pick another. /rewind in the editor lists every point and rewinds as soon as you pick one.

Keep both with /branch

#

/branch (/fork) is the non-destructive alternative: a new chat that carries the conversation, the standing goal, the todos and the recovery points, while the chat you came from stays as it stands (its /recall archive of compacted turns stays with it). Nothing is reverted. The editor offers it under a finished answer.

What is not rewindable

#
  • Some of what commands change. A file Git converts, one over the copy limits above, and anything Git ignores (node_modules, build output) or outside the project has no exact earlier copy, so Undo leaves it; the Edited card names the ones Git can see. Git's own state (staging, HEAD, branches, stashes, commits) is never undone. A background shell is not watched. MCP tools, save_memory (your project's DGC.md) and add_skill are never snapshotted. A file a command changed and a file tool then wrote comes back to its state before the turn when the command's change could be put in the point (a clean file), and otherwise to the state the file tool found it in.
  • Files outside the project. An approved external path is rewindable in the current process only; its snapshot is never saved with the session.
  • A moved project. Points are bound to the directory they were saved from and do not load after a move or rename — and the first prompt in the moved directory saves over them, so they are gone for good. Move the project back before resuming if you need them.

Where they live

#

Points are saved inside the session itself, re-saved the moment a point opens and the moment a file is first captured, so they survive /resume and context compaction. There is no time limit: the newest 512 points are kept, up to 4,096 files each, within 128 MB of snapshots in total. Redaction rewrites the conversation each point holds; file snapshots stay byte-for-byte as captured, because they are the rollback data.

Documentation