DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

LeonSone /

LeonSone/dsh-trash

Verified

A DeepSeek Harness (DSH) plugin: every delete operation goes through a recoverable trash store — accidental deletes are one restore away.

★ 0 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHub
READMESource: main@e40d8f25

dsh-trash

English | 中文

A DeepSeek Harness plugin that turns every delete operation into a recoverable trash move — even under the highest permission (danger-full-access). Accidentally deleted something? Restore it in one call.

  • Intercepts delete commands in the pwsh / bash / run_code tools (Remove-Item, rm, del, rd, rmdir, unlink, [System.IO.*]::Delete, fs.unlink/rm/rmdir, os.remove, shutil.rmtree, …) at the tool pipeline's tools/pre-execute gate, denies them, and guides the model to the trash tools.
  • Ships 4 tools: trash (delete = move to trash), trash-list (inspect), trash-restore (recover), trash-purge (confirmed permanent cleanup — the only path that truly deletes).
  • Zero runtime dependencies (Node built-ins only), installable from anywhere (registry / file: / link: / GitHub).

How it works

Layer What happens
Interceptor A tools/pre-execute listener (prepended, so it runs first) scans pwsh.command, bash.command, and run_code.code for delete patterns. On a hit it returns { kind: "deny" } — denials are monotonic, so no later stage (approval, guard, dispatch) can let the call through. The model sees an actionable message telling it to use trash instead.
Trash store Each "delete" becomes one entry under the trash root (default $DSH_HOME/trash): data/ keeps the original names, meta.json records original paths, timestamps, sizes, and an optional reason. Cross-volume moves degrade to copy-then-clean.
Tools trash / trash-list / trash-restore / trash-purge — see below.
<trashRoot>/
  <entryId>/
    data/...        the "deleted" files & directories (original names preserved)
    meta.json       original path, deleted-at, size, reason

Installation

# From a local checkout (dev / link mode — edits to the source take effect immediately)
dsh plugin --profile web add link:D:/path/to/dsh-trash

# Or straight from GitHub (requires git + a GitHub token on this machine)
dsh plugin --profile web add github:LeonSone/dsh-trash

dsh plugin add adds the package to the profile's dependencies; because the package declares dsh.bundle, it is automatically appended to dsh.profile.bundles. Restart dsh web (or the headless runner) for the plugin to load.

Headless profile: dsh plugin --profile headless add <spec> — same flow.

Usage

Once installed, the model's behavior changes automatically:

Scenario Behavior
Model runs Remove-Item / rm / del / … Blocked with a message explaining the trash workflow
Model calls trash(paths=[...]) Files/dirs move into the trash (recoverable)
Accidental delete trash-restore(entry_id=...) restores to the original path; or trash-restore(path="<substring of original path>") finds the newest matching entry
Permanent cleanup trash-purge(confirm: true) — optionally scoped to specific entry_ids

Tool reference

Tool Purpose
trash(paths, reason?) Move files/directories into the trash. Returns entry_id, trash_root, moved.
trash-list(path?) List trash entries (deleted-at, size, reason, original paths). Optional substring filter on the original path.
trash-restore(entry_id? | path?, target_path?, overwrite?) Restore an entry to its original location (or target_path for single-item entries). If the target exists, it refuses unless overwrite: true — in which case the existing content is first moved to the trash itself, then the restore proceeds. Nothing is ever lost.
trash-purge(entry_ids?, confirm: true) Permanently delete trash entries. The only real deletion in the whole plugin.

Configuration (optional)

Append to your profile's cordis.patch.yml:

- id: dsh-trash
  config:
    location: D:/data/dsh-trash   # trash root; same drive as the workspace = instant renames
    interceptPwsh: true           # intercept deletes in pwsh (default true)
    interceptBash: true           # intercept deletes in bash (default true)
    interceptRunCode: true        # intercept fs.* deletes in run_code (default true)

Security notes

  • Fail-safe by design: the detector prefers false positives over letting a real delete through (e.g. a tutorial string mentioning Remove-Item is blocked too; the denial message explains why). Short aliases (rm/del/rd/ri) only match in command position, so cat /tmp/rm, Test-Path C:\rd, or grep 'rm -rf' docs are not flagged.
  • One true delete path: only trash-purge(confirm: true), and it only touches the trash root.
  • Restore safety: entry_id is strictly validated (no path traversal); target_path may not point inside the trash root.
  • Overwrite safety: restoring over an existing file first backs that file up into the trash — every step is reversible.

Development

node test/unit.test.mjs   # 48 cases: detector hit/miss matrix + full trash-store workflow

Uninstall

dsh plugin --profile web remove dsh-trash

The trash directory itself is left untouched; move it away first if you want to keep the data.

License

MIT

—/ 5

No ratings yet

Verified DSH bundle

Commit e40d8f257ecb

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout