# dsh-recall-plugin

> Add a recall button next to DSH user messages to roll back both project files and conversation history to their state before that message was sent, using shadow git repository snapshots with official sessions.fork.

## Metadata

- Author: [@limbo947](https://github.com/limbo947)
- Repo: <https://github.com/limbo947/dsh-recall-plugin.git>
- GitHub: [limbo947/dsh-recall-plugin](https://github.com/limbo947/dsh-recall-plugin)
- Stars: 24
- Language: JavaScript
- License: [MIT](https://spdx.org/licenses/MIT.html)
- Topics: `cordis`, `deepseek-harness`, `dsh`, `dsh-plugin`, `plugin`, `windows`
- Forks: 2
- Open Issues: 4
- Last push: 2026-08-20T12:51:55.000Z
- Added: 2026-08-16T00:00:00.000Z

## Install

```bash
dsh plugin --profile web add github:limbo947/dsh-recall-plugin
```

## Wiki

## One-Line Description
Add a "↶ Recall" button next to user message bubbles in DSH. One click rolls back workspace files and conversation history to before that message was sent; uses an independent shadow repository for file snapshots and official sessions.fork for session branching.

## Core Features
- One-click rollback of entire interaction: When recalling, restore project files, switch conversation to before that message, open new session, archive original session for easy retrieval
- Dual-track file and conversation sync: First show file list confirmation (modify/restore/delete), only proceed after confirmation, won't blindly overwrite
- Shadow git repository storage: Snapshots stored in independent git repository under home (`~/.dsh/dsh-recall-snapshots/<workspace path SHA256>/`), won't pollute project's own git, won't touch staging area or uncommitted changes
- Auto disk maintenance: Run `git gc` in background when 50 snapshots accumulate or every 24 hours; automatically clean up all snapshots of a session when session logs are completely deleted
- Visual exclude configuration: Edit `exclude.txt` in settings (gitignore syntax), takes effect immediately for next snapshot/rollback; files over 100MB automatically skipped
- Tree snapshot management: Settings page displays workspace → session → snapshot three-level tree for viewing and deletion, leaves show corresponding message content summary

## Technical Implementation
- **Language**: Pure JavaScript (ESM, zero build steps)
- **Key Dependencies**: `@deepseek-ai/cordis` (plugin framework), `@deepseek-ai/dsh-shell` (PowerShell/bash executor), `@deepseek-ai/dsh-session-query` (cold log reading), `@deepseek-ai/dsh-sandbox-policy` (session cwd parsing)
- **Architecture Pattern**: Dual bundle persistent mount: Host half injected via `cordis.patch.yml` insert line, registers `/api/recall/*` HTTP API for frontend calls; Client half injected via `dsh.client` bundle, registers `conversation.chat.node` render slot (priority -1, negative decrement retry to -3) to render user message bubbles
- **Entry Files**: `lib/index.js` (Host main entry, 791 lines assembling domain modules) / `lib/client.js` (Client main entry, UI injection 927 lines) / `lib/snapshots.js` (snapshot domain: captureSnapshot / diffFor / rollbackFor / resolveCutSeq)

## Use Cases
When AI modifies many files and you realize the direction is wrong, you want to return to the state "before this message" and continue—traditional approach is manual git stash or discard changes, but you still need to preserve conversation context to continue. This plugin makes "recall to a certain message" a single click operation, with files and conversation both returning to that moment. Suitable for long iteration with DSH, frequent changes, and frequent rollback scenarios.

## Prerequisites & Compatibility

| Dependency | Min Version | Description |
|---|---|---|
| DSH | >= 0.1.0-rc.8 | peerDependencies: cordis ^4.0.1, dsh-session/shell/sandbox-policy/session-query/host-webserver/client-web-react all ^0.1.0-rc.8 |
| Node.js | >= 20 | engines.node declared |
| git | any executable version | When not detected, recall button won't appear, page top shows `gitMissing`, DSH itself unaffected |
| Windows | PowerShell 5.1 / 7 | Script templates use `[Text.Encoding]::UTF8` and `SHA256::Create()` compatible with PS 5.1 |
| Linux / macOS | bash 3.2+ | POSIX and pwsh templates with same export name, single selection in store.js by platform |
| React | ^18.2.0 | Client half's peerDependency |

## Installation
```bash
dsh plugin --profile web add github:limbo947/dsh-recall-plugin
```

After installation, need to **restart DSH process** (`dsh web` foreground restart or `pm2 restart <your-dsh-process-name>`), then hard refresh browser page (Ctrl+Shift+R)—hover over any user message sent after plugin enablement, "↶" appears next to copy button to confirm it's active.

## Configuration Options

| Config | Type | Description | Default |
|---|---|---|---|
| `gcSnaps` | integer | Number of snapshots to accumulate before triggering git gc | 50 |
| `gcHours` | integer | Hours since last gc to trigger (whichever comes first) | 24 |
| `maxFileBytes` | integer (bytes) | Files exceeding this size won't be snapshotted or rolled back | 104857600 (100MB) |
| `baseExcludes` | string array | Base exclude list (gitignore syntax), applies to all projects | `['.git', 'node_modules/', '.dsh-recall-snapshots/']` |
| `DSH_RECALL_GC_SNAPS` (env var) | integer | Same as gcSnaps, but takes priority over config above | — |
| `DSH_RECALL_GC_HOURS` (env var) | integer | Same as gcHours, but takes priority over config above | — |

Write configuration in profile's `cordis.patch.yml` and restate the entire line by `id: recall` to override defaults; for the most common use case "add one exclude", directly edit `exclude.txt` or settings page, no restart needed.

## FAQ

**Q: What if the recall button doesn't appear?**

A: 90% chance DSH process wasn't restarted, or git CLI not in PATH. After restart, hard refresh the page (Ctrl+Shift+R). Messages sent before plugin enablement also have no snapshots, button won't appear on those.

**Q: Will recall pollute project's own git repository?**

A: No. Snapshots stored in independent shadow git repository under home (`~/.dsh/dsh-recall-snapshots/<SHA256>/git/`), won't touch your project's `.git`, staging area, or uncommitted changes; `.git`, `node_modules` already excluded by default.

**Q: Where is data stored when home is not writable?**

A: Falls back to project `.dsh-recall-snapshots/`, page top shows one-time fallback notice. Once home becomes available again, data automatically migrates back to home before next snapshot and cleans up project directory.

**Q: How to exclude a directory from snapshots?**

A: Settings → Plugins → Recall Settings visually edit `exclude.txt` (gitignore syntax, one per line), takes effect immediately for next snapshot/rollback; or directly edit `dsh-recall-snapshots/exclude.txt` under home. When rolling back to an earlier snapshot, files not yet excluded at that time will still be restored (that's the semantics of rollback).

**Q: Are snapshots kept after session deletion?**

A: Archiving doesn't count as deletion—original session snapshots archived by recall feature are kept retrievable; only when session logs truly disappear from disk will next maintenance automatically clean up all snapshots of that session. Judgment is conservative: cold sessions won't be accidentally cleared.

**Q: Can I recover if I recall wrongly?**

A: Yes. Before rollback, a safety snapshot tag `snap-pre-rollback-<timestamp>` is automatically created (not in index list, but visible with `git tag -l`), restore from that tag—this is the fallback for "recall is the only irreversible operation".

**Q: Will snapshot data be deleted after uninstall?**

A: No. `dsh plugin --profile web remove` only removes dependencies and mount layer, snapshot data remains in home under `dsh-recall-snapshots/`; to completely clear, manually delete that directory.

## Learning Curve
Beginner — install and restart to use, no mandatory config; advanced usage (custom excludes, manual gc, batch delete snapshots) all visually completed in settings page.

## Known Issues & Limitations
- **Only snapshot messages sent after enablement**: Historical messages before plugin enablement have no snapshots, naturally don't show recall button (README.md:44)
- **First message only rolls back files**: First user message in session can't rollback conversation because `sessions.fork` needs earlier turn boundary (README.md:45)
- **macOS not yet tested on real machine**: Scripts written for bash 3.2 compatibility, but currently only full流程 tested on Windows real machine and WSL2 Ubuntu (bash 5.3 + git 2.53) (README.md:46)
- **Nested git repositories not snapshotted**: Sub-repos with `.git` in workspace subdirectories (gitlinks) don't participate in snapshot and rollback (scripts.pwsh.js:36-39)
- **Filename with newline/TAB parsing abnormal**: Diff list parsing split by TAB, extreme cases with these characters in filename will be misparsed (scripts.pwsh.js:191-194)
- **Recall requires git CLI**: Without git installed, recall button doesn't appear, page top shows one-time hint, DSH itself unaffected (README.md:52)
- **Fork doesn't inherit original title increment**: Already fixed—multiple recalls of new session won't become "xxx 2/3/4" (CHANGELOG.md:84-85, lib v1.2.2)

---

This document is auto-generated by [deepseek-plugin.org](https://deepseek-plugin.org). HTML page: [dsh-recall-plugin](https://deepseek-plugin.org/plugins/limbo947/dsh-recall-plugin)
Wiki generated by AI (model: `MiniMax-M2.5`)
