Browse file edit history across sessions to find past versions and understand file evolution
Browses file edit history to find past versions, view diffs, and restore files.
/plugin marketplace add melodic-software/claude-code-plugins/plugin install claude-code-observability@melodic-software<file-path> [--list] [--diff VERSION] [--restore VERSION]Browse file edit history stored in ~/.claude/file-history/ to find past versions, view diffs, and understand how files evolved across sessions.
| Argument | Description |
|---|---|
<file-path> | Path to file you want version history for |
--list | List all versions of the file |
--diff VERSION | Show diff between current and specified version |
--restore VERSION | Restore file to specified version |
--sessions | Group versions by session |
| (no args) | Show version summary for current directory |
Claude Code stores file checkpoints in ~/.claude/file-history/:
~/.claude/file-history/
├── {session-uuid-1}/
│ ├── {content-hash-a}@v1
│ ├── {content-hash-b}@v2
│ └── {content-hash-c}@v3
└── {session-uuid-2}/
└── ...
Note: File history enables the /rewind command. Cleaning this directory removes undo capability.
import hashlib
from pathlib import Path
claude_dir = Path.home() / ".claude"
file_history = claude_dir / "file-history"
target_file = Path("src/auth/login.ts") # From argument
def find_versions(target_path):
"""Find all versions of a file in history."""
versions = []
if not file_history.exists():
return versions
# Search all sessions
for session_dir in file_history.iterdir():
if not session_dir.is_dir():
continue
for version_file in session_dir.iterdir():
# Version files contain the original file path and content
# Format varies - this is simplified
try:
content = version_file.read_text()
# Check if this version is for our target file
# (actual format inspection needed)
versions.append({
"session": session_dir.name,
"version": version_file.name,
"path": version_file,
"mtime": version_file.stat().st_mtime,
"size": version_file.stat().st_size
})
except Exception:
continue
return sorted(versions, key=lambda v: v["mtime"], reverse=True)
from datetime import datetime, timezone
def display_versions(versions, target_file):
"""Display version list."""
print(f"# File Versions: {target_file}\n")
print(f"Found {len(versions)} version(s)\n")
current_session = None
for i, v in enumerate(versions):
# Group by session
if v["session"] != current_session:
current_session = v["session"]
print(f"\n## Session: {current_session[:8]}...")
mtime = datetime.fromtimestamp(v["mtime"], tz=timezone.utc)
print(f" v{i+1}: {mtime.strftime('%Y-%m-%d %H:%M')} ({v['size']} bytes)")
import difflib
def show_diff(current_file, version_path):
"""Show diff between current file and historical version."""
current_content = current_file.read_text().splitlines()
version_content = version_path.read_text().splitlines()
diff = difflib.unified_diff(
version_content,
current_content,
fromfile=f"v{version_num} ({version_path.name})",
tofile="current",
lineterm=""
)
for line in diff:
if line.startswith("+"):
print(f"\033[32m{line}\033[0m") # Green
elif line.startswith("-"):
print(f"\033[31m{line}\033[0m") # Red
else:
print(line)
import shutil
def restore_version(target_file, version_path):
"""Restore file to historical version."""
# Create backup of current
backup_path = target_file.with_suffix(target_file.suffix + ".backup")
shutil.copy2(target_file, backup_path)
# Restore version
shutil.copy2(version_path, target_file)
print(f"✅ Restored {target_file} to version")
print(f" Backup saved to {backup_path}")
# File Versions: src/auth/login.ts
Found 8 versions across 3 sessions
## Session: abc123... (2025-12-30)
| Version | Time | Size | Summary |
|---------|------|------|---------|
| v8 | 15:30 | 2.4 KB | Added error handling |
| v7 | 15:25 | 2.1 KB | Fixed validation |
| v6 | 15:20 | 1.9 KB | Initial implementation |
## Session: def456... (2025-12-29)
| Version | Time | Size | Summary |
|---------|------|------|---------|
| v5 | 10:00 | 1.5 KB | Refactored auth flow |
| v4 | 09:45 | 1.8 KB | Added JWT support |
## Session: xyz789... (2025-12-28)
| Version | Time | Size | Summary |
|---------|------|------|---------|
| v3 | 14:00 | 1.2 KB | Basic auth |
| v2 | 13:30 | 0.8 KB | Scaffold |
| v1 | 13:00 | 0.3 KB | Created file |
## Quick Actions
- View diff: `/user-config:file-versions src/auth/login.ts --diff v5`
- Restore version: `/user-config:file-versions src/auth/login.ts --restore v5`
- Use /rewind: `/rewind` (built-in)
# Diff: src/auth/login.ts
**Comparing:** v5 (2025-12-29 10:00) → current
```diff
--- v5 (2025-12-29 10:00)
+++ current
@@ -15,6 +15,12 @@ export async function login(email: string, password: string) {
const user = await findUser(email);
if (!user) {
- throw new Error("User not found");
+ throw new AuthError("USER_NOT_FOUND", "User not found");
+ }
+
+ // Added: rate limiting check
+ if (await isRateLimited(email)) {
+ throw new AuthError("RATE_LIMITED", "Too many attempts");
}
const valid = await verifyPassword(password, user.passwordHash);
Changes:
This command complements the built-in /rewind command:
| Feature | /rewind | /user-config:file-versions |
|---|---|---|
| Purpose | Undo recent changes | Browse full history |
| Scope | Current session | All sessions |
| Interface | Interactive | CLI with options |
| History source | Same (file-history/) | Same (file-history/) |
Use /rewind for quick undo, use this command for history exploration.
/rewind - Interactive file undo (built-in)/user-config:retrospective - Session analysis/user-config:transcript-search - Find when changes were made/user-config:storage - See file-history storage usageThis command uses the user-config-management skill for: