Recall any user message: rolls the conversation (official session fork) and workspace files (per-message shadow git snapshots) back to before it, with a diff-preview confirmation panel.
Install
# from npm (prebuilt)
dsh plugin --profile web add dsh-recall-plugin
# from GitHub (first run asks for allowBuilds approval — follow the hint, retry)
dsh plugin --profile web add github:limbo947/dsh-recall-plugin
Any plugin you install runs third-party code with your own permissions — it can read your files, use your credentials, and reach the network, and tool approvals don’t sandbox it. GitHub-sourced plugins also run build scripts at install time. Only install sources you trust, and pin a commit (github:owner/repo#sha).
README
Recall a message, and your project files go back with it.
简体中文 | English
Under any message you've sent, click "↶ Recall", and both your workspace files and the conversation history roll back to the moment right before that message was sent.
UI Preview
- Recall button location

| Confirmation panel · file change list | |
|---|---|
![]() |
![]() |
Highlights
- Files + conversation, rolled back together: recalling isn't just about chat history — files the agent modified go back to their original state too.
- Never touches your project's own git: snapshots live in an independent shadow git repository; your branches, staging area, and uncommitted changes are untouched.
.gitandnode_modulesare excluded automatically. - Keeps your project directory clean: snapshots always live under
$DSH_HOME, nothing is ever dropped into your project — regardless of the session's sandbox permission (workspace-write / read-only sessions snapshot and recall as usual). Only when home itself is unwritable (e.g. pointed at a read-only drive) does it fall back to an in-project.dsh-recall-snapshotsdirectory (the page shows a notice when degraded); once home is writable again, data migrates back and the fallback directory is cleaned up. - Change your mind as many times as you like: as long as the session still exists (including archived ones), snapshots are fully retained and never pruned. After one recall you can recall again to an even earlier point; files overwritten during a recall always remain recoverable. Once a session is permanently deleted, its snapshots are cleaned up accordingly (see below).
- See the list before you act: clicking recall first shows the list of files that will change (modified / restored / deleted); nothing is overwritten until you confirm.
- Disk-friendly: snapshots use git delta compression — incremental, not full-directory copies. Files larger than 100MB are skipped automatically.
- Automatic housekeeping: periodic
git gcpacks loose objects (lossless — not a single snapshot is lost); snapshots of deleted sessions are cleaned up automatically; build artifacts can be excluded globally viaexclude.txt(see below).
Known Limitations
- Snapshots are created when a message is sent; messages from before the plugin was enabled have no snapshot and show no recall button.
- The first user message of a session cannot roll back the conversation (files only), because fork requires an earlier turn boundary.
- Supports Windows (PowerShell 5.1/7 + git CLI) and Linux/macOS (bash + git CLI). Windows is thoroughly verified on real machines; Linux has been fully tested on WSL2 (Ubuntu 26.04, bash 5.3 + git 2.53), including Chinese paths, home fallback, session cleanup, and gc; the macOS side is written to be bash 3.2 compatible but has not been tested on real hardware yet.
- Nested git repositories inside the workspace (subdirectories with their own
.git) are not snapshotted; their contents do not participate in recalls. - Extreme cases like filenames containing newlines/TAB are beyond the diff list's parsing capability (negligible probability).
Installation
Prerequisites: git CLI (without it the recall button won't appear and a notice shows at the top of the page — DSH itself keeps running); PowerShell 5.1 / 7 on Windows, bash + git on Linux/macOS; DSH 0.1.0-rc.x (see peerDependencies for dependency versions).
- Official DSH plugin command: install and auto-mount into the web profile
dsh plugin --profile web add dsh-recall-plugin
- Or install directly from git (pure JS, no build step, no prepare/allowBuilds needed):
dsh plugin --profile web add github:limbo947/dsh-recall-plugin
- Restart the DSH process (pick whichever matches how you start it)
dsh web # run in the foreground
pm2 restart <your-dsh-name> # if managed by pm2
Verify: after restarting, hard-refresh the page (Ctrl+Shift+R) and hover over any user message sent after the plugin was enabled — the "↶" appearing next to the copy button means it works. No button? Nine times out of ten the DSH process wasn't restarted, or git CLI isn't on PATH.
Uninstall: dsh plugin --profile web remove dsh-recall-plugin (removes both the dependency and the mount layer). Snapshot data is kept under dsh-recall-snapshots/ in home; delete that directory manually if you want it fully gone.
Usage
- Hover over any user message sent after the plugin was enabled — "↶ Recall" appears to the left of the copy button.
- Click it → the confirmation panel shows the list of files that will change (modified / restored / deleted).
- Click "Confirm rollback" → files are restored to their state before that message was sent; the view switches to a new session (that message and everything after it is removed), while the original session is archived and can be recovered anytime.
Snapshot Maintenance & Cleanup
Snapshots are fully retained as long as "the session might still be recoverable"; on top of that, the plugin manages disk usage automatically — no manual housekeeping needed:
Periodic gc: every 50 snapshots or 24 hours since the last gc (whichever comes first),
git gcruns in the background to pack loose objects. This is lossless — every snapshot remains recallable. The throttle token lives ingc.stampinside the shadow repository, so restarting DSH does not reset the cycle. Both thresholds can be overridden via environment variables (rarely needed):DSH_RECALL_GC_SNAPS,DSH_RECALL_GC_HOURS.Session-deletion cleanup: once a session is permanently deleted (its log gone from disk), the next maintenance pass automatically removes all of its snapshots and frees the space. Archiving is not deletion — logs of sessions archived by the recall feature itself still exist, so their snapshots are kept and recoverable from the archive. The check is conservative: a session that is merely cold (not in memory) is never cleaned, and when the log's state cannot be verified, it is left alone.
User-defined exclusions: put one gitignore-style pattern per line in
dsh-recall-snapshots/exclude.txtunder home (i.e.$DSH_HOME/dsh-recall-snapshots/exclude.txt, or~/.dsh/dsh-recall-snapshots/exclude.txtwhen unset; UTF-8; lines starting with#are comments), for example:# keep build artifacts out of snapshots dist/ build/ *.logThis applies to all projects and takes effect on the next snapshot/recall, no restart needed. New exclusions only affect future snapshots; when recalling to an earlier snapshot, files that weren't excluded at that time are still restored (returning to the state as it was — that's exactly what recall means). To fully purge a directory that already made it into snapshots, manually delete the corresponding hash directory under
dsh-recall-snapshots/in home.
How It Works
When each user message is sent (before the agent touches any files), the workspace is snapshotted into an independent shadow git repository; on recall, files are restored via git archive and the conversation is rewound through DSH's official sessions.fork mechanism. Binary-safe, and your project's own git state is never touched.
Snapshot storage:
dsh-recall-snapshots/<SHA256(project absolute path)>/under home, containing the shadow git repository (git/, tags namedsnap-<messageID>) and the index fileindex.json(message ID → snapshot time / session). Scripts run via PowerShell on Windows and bash on Linux/macOS (forked automatically by the executor mounted on thectx.shellplatform layer).To browse historical snapshots directly:
git --git-dir="<store>\git\.git" tag -l git --git-dir="<store>\git\.git" ls-tree -r --name-only snap-<messageID>
Local Development (without publishing)
# Drop the package directory into the web profile's node_modules and register it in bundles
$pkg = '<path-to-your-clone>\dsh-recall-plugin'
$profile = "$env:USERPROFILE\.dsh\profiles\web"
Copy-Item -Recurse -Force $pkg "$profile\node_modules\dsh-recall-plugin"
# Manually edit $profile\package.json:
# add "dsh-recall-plugin": "1.0.0" to dependencies
# add "dsh-recall-plugin" to dsh.profile.bundles
# then restart DSH and hard-refresh the page
License
MIT
Links
More in this category
Anionex/dsh-turn-rewind★ 52
Rewind conversation and workspace state, powered by a persistent Change Ledger.
Nwflower/dsh-chat-import★ 35
Import full-fidelity chat histories from 13 coding agents (Claude Code, Codex, ChatGPT, Cursor, Gemini, opencode, and more) as resumable DeepSeek Harness sessions, with reverse export back to Claude Code.
Chinesezjc/dsh-interconnect★ 27
Cross-instance message and event handoff between DSH instances via an interconnect server.
whyihaveyou/dsh-suite#plugin-session-export★ 27
Export the append-only session log as human-readable Markdown or HTML, grouped by trajectory source.
Moeblack/dsh-message-edit★ 22
Branch-based message editing, reroll, retry, and a version timeline.
hellodigua/dsh-share★ 19
Share your conversations with one click.

