Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Archive CLI

Archive commands package gamedata into X-Ray .db or .xdb volumes, inspect their contents, and extract or verify stored files. Use pack for a full distribution and pack-patch for added or modified files relative to an installation.

Packing examples run from a project containing target/gamedata. Inspection and unpacking examples use a db directory in the current working directory. Source paths and output destinations are separate.

Pack an archive

Pack the assembled tree, then verify the written volumes:

xrf-cli archive pack target\gamedata --dest target\db --name gamedata
xrf-cli archive verify --path target\db

Example output excerpt — pack an archive:

Packed 29 file(s) into 1 volume(s) in 23 ms
Phases: 10 ms collecting, 13 ms writing, 0 ms finalizing
Summary: 14 compressed, 15 stored, 0 aliased, 0 skipped
Size: 2.37 MB source, 2.37 MB written
Speed: 103 MB/s

Exit code: 0.

The command compresses file types the engine normally compresses and stores the rest. It writes one volume as gamedata.db; when the archive needs more than one volume, it writes gamedata.db0, gamedata.db1, and so on.

By default, a volume can be up to 1900 MB and receives a header that mounts its contents at $fs_root$\gamedata\. That is the usual setting for a gamedata archive. To add or change one entry, name it:

xrf-cli archive pack target\gamedata --dest target\db --name gamedata `
  --header 'creator="Modder"' --header 'link="www.moddb.com/mods/my-mod"'

Each --header value is key=value, merged over the default header, so naming creator keeps auto_load and entry_point. level_name, level_ver, creator, and link are the entries mod templates conventionally carry; they are yours to set and the engine ignores them.

The engine requires auto_load and entry_point; a volume missing either can stop the game on load. Packing validates the effective header before writing, including values supplied through a configuration file.

Choose what to pack

Without selection options, the command packs the whole source directory. Use a configuration file when the selection is shared or checked in; use command-line options for a one-off build. They cannot be combined.

An .ltx configuration uses the xrCompress dialect:

[options]
exclude_exts = *.txt,*.json

[include_folders]
configs = true
scripts = true

[include_files]
gamemtl.xr

[header]
auto_load = true
entry_point = $fs_root$\gamedata\
xrf-cli archive pack target\gamedata --dest target\db --name gamedata --config pack.ltx

In [include_folders] and [exclude_folders], true applies to the directory and everything below it; false applies only to the named directory. Use .\ for the packed root. An .ltx or .json configuration may contain selection rules and a header only. Source path, destination, volume name, and run options remain on the command line.

A JSON configuration for the same selection looks like this:

{
  "excludeExtensions": ["*.txt", "*.json"],
  "includeFiles": ["gamemtl.xr"],
  "includeDirectories": [
    { "path": "configs", "isRecursive": true },
    { "path": "scripts", "isRecursive": true }
  ],
  "header": [
    { "key": "auto_load", "value": "true" },
    { "key": "entry_point", "value": "$fs_root$\\gamedata\\" }
  ]
}
xrf-cli archive pack target\gamedata --dest target\db --name gamedata --config pack.json

For a direct selection, repeat the relevant option:

xrf-cli archive pack target\gamedata --dest target\db --name configs `
  --include-directory configs --include-directory spawns --include-file gamemtl.xr `
  --exclude-extension '*.txt'

--include-directory-shallow includes a directory’s files but not the files in its child directories. --exclude-directory-shallow excludes the named directory only; its contents can still be packed. All paths are relative to the source.

Common packing options

  • Use --store to store every file without compression.
  • Use --max-size <MB> to choose a volume cap from 1 through 1900 MB. --oversized-volumes permits a larger cap only for an engine fork that supports it.
  • Use --xdb to create .xdb volumes.
  • Use --no-skip-list to retain editor and source leftovers that the normal engine-build skip list excludes.
  • Use --verbose to see every selected, skipped, stored, compressed, and deduplicated file while packing.

Performance compared with xrCompress

These are median results from interleaved runs of both tools on the same machine and source tree. xrCompress -fast uses the compression mode that matches archive pack; the xrCompress default trades time for a smaller archive. Each time/RAM value is wall-clock seconds and peak resident memory in megabytes.

Inputarchive pack time / peak RAM (s / MB)xrCompress -fast time / peak RAM (s / MB)
1,657 config files, 9.89 MB0.22 s / 11 MB0.57 s / 99 MB
4,206 Anomaly configs and scripts, 35 MB0.86 s / 13 MB0.97 s / 101 MB
1,017 mesh files, 275 MB0.17 s / 28 MB1.07 s / 115 MB
Vanilla gamedata, 36,925 files, 4.69 GB4.6 s / 180 MB16.8 s / 275 MB

For inputs that contain compressible files, these are the resulting archive sizes:

Inputarchive packxrCompress -fastxrCompress
1,657 config files, 9.89 MB2.00 MB2.49 MB1.93 MB
Anomaly configs and scripts, 35 MB8.57 MB10.63 MB8.26 MB

In these comparisons, archives packed from the same source by either tool unpacked to byte-identical files.

Replace an existing archive

Packing refuses to overwrite volumes with the same name. Add --force only when replacing that set is intended:

xrf-cli archive pack target\gamedata --dest target\db --name gamedata --force

--force replaces volumes as it writes and cannot restore the previous set after a partial failure. It also does not prune higher-numbered volumes left by a larger previous build. Prefer a fresh output directory, verify its complete set, then replace the old distribution. A non-forced failed run removes the volumes it created.

Build a patch

archive pack-patch creates .db volumes containing added and modified files. To package edits from a game’s loose gamedata\, point at the installation:

xrf-cli archive pack-patch 'C:\Games\Anomaly' --dest target\patch --name mypatch

Without --target, the command compares the installation’s archives with its loose files. Unchanged copies are omitted, and archived files absent from gamedata\ remain untouched. The installation must contain archives and loose files to compare.

Write outside the input and target trees; destinations inside either are refused. Copy the resulting volumes to a directory mounted after the base archives in fsgame.ltx, usually db\patches\.

Loose files in the player’s gamedata\ take priority over patch archives. Distribute loose replacements when those files need updating.

A patch cannot remove a base file: archive registration can replace an entry but has no deletion marker. Removing content requires replacing or removing it from the installed base distribution.

Deliver a tree of your own

Use --target to deliver files from a separate folder:

xrf-cli archive pack-patch 'C:\Games\Anomaly' --target C:\work\mymod\gamedata `
  --dest target\patch --name mypatch

For a loose target, name the gamedata directory itself, with paths such as configs\ and textures\ directly inside it. Naming its parent adds an unwanted gamedata\ prefix to archive entries.

Preview before writing

Use --dry-run to compare without writing volumes. Add --report to save every changed entry:

xrf-cli archive pack-patch 'C:\Games\Anomaly' --dry-run --report patch-preview.json

The size shown is the total unpacked payload; the final archive size is known only after writing.

  • --include configs limits both sides to a logical prefix.
  • --ignore configs\debug excludes a prefix, even when included.
  • --exclude-extension '*.txt' excludes matching file extensions.
  • --verify-payload reads and compares both payloads when their sizes and checksums match.

The three filter options are repeatable.

Inspect or extract files

For info, list, find, extract, and verify, --path may name one volume or a directory. A volume reads only that file; a directory reads all .db and .xdb volumes below it as one merged archive set.

# Check the number of volumes, entries, and their sizes.
xrf-cli archive info --path .\db

# List file paths, or search their names without unpacking.
xrf-cli archive list --path .\db --files
xrf-cli archive find --path .\db --query wpn_ak74 --files

# Extract one logical file, or an entire logical directory.
xrf-cli archive extract --path .\db --file textures\wpn\wpn_ak74.dds --dest .\ak74.dds
xrf-cli archive extract --path .\db --directory configs --dest .\extracted-configs

list --verbose and find --verbose show a file’s sizes and source volume. If identical files share one stored payload, they also name the other paths that read those bytes.

Unpack an archive

Unpack a complete volume set by giving its containing directory:

xrf-cli archive unpack --path .\db --dest .\unpacked

The archive’s mount prefix is retained beneath the destination. An archive packed with the default gamedata header therefore writes files under unpacked/gamedata, rather than directly under unpacked.

To unpack one volume by itself, pass the volume path instead. --dry opens the archive and prints its summary without writing files. Use -j to control the worker count, for example -j 8 or -j 50%.

xrf-cli archive unpack --path .\db\configs.db --dest .\unpacked\configs --dry

Use a new or empty destination directory. Existing files can otherwise be replaced while the archive is unpacked.

Unpacking speed and memory

These results use the same measurement method. The default run uses the available worker count; -j 1 is the single-worker comparison.

Archivearchive unpack time / peak RAM (s / MB)-j 1 time / peak RAM (s / MB)
Vanilla configs, 1,657 files, 2.00 MB0.20 s / 12 MB0.40 s / 10 MB
Vanilla gamedata, 36,925 files, 4.48 GB6.1 s / 28 MB12.3 s / 21 MB

Verify an archive

Verify every file after packing or copying an archive:

xrf-cli archive verify --path .\db

Example output — verify an archive:

Verified 29 file(s) in 29 ms

Exit code: 0.

The command reads every payload, checks decompression, and validates its CRC. It reports damaged files as failures; use --report archive-verify.json to save the findings. Successful archive verification establishes payload integrity; run gamedata verification to check the files’ formats and references in their installed context.

Command reference

xrf-cli archive extract

Extract one archive file or directory without unpacking the complete set

xrf-cli archive extract [OPTIONS] --path <path> --dest <dest>
OptionRequiredDefaultDescription
-p, --path <path>yesPath to an archive volume or a directory containing volumes
--file <file>Exact logical path of one archive file; –dest is the output file
--directory <directory>Logical directory to extract; –dest receives that directory’s contents
-d, --dest <dest>yesOutput file for –file, or output directory for –directory
-s, --silentTurn off logging
-v, --verboseTurn on verbose logging
--jsonWrite the run’s JSON report to stdout, moving human output to stderr
--report <PATH>Write the run’s JSON report to a file

xrf-cli archive find

Find archive entries whose logical path contains text

xrf-cli archive find [OPTIONS] --path <path> --query <query>
OptionRequiredDefaultDescription
-p, --path <path>yesPath to an archive volume or a directory containing volumes
-q, --query <query>yesCase-insensitive text to find in an entry’s logical path
--filesSearch files only, excluding directory records
--directoriesSearch directory records only, excluding files
-s, --silentTurn off logging
-v, --verboseTurn on verbose logging
--jsonWrite the run’s JSON report to stdout, moving human output to stderr
--report <PATH>Write the run’s JSON report to a file

xrf-cli archive info

Describe an X-Ray archive volume or volume set

xrf-cli archive info [OPTIONS] --path <path>
OptionRequiredDefaultDescription
-p, --path <path>yesPath to an archive volume or a directory containing volumes
-s, --silentTurn off logging
-v, --verboseTurn on verbose logging
--jsonWrite the run’s JSON report to stdout, moving human output to stderr
--report <PATH>Write the run’s JSON report to a file

xrf-cli archive list

List the merged entries in an X-Ray archive volume or volume set

xrf-cli archive list [OPTIONS] --path <path>
OptionRequiredDefaultDescription
-p, --path <path>yesPath to an archive volume or a directory containing volumes
--filesList files only, excluding directory records
--directoriesList directory records only, excluding files
-s, --silentTurn off logging
-v, --verboseTurn on verbose logging
--jsonWrite the run’s JSON report to stdout, moving human output to stderr
--report <PATH>Write the run’s JSON report to a file

xrf-cli archive pack

Command to pack provided directory into *.db archive volumes

xrf-cli archive pack [OPTIONS] <SOURCE>
OptionRequiredDefaultDescription
<SOURCE>yesDirectory to pack, normally a gamedata root
-d, --dest <dest>packedPath to folder for writing the volumes
-n, --name <name>gamedataBase name of the volumes, written as <name>.db0, <name>.db1 and so on
--config <config>Path to a packing configuration describing what to include, as *.ltx or *.json
--include-file <include-file>...File to pack, named relative to the source, repeatable
--include-directory <include-directory>...Directory to pack with everything below it, relative to the source, repeatable
--include-directory-shallow <include-directory-shallow>...Directory whose own files are packed while its subdirectories only get listed, repeatable
--exclude-directory <exclude-directory>...Directory to leave out along with everything below it, repeatable
--exclude-directory-shallow <exclude-directory-shallow>...Directory to leave out while its contents still pack, repeatable
--exclude-extension <exclude-extension>...Extension pattern that keeps a file out, such as *.txt, repeatable
--header <header>...Header entry written into the archive as <key>=<value>, repeatable, merged over the default header
--storeStore every file instead of compressing what the engine expects compressed
--max-size <max-size>Maximum volume size in megabytes, from 1 to 1900
--oversized-volumesLet –max-size exceed 1900 MB, which only an engine fork that raised XRP_MAX_SIZE can mount
--xdbWrite volumes with the xdb extension
--no-skip-listKeep editor and source leftovers the engine build normally drops
-f, --forceReplace volumes of the same set the destination already holds
-s, --silentTurn off logging
-v, --verboseTurn on verbose logging
--jsonWrite the run’s JSON report to stdout, moving human output to stderr
--report <PATH>Write the run’s JSON report to a file

xrf-cli archive pack-patch

Command to pack what a gamedata tree changes about an installation into overriding *.db archive volumes

xrf-cli archive pack-patch [OPTIONS] <SOURCE>
OptionRequiredDefaultDescription
<SOURCE>yesWhat to patch: an installation, a directory of volumes, or a gamedata tree
--target <target>Tree the patch delivers; omit to use the loose gamedata of the input itself
-d, --dest <dest>packedPath to folder for writing the volumes
-n, --name <name>patchBase name of the volumes, written as <name>.db0, <name>.db1 and so on
--dry-runReport the difference and write no volumes
--config <config>Path to a patching configuration describing the comparison scope and header, as *.ltx or *.json
--include <include>...Logical prefix the comparison is restricted to, such as configs, repeatable
--ignore <ignore>...Logical prefix dropped from the comparison, repeatable
--exclude-extension <exclude-extension>...Extension pattern that keeps a file out of the comparison, such as *.txt, repeatable
--header <header>...Header entry written into the archive as <key>=<value>, repeatable, merged over the default header
--verify-payloadConfirm every checksum match by comparing the payloads themselves
--storeStore every file instead of compressing what the engine expects compressed
--max-size <max-size>Maximum volume size in megabytes, from 1 to 1900
--oversized-volumesLet –max-size exceed 1900 MB, which only an engine fork that raised XRP_MAX_SIZE can mount
--xdbWrite volumes with the xdb extension
-f, --forceReplace volumes of the same set the destination already holds
-s, --silentTurn off logging
-v, --verboseTurn on verbose logging
--jsonWrite the run’s JSON report to stdout, moving human output to stderr
--report <PATH>Write the run’s JSON report to a file

xrf-cli archive unpack

Command to unpack provided *.db into separate files

xrf-cli archive unpack [OPTIONS] --path <path>
OptionRequiredDefaultDescription
-p, --path <path>yesPath to *.db file
-d, --dest <dest>unpackedPath to folder for exporting
--dryRun in dry mode without actually unpacking to disk
-j, --jobs <JOBS>autoHow much of the machine to use: ‘auto’, a worker count, or a share such as ‘50%’
-s, --silentTurn off logging
-v, --verboseTurn on verbose logging
--jsonWrite the run’s JSON report to stdout, moving human output to stderr
--report <PATH>Write the run’s JSON report to a file

xrf-cli archive verify

Read every archive payload and verify decompression and CRC checks

xrf-cli archive verify [OPTIONS] --path <path>
OptionRequiredDefaultDescription
-p, --path <path>yesPath to an archive volume or a directory containing volumes
-s, --silentTurn off logging
-v, --verboseTurn on verbose logging
--jsonWrite the run’s JSON report to stdout, moving human output to stderr
--report <PATH>Write the run’s JSON report to a file