Skip to content

CLI Reference

asdfmonster261 edited this page May 4, 2026 · 6 revisions

CLI Reference

patchforge build — Update Patch mode

patchforge build \
  --source-dir game_v1.0/ \
  --target-dir game_v1.1/ \
  --output-dir dist/ \
  --app-name "My Game" \
  --version 1.1 \
  --engine hdiffpatch \
  --compression set6_lzma2 \
  --arch x64

Output: dist/MyGame_1.1_patch_x64.exe

Use --patch-exe-name to override the output filename stem:

patchforge build ... --patch-exe-name "MyGame_Update_Nov2025"
# → dist/MyGame_Update_Nov2025_x64.exe

All build flags

Flag Default Description
--project FILE Load settings from a .xpm project file (CLI flags override)
--source-dir DIR Original (old) game folder
--target-dir DIR Patched (new) game folder
--output-dir DIR . Directory for the output .exe
--app-name NAME Application name shown in the patcher UI
--app-note TEXT Short subtitle shown next to the app name
--version VER Version string (e.g. 1.1)
--description TEXT Optional description shown in the patcher
--copyright TEXT Copyright notice shown in the patcher window
--contact TEXT Contact email or URL shown in the patcher window
--company-info TEXT Publisher / company name shown in the patcher window
--window-title TEXT Title bar text of the patcher window (defaults to app name)
--patch-exe-name STEM Output exe filename stem (default: auto from app name + version)
--patch-exe-version VER Informational version string for the patch exe (e.g. 1.0.0.0)
--engine ENGINE hdiffpatch hdiffpatch | jojodiff
--compression PRESET engine default Compression preset key (see Engines-and-Presets)
--threads N 1 Worker threads for patch generation
--quality LEVEL max HDiffPatch compressor quality: fast / normal / max
--verify METHOD crc32c crc32c | md5 | filesize
--find-method METHOD manual manual | registry | ini
--registry-key KEY Windows registry key path
--registry-value VALUE InstallPath Registry value name
--ini-path FILE Path to INI file
--ini-section SECTION INI section name
--ini-key KEY INI key name
--arch ARCH x64 x64 | x86
--icon-path FILE .ico file to embed as the patcher's icon
--backdrop FILE Background image for the patcher window (PNG/JPEG/BMP)
--extra-args ARGS Extra CLI arguments passed verbatim to the diff engine
--delete-extra-files on Delete game files absent from the target version
--no-delete-extra-files Keep game files absent from the target version
--preserve-timestamps off Preserve original file timestamps when applying the patch
--run-on-startup CMD Shell command to run when the patcher window first opens
--run-before CMD Shell command to run immediately before patching starts
--run-after CMD Shell command to run after patching succeeds
--run-on-finish CMD Shell command to run when the patcher window closes (always, not just on success)
--extra-file SRC[:DEST] Bundle an extra file into the patch exe; optional :DEST sets the relative install path (repeatable)
--backup-at MODE same_folder disabled | same_folder | custom
--backup-path DIR Backup directory (used when --backup-at custom)
--save-project FILE Save resolved settings to a .xpm after building
--check off Validate inputs and resolved settings, then exit without invoking the engine
--quiet / -q off Suppress progress output (errors still go to stderr); mutually exclusive with --verbose
--verbose / -v off Verbose output (reserved for future debug logging); mutually exclusive with --quiet
--json off Emit a single JSON result object on stdout (implies --quiet for progress)

Project file commands

patchforge new-project --output patch.xpm --app-name "My Game" --engine hdiffpatch
patchforge show-project patch.xpm

patchforge repack — Repack mode

patchforge repack \
  --game-dir game/ \
  --output-dir dist/ \
  --app-name "My Game" \
  --codec lzma \
  --compression max \
  --threads 8 \
  --arch x64

Output: dist/MyGame_1.0_installer_x64.exe

With optional components:

patchforge repack --game-dir game/ --app-name "My Game" \
  --component '{"label":"High-res textures","folder":"hires/","default_checked":false,"group":""}' \
  --component '{"label":"English voices","folder":"voices_en/","default_checked":true,"group":"voices"}' \
  --component '{"label":"Japanese voices","folder":"voices_jp/","default_checked":false,"group":"voices"}'

Load a .xpr project file and override individual fields:

patchforge repack --project installer.xpr --threads 16 --output-dir dist/

Component JSON fields

Each --component is a JSON object:

Key Type Description
label string Display name shown in the installer
folder string Path to the folder of files for this component
default_checked bool Whether the component is selected by default
group string Empty = standalone checkbox; shared name = mutually exclusive radio-button group
requires int[] 1-based indices of components that must be selected for this one to be enabled
shortcut_target string Overrides the main shortcut target when this component is selected
sac_warning bool Show an antivirus / Smart App Control warning when this component is selected
external bool Store this component's compressed stream in a separate .bin sidecar file; components in the same group share one sidecar

All repack flags

Flag Default Description
--project FILE Load settings from a .xpr project file (flags override)
--game-dir DIR Game directory to compress
--output-dir DIR . Directory for the output .exe
--app-name NAME Application name shown in the installer
--app-note TEXT Short subtitle shown next to the app name
--version VER Version string (e.g. 1.0)
--description TEXT Description shown in the installer
--copyright TEXT Copyright notice
--contact TEXT Contact email or URL
--company-info TEXT Publisher / company name
--window-title TEXT Installer title bar text (defaults to app name)
--installer-exe-name STEM Output exe filename stem (default: auto)
--installer-exe-version VER Informational version string for the exe
--codec CODEC lzma lzma | zstd
--compression QUALITY max LZMA: fast | normal | max — Zstd: fast | normal | max | ultra
--threads N 1 Compression threads (auto-populated from CPU count in GUI)
--arch ARCH x64 x64 | x86
--icon-path FILE .ico file to embed as the installer's icon
--backdrop FILE Background image (PNG/JPEG/BMP); displayed at 616:353 aspect ratio
--install-registry-key KEY Registry key written to HKCU after install
--run-after CMD Shell command to run after successful install
--detect-running EXE Warn if this process is running before install
--close-delay N 0 Seconds before auto-closing after success (0 = stay open)
--required-free-space GB 0 Warn if disk space is below this threshold in GB (0 = disabled)
--no-verify-crc32 Skip CRC32 integrity check after installation (default: enabled)
--shortcut-target REL_PATH Relative path to the exe for shortcuts (e.g. Bin\Game.exe)
--shortcut-name NAME Shortcut display name (default: app name)
--shortcut-desktop / --no-shortcut-desktop off Create a Desktop shortcut
--shortcut-startmenu / --no-shortcut-startmenu on Create a Start Menu shortcut
--component JSON Add an optional component (repeatable; see above)
--no-uninstaller Omit the uninstaller and Add/Remove Programs registration
--split-bin auto Force the base game archive into a base_game.bin sidecar even below the 3.5 GB auto-split threshold
--max-part-size-mb MB 0 Split base_game.bin into .001, .002, ... parts of this size in MB (0 = no split)
--save-project FILE Save resolved settings to a .xpr after building
--check off Validate inputs and resolved settings, then exit without invoking the engine
--quiet / -q off Suppress progress output (errors still go to stderr); mutually exclusive with --verbose
--verbose / -v off Verbose output (reserved for future debug logging); mutually exclusive with --quiet
--json off Emit a single JSON result object on stdout (implies --quiet for progress)

Project file commands

patchforge new-repack-project --output installer.xpr --app-name "My Game" --compression max
patchforge show-repack-project installer.xpr

Scripting

Exit codes

The CLI uses distinct exit codes so scripts can branch on outcome class:

Code Meaning
0 Success
1 Generic / unspecified runtime error
2 Argparse usage error (unknown flag, missing required value, mutually-exclusive group conflict, etc.)
3 Input error: missing file/dir, malformed project file, malformed --component JSON, or any failure validating user-supplied data
4 Build error: engine ran but produced an error or non-zero output

--check and --json for scripted use

# Validate without building
if patchforge build --project app.xpm --check --quiet; then
    echo "settings ok"
fi

# Capture resolved settings as JSON
patchforge build --project app.xpm --check --json | jq .
# {"success": true, "checked": true, "app_name": "My Game", ...}

# Run a build and post-process the result
result=$(patchforge build --project app.xpm --json)
output=$(echo "$result" | jq -r .output_path)
echo "Built: $output"

In --json mode the CLI emits exactly one JSON object on stdout, and the exit code still reflects success/failure (so scripts can choose to branch on either the JSON success field or the exit code).

Tab completion (optional)

argcomplete provides bash/zsh/fish completion for subcommands and --engine / --codec choice lists. Install it once and register the completer in your shell rc file:

pip install argcomplete
eval "$(register-python-argcomplete patchforge)"

PatchForge's CLI is wired up to use argcomplete if it's available; if it isn't installed, the autocomplete call is a silent no-op and nothing else changes.


patchforge archive — Steam archive mode

Steam-side download / poll / upload pipeline. Requires the optional archive extra (pip install patchforge[archive]). See Archive-Mode for the full reference; the most-used subcommands are summarised here.

patchforge archive login                                          # one-shot QR / password
patchforge archive download --project mygame.xarchive             # single pass over project apps
patchforge archive download --project mygame.xarchive \
    --restart-delay 1800                                          # poll every 30 min
patchforge archive depot --app 4048390 --depot 4048391 \
    --manifest 5520155637093182018                                # historical-build pull
patchforge archive show-app 730                                   # raw product-info for one appid
patchforge archive new-project --output mygame.xarchive
patchforge archive add-app     mygame.xarchive 730
patchforge archive add-app     mygame.xarchive 4048390 --branch beta --platform linux
patchforge archive remove-app  mygame.xarchive 730
patchforge archive show-project mygame.xarchive

Subcommands

Subcommand Purpose
archive login QR code or password login. Saves a refresh token to archive_credentials.json; subsequent commands reuse it.
archive logout Clear the saved refresh token (web API key + bot tokens are preserved).
archive show-app APPID... Print raw product-info for one or more app IDs (depots, branches, build IDs, DLC).
archive download The main workhorse — single-pass over --app-ids or polling driver over a --project of apps.
archive depot DepotDownloader-style historical pull of a single (--app, --depot, --manifest) triple.
archive new-project Create a fresh .xarchive JSON project.
archive add-app PROJECT APPID [--branch NAME] [--platform {windows,linux,macos}] [--crack {off,gse,coldclient,all}] Append an app to an existing .xarchive. Duplicate app_id → exit 3. --crack sets a per-app override; off skips crack for this app even when the project default enables one.
archive remove-app PROJECT APPID Drop an app from an existing .xarchive. Missing app_id → exit 3. Other state (manifest_history etc.) is preserved.
archive show-project FILE Pretty-print a .xarchive to stdout (with manifest_history summary).

See Archive-Mode for every flag, the project-file schema, and the BBCode template format.