Skip to content

Latest commit

 

History

History
475 lines (361 loc) · 17.8 KB

File metadata and controls

475 lines (361 loc) · 17.8 KB

CLI Reference

The zar command-line tool provides pack, extract, convert, and batch operations. It matches the zarchive.exe exit codes and behavior for compatibility.

The global tool command is zar; the standalone release bundles ship the same CLI as ZArchiveSharp (ZArchiveSharp.exe on Windows) and require the matching .NET runtime. Help and usage text always name the executable you launched, so swap zar for ZArchiveSharp when running a bundle.

Installation

dotnet tool install -g ZArchiveSharp.Cli

Usage

zar [options] [input] [output]
zar zstd -c|-d [options] [input] [output]
zar seekable compress|decompress|list [options] [input] [output]

Args are exactly input [output], like zarchive.exe: extras fail with -1 / Too many paths specified, never silently dropped. -o/--output occupies the output slot (zar in -o out extra is a usage error); zar --iso x [out.zar] takes the output positionally or via -o, not both.

Unknown options (except after the zstd/seekable subcommand tokens, where they belong to that subcommand's parser) are -1 usage errors rather than silently becoming input paths. -- ends option parsing everywhere — the plain pack/extract shape and inside zar zstd / zar seekable — so a path that begins with - stays reachable: zar -- -odd out.zar and zar zstd -c -- -in.bin out.zst.

Value-taking options must not be followed by another known option (zar --jobs --quiet in out is -1), but other dash-prefixed values are accepted as paths: zar -o -out.zar src and zar --iso -game.iso out.zar work. Missing values for -o/--iso/--jobs/--level/--policy/--dict/--mode/--seven-zip are always -1. zar -o game.zar without an input path is -1, and --iso cannot be combined with --batch.

Usage stats, the GitHub update check, and the bug-report sink are opt-out: pass --no-telemetry or set ZAR_BUG_REPORT=off; --help/--version launches never send anything. See Telemetry and Update Checks.

Commands

Compress/Decompress Single zstd Streams

zar zstd -c [input] [output]
zar zstd -d [input] [output]

Compresses or decompresses a single zstd stream (not a .zar archive). Omitted input reads stdin, omitted output writes stdout, so pipes work:

zar zstd -c big.bin | zar zstd -d > big.back
zar zstd -c big.bin compressed.zst
zar zstd -d compressed.zst restored.bin

With --dict, both sides use the dictionary (zstd -D semantics — the dictionary file is never stored, keep it alongside):

zar zstd -c --dict words.dict small.txt small.zst
zar zstd -d --dict words.dict small.zst restored.txt

Subcommand options: -c/--compress, -d/--decompress (exactly one is required), -l/--level <N> (compress only), --dict <file>, --check/--no-check (compress only, last wins), --stdout (explicit stdout; an error together with an output path), -q/--quiet, -h/--help. Inside zar zstd, -c means --compress (not --stdout).

Note: a pack/extract path literally named zstd must be spelled ./zstd so it is not taken for the subcommand.

Seekable zstd Files

zar seekable compress [input] [output]
zar seekable decompress [input] [output]
zar seekable list <file>

Compresses, decompresses, or inspects seekable zstd files (zeekstd-compatible framing: independently compressed frames plus a seek table) — not single-frame zar zstd streams and not .zar archives. Omitted input reads stdin (compress streams it in 128 KiB chunks; decompress buffers it, since the Foot table lives at the end of the file), omitted output writes stdout, so pipes work:

zar seekable compress big.bin | zar seekable decompress > big.back
zar seekable compress big.bin big.zst
zar seekable decompress big.zst restored.bin
zar seekable list big.zst

Compress derives the output name when omitted (<input>.zst); decompress defaults to stdout. Compress options: -l/--level <N> 1–22 (default: 3, like the oracle — an explicit global -l before seekable overrides it), -s/--frame-size <S> with B/K/M/G suffixes (default: 2M, capped at 1G), --frame-size-policy compressed|uncompressed (default: uncompressed), --checksum/--no-checksum (also --check/--no-check; default on, last wins), --seek-table-file <file> (write a standalone Head table there instead of appending the Foot table). Decompress options: --from/--to byte offsets (--to takes end), --from-frame/--to-frame frame indices (--to-frame takes last), --seek-table-file <file> (read the table from there instead of the file tail). List options: --from-frame/--to-frame/--num-frames, -d/--detail (per-frame table; implied by frame bounds), --seek-table-format foot|head (head means the input IS a standalone table file). -f/--force overwrites existing outputs (default: refuse, -11); -c/--stdout forces stdout; -q/--quiet suppresses the input → output line (ignored by list, whose table always prints). A global --dict with seekable is a usage error (seekable frames carry no dictionary).

Subcommand aliases: c, d, l. A path literally named seekable must be spelled ./seekable.

Deliberate deviations from the zeekstd 0.4.5 CLI: argument shape follows this CLI's convention (positional [input] [output], not -o); existing outputs are refused rather than prompting (-f overrides); sizes always print raw (no humanized units, no -r/--raw-bytes); no progress bar (no --no-progress); --patch-from/--patch-apply (diff engine) and --mmap-prefix are unsupported (managed code, no diff engine); levels run 1–22 (the oracle stops at 19); size suffixes accept any case.

Pack a Directory

zar <directory> [output.zar]

Packs the specified directory into a .zar archive. If no output path is specified, creates <directory_name>.zar in the same location. --dict packs with dictionary frames (extract needs the same --dict); --no-compress stores raw and ignores --dict.

Examples:

# Pack with default settings
zar C:\game

# Pack to specific output
zar C:\game C:\archives\game.zar

# Pack with custom compression level
zar -l 9 C:\game C:\game.zar

Extract an Archive

zar <archive.zar> [output_dir]

Extracts the archive to the specified directory. If no output path is specified, creates <archive_name>_extracted in the same location.

Examples:

# Extract with default output
zar C:\game.zar

# Extract to specific directory
zar C:\game.zar C:\extracted\game

Convert XISO to ZAR

zar --iso <game.iso> [output.zar]

Converts an Xbox ISO (XISO) file to a .zar archive. Requires the XISOSharp dependency.

The CLI consumes XISOSharp as a NuGet package, so zar --iso works out of a clean clone. Building with -p:XisoSharpAvailable=false produces a tool without XISO support: zar --iso fails fast on stderr (exit -1) with rebuild instructions and --help marks the flag unavailable; everything else works.

Redump ISOs (full disc dumps starting with the video partition) are auto-detected by exact file size: the CLI resolves the wave-dependent game partition offset from the same XgdTables the XISOSharp.Cli --zar mode uses (PVD wave read for the ambiguous sizes, video-type-0 fallback when the wave is unreadable) and packs the game partition — never the video area. A Redump pack is byte-identical to packing the plain extracted XISO. game derives from game.redump.iso to game.zar.

Examples:

# Convert with default output
zar --iso C:\game.iso

# Convert to specific output
zar --iso C:\game.iso C:\game.zar

Batch Operations

zar --batch <input_dir> [output_dir]

Processes all eligible files in the input directory in parallel. --mode selects the pipeline stages per entry (ZarManager parity):

  • auto (default): archives run the 7z container stage (extract to a unique temp_<stem>_<id>, first .iso keeps going as <stem>.iso, otherwise the whole tree becomes <stem>/) then continue to .zar; plain ISOs convert straight to .zar; directories pack to .zar.
  • extract-archive (aliases extract-arc, archive): .zip/.rar/.7z/.tar/.gz only — extract with 7z and stop (no .zar).
  • extract-iso (aliases extract, iso): .iso only — convert to .zar.
  • compress: directories only — pack to .zar.

7z stays external: the CLI uses 7z/7zz from PATH (plus the standard Windows install location); --seven-zip <exe> overrides the path, and archive items fail with rebuild-free instructions when no binary is found. --delete-source removes each source (archive and intermediate) after its .zar succeeds, mirroring ZarManager's keep_originals == false; sources are kept by default (--keep-originals, last wins against --delete-source). A source is deleted only after the terminal .zar stage actually completed — a failed or skipped downstream stage keeps the original. The collision --policy applies to every stage output (intermediate and .zar), and same-stem archives get unique scratch/extraction destinations so parallel workers never race. All three flags are --batch-only.

Examples:

# Batch process with defaults
zar --batch C:\games

# Batch process with 8 workers
zar -b -j 8 C:\games C:\archives

# Pack only the extracted directories, deleting each source on success
zar -b --mode compress --delete-source C:\games C:\archives

# Extract just the containers, keep the trees/ISOs, no .zar files
zar -b --mode extract-archive C:\games C:\unpacked

# Use a 7z outside PATH
zar -b --seven-zip "D:\tools\7z.exe" C:\games C:\archives

Options

Compression

Option Short Description Default
--level <N> -l Compression level (1–22; seekable compress: 1–22, default 3) 6
--dict <file> Dictionary file (pack/zstd; never stored, keep alongside) none
--check / --no-check Write / omit content checksums (pack/zstd compress; last wins; seekable compress defaults on) off
--no-compress Store blocks without compression (ignores --dict) false

Input / Output

Option Short Description Default
--stdout -c Stream to stdout — with zar zstd (its default output) and zar seekable compress/decompress; inside zar zstd, -c means --compress off

Output

Option Short Description Default
--output <path> -o Output path Auto-derived
--policy <P> -p Collision policy: fail, skip, overwrite, auto-rename (--batch only) fail

Parallelism

Option Short Description Default
--jobs <N> -j Parallel workers: batch items plus 64 KiB block fan-out inside a single pack/extract (capped by CPU; byte-identical) 4
--mode <M> Batch stages: auto, extract-archive, extract-iso, compress (--batch only) auto
--seven-zip <exe> 7z binary for the archive stage: explicit path, else PATH + install location (--batch only) auto-detect
--keep-originals / --delete-source Keep / delete each batch source after its pack succeeds (--batch only, last wins) keep

Other

Option Short Description
--quiet -q Suppress output
--no-telemetry Disable usage stats, update checks and bug reports (also ZAR_BUG_REPORT=off)
--version -v Show version
--help -h Show help

Telemetry and Update Checks

The CLI sends three kinds of outbound traffic; all are opt-out:

  • Usage stats — one anonymous hit per non-informational launch (application id and version only) to the PureLogicCode ApplicationStats API.
  • GitHub update check — a background lookup of the latest release. When a newer version exists it prints a notice on stderr and, on an interactive console only, offers to open the release page or the platform download. The prompt waits at most 15 s and never blocks redirected/piped runs.
  • Bug reports — logging flows through Serilog and Warning/Error/Fatal events are forwarded with environment, error, and exception details. The user profile directory and account name are redacted before sending. At most 9 reports/minute.

Disable all three with --no-telemetry or by setting ZAR_BUG_REPORT to off, 0, false, or no. --help/--version launches never send anything. The exit flush is best-effort and bounded to well under a second, so a slow or unreachable endpoint never delays the command.


Exit Codes

The CLI returns the same exit codes as zarchive.exe for compatibility:

Code Constant Description
0 Ok Success
-1 BadUsage Usage error (too many paths, unknown option, missing option value, invalid input)
-3 OutputNotDirectory Extract output path exists and is not a directory
-4 OutputDirectoryNotCreated Extract output directory could not be created
-10 NotFound Archive file not found, or pack output exists and is not a regular file
-11 Refused Archive failed to open, or pack output already exists
-12 ExtractionFailed Extraction failed (corrupt archive or I/O error)
-13 PackFailed Pack failed on archive structure
-14 ArchiveEntryFailed Pack failed to create an archive entry (duplicate or bad path)
-15 InputNotReadable Pack failed to open an input file
-16 PackOutputFailed Pack failed on output I/O
130 Interrupted by Ctrl+C (shell SIGINT convention, not a pack/extract code)

zar zstd reuses this table with no new codes: compress failures report pack codes (-13 failure, -15 unreadable input, -16 uncreatable output), decompress failures report extract codes (-12 failure, -10 missing input). Refusing to overwrite an existing output is -11 on both sides; a missing/unreadable --dict is -1. Errors go to stderr; the input → output line goes to stdout, except to stderr when stdout carries binary data. A file output created by zar zstd is deleted when the run fails, like incomplete pack outputs.

zar seekable reuses the same table the same way: compress failures report pack codes (-13 failure, -15 unreadable input, -16 uncreatable output), decompress and list failures report extract codes (-12 failure — including a missing/unparseable seek table, an out-of-range frame, or a bad range — -10 missing input/table file). Refusals are -11, bad ranges that do not depend on the file (--from past --to, start frame past end frame) are -1. Failed runs delete the file outputs they created.

Batch runs aggregate per-item results: if every failure was a collision refusal under the fail policy, the run exits -11; any other failed item makes it -13, as do an unreadable batch input directory and a missing 7z binary. --mode mismatches and --iso + --batch are -1.


Collision Policies

On --batch runs, when a stage output already exists, the --policy option controls behavior:

Policy Behavior
fail Exit with error code -11 (default, matches zarchive.exe)
skip Skip the item, continue processing
overwrite Delete existing file and write new one
auto-rename Write to {stem}_{n}{suffix} (first free n from 1)

Resolution is race-safe: when parallel batch items (or another process) claim the chosen name between resolve and write/move, the output is re-resolved from the requested path, keeping suffixes canonical (game.zar, game_1.zar, …) instead of compounding. A batch whose only failures are fail-policy collisions exits -11; any other failure makes the batch exit -13.

Single pack/extract/--iso and the zstd/seekable subcommands keep the zarchive.exe contract instead: an existing pack output is refused with -11 (extract overwrites into the destination directory, like the native tool), and an explicit non-fail --policy there is a -1 usage error — never silently ignored. Unknown values (--policy bogus) and a missing value are -1 on every path.


Examples

Basic Pack/Extract Workflow

# Pack a directory
zar C:\myproject C:\myproject.zar

# Verify the archive
zar C:\myproject.zar C:\verify

High-Compression Archive

# Use level 19 for maximum compression
zar -l 19 C:\data C:\data.zar

Batch Processing

# Process all directories in a folder with 8 workers
zar -b -j 8 C:\games C:\archives

# Overwrite existing archives
zar -b -p overwrite C:\games C:\archives

XISO Conversion

# Convert Xbox ISO to ZAR
zar --iso C:\games\game.iso C:\games\game.zar

Seekable Files

# Compress with small frames, inspect, slice-decode one range
zar seekable compress -s 256K big.bin big.zst
zar seekable list big.zst
zar seekable list --detail --from-frame 2 --to-frame 4 big.zst
zar seekable decompress --from 1M --to 2M big.zst slice.bin

Quiet Mode

# Suppress all output
zar -q C:\data C:\data.zar

Stdout Behavior

The CLI produces output matching zarchive.exe:

Pack mode:

Outputting to: C:\data.zar
Adding file1.txt
Adding subdir/file2.dat

Extract mode:

Extracting to: C:\data_extracted
/file1.txt
/subdir
/subdir/file2.dat

Note: Extract entry lines include a leading / (the native quirk) and use OS-native path separators for the Adding display line only.


Differences from zarchive.exe

ZArchiveSharp's CLI is intentionally compatible but has three documented deviations where native behavior is a bug:

  1. Unopenable extract output — Throws an exception (native writes into the dead stream)
  2. Mid-file read errors — Fails the pack with -16 (native silently truncates)
  3. Error string paths — Uses / on every OS (native uses \ on Windows)