Fix claude-code-history-files-finder: preserve directory structure on recovery
Previously, recover_content.py saved all files flat in the output directory, causing files with the same name (e.g., src/utils.py and tests/utils.py) to overwrite each other. Now the script preserves the original directory structure, creating subdirectories as needed within the output directory. - Bump version: 1.0.0 → 1.0.1 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -378,7 +378,7 @@
|
|||||||
"description": "Find and recover content from Claude Code session history files. Use when searching for deleted files, tracking changes across sessions, analyzing conversation history, or recovering code/documents from previous Claude interactions. Triggers include mentions of session history, recover deleted, find in history, previous conversation, or .claude/projects",
|
"description": "Find and recover content from Claude Code session history files. Use when searching for deleted files, tracking changes across sessions, analyzing conversation history, or recovering code/documents from previous Claude interactions. Triggers include mentions of session history, recover deleted, find in history, previous conversation, or .claude/projects",
|
||||||
"source": "./",
|
"source": "./",
|
||||||
"strict": false,
|
"strict": false,
|
||||||
"version": "1.0.0",
|
"version": "1.0.1",
|
||||||
"category": "developer-tools",
|
"category": "developer-tools",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"session-history",
|
"session-history",
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ class SessionContentRecovery:
|
|||||||
self, write_calls: List[Dict[str, Any]], keywords: Optional[List[str]] = None
|
self, write_calls: List[Dict[str, Any]], keywords: Optional[List[str]] = None
|
||||||
) -> List[Dict[str, Any]]:
|
) -> List[Dict[str, Any]]:
|
||||||
"""
|
"""
|
||||||
Save recovered files to disk.
|
Save recovered files to disk, preserving original directory structure.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
write_calls: List of Write tool calls
|
write_calls: List of Write tool calls
|
||||||
@@ -152,18 +152,43 @@ class SessionContentRecovery:
|
|||||||
# Save files
|
# Save files
|
||||||
for file_path, call in files_by_path.items():
|
for file_path, call in files_by_path.items():
|
||||||
try:
|
try:
|
||||||
filename = Path(file_path).name
|
if not file_path:
|
||||||
if not filename:
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
output_file = self.output_dir / filename
|
# Preserve original directory structure
|
||||||
|
# Convert absolute path to relative path within output directory
|
||||||
|
original_path = Path(file_path)
|
||||||
|
|
||||||
|
# Handle absolute paths: extract meaningful relative path
|
||||||
|
# e.g., /Users/username/project/src/file.py -> src/file.py
|
||||||
|
# e.g., /home/user/workspace/project/lib/module.py -> lib/module.py
|
||||||
|
path_parts = original_path.parts
|
||||||
|
if len(path_parts) > 1 and path_parts[0] == "/":
|
||||||
|
# For absolute paths, try to find a project-like directory
|
||||||
|
# Skip leading /, Users/username, home/username patterns
|
||||||
|
start_idx = 1 # Skip leading "/"
|
||||||
|
if len(path_parts) > 2 and path_parts[1].lower() in ("users", "home", "user"):
|
||||||
|
start_idx = 3 # Skip /Users/username or /home/user
|
||||||
|
relative_parts = path_parts[start_idx:]
|
||||||
|
else:
|
||||||
|
relative_parts = path_parts
|
||||||
|
|
||||||
|
# Construct output path preserving structure
|
||||||
|
if relative_parts:
|
||||||
|
output_file = self.output_dir.joinpath(*relative_parts)
|
||||||
|
else:
|
||||||
|
# Fallback to filename only if path is too shallow
|
||||||
|
output_file = self.output_dir / original_path.name
|
||||||
|
|
||||||
|
# Create parent directories
|
||||||
|
output_file.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
with open(output_file, "w") as f:
|
with open(output_file, "w") as f:
|
||||||
f.write(call["content"])
|
f.write(call["content"])
|
||||||
|
|
||||||
saved.append(
|
saved.append(
|
||||||
{
|
{
|
||||||
"file": filename,
|
"file": output_file.name,
|
||||||
"original_path": file_path,
|
"original_path": file_path,
|
||||||
"size": len(call["content"]),
|
"size": len(call["content"]),
|
||||||
"lines": call["content"].count("\n") + 1,
|
"lines": call["content"].count("\n") + 1,
|
||||||
|
|||||||
Reference in New Issue
Block a user