@amirdaraee/namewise
v0.9.0
Published
AI-powered CLI tool that intelligently renames files based on their content using Claude or OpenAI
Maintainers
Readme
Namewise
AI-Powered File Renaming CLI Tool
Automatically rename files based on their content using AI providers (Claude, OpenAI, Ollama, LMStudio). Transform messy filenames like document1.pdf or IMG_20240315_143022.pdf into descriptive names like project-requirements-document.pdf or quarterly-sales-report-q4-2023.pdf.
Perfect for: Document management, file organization, bulk renaming based on content analysis
Features
- AI-Powered Renaming: Uses cloud providers (Claude, OpenAI) or local LLMs (Ollama, LMStudio) to generate descriptive filenames
- Privacy First: Local LLM support means your files never leave your machine
- No-AI Mode: Rename using file metadata only — no API key required (
--no-ai) - Interactive Setup: First-time wizard to configure provider, API key, naming convention and more (
namewise init) - Batch Rename (no AI): Sequence-number, prefix/suffix, date-stamp, strip, or truncate filenames in bulk (
--sequence,--prefix,--suffix,--date-stamp,--strip,--truncate) - Pattern Rename: Regex/sed-style find-and-replace on filenames, chainable, no AI needed (
--pattern) - Watch Mode: Monitor a directory and auto-rename new files as they arrive (
namewise watch) - Sanitize: Clean filenames by removing unsafe characters and applying naming conventions (
namewise sanitize) - Dedup: Find and optionally delete duplicate files by content hash (
namewise dedup) - Apply Plans: Execute a saved rename plan from a previous
--outputreport (namewise apply) - Config Management: Manage
~/.namewise.jsonfrom the CLI (namewise config get|set|list) - Storage Stats: Show file count and size breakdown by type (
namewise stats) - Tree View: Visual directory tree with file sizes and per-folder summaries (
namewise tree) - File Info: Detailed metadata for any file or directory including SHA-256 hash (
namewise info) - Organize: Move files into subfolders by extension, date, or size (
namewise organize) - Flatten: Move all nested files up to the root directory (
namewise flatten) - Clean Empty Dirs: Find and remove empty directories recursively (
namewise clean-empty) - Find: Search files by extension, name glob, size range, or date range (
namewise find) - Diff Directories: Compare two directories by filename or content hash (
namewise diff) - Recursive Scanning: Scan nested directories with an optional depth limit
- Undo Support: Reverse any previous rename session via
namewise undo(orundo --all) - Config File: Set persistent defaults in
~/.namewise.jsonor per-project.namewise.json - Concurrency Control: Process multiple files in parallel with a configurable limit
- Conflict Auto-Numbering: When a target name is taken, automatically appends
-2,-3, etc. - JSON Report Output: Save a full rename report to a file with
--output - Personal File Templates: Customizable templates for different file categories (documents, movies, music, series, photos, books)
- Smart Categorization: Automatic file type detection or manual category selection
- Naming Convention Options: 6 different formats (kebab-case, snake_case, camelCase, PascalCase, lowercase, UPPERCASE)
- Multiple File Types: Supports PDF, DOCX, DOC, XLSX, XLS, TXT, MD, RTF, JPG, JPEG, PNG, GIF, BMP, TIFF, HEIC, and WEBP files
- Image Renaming: Vision-capable models analyze image content to generate descriptive filenames
- EXIF Fallback:
--no-aimode extracts EXIF metadata (description, date) from image files when available - Dry Run Mode: Preview changes before renaming files
- Size Limits: Configurable maximum file size limits
- Session Logs: Structured JSON logs written to
~/.namewise/logs/when enabled with--logor"log": truein config
Quick Start
# Install
npm install -g @amirdaraee/namewise
# Run the interactive setup wizard (recommended for first use)
namewise init
# Preview renames (recommended first)
namewise rename ./my-documents --dry-run --provider claude
# Actually rename
namewise rename ./my-documents --provider claude --api-key your-api-keyInstallation
npm install -g @amirdaraee/namewiseUsage
Command Structure
namewise init # First-time setup wizard
namewise rename [directory] [options] # AI-powered rename (or batch rename with flags)
namewise sanitize [directory] [options] # Clean filenames without AI
namewise dedup [directory] [options] # Find and remove duplicate files
namewise watch [directory] [options] # Auto-rename new files as they arrive
namewise apply <plan.json> [options] # Execute a saved rename plan
namewise config <list|get|set> [key] [val] # Manage ~/.namewise.json
namewise undo [session-id] [options] # Reverse a previous rename session
namewise stats [directory] [options] # Storage breakdown by file type
namewise tree [directory] [options] # Visual directory tree with sizes
namewise info <path> # Metadata for a file or directory
namewise organize [directory] [options] # Move files into subfolders
namewise flatten [directory] [options] # Move all nested files to root
namewise clean-empty [directory] [options] # Remove empty directories
namewise find [directory] [options] # Search files by criteria
namewise diff <dir1> <dir2> [options] # Compare two directoriesinit
Run namewise init to launch the interactive setup wizard. It will ask:
| Step | Question | Notes |
|------|----------|-------|
| 1 | Scope — global (~/.namewise.json) or project (./.namewise.json) | Global applies everywhere |
| 2 | AI provider — claude, openai, ollama, lmstudio | |
| 3 | API key | Cloud providers only; stored in config file |
| 4 | Base URL | Local providers only; skipped if using the default |
| 5 | Model | Leave blank to use the provider default |
| 6 | Naming convention | kebab-case, snake_case, camelCase, etc. |
| 7 | Output language | e.g. English, French — leave blank to match document language |
| 8 | Always dry-run by default? | Recommended Yes for first-time users |
| 9 | Your name | Optional; used in document/photo templates |
| 10 | Context | Optional; guides AI naming for files in this scope |
After init, all saved settings apply automatically — no flags needed on every run.
rename Options
| Option | Description | Default |
|--------|-------------|---------|
| --provider | AI provider (claude, openai, ollama, lmstudio) | claude |
| --base-url | Base URL for local LLM providers | Auto-detected |
| --model | Model name (overrides provider default for any provider) | Provider default |
| --api-key | API key for the chosen provider | Interactive prompt |
| --case | Naming convention (kebab-case, snake_case, camelCase, PascalCase, lowercase, UPPERCASE) | kebab-case |
| --template | File category template (document, movie, music, series, photo, book, general, auto) | general |
| --name | Personal name to include in filenames | - |
| --date | Date format (YYYY-MM-DD, YYYY, YYYYMMDD, none) | none |
| --dry-run | Preview changes without renaming | false |
| --max-size | Maximum file size in MB | 10 |
| -r, --recursive | Recursively scan subdirectories | false |
| --depth <n> | Maximum recursion depth (requires --recursive) | Unlimited |
| --concurrency <n> | Files to process in parallel | 3 |
| --output <path> | Save rename report as JSON to this path | - |
| --pattern <pattern> | Regex rename pattern (repeatable); skips AI | - |
| --no-ai | Use file metadata instead of AI (no API call) | false |
| --language <lang> | Output language for generated filenames (e.g. English, French) | Document language |
| --context <text> | Free-form context about the files to guide AI naming (e.g. "These are John's 2023 tax documents") | - |
sanitize Options
| Option | Description | Default |
|--------|-------------|---------|
| --dry-run | Preview changes without renaming | false |
| -r, --recursive | Process subdirectories | false |
| --case | Naming convention to apply | kebab-case |
dedup Options
| Option | Description | Default |
|--------|-------------|---------|
| -r, --recursive | Scan subdirectories | false |
| --delete | Delete duplicates after confirmation | false |
undo Options
| Option | Description |
|--------|-------------|
| --list | List recent rename sessions with their IDs |
| --all | Undo all sessions at once |
| [session-id] | Undo a specific session by ID (default: most recent) |
Batch rename flags (on rename, no AI required)
| Flag | Description | Example |
|------|-------------|---------|
| --sequence | Replace filenames with padded sequence numbers | 001.pdf, 002.pdf |
| --sequence-prefix <p> | Prefix for sequence numbers | --sequence-prefix photo → photo-001.jpg |
| --prefix <text> | Prepend text to every filename stem | --prefix "2024-" |
| --suffix <text> | Append text to every filename stem | --suffix "-final" |
| --date-stamp <created\|modified> | Prepend file date to stem | --date-stamp modified |
| --strip <pattern> | Remove a substring or regex from stems | --strip "IMG_" |
| --truncate <n> | Truncate stems to N characters | --truncate 20 |
stats Options
| Option | Description | Default |
|--------|-------------|---------|
| -r, --recursive | Include subdirectories | false |
tree Options
| Option | Description | Default |
|--------|-------------|---------|
| --depth <n> | Maximum depth to display | Unlimited |
organize Options
| Option | Description | Default |
|--------|-------------|---------|
| --by <mode> | Organisation mode: ext | date | size | ext |
| -r, --recursive | Include subdirectories | false |
| --dry-run | Preview without moving files | false |
flatten Options
| Option | Description | Default |
|--------|-------------|---------|
| --dry-run | Preview without moving files | false |
clean-empty Options
| Option | Description | Default |
|--------|-------------|---------|
| --dry-run | Preview without deleting directories | false |
find Options
| Option | Description |
|--------|-------------|
| --ext <ext> | Filter by file extension (e.g. pdf) |
| --name <glob> | Filter by filename glob (e.g. "*.report*") |
| --larger-than <size> | Minimum size (e.g. 5mb, 100kb, 500) |
| --smaller-than <size> | Maximum size (e.g. 10mb) |
| --newer-than <date> | Modified after date (YYYY-MM-DD) |
| --older-than <date> | Modified before date (YYYY-MM-DD) |
| -r, --recursive | Search subdirectories (default: true) |
diff Options
| Option | Description | Default |
|--------|-------------|---------|
| --by <mode> | Compare by name or hash (content-aware, detects renames) | name |
| -r, --recursive | Compare subdirectories | true |
Examples
First-time setup:
namewise init
# Walks through provider, API key, naming convention, dry-run preference, and your name
# Saves to ~/.namewise.json or ./.namewise.jsonBasic usage:
namewise rename ./documents --dry-run
# Result: quarterly-financial-report.pdfRecursive scan with depth limit:
namewise rename ./projects --recursive --depth 2 --dry-runSave a JSON report:
namewise rename ./documents --output ./report.jsonRename using metadata only (no API key needed):
namewise rename ./documents --no-ai --dry-runForce output language (e.g. rename Farsi documents with English names):
namewise rename ./farsi-docs --language English --dry-run
namewise rename ./documents --language FrenchProvide context to guide AI naming:
namewise rename ./tax-docs --context "These are John's 2023 tax documents" --dry-run
namewise rename ./contracts --context "Legal agreements for Acme Corp projects"Regex pattern rename (no AI):
namewise rename ./docs --pattern "s/IMG_//i" --pattern "s/ /-/g" --dry-runClean filenames without AI:
namewise sanitize ./downloads --dry-run
namewise sanitize ./downloads --case snake_caseFind and remove duplicate files:
namewise dedup ./photos --recursive
namewise dedup ./photos --recursive --deleteWatch a directory and auto-rename new files:
namewise watch ./inbox --provider claude --template document
namewise watch ./inbox --no-ai --case snake_caseApply a saved rename plan:
namewise rename ./docs --output ./plan.json --dry-run
namewise apply ./plan.jsonManage config from the CLI:
namewise config list
namewise config get provider
namewise config set case snake_caseUndo the last rename session:
namewise undo
namewise undo --allList and undo a specific session:
namewise undo --list
namewise undo 2026-04-02T10:30:00.000ZBatch rename without AI:
namewise rename ./photos --sequence --sequence-prefix holiday
# holiday-001.jpg, holiday-002.jpg, ...
namewise rename ./docs --prefix "2024-" --dry-run
namewise rename ./exports --suffix "-final" --truncate 30
namewise rename ./downloads --strip "IMG_" --date-stamp modifiedStorage stats:
namewise stats ./documents
namewise stats ./projects --recursiveDirectory tree:
namewise tree ./src
namewise tree ./src --depth 3File or directory info:
namewise info ./report.pdf
namewise info ./downloadsOrganise files into subfolders:
namewise organize ./downloads --by ext --dry-run
namewise organize ./photos --by date
namewise organize ./backup --by size --dry-runFlatten nested directories:
namewise flatten ./inbox --dry-run
namewise flatten ./inboxRemove empty directories:
namewise clean-empty ./projects --dry-run
namewise clean-empty ./projectsFind files by criteria:
namewise find ./downloads --ext pdf
namewise find ./photos --larger-than 5mb --newer-than 2024-01-01
namewise find . --name "*.report*" --smaller-than 1mbCompare two directories:
namewise diff ./backup ./original
namewise diff ./backup ./original --by hash # detects renamed filesPersonal documents with your name and date:
namewise rename ./documents --template document --name "john" --date "YYYYMMDD" --dry-run
# Result: driving-license-john-20250905.pdfMovies with automatic detection:
namewise rename ./movies --template auto --dry-run
# Result: the-dark-knight-2008.mkvTV series with season/episode detection:
namewise rename ./shows --template auto --dry-run
# Result: breaking-bad-s01e01.mkvSnake case naming convention:
namewise rename ./docs --case snake_case --dry-run
# Result: project_requirements_document.pdfLocal LLMs (no API key required):
# Ollama - requires 'ollama serve' running
namewise rename ./documents --provider ollama --dry-run
# LMStudio - requires local server enabled
namewise rename ./contracts --provider lmstudio --dry-runCloud providers:
export ANTHROPIC_API_KEY=your-key
namewise rename ./documents --provider claude --dry-run
export OPENAI_API_KEY=your-key
namewise rename ./files --provider openai --dry-runBefore and after:
Before:
├── IMG_20240315_143022.pdf
├── document1.docx
├── Report Q4 2023 FINAL FINAL.xlsx
After:
├── quarterly-financial-report-q4-2023.pdf
├── project-requirements-specification.docx
├── annual-sales-performance-summary.xlsxConfig File
Set persistent defaults so you don't have to repeat flags on every run.
User-wide defaults (~/.namewise.json):
{
"provider": "claude",
"case": "snake_case",
"concurrency": 5
}Per-project overrides (<targetDir>/.namewise.json):
{
"template": "document",
"name": "alice",
"date": "YYYYMMDD"
}Priority order (highest to lowest): CLI flags > project config > user config.
Supported keys: provider, apiKey, case, template, name, date, maxSize, model, baseUrl, concurrency, recursive, depth, output, dryRun, language, context.
Supported File Types
| Type | Extensions | Parser |
|------|------------|--------|
| PDF Documents | .pdf | pdf-extraction |
| Microsoft Word | .docx, .doc | mammoth |
| Microsoft Excel | .xlsx, .xls | exceljs |
| Text Files | .txt, .md, .rtf | Native fs |
| Images | .jpg, .jpeg, .png, .gif, .bmp, .tiff, .heic, .webp | canvas + heic-convert |
File Templates
| Template | Pattern | Example Output | When to Use |
|----------|---------|----------------|-------------|
| general | {content} | meeting-notes-q4-2024.pdf | Default — simple descriptive names |
| document | {content}-{name}-{date} | driving-license-john-20250905.pdf | Personal documents, contracts, certificates |
| movie | AI provides full name | the-dark-knight-2008.mkv | Movie files — AI includes release year |
| series | AI provides full name | breaking-bad-s01e01.mkv | TV series — AI includes season/episode |
| music | AI provides full name | the-beatles-hey-jude.mp3 | Music files — AI includes artist name |
| photo | {content}-{name}-{date} | vacation-paris-john-20240715.jpg | Personal photos |
| book | AI provides full name | george-orwell-1984.pdf | Books — AI includes author name |
| auto | Automatic | Varies by detected type | Let AI detect and choose best template |
AI Provider Setup
| Provider | Vision Support | API Key Required | Default Model |
|----------|---------------|-----------------|---------------|
| claude | Yes | Yes (ANTHROPIC_API_KEY) | claude-sonnet-4-5-20250929 |
| openai | Yes | Yes (OPENAI_API_KEY) | gpt-4o |
| ollama | Model-dependent | No | llama3.1 |
| lmstudio | Model-dependent | No | local-model |
Image files require a vision-capable model. If the selected model does not support vision, the file is recorded as failed and skipped — no rename is attempted.
Image Files
To rename image files, use any vision-capable provider:
# Claude (vision enabled by default)
namewise rename ./photos --provider claude --dry-run
# OpenAI GPT-4o (vision enabled by default)
namewise rename ./photos --provider openai --dry-run
# Ollama with a vision model
namewise rename ./photos --provider ollama --model llava --dry-runFor --no-ai mode, Namewise reads EXIF metadata from image files:
- Uses
ImageDescriptionorUserCommentif present - Falls back to
DateTimeOriginal→photo-YYYY-MM-DDformat - Falls back to the original filename stem if no EXIF data is found
namewise rename ./photos --no-ai --dry-run
# Result: photo-2024-07-15.jpg (from EXIF date) or vacation-paris.jpg (from filename)Local LLMs (no API keys required)
Ollama
- Install: Download from ollama.ai
- Start server:
ollama serve - Pull a model:
ollama pull llama3.1 - Use:
--provider ollama
LMStudio
- Install: Download from lmstudio.ai
- Download and load a model in LMStudio
- Enable "Local Server" mode
- Use:
--provider lmstudio
Cloud Providers (API keys required)
Claude (Anthropic) — recommended for accuracy
- Visit Anthropic Console
- Generate an API key
export ANTHROPIC_API_KEY=your-key- Default model:
claude-sonnet-4-5-20250929(override with--model)
OpenAI
- Visit OpenAI Platform
- Create an API key
export OPENAI_API_KEY=your-key- Default model:
gpt-4o(override with--model)
How It Works
- File Discovery: Scans directory (recursively if
--recursive) for supported file types - Content Extraction: Uses specialized parsers to extract text and metadata; falls back to vision AI for scanned PDFs
- AI Processing: Sends up to 5000 characters of content plus metadata to the configured AI provider for filename suggestions
- Template & Convention: Applies the chosen category template and naming convention; for
documentandphototemplates, uses the document's own creation date from metadata when available - Conflict Resolution: If the target name exists, auto-numbers (
-2,-3, …) - Rename / Preview: Renames files on disk, or shows a preview in dry-run mode
- History: Saves the session to
~/.namewise/history.jsonfor later undo (includes token usage for cloud providers)
Token Usage
After each rename session using a cloud provider (Claude or OpenAI), Namewise displays token counts in the stats summary:
Stats: 1.2s elapsed | 0.45 MB processed | 2 PDF, 1 TXT
Tokens: 1,240 input / 87 outputToken usage is also saved to ~/.namewise/history.json alongside the rename records, so you can track API consumption over time.
For local providers (Ollama, LMStudio), token counts are not available:
Tokens: N/A (local provider)Session Logs
Session logging is off by default. Enable it with --log on any command, or set it permanently in your config file.
# Enable for a single run
namewise rename ./docs --dry-run --log
# Enable permanently
namewise config set log trueWhen enabled, a structured log is written to ~/.namewise/logs/ for every run.
Log file naming: YYYY-MM-DDTHH-MM-SS-<command>.log
Example: 2026-04-12T10-30-00-rename.log
Format: Newline-delimited JSON (one object per line):
{"ts":"2026-04-12T10:30:00.000Z","level":"info","msg":"session_start","command":"rename","directory":"/Users/amir/docs","provider":"claude","dryRun":false}
{"ts":"2026-04-12T10:30:02.456Z","level":"warn","msg":"vision_skipped","file":"photo.jpg","reason":"provider does not support vision"}
{"ts":"2026-04-12T10:30:03.789Z","level":"error","msg":"ParseError","hint":"The file may be corrupt or in an unsupported format","stack":"ParseError: ..."}
{"ts":"2026-04-12T10:30:04.000Z","level":"info","msg":"session_end","total":55,"succeeded":54,"failed":1,"elapsedMs":4123}Auto-pruned to the 20 most recent files — older logs are deleted automatically at the start of each run.
Reading logs:
# View the latest log
cat ~/.namewise/logs/$(ls -t ~/.namewise/logs/ | head -1)
# Pretty-print with jq
cat ~/.namewise/logs/2026-04-12T10-30-00-rename.log | jq .
# Show only errors
cat ~/.namewise/logs/2026-04-12T10-30-00-rename.log | jq 'select(.level == "error")'Error output: When a known error occurs, Namewise shows the message and a hint directly in the terminal:
✗ API key required for Claude
→ Check your API key — ensure ANTHROPIC_API_KEY or OPENAI_API_KEY is set, or run: namewise config set apiKey YOUR_KEYFor unexpected errors, the terminal either points to the log (if --log was used) or prompts you to enable it:
# With --log enabled:
✗ An unexpected error occurred.
→ See log: ~/.namewise/logs/2026-04-12T10-30-00-rename.log
# Without --log:
✗ An unexpected error occurred.
→ Run with --log for detailed error information.Safety Features
- Dry Run Mode: Always preview changes first with
--dry-run - Undo: Reverse any session with
namewise undo(orundo --all) - Conflict Auto-Numbering: Never overwrites an existing file
- File Size Limits: Skips files above
--max-size - Extension Preservation: Original file extensions are never changed
- Comprehensive Testing: 867 tests with 100% coverage
Testing & Development
# Development
npm run dev # Run in development mode
npm run build # Build TypeScript
npm start # Run built version
# Testing
npm test # Run all tests (watch mode)
npm run test:run # Run tests once
npm run test:coverage # Coverage report
npm run test:unit # Unit tests only
npm run test:integration # Integration tests onlyContributing
- Fork the repository
- Create a feature branch:
git checkout -b feature-name - Make your changes and add tests
- Run tests:
npm test - Submit a pull request
Requirements
- Node.js: 20.0.0 or higher
- AI Provider: Choose one:
- Local: Ollama or LMStudio (no API key needed)
- Cloud: Claude (Anthropic) or OpenAI API key
Troubleshooting
Enable session logging for details — run with --log to capture a full structured log in ~/.namewise/logs/:
namewise rename ./docs --logWhen an unexpected error occurs with --log enabled, the terminal prints the exact log path:
✗ An unexpected error occurred.
→ See log: ~/.namewise/logs/2026-04-12T10-30-00-rename.logPDF parsing errors:
- Ensure the PDF is not password protected
- Check the file is not corrupted
- Try reducing the
--max-sizelimit
API errors (cloud providers):
- Verify the API key is valid and has sufficient credits
- Check your internet connection
- Run again to confirm the error is not transient (rate limits auto-hint wait time)
Local LLM connection errors:
- Ensure Ollama server is running (
ollama serve) - Check LMStudio local server is enabled
- Verify correct base URL and port
- Confirm the model is loaded and available
Permission errors:
- Check file permissions
- Run with appropriate user privileges
- Ensure files are not open in another application
License
MIT License — Feel free to use, modify, and distribute this project.
