Skip to content

forethought-studio/ai-trash

Repository files navigation

ai-trash — Recover files deleted by AI coding tools

Test macOS / Linux Test Windows PowerShell

A safe rm replacement that intercepts file deletions by AI coding assistants — Claude Code, Codex, Cursor, Copilot, and others — and moves them to a recoverable trash instead of permanently destroying them. Works transparently on macOS, Linux, and Windows with zero workflow changes.

ai-trash demo

The problem

AI coding agents delete the wrong file more often than you'd expect. By the time you notice, rm has already destroyed it and there's no undo. ai-trash intercepts every rm call at the system level so deleted files are always recoverable, without changing how you or your scripts use rm.

How it works

  • /usr/local/bin/rm (or /opt/homebrew/bin/rm on Apple Silicon) is replaced with a wrapper. Since that directory precedes /bin in the default PATH, all rm calls — from your shell, scripts, build tools, and AI agents — go through it automatically.
  • macOS: files on the boot volume go directly to ~/.Trash/ via FSMoveObjectToTrashSync (CoreServices), so Finder's Put Back works out of the box. They are tagged with com.ai-trash.* extended attributes so ai-trash list/restore/empty can identify them. Files on external drives use <volume>/.Trashes/<uid>/ai-trash/.
  • Linux: files go to ~/.local/share/Trash/ai-trash/; other volumes use <mountpoint>/.Trash-<uid>/ai-trash/.
  • Windows: a PowerShell Remove-Item function is dot-sourced from $PROFILE and routes deleted files to the Windows Recycle Bin via Microsoft.VisualBasic.FileIO.FileSystem.DeleteFile. A JSON manifest at %USERPROFILE%\.config\ai-trash\manifest.json tracks each deletion so ai-trash list/restore/empty can find and recover items. Explorer's native "Restore" also works, since the files are in the real Recycle Bin.
  • Each trashed item keeps its original filename. Name collisions are handled Finder-style: file (2).txt, file (3).txt.
  • Metadata is stored as extended attributes on the file itself: original path, deletion time (UTC), who deleted it, and original size.
  • A LaunchAgent runs every 6 hours and permanently purges items older than RETENTION_DAYS (default: 30 days, configurable in ~/.config/ai-trash/config.sh).
  • Daemon-safe: if $HOME is unset or points to /var/root (system launchd daemons), the wrapper falls through to real rm. Non-interactive contexts (pipes, cron) never hang on -i/-I prompts.

Protection modes

ai-trash has three modes, configured in ~/.config/ai-trash/config.sh:

Mode Your rm calls AI tool rm calls
selective (default) pass through to /bin/rm unchanged → ai-trash
safe → system Trash (recoverable, with Put Back, tracked by ai-trash) → ai-trash

selective is the default — your own commands behave exactly as before, only AI tool deletions are intercepted. safe routes your own deletions to the system Trash and tags them with ai-trash metadata, so ai-trash list shows everything and nothing silently disappears.

Detection works by checking environment variables first (IDE terminals like Cursor and VS Code set TERM_PROGRAM), then walking the full process tree up to PID 1. Covered out of the box: Claude Code, Gemini CLI, Codex, Aider, Goose, OpenCode, Devin, Kiro CLI, OpenHands, GitHub Copilot CLI, Cursor, VS Code, Windsurf, and Warp. Add your own tools in the config file.

Requirements

macOS

  • macOS Monterey 12+ (Ventura 13+, Sonoma 14+ also tested)
  • Bash 3.2+ (ships with macOS)
  • Python 3 (for Put Back support via FSMoveObjectToTrashSync — falls back to plain move without it)
  • /usr/local/bin (Intel) or /opt/homebrew/bin (Apple Silicon) must precede /bin in PATH

Linux

  • Bash 4.0+
  • /usr/local/bin in PATH before /bin

Windows

  • PowerShell 5.1+ or PowerShell 7+
  • $PROFILE must be loaded in your sessions (the installer handles this)

Install

macOS / Linux

curl -fsSL https://raw.githubusercontent.com/forethought-studio/ai-trash/main/install.sh | bash

Or if you prefer to inspect before running:

git clone https://github.com/forethought-studio/ai-trash.git
cd ai-trash && ./install.sh

The installer copies rm_wrapper.sh, ai-trash, and ai-trash-cleanup to the bin directory, symlinks rm and rmdir to the wrapper, and sets up the cleanup scheduler (LaunchAgent on macOS, cron on Linux).

Windows (PowerShell)

git clone https://github.com/forethought-studio/ai-trash.git
cd ai-trash/windows
.\install.ps1

The installer copies the scripts to $env:USERPROFILE\.ai-trash\, dot-sources the wrapper from your $PROFILE, and registers a scheduled task that runs every 6 hours to purge items older than 30 days.

Usage

rm works exactly as before — no change to your workflow.

rm myfile.txt          # moves to ~/.Trash/ (macOS) or ~/.Trash/ai-trash/ (Linux) — recoverable
rm -rf build/          # same — whole directory is recoverable
find . -name "*.bak" | xargs rm   # works correctly — files are trashed, no hanging

What it looks like

$ ai-trash list
NAME                                  DELETED (UTC)         SIZE   BY          ORIGINAL PATH
------------------------------------  --------------------  -----  ----------  ------------------------------
config.json                           2026-03-21 14:22:10   2.1K   user        /Users/user/dev/myapp/config.json
server.js                             2026-03-21 14:22:11   18.4K  claude      /Users/user/dev/myapp/server.js
migrations/                           2026-03-20 09:15:33   dir    cursor      /Users/user/dev/myapp/db/migrations

3 item(s) in AI trash

$ ai-trash restore server.js
restored → /Users/user/dev/myapp/server.js

ai-trash CLI

ai-trash list                      # show all trashed items
ai-trash restore myfile.txt        # restore to original location
ai-trash empty                     # permanently delete all AI trash (confirms first)
ai-trash empty --force             # skip confirmation
ai-trash empty --older-than 7      # delete only items older than 7 days

Recovery metadata

On macOS and Linux, each trashed item carries com.ai-trash.* extended attributes you can inspect directly:

# macOS (top-level ~/.Trash/)
xattr -p com.ai-trash.original-path  ~/.Trash/myfile.txt
xattr -p com.ai-trash.deleted-at     ~/.Trash/myfile.txt
xattr -p com.ai-trash.deleted-by     ~/.Trash/myfile.txt
xattr -p com.ai-trash.original-size  ~/.Trash/myfile.txt
xattr -p com.ai-trash.deleted-by-process  ~/.Trash/myfile.txt   # e.g. "claude --resume abc123"

# Linux / external drives
xattr -p com.ai-trash.original-path  ~/.local/share/Trash/ai-trash/myfile.txt

On Windows, metadata is stored in a JSON manifest instead:

Get-Content "$env:USERPROFILE\.config\ai-trash\manifest.json" | ConvertFrom-Json

Customising

The config file at ~/.config/ai-trash/config.sh (installed automatically) controls the protection mode and which AI tools are recognised. It's well-commented — open it and everything is explained inline.

To add a tool not on the default list, find its process name with ps aux | grep <toolname> and add it to AI_PROCESSES or AI_PROCESS_ARGS in the config.

Uninstall

macOS / Linux

./uninstall.sh

Windows

.\windows\uninstall.ps1

Both uninstallers remove all installed files and leave your trash contents intact. Delete them manually if you want.

Known limitations

  • macOS App Sandbox blocks wrapper execution. Sandboxed apps (those with an APP_SANDBOX_CONTAINER_ID entitlement) cannot execute binaries from /usr/local/bin/ or /opt/homebrew/bin/. The OS rejects the exec before the wrapper script starts running. This is a macOS platform constraint, not an ai-trash bug.
  • Workaround for sandboxed apps: Use absolute paths (/bin/rm, /usr/bin/find) instead of bare rm/find. This bypasses the wrapper entirely.
  • Defense-in-depth: If a partial sandbox allows the script to start, the wrappers detect APP_SANDBOX_CONTAINER_ID and pass through to the real binary immediately.

Compared to other tools

Tool Trashes files Replaces rm AI-aware Recovery CLI Cross-platform
ai-trash Yes Yes Yes Yes macOS, Linux, Windows
safe-rm No (blocks deletion) Yes No No Linux
trash-cli Yes No No Yes Linux
trash Yes No No No macOS
rm-protection No (blocks deletion) Yes No No macOS, Linux

FAQ

Claude Code / Cursor / Copilot deleted my files — can I get them back? If ai-trash was installed before the deletion, run ai-trash list to see all recoverable files and ai-trash restore <filename> to put them back. If ai-trash wasn't installed yet, install it now to prevent future losses.

Does this slow down rm? The overhead is a few milliseconds for the process-tree check. Build tools, CI pipelines, and interactive use are unaffected in practice.

Does it work with find -delete and git clean? Yes. ai-trash also ships wrappers for find and git that intercept -delete, git clean, git checkout -- ., and git reset --hard when run by AI tools.

Can I use it as a general safe-rm for all deletions, not just AI? Yes — set MODE=safe in ~/.config/ai-trash/config.sh and every rm call (yours included) will go to the system Trash instead of being permanent.

License

MIT — see LICENSE. Your copyright notice must be retained in any copy or fork.

If you use ai-trash in a commercial product, a mention in your documentation or credits would be appreciated.

About

AI deleted my files? ai-trash intercepts rm from Claude Code, Cursor, Copilot, Codex and others — moves files to recoverable trash instead of permanent deletion. macOS, Linux, Windows.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors