The cartkit CLI
tools/cartkit.py is the cart-author command line: scaffold, validate,
pin, pack, add-release-workflow, selftest. Python 3, no other
dependencies (unlike modkit it never drives the engine,
so it runs anywhere).
python3 tools/cartkit.py <subcommand> [args]
Global flags: --repo PATH (repo root override), --json, --quiet.
First cart workflow
Run this from the engine repository root, or pass --repo /path/to/engine
when the cart lives in a separate repository. A pin names one exact
published mod release; a cart is the bundle that records those pins.
python3 tools/cartkit.py scaffold my_cart --base red --author "Your Name"
python3 tools/cartkit.py pin my_cart owner/example-mod@1.2.3
python3 tools/cartkit.py validate my_cart --online
python3 tools/cartkit.py pack my_cart -o my_cart-1.0.0.g1rcart
Scaffold creates the cart source files and a placeholder pin. pin replaces
that placeholder and records the published release hash. Online validation
checks the remote release; packaging writes the .g1rcart file. If validation
fails, fix the named field or pin and rerun it. If an existing workflow or
label would be overwritten, stop and inspect it before using --force.
The cart repo is the directory containing cart.json, label.png, and
README.md. It is separate from the engine's mods/ directory when you use
--into or a path outside the engine checkout.
A cart repo holds cart.json, label.png, a README.md, a
CHANGELOG.md and a release workflow. The built .g1rcart is an output,
not a source file; see Custom Carts for what that
file is.
scaffold
python3 tools/cartkit.py scaffold my_cart
python3 tools/cartkit.py scaffold my_cart --base gold --seal sealed+ \
--title "My Cart" --author you --github owner/my-cart
Writes a new cart repo with a cart.json carrying a placeholder pin, a
generated label.png in the shell colour, and the release workflow.
Flags: --title (1..48 characters), --author, --summary (<=120),
--base (any version id: red, blue, yellow, gold, silver,
crystal, firered, leafgreen, ruby, sapphire, emerald; default
red), --shell "#rrggbb",
--seal sealed|sealed+|open, --github owner/repo, --into DIR,
--force.
Replace the placeholder pin with a real one before validating; pin
drops it for you.
A pinned mod loads only when its manifest games covers the cart's base
version, as with any mod on that game (see Portable Mods for one mod
across Gen 1, 2 and 3).
pin
python3 tools/cartkit.py pin my_cart owner/repo@1.2.3
python3 tools/cartkit.py pin my_cart https://gamebanana.com/mods/512345
python3 tools/cartkit.py pin my_cart owner/repo@1.2.3 --option difficulty=hard
Adds or updates one pin and resolves its hash for you. For a GitHub
spec it reads the release's own sha256sums.txt and records the hash of
the archive that release actually publishes. Do not copy a hash from a
locally packed zip: a mod's release workflow rewrites the version inside
the archive, so a local build of the same version hashes differently and
the pin will never verify.
Flags: --id ID (the mod's id in the cart, if it cannot be derived),
--file FILE (GameBanana file id when the mod publishes several),
--option KEY=VALUE (freeze an option; true/false and numbers are
parsed), --clear-options.
Frozen options ride the cart and are part of its hash, so a cart's mods arrive configured.
validate
python3 tools/cartkit.py validate my_cart
python3 tools/cartkit.py validate my_cart --online --strict
Offline by default: shape, vocabulary and internal consistency. --online
resolves every pin against GitHub and GameBanana and checks the recorded
hashes against what those releases publish, which is the check that
catches a stale pin.
| Rule | Refuses |
|---|---|
| CK001 | no cart.json in that directory |
| CK002 | a field missing, malformed, or outside its vocabulary |
| CK003 | label art that is not a .png |
| CK004 | a mods list that is not 1 to 64 pins |
| CK005 | a load_order that does not match the pins |
| CK100 | a GitHub pin that does not resolve to a release |
| CK101 | a GitHub pin whose sha256 disagrees with the published archive |
| CK110 | a GameBanana pin that does not resolve |
| CK111 | a GameBanana pin whose md5 disagrees with the published file |
--no-download stops validate fetching a release asset purely to hash
it; a pin it could not check is reported as unchecked rather than passed.
cartkit packs only the fields it documents, so an unknown field warns
rather than being silently carried. If you add a field to the cart format,
teach cartkit about it in the same change or it will be dropped from every
packed cart.
pack
python3 tools/cartkit.py pack my_cart
Writes <id>-<version>.g1rcart into the working directory (or -o PATH):
the manifest, the pins and the label PNG base64'd inline. --online and
--no-download behave as they do for validate.
add-release-workflow
python3 tools/cartkit.py add-release-workflow my_cart
Copies in .github/workflows/release.yml, which on every push to main
fetches cartkit, runs selftest, validates the cart --online --strict,
packs it, and publishes the .g1rcart with a sha256sums.txt. A version
that already has a release is skipped rather than rebuilt, so cutting a
release is bumping version in cart.json.
The workflow fetches cartkit from the engine repo at
CARTKIT_REPO/CARTKIT_REF, which is how a cart repo stays in step with
the format without vendoring the tool.
selftest
python3 tools/cartkit.py selftest
Runs cartkit's own checks, including a scaffold/validate/pack round trip and a determinism check on the generated label. The release workflow runs this before it trusts a fetched copy of the tool.
A cart from nothing
python3 tools/cartkit.py scaffold my_cart --base red --author you \
--github owner/my-cart
python3 tools/cartkit.py pin my_cart owner/some-mod@1.0.0
python3 tools/cartkit.py validate my_cart --online
python3 tools/cartkit.py pack my_cart
Then push the repo, let the workflow cut the release, and add an entry
under carts/ in the mod index. The index entry's
repo names the cart's repo, not the repo of a mod it pins.
Check and recover
The first workflow should finish with a .g1rcart file in the cart directory;
validate should report no CK findings before pack is used. If a pin or
online check fails, fix the named pin in cart.json and rerun validate; if
scaffold or a workflow would overwrite an existing file, stop and inspect it
instead of adding --force.
Start here
Playing
Tutorials
- Choose a tutorial
- 01 Sprite and Text Tweak
- 02 Balance Patch
- 03 New Species
- 04 New Item and Ball
- 05 New Move
- 06 NPC and Dialogue
- 07 New Map
- 08 Quest
- 09 Custom Music
- 10 New Mechanic
- 11 Custom UI Screen
- 12 Mini Total Conversion
Creative guides
Concepts
Recipes and reference
Author and developer tools
Home · Start Playing · Glossary · Troubleshooting · Repository · Community
Game data is imported locally from a supported ROM supplied by the player. Shared mods contain original work or transform recipes, never extracted game content. Check each guide's target game before using its examples.