feat(cli): filesmith command line and Claude skill (#30) - #31
Merged
Merged
Conversation
Refs #30 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Proved: packed Filesmith.exe runs app.asar/out/main/cli.js under ELECTRON_RUN_AS_NODE (with and without --use-system-ca), resourcesPath = <install>/resources. No asarUnpack needed; the script path stays app.asar/out/main/cli.js. Refs #30 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… engine toolResolver, pid/paths, ncnnModels, comfy/store, generate, net, registry read paths and fetch from one provider set by the app (and later the CLI). Startup moves to boot.ts. comfy-upscalers.json and integrity.json are written atomically per process. Refs #30 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Refs #30 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ve ComfyUI record installPid, installComfyEngine and companion downloads take a machine-wide lock file, an AbortSignal and a byte-progress callback. ensureUv moves to uvInstall.ts (public, downloads to userData/uv). The app records the ComfyUI it launched in comfy-live.json. Refs #30 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…eadiness checks removebg runs an installed rembg with U2NET_HOME=%APPDATA%\Filesmith\models\rembg; removebg:status.ready is now true only when the tool and model exist. Jobs take allowDownload; with false (the CLI) a missing AI runtime fails with 'Run: filesmith setup <tool>'. rembg 2.0.85 downloads into <U2NET_HOME>/models/<name>/<name>.onnx, so presence accepts that layout as well as the flat one. Refs #30 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Refs #30 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… help Refs #30 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…idation Refs #30 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Refs #30 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Covers the literal, folder, relative glob, ** glob and absolute glob routes and asserts the absolute paths come back unchanged. Refs #30 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e is touched Refs #30 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…n cancel convert, compress, resize, upscale and removebg run on a JobQueue in the CLI process with allowDownload false. Ctrl+C and a closed stdout cancel running and queued jobs and exit 130. Refs #30 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… always last - An --out folder whose nearest existing ancestor is a file, or whose drive does not exist, is exit 2 OUT_DIR_MISSING before planning in both modes. - Run-level failures after the run event end with one summary whose counts match the events above it; an internal crash in JSON mode also ends with a summary. - The dry-run summary totals inBytes of ready jobs. - runPlanned starts nothing when the signal was aborted before the run. - Ctrl+C while reading stdin cancels at once (exit 130). - Tests: uncreatable --out (under a file, mkdirp throws, missing drive) for dry and real runs; e2e checks no upscaler process outlives a closed stdout. Refs #30 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…images, compress Refs #30 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…y default) GenerateOptions gains outDir; the app leaves it unset and keeps Downloads. Refs #30 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nd real runs runGenerate now checks uncreatableReason before scanning or running and turns a failing mkdirp into OUT_DIR_MISSING (exit 2) instead of INTERNAL, matching files.ts. Adds generate tests for --out as a file, a folder under a file, a missing drive and mkdirp throwing (dry and real), plus the non-cancel engine failure path. Refs #30 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…te, realesrgan and remove Progress with bytes, ETA and a 5 s heartbeat; GPU gate and disk check; cross-process locks; removal goes to the Recycle Bin, or needs --permanent above 5 GB. Refs #30 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Refs #30 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The shims run Filesmith.exe as Node (ELECTRON_RUN_AS_NODE) with --use-system-ca and NODE_USE_ENV_PROXY. path.ps1 edits HKCU PATH safely; uninstall removes the entry except during updates. Refs #30 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…Settings button Refs #30 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…convert Also fix verify-bundle ignoring the resources root argument when --manifest is not passed. Refs #30 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ames doctor warnings A result line whose name overflows the column now keeps a two-space gap before the sizes, a one-file folder output reads '1 file', and doctor's closing line counts warn checks instead of a bare 'No problems found.' Stale 'no Electron' comments now refer to the engine env. Refs #30 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
File names, paths and tool or engine messages could carry ESC, OSC, C1 CSI or a bare carriage return and spoof or hide terminal output. One pure sanitizer turns line breaks and tabs inside a field into spaces and every other C0, DEL or C1 control into U+FFFD; the human reporter applies it to each value it prints, and crash stacks keep only their newlines. JSON mode is unchanged. Refs #30 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…own folder Refs #30 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…g files 'convert a.pdf photo.png --to png' now ends with "Nothing to convert: 1 file skipped (already png), 1 file cannot become png (a.pdf)." instead of "No input can be converted to png". Exit code stays 2. Refs #30 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…mitted The CLI picks the seed once (same range as the engine) and each image uses seed + i, so every done event carries a seed that repeats that image. Refs #30 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Refs #30 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Refs #30 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…uccess Every tool now writes `name (tag).filesmith-part.ext` (folders: `base.filesmith-part`) next to the reserved placeholder and renames it onto the final name only when the job succeeded. A failed or canceled job removes both, so a half-written file never appears under the final name. The reservation, collision names and dry-run predictions are unchanged; the rename only ever replaces our own untouched empty placeholder, otherwise the output takes the next free name. Covers convert, compress, resize, the PDF tools (files and folders), archives, upscale, removebg and generate. Refs #30 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… hard kills Filesmith.exe in Node mode never runs a SIGINT/SIGBREAK handler on Windows: the GUI-subsystem process is attached to the console by Electron after libuv registered its console control handler, so the default handler ends it at once (0xC000013A). The CLI now reads the console in raw mode under Electron, where the Ctrl+C key arrives as 0x03 instead of a signal: jobs emit `canceled`, the summary prints, exit 130, ffmpeg is stopped, and cmd no longer asks "Terminate batch job". Ctrl+Break, closing the window or a hard kill still end the process at once; a detached watchdog started with the first output then kills the tools it left and removes its part files and placeholders. A second Ctrl+C kills the tools before leaving. Refs #30 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Refs #30 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # package-lock.json # package.json
Refs #30 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #30.
What
filesmithcommand bundled with the app and on the per-user PATH: convert, compress, resize, upscale, removebg, generate,pdf <tool>, plus formats, doctor, setup, skill. Verb-first, option names and values mirror the app,--dry-runeverywhere,--jsonNDJSON events (schema v1), exit codes 0/1/2/130, never overwrites.filesmith.cmdand an sh shim, so it works while the app is open and its jobs never reach the app.filesmith setup <tool>is the only command that downloads (progress with bytes, ETA and heartbeats; cross-process locks).resources/skill/filesmith, installed byfilesmith skill installor Settings > CLAUDE.docs/cli.md. Version 0.6.0.Engine changes outside src/cli
EngineEnv provider (no electron imports in the engine), shared boot, dry-run output planners, readiness checks and
allowDownload, explicit rembg install with a pinned model folder (fixes the always-false removebg ready flag), cross-process install locks, atomic state writes,comfy-live.json,GenerateOptions.outDir, per-user PATH in the installer.Atomic outputs (app and CLI): every tool now writes
name (tag).filesmith-part.ext(folders:base.filesmith-part) next to the reserved placeholder and renames it onto the final name only on success (src/main/atomicOutput.ts). A failed or canceled job removes both. Reservation, collision names and dry-run predictions are unchanged; the rename only ever replaces our own untouched empty placeholder, otherwise the output takes the next free name. Covers convert, compress, resize, PDF tools (files and folders), archives, upscale, removebg, generate.For the owner
setup remove --permanentabove 5 GB, two additive event fields, LibreOffice checked at run time, barefilesmithprints help, README left as logo and badges (docs/cli.md instead).electron.exe(node.exe: handler runs; electron.exe: killed), and the same loss reproduces in pythonw when a handler is registered beforeAttachConsole(after it: works). No JavaScript can register a handler again. Fix: under Electron the CLI reads\\.\CONIN$in raw mode, where the Ctrl+C key arrives as byte 0x03 instead of a signal (src/cli/consoleCtrlC.ts). Side effect: cmd never sees the Ctrl+C, so the "Terminate batch job (Y/N)?" prompt (spec O3) is gone and exit 130 passes through.taskkill /F, programmaticGenerateConsoleCtrlEvent. For those a small detached watchdog (src/cli/watchdog.ts, started with the first output of a run, Electron runtime only) stops the tools the run left running (pid plus image-name check) and removes its part files and placeholders. No summary or exit 130 in those cases.> file,| findstr), Windows starts Filesmith.exe without a console, so a Ctrl+C key never reaches it and the run completes (cmd then asks "Terminate batch job"). A native console launcher (O3) would close this; not done here.Verification
npm test: 84 files, 817 passed, 1 skipped (new:test/atomic-output.test.ts,test/atomic-tools-live.test.tswith real ffmpeg/magick/mutool/7-Zip: a canceled video compress, a failing convert, resize, split-pages cancel and a corrupt archive extract leave nothing; successes leave exactly the final file with unchanged collision names;test/cli-watchdog.test.ts).npm run typecheck,npm run lint,npx prettier --check .,npm run build: all pass.npm run test:e2e(withdist/win-unpackedbuilt from this commit): 68 passed, 1 skipped (the opt-in visual capture). The two GPU tests that failed earlier (upscale: Real-ESRGAN 2x ...,generate: one 512px image ...) passed in this run. App workflows (convert, compress, PDF folders, archives, upscale, removebg, generate) still report the final path in theirdoneevents.e2e/cli-packed.spec.ts›Ctrl+C in a console cancels cleanlyruns the packed cmd shim in a new minimized console (e2e/ctrlc-console.ps1), writes a Ctrl+C key record into the console input during a 1080p h265 compress, and checks exit 130,1 canceledon screen, no "Terminate batch job", no new ffmpeg.exe and only the source left.e2e/cli.spec.ts›a CLI killed outright ...runs the CLI under Electron,taskkill /Fs it mid-encode (ffmpeg orphaned) and checks the watchdog stops ffmpeg and removes the part and the placeholder. Packed spec 4/4, CLI spec 17/17.Filesmith-Setup-x64-0.6.0.exesilently (/S), exe 0.6.0, app relaunched and left open. Hands-on against the INSTALLED shims, app open, 1080pcompress --codec h265, each in a fresh real console, interrupt ~8 s in:filesmith.cmd ... --json:canceledevent,summarywithcanceled: 1, exitCode: 130, process exit 130 after 0.4-0.6 s, no ffmpeg.exe left, folder holds only the source (the.filesmith-part.mp4and the placeholder were there during the run).stop long video.mp4,1 file: 0 ok, 0 skipped, 0 failed, 1 canceled, exit 130, no ffmpeg, only the source.GenerateConsoleCtrlEvent(CTRL_BREAK)(cmd and sh shims) andGenerateConsoleCtrlEvent(CTRL_C)(cmd): Filesmith.exe ends at once (0xC000013A via sh; cmd then waits on its prompt), no ffmpeg left, and the watchdog removed the part file and placeholder: only the source remains.doneand exit 0, then cmd's prompt. This is the documented limit above.WriteConsoleInputWis what a key press puts in the console input, and in raw mode the console delivers it as 0x03 rather than a signal.filesmith skill install/ status; silent uninstall/reinstall PATH handling.🤖 Generated with Claude Code