3.7 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Commands
npm start # Run the Electron app in development
npm run build # Build macOS app bundle (no DMG, arm64 + x64)
npm run dist # Build and package as DMG for distribution
./setup.sh # First-time setup: npm install + npm start
There are no tests or linting configured.
Architecture
This is a macOS Electron desktop app for batch-renaming photo files. It follows strict Electron security practices: contextIsolation: true, nodeIntegration: false.
Process boundary: All filesystem access lives exclusively in src/main/ (main process). The renderer never touches fs directly.
File structure
src/
├── main/
│ ├── index.js # Main process entry point; creates BrowserWindow, calls registerAll()
│ └── ipc/
│ ├── index.js # registerAll(mainWindow) — delegates to folder and files modules
│ ├── folder.js # select-folder, reveal-folder
│ └── files.js # list-images, read-image, rename-files
├── preload/
│ └── index.js # Bridges IPC to window.api via contextBridge (isolated context)
└── renderer/
├── index.html # App shell (dark theme, CSS variables in :root)
├── style.css # All CSS
├── renderer.js # Main renderer logic; imports state and handlers
├── state.js # Shared mutable state: files[], currentFolder, selectedIdxs, sortMode
└── handlers/
├── drag-drop.js # Card drag-and-drop reorder (single and multi-card)
├── selection.js # Rubber-band selection, Shift-click, Cmd+click
├── pinch-zoom.js # Trackpad pinch to resize thumbnails (CSS --thumb-size, 150–400px)
└── hover-preview.js # Hover preview overlay
IPC surface
Defined in src/main/ipc/, bridged via src/preload/index.js as window.api:
| Channel | Direction | Description |
|---|---|---|
select-folder |
invoke | Opens native folder picker, returns path or null |
list-images |
invoke | Reads directory, returns {name, path, mtime, size}[] filtered to image extensions, sorted by filename |
read-image |
invoke | Reads file, returns base64 data URL for display |
rename-files({folderPath, files, prefix, digits}) |
invoke | Two-phase rename: temp names first, then final names to avoid collisions |
reveal-folder |
invoke | Opens folder in Finder via shell.openPath |
fullscreen-change |
push (main→renderer) | Sent on enter-full-screen / leave-full-screen window events |
Renderer (src/renderer/)
Uses ES module imports (type="module"). No framework.
State (src/renderer/state.js):
files[]— ordered array of file objects; order determines rename sequenceselectedIdxs—Set<number>of selected card indicescurrentFolder— active directory pathsortMode—'name'|'date'|null
Thumbnail loading: Uses IntersectionObserver with rootMargin: '400px 0px' — images load lazily as cards enter the viewport. DOM card elements are created immediately without src; the observer fills in img.src on entry. Drag-and-drop reorder remaps existing card elements via card.dataset.filepath to avoid re-fetching images.
Styling: All CSS lives in src/renderer/index.html. Dark theme with CSS variables defined in :root. The macOS traffic-light buttons sit in #titlebar with -webkit-app-region: drag.
Build output: electron-builder targets DMG for arm64 and x64. The app icon must be at assets/icon.icns.