Set Up a Mod Project
The x4cat init command scaffolds a complete mod project with a Makefile, tests, and directory structure based on the extension_poc template. This gives you a repeatable build pipeline for developing, validating, and distributing your mod.
What you will build
A fully structured mod project with:
content.xmlextension manifestMakefilewith build, validate, lint, and test targetspyproject.tomlfor dependency management via uv- Automated XML validation tests
- Standard directory layout matching X4 conventions
Step 1: Scaffold the project
x4cat init my_balance_mod \
--author "Your Name" \
--description "Ship and weapon balance adjustments for X4" \
--game-version 900 \
--repo youruser/my_balance_mod \
--git
This creates:
my_balance_mod/
content.xml
Makefile
pyproject.toml
README.md
.gitignore
src/
md/
my_balance_mod.xml -- starter MD script
aiscripts/
libraries/
tests/
__init__.py
test_mod.py
Step 2: Understand the project structure
content.xml
The extension manifest that X4 reads to load your mod:
<?xml version="1.0" encoding="utf-8"?>
<content id="my_balance_mod"
version="100"
name="my_balance_mod"
description="Ship and weapon balance adjustments for X4"
author="Your Name"
date="2026-04-13"
enabled="1"
save="0">
<dependency version="900" />
</content>
Edit the name to something human-friendly, and set save="1" if your mod affects gameplay/save data.
src/ directory
All mod content goes here. This directory is packed into ext_01.cat/dat during build. The directory structure mirrors X4’s virtual filesystem:
src/
md/ -- Mission Director scripts
aiscripts/ -- AI scripts
libraries/ -- diff patches for game data XML
t/ -- translation files
index/ -- macro/component index diffs
assets/ -- macro files for new content
Makefile
The Makefile provides standard targets:
| Target | Command | Description |
|---|---|---|
all | make all | validate + build + test |
build | make build | Pack src/ into dist/ext_01.cat |
validate | make validate | Run structural XML validation (pytest) |
lint | make lint X4_GAME_DIR=... | Validate diff patches against game files |
schemas | make schemas X4_GAME_DIR=... | Extract XSD schemas from game |
schema-validate | make schema-validate | Full XSD validation (slow) |
test | make test | Run all tests |
clean | make clean | Remove dist/ |
pyproject.toml
Manages x4cat as a development dependency:
cd my_balance_mod
uv sync # install dependencies
After uv sync, all x4cat commands are available through uv run:
uv run x4cat list "$X4"
Step 3: Add mod content
Add your mod files under src/. For example, to add a stat modification:
# Extract a ship macro
uv run x4cat extract-macro ship_arg_s_fighter_01_a_macro -o ./base/
# Copy for editing
cp -r ./base/ ./modified/
# Edit the macro
$EDITOR ./modified/assets/units/size_s/macros/ship_arg_s_fighter_01_a_macro.xml
# Generate diff patch into src/
uv run x4cat xmldiff \
--base ./base/assets/units/size_s/macros/ship_arg_s_fighter_01_a_macro.xml \
--mod ./modified/assets/units/size_s/macros/ship_arg_s_fighter_01_a_macro.xml \
-o src/assets/units/size_s/macros/ship_arg_s_fighter_01_a_macro.xml
# Clean up working directories
rm -rf base/ modified/
Or scaffold new content:
uv run x4cat scaffold ware --id quantum_tubes --name "Quantum Tubes" \
--group hightech --price-avg 5000 -o ./src
Step 4: Build
make build
This runs x4cat pack src/ -o dist/ext_01.cat and copies content.xml into dist/.
Output:
12 file(s) packed into dist/ext_01.cat
Build complete: dist/
Step 5: Validate
Structural validation
make validate
Runs pytest tests that check XML well-formedness and basic structural rules.
Diff patch validation
make lint X4_GAME_DIR="$X4"
Runs x4cat validate-diff against the actual game files. This catches XPath selectors that do not match, which would cause silent failures in-game.
Full pipeline
make all
Runs validate, build, and test in sequence. Use this before every commit.
Step 6: Install
Copy the built mod to your extensions directory:
cp -r dist/ "$X4/extensions/my_balance_mod/"
Or create a symlink for development (so changes rebuild in place):
ln -s "$(pwd)/dist" "$X4/extensions/my_balance_mod"
Step 7: Development workflow
The recommended development cycle:
edit src/ files
|
v
make lint X4_GAME_DIR="$X4" -- catch broken XPaths early
|
v
make all -- validate + build + test
|
v
launch X4 with -prefersinglefiles -- or test with packed catalog
|
v
check debug.log for errors
|
v
commit with conventional commit message
Use the -prefersinglefiles launch option during development to skip catalog packing. X4 will load loose files from src/ directly if you place them in the extensions directory.
Project conventions
File naming
- MD scripts in
src/md/must be lowercase or X4 silently ignores them - Ware IDs should be lowercase with underscores
- Translation files follow the pattern
NNNN-lLLL.xml(e.g.,0001-l044.xmlfor English)
Version numbering
The version attribute in content.xml is an integer: 100 means version 1.00, 210 means version 2.10.
Git workflow
The template includes a .gitignore that excludes dist/, schemas/, and other generated files. Commit only source files.
Next steps
- Follow the stat mod tutorial or new ware tutorial to add content
- Read the CLI Reference for all available commands
- See extension_poc for a working example project