Install
$ agentstack add skill-therocksss-hermes-skills-portfolio-file-organizer ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ● Filesystem access Used
- ✓ Shell / process execution No
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
file-organizer
Overview
Organize files in a directory by type, date, or custom patterns. The agent scans a directory, categorizes files, and moves them into a structured layout. Supports dry-run mode to preview before moving.
When to Use
- The user has a messy directory (Downloads, Desktop) and wants it organized.
- The user wants to sort files by type, date, or name pattern.
- The user wants to find and remove duplicate files.
- The user says "organize my downloads", "clean up this folder", or "sort these files".
Organize by Type
import os
import shutil
from pathlib import Path
CATEGORY_MAP = {
"Images": [".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp", ".svg", ".heic"],
"Videos": [".mp4", ".avi", ".mov", ".mkv", ".wmv", ".flv", ".webm"],
"Audio": [".mp3", ".wav", ".flac", ".aac", ".ogg", ".m4a"],
"Documents": [".pdf", ".doc", ".docx", ".txt", ".md", ".odt", ".rtf", ".pages"],
"Spreadsheets": [".xls", ".xlsx", ".csv", ".ods", ".numbers"],
"Presentations": [".ppt", ".pptx", ".key", ".odp"],
"Archives": [".zip", ".tar", ".gz", ".rar", ".7z", ".bz2", ".xz"],
"Code": [".py", ".js", ".ts", ".jsx", ".tsx", ".java", ".cpp", ".c", ".h", ".go", ".rs", ".rb", ".php", ".sh", ".html", ".css", ".json", ".xml", ".yaml", ".yml"],
"Executables": [".exe", ".msi", ".deb", ".rpm", ".dmg", ".app", ".apk"],
"Fonts": [".ttf", ".otf", ".woff", ".woff2", ".eot"],
"Data": [".db", ".sqlite", ".sql", ".json", ".csv"],
}
def organize_by_type(directory: str, dry_run: bool = True) -> dict:
"""Organize files into subdirectories by category."""
moved = {}
skipped = []
for item in Path(directory).iterdir():
if item.is_dir():
continue
ext = item.suffix.lower()
category = "Misc"
for cat, extensions in CATEGORY_MAP.items():
if ext in extensions:
category = cat
break
target_dir = Path(directory) / category
target_path = target_dir / item.name
if dry_run:
moved[str(item)] = str(target_path)
else:
target_dir.mkdir(exist_ok=True)
if target_path.exists():
# Append number to avoid overwriting
stem = item.stem
i = 1
while target_path.exists():
target_path = target_dir / f"{stem}_{i}{item.suffix}"
i += 1
shutil.move(str(item), str(target_path))
moved[str(item)] = str(target_path)
return {"moved": moved, "count": len(moved), "dry_run": dry_run}
Organize by Date
import datetime
def organize_by_date(directory: str, dry_run: bool = True) -> dict:
"""Organize files into year/month subdirectories by modification date."""
moved = {}
for item in Path(directory).iterdir():
if item.is_dir():
continue
mtime = datetime.datetime.fromtimestamp(item.stat().st_mtime)
year = str(mtime.year)
month = mtime.strftime("%m-%B")
target_dir = Path(directory) / year / month
target_path = target_dir / item.name
if dry_run:
moved[str(item)] = str(target_path)
else:
target_dir.mkdir(parents=True, exist_ok=True)
shutil.move(str(item), str(target_path))
moved[str(item)] = str(target_path)
return {"moved": moved, "count": len(moved), "dry_run": dry_run}
Find Duplicates
import hashlib
def find_duplicates(directory: str) -> dict:
"""Find duplicate files by content hash."""
hashes = {}
duplicates = {}
for item in Path(directory).rglob("*"):
if item.is_file():
h = hashlib.sha256(item.read_bytes()).hexdigest()
if h in hashes:
if h not in duplicates:
duplicates[h] = [hashes[h]]
duplicates[h].append(str(item))
else:
hashes[h] = str(item)
return {
"total_files": len(hashes) + sum(len(v) - 1 for v in duplicates.values()),
"duplicate_groups": len(duplicates),
"duplicates": duplicates,
}
Workflow
- Identify the directory to organize
- Run in dry-run mode first to show what would move where
- Show the user the proposed organization
- If approved, run without dry-run to actually move files
- Report: files moved, categories created, any duplicates found
Common Pitfalls
- Always dry-run first — Never move files without showing the user what will happen. A wrong category mapping could scatter files unexpectedly.
- Name collisions — Files with the same name in different categories will collide. The code handles this by appending
_1,_2, etc. - Symlinks —
Path.iterdir()includes symlinks. Moving a symlink moves the link, not the target. Handle symlinks separately if needed. - Hidden files — Files starting with
.(.gitignore,.env) are included by default. Filter them out if the user doesn't want them moved. - Permission errors — Moving files requires write permission on both the source and target. On Windows, files in use can't be moved.
- Large directories —
find_duplicatesreads every file to hash it. For directories with thousands of large files, this is slow. Consider hashing only files above a size threshold first.
Verification Checklist
- [ ] Dry-run output was shown to and approved by the user before any real move ran
- [ ] Post-move file count matches pre-move count — nothing was lost or silently overwritten
- [ ] Any name-collision case produced a
_1/_2suffixed file instead of overwriting the original - [ ]
find_duplicatesgroups spot-checked (same hash, same actual content) before deleting anything
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: THEROCKSSS
- Source: THEROCKSSS/hermes-skills-portfolio
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.