asset and package command groups in detail.
Assets & packages
Games are mostly content: images, models, sounds, data files. In DemiEngine that content is managed as assets (files the game loads by stable ID) and packages (reusable bundles of scripts and assets other projects can depend on). This page covers the demi asset and demi package command groups, using the sample game "Skyforge" at games/my_game.
What an asset is
An asset is one piece of game content plus a small JSON manifest that names it. The manifest lives at assets/<name>.asset.json and gives the asset a stable ID like asset://textures/brick. Scenes and scripts reference that ID, never a file path, so the file behind it can be reimported or re-exported without rewriting the game.
Why manifests instead of raw paths? Because IDs survive reimports, cooking, and packaging. A scene that says asset://ui/theme keeps working when the theme source file is replaced by a newer export from your art tool.
Inspect an asset
Before debugging a missing texture, ask the engine what it knows about the asset:
demi asset inspect assets/textures/brick.asset.json
asset inspect— takes the manifest path, validates it, and prints a summary: ID, type, importer, source path, and source hash.
Exits 0 when the manifest is valid, 1 when validation reports errors.
demi asset deps assets/textures/brick.asset.json
asset deps— takes the manifest path and lists what this asset depends on: first the IDs of asset dependencies, then the source-file paths. One per line, so it is easy to use in a build script to decide whether a reimport is needed.
Import and reimport
Import takes a source file from anywhere on disk (an art export, a WAV, a glTF model), copies it into the project's asset area, and writes the manifest that registers it.
demi asset import ~/art/brick.png \
--id asset://textures/brick
asset import <source>— the file to bring in.--id asset://textures/brick— the stable ID the new manifest will declare.--importer <id>— optional; names the importer when the file type alone is ambiguous (for example a model that could be static or skinned).
Returns 0 and prints the manifest path on success. When the source file changes later, refresh the registered output:
demi asset reimport assets/textures/brick.asset.json
asset reimport— takes the manifest path, regenerates the asset output, updates the source hash and metadata, and leaves the asset ID unchanged.
Content produced by another tool already inside the project can be registered without a copy:
demi asset register-generated assets/textures/brick_atlas.png \
--id asset://textures/brick_atlas
asset register-generated <source>— registers a tool-generated source underassets/so it becomes a first-class asset.
Colliders, packs, and budgets
Three specialized asset commands cover physics shapes, portable packs, and performance checks:
demi asset collider assets/models/crate.asset.json \
--id asset://colliders/crate
asset collider— generates a collider asset from a model asset, so physics uses the authored shape instead of a rough box.
demi asset export \
--output skyforge_props.demipack \
--asset asset://textures/brick
asset export --output file.demipack --asset asset://id— writes a portable asset pack: a single file other projects can import. At least one--asset asset://idis required; repeat the flag to export several assets. Without it the command exits with a usage error.
demi asset import-package skyforge_props.demipack
asset import-package file.demipack— verifies the pack and imports its assets into the project. Returns1if verification fails.
demi asset budget games/my_game/demi.project.json --platform android
asset budget— takes the project file (demi.project.json, not a directory) and reports 3D budget usage against the platform's profile.--platform android|linux— which platform's budget profile to measure against.
Budgets are declared in the project file and are covered in demi.project.json.
What a package is
A package is a versioned, reusable unit of game code and content: Lua modules, scenes, prefabs, and assets that several games can share. Packages exist so "health bars", "third-person movement", or "prototype textures" are written once and depended on, instead of copied between projects. Installing packages is covered on Installing packages; publishing your own is on Publishing packages.
Add and remove dependencies
Dependencies are declared in the project file and managed with the package commands:
demi package add demi.gameplay.health@^1.0.0
package add name@constraint— resolves the name against the registry and records the constraint as a direct dependency.name@constraint— for exampledemi.gameplay.health@^1.0.0, meaning "any 1.x release at 1.0.0 or newer".
Resolves and records the dependency, updates demi.packages.lock.json with the pinned version, and exits 0.
demi package remove demi.gameplay.health
package remove name— removes the named direct dependency and re-resolves the lock file.
Install, update, and inspect
demi package install
package install— installs every resolved package into.demi/packages, a derived folder that is safe to delete and regenerate.--locked— installs exactly the versions indemi.packages.lock.jsonand fails instead of re-resolving. Use this in continuous integration.--offline— installs from the local cache only; no network access. Returns1if a needed version is not cached.--dry-run— prints the install plan and exits without writing anything.
demi package update demi.gameplay.health
package update [name]— re-resolves within the declared constraints. With a name, updates that package only; without one, updates every package.
demi package list
demi package outdated --format json
package list— prints the resolved versions currently installed.package outdated— prints resolved versions that have a newer release satisfying the constraint.--format json— same information as a JSON document for scripts and editors.
Both return the listing on standard output and exit 0 when the project's dependency state is consistent.
Test a package
Packages can ship their own tests so consumers can trust an upgrade:
demi package test packages/skyforge-kit
package test [dir]— runs the declared Lua package tests in the given package directory (default: the current directory).- Returns
0when all tests pass,1when any test fails.
Publish a package
demi package publish packages/skyforge-kit \
--registry https://demiengine.de
package publish [dir]— packages the directory and uploads a release to the registry.--registry <url-or-path>— where to publish.https://demiengine.deis the public store.
Releases are immutable once published: a version number is a promise that its content will not change. The full workflow, including the audited package content roots, is documented on Publishing packages.
Command map
| Goal | Command |
|---|---|
| Summarize an asset | demi asset inspect <manifest> |
| List asset sources | demi asset deps <manifest> |
| Bring a file in | demi asset import <source> --id asset://… |
| Refresh after art changes | demi asset reimport <manifest> |
| Register tool output | demi asset register-generated <source> --id asset://… |
| Make a physics shape | demi asset collider <model.asset.json> --id asset://… |
| Share assets as a pack | demi asset export --output file.demipack --asset asset://… |
| Consume an asset pack | demi asset import-package file.demipack |
| Check budget usage | demi asset budget demi.project.json --platform android|linux |
| Add a dependency | demi package add name@constraint |
| Install resolved packages | demi package install [--locked] [--offline] [--dry-run] |
| Upgrade within constraints | demi package update [name] |
| See resolved and outdated versions | demi package list|outdated [--format json] |
| Run package tests | demi package test [dir] |
| Ship a release | demi package publish [dir] --registry <url> |
See also Installing packages, Publishing packages, and the CLI reference.