CLI reference¶
$ good --help
Usage: good <command> [options]
Commands:
create Scaffold a new Flutter project wired up to good.
generate Write lib/good.generated/ from the assets the pubspec declares.
assets Convert and pack the assets a project ships.
build Build and package a game for a target platform.
Options:
--help Show this help and exit.
The commands are listed in the order a project meets them: make one, generate its bindings, build it.
Installing¶
Or run it straight out of a clone, which is what to do in CI or when tracking the engine's source:
Syntax¶
| Form | Meaning |
|---|---|
--option=value |
An option and its value |
--option value |
The same |
--flag |
A flag. There is no --no-flag — leave it out to turn it off |
-- |
Everything after is positional, however it is spelled |
--help, -h |
Works at every level: good assets pack --help |
--verbose is available on every command that does work, and shows every file
touched and every decision made.
good create¶
Scaffolds a Flutter app wired up to good, patches the pubspec, and runs
good generate.
| Option | Default | Description |
|---|---|---|
<project_name> |
(required) | The package and directory name. Must be a valid Dart package name |
--directory=<dir> |
. |
Where to create the project |
--2d |
on | Build against goo2d |
--3d |
Build against goo3d |
|
--dry-run |
off | Report what would be created, and create nothing |
--no-flutter-create |
off | Write only the good files, into a project that already exists |
--verbose |
off | Verbose output |
good create my_game
good create my_game --directory=games
good create my_existing_app --no-flutter-create
good create my_game --dry-run
Never writes over an existing file — scaffolding is a starting point, and
replacing a main.dart someone has worked in is the one unrecoverable thing it
could do. Refuses an existing directory unless --no-flutter-create, because
flutter create rewrites platform folders.
See Create a project.
good generate¶
Writes lib/good.generated/ from the assets the pubspec declares.
| Option | Default | Description |
|---|---|---|
--project-dir=<dir> |
. |
The project to generate into |
--dry-run |
off | Report what would be written, and write nothing |
--rotate-keys |
off | Regenerate asset_key.dart |
--verbose |
off | Verbose output |
| File | Rewritten |
|---|---|
textures.dart |
Every run — a pure function of the pubspec |
audios.dart |
Every run |
good.dart |
Every run — ensureGameReady() |
asset_key.dart |
Once, then left alone |
--rotate-keys
Every existing asset pack stops decrypting. Repack immediately after, and understand that any build already shipped can no longer read a pack made with the new keys.
Scans what the pubspec declares under flutter: assets:, not what is on
disk — a file in an unlisted directory is invisible to it, and to Flutter.
good assets¶
Usage: good assets <command> [options]
Commands:
compact Convert source art into the one canonical format per kind.
pack Chunk, compress and encrypt the assets a build ships.
good assets compact¶
Converts everything in the source directory into one canonical format per kind — WebP for images, Ogg Vorbis for audio — using ffmpeg.
| Option | Default | Description |
|---|---|---|
--project-dir=<dir> |
. |
The project whose assets to compact |
--dry-run |
off | Report the plan, convert nothing |
--force |
off | Reconvert everything, ignoring what is already up to date |
--no-download |
off | Fail instead of downloading ffmpeg when none is installed |
--verbose |
off | Verbose output |
Incremental by default: a hash of each source plus its settings lives in
.dart_tool/good/compact.json. A file already in the canonical format is
copied, not re-encoded — re-encoding is generation loss.
good assets pack¶
Chunks, compresses and encrypts what a build ships, then writes the chunk
mapping back into asset_key.dart.
| Option | Default | Description |
|---|---|---|
--project-dir=<dir> |
. |
The project whose assets to pack |
--output-dir=<dir> |
the packed: directory |
Where chunks are written |
--mode=<development\|release> |
release |
Loose files, or a packed bundle |
--encryption=<none\|aes> |
aes |
Encryption for packed chunks |
--compression=<none\|fast\|normal\|best> |
normal |
Applied before encryption |
--dry-run |
off | Report the plan, write nothing |
--verbose |
off | Show chunk membership |
Writes the chunks and leaves the loose assets alone. Only good build strips
them — only there is good the one who compacted them and able to say which files
are safe to delete.
--mode=development writes nothing and clears the mapping, which is what
switches a project back to loose assets.
See The asset pipeline.
good build¶
Usage: good build <command> [options]
Commands:
windows Build for Windows.
linux Build for Linux.
android Build for Android.
ios Build for iOS.
Runs the whole pipeline in the order that makes it correct, then hands off to Flutter:
Every platform takes the same options:
| Option | Default | Description |
|---|---|---|
--project-dir=<dir> |
. |
The project to build |
--assets=<development\|release> |
release |
Loose files, or a packed bundle |
--asset-encryption=<none\|aes> |
aes |
Encryption for packed assets |
--asset-compression=<none\|fast\|normal\|best> |
normal |
Compression for packed assets |
--no-download |
off | Fail instead of downloading ffmpeg |
--dry-run |
off | Report the plan, and do nothing |
--verbose |
off | Verbose output |
One command per platform, not a --platform option, because each grows
its own signing and packaging options and an option that applies to one target
is one every other target's help has to explain away.
Release is the default for a build: flutter run is the development path
and does not come through here.
Configuration¶
Read from the good: section of the project's pubspec.yaml — not a separate
file. A project already has one file that says what it is and what it ships.
good:
assets:
source: assets_src/ # originals you edit and commit
output: assets/ # canonical files, generated
packed: assets/packed/ # release chunks, generated
strip-originals: false # may a build delete art it cannot rebuild
texture:
format: webp
quality: 90
audio:
format: ogg
quality: 5
Every value shown is the default and every key is optional — a project with no
good: section works, because a new project should run before anyone has
configured anything. Directory values are normalised to end in /, so assets
and assets/ mean the same thing.
Both output and packed must appear under flutter: assets: — that list is
the only thing Flutter bundles from.
strip-originals covers one case: a file you put in output yourself, which
packing takes and stripping would delete with no source to rebuild it from. The
build stops and names those files. Turn it on when source holds every original
and output is disposable.
Exit codes¶
0 on success, non-zero on failure. Every failure prints what went wrong and,
where there is one, the command that fixes it.