# TransferForge (CLI prototype) TransferForge is a working prototype that performs a checksum-verified, resumable, parallel transfer of a shoot folder (photos, video, audio, and anything else a memory card holds) to a destination, and produces a client-deliverable JSON transfer manifest grouped by media type (RAW / JPEG / Video / Audio / Other) with per-group file counts and byte totals. It is built for photographers and video teams who need a "proof of transfer" document they can hand to a client or keep for their own records after offloading a card. TransferForge shares its copy+verify engine with the sibling tools CopySure (checksum-verified copy) and MoveGuard (checksum-verified move) in the same product line -- each file is copied to a temporary name, the freshly written destination file is re-read and re-hashed, and the hash is compared against the source before the file is renamed into place, so nothing is ever left half copied or unverified. What TransferForge adds on top of that proven engine is a different deliverable: instead of a plain per-file console log, it produces a professional, media-aware JSON report suitable for attaching to an invoice or archiving alongside the footage. Explorer integration (drag-and-drop transfer panels, shell context menus) and any sync rules from the full product concept are on the roadmap and not part of this CLI prototype -- see ../plan.md for the full product plan. ## Build from source Requires Go 1.24+, no external dependencies. go build -o transferforge . Cross-compile for another platform: GOOS=windows GOARCH=amd64 go build -o transferforge.exe . GOOS=darwin GOARCH=arm64 go build -o transferforge . ## Usage transferforge transfer --report report.json [--workers N] [--client "Acme Wedding Co"] [--job "2026-08-10 Smith Wedding"] Flags: --report PATH Path to write the JSON transfer manifest (required) --workers N Number of parallel copy workers (default 4) --client TEXT Free-text client name, carried through into the report as-is --job TEXT Free-text job/shoot name, carried through into the report as-is transferforge walks recursively and copies every file to , preserving the relative folder structure. Each file is copied using the same checksum-verified technique as CopySure: written to a temp name first, then the destination is re-hashed and compared against the source hash before being renamed to its final path. If a destination file already exists with a byte-identical, hash-matching copy, it is skipped instead of re-copied -- so re-running the same transfer command is safe and resumable, and only files that changed (or are new) at the source are actually copied. Use --workers to control how many files are copied in parallel. ### Media type grouping Each file's extension (case-insensitive) is classified into one group: RAW .raw .cr2 .cr3 .nef .arw .dng .orf .rw2 JPEG .jpg .jpeg Video .mp4 .mov .mxf .avi .mkv .braw Audio .wav .mp3 .aac .m4a Other everything else ### Report JSON shape { "generated_at_utc": "2026-08-10T01:52:00Z", "client": "Acme Wedding Co", "job": "2026-08-10 Smith Wedding", "source": "E:\\DCIM", "destination": "D:\\Shoots\\Smith Wedding", "groups": [ { "type": "RAW", "file_count": 4, "total_bytes": 168 }, { "type": "JPEG", "file_count": 3, "total_bytes": 123 }, { "type": "Video", "file_count": 1, "total_bytes": 42 }, { "type": "Audio", "file_count": 1, "total_bytes": 42 }, { "type": "Other", "file_count": 1, "total_bytes": 22 } ], "total_files": 10, "total_bytes": 397, "verified_ok": 10, "verify_failures": 0, "skipped_already_present": 0, "files": [ { "path": "shoot001.cr2", "type": "RAW", "size": 42, "sha256": "...", "status": "copied" }, ... ] } "groups" always lists all five media types, in that fixed order, even if a group had zero files transferred (file_count and total_bytes are 0 in that case). Each entry under "files" has status "copied" (new or changed file written and verified), "skipped" (destination already had a matching, verified copy), or "failed" (the file was copied but the post-write hash did not match the source, so it was NOT left at the destination -- the transfer continues with the rest of the batch, and verify_failures reflects the true count). A client-facing report is never allowed to claim overall success while verify_failures is nonzero; the CLI also exits with status code 2 if any file fails verification, so scripts can detect a partial transfer. transferforge prints a human-readable summary to stdout as the transfer runs (per-file status, per-media-type breakdown, and any failures) -- that is for the operator running the transfer. The JSON file written to --report is the artifact meant to be handed to the client or archived. ## Prebuilt binaries See ../downloads/ for prebuilt binaries (Windows/macOS/Linux) and CHECKSUMS.txt for their SHA-256 hashes. These are unsigned indie builds -- Windows SmartScreen and macOS Gatekeeper will warn on first run, which is expected until a code-signing certificate is in place.