DEMIENGINEDOCUMENTATION Everything is free
Packages · Ship

add, install, lockfile, and requiring modules.

Installing packages

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 common gameplay (health, inventory, camera) and common art (prototype textures) are written once and depended on, instead of copied between projects. This page explains how to add, install, update, and use packages in your own game, with examples on "Skyforge" at games/my_game.

What a package contains

Every package is a directory with a manifest describing what it is and what it needs:

{
  "format_version": 1,
  "name": "demi.gameplay.health",
  "version": "1.2.0",
  "engine": "^1.0.0",
  "dependencies": {
    "demi.gameplay.events": "^1.0.0"
  },
  "public_modules": ["demi.gameplay.health"],
  "files": ["scripts/demi/gameplay/health.lua"]
}
FieldMeaning
format_versionAlways required. Documents without it are rejected.
nameThe package's identity in the registry, for example demi.gameplay.health.
versionThe release version of this package, in semantic versioning form (major.minor.patch).
engineThe engine version range this package supports.
dependenciesOther packages this one needs, each with a version constraint.
public_modulesModule names other projects may require. Everything else in the package is private to it.
filesThe files the package ships: scripts, scenes, prefabs, assets.

Why public_modules? Because a package should hide its internals. You depend on its declared API surface; its helper files can change without breaking your game.

Declaring a dependency

Dependencies live in demi.project.json and are managed with the package commands:

"package_registry": "https://demiengine.de",
"packages": {
  "demi.gameplay.health": "^1.0.0",
  "kenney.textures.prototype": "^1.0.0"
}
  • package_registry — where package names are resolved.
  • packages — direct dependencies with version constraints. ^1.0.0 means "any 1.x release at 1.0.0 or newer, below 2.0.0".

Add one from the command line:

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.
  • Returns 0 and updates the project's packages map and demi.packages.lock.json.

Remove one with demi package remove name, which drops the direct dependency and re-resolves the lock file.

Installing into the project

Declaring a dependency records intent; installing places the resolved files where the game can load them.

demi package install
  • package install — resolves every dependency and installs the package files into .demi/packages.
  • --locked — installs exactly the versions pinned in demi.packages.lock.json and fails rather than re-resolving. Use this in continuous integration so builds are reproducible.
  • --offline — installs from the local cache only, with no network access. Returns 1 when a needed version is not cached.
  • --dry-run — prints the install plan and exits without writing anything.

Two files and one folder are involved:

PathRole
demi.project.jsonDeclares what you want: names and constraints.
demi.packages.lock.jsonPins what you got: exact resolved versions and their hashes. Commit this file.
.demi/packagesA derived install folder. Safe to delete; install recreates it.

Why pin a lock file? Because "it worked on my machine" is not a build. The lock file makes two installs of the same project byte-identical in dependency content.

Updating and inspecting versions

demi package update demi.gameplay.health
 
  • package update [name] — re-resolves dependencies within their declared constraints and refreshes the lock file. With a name, updates that package only; with no name, updates every package.
demi package list
demi package outdated --format json
  • package list — prints every resolved version currently installed.
  • package outdated — prints resolved versions that have a newer release satisfying the constraint.
  • --format json — the same listing as JSON for scripts and tools.

Both exit 0 when the dependency state is consistent.

Using package modules from Lua

Installed packages are loaded through their public modules, named exactly as in the manifest:

local GameplayEvents = require("demi.gameplay.events")
local Health = require("demi.gameplay.health")

local health = Health.new(GameplayEvents.new())
health:add(self.id, 100)
print(health:get(self.id).current)   -- current hit points as a number
  • require("demi.gameplay.health") — loads the package's public module and returns its API table.
  • Call shapes depend on the package: each package documents its own functions and return values. The pattern is always "require the public module, call its functions, read its return values".

Requiring a module that is not a declared public module fails with a clear error — the package's private files are not part of the contract.

Engine services follow the same import style (require("demi.input"), require("demi.transform3d"), and so on); package modules simply live under their own namespace.

Package families

The public catalog organizes packages into families. Names say what they cover:

FamilyExamplesWhat you get
demi.gameplay.*health, controllers, projectiles, interactions, inventory, encounters, camera, traversal, third_person, destruction, coreReusable gameplay systems as Lua modules and prefabs.
demi.ui.*language_file, localizationHUD language files and localization helpers.
demi.network.lobbylobbyLobby and matchmaking flows for sessions.
kenney.textures.prototypeprototype texturesPlaceholder art assets for grayboxing.

Each family ships its own manifest, public modules, and tests. Run a package's tests before adopting a new version:

demi package test .demi/packages/demi.gameplay.health
  • package test [dir] — runs the package's declared Lua tests. Returns 0 on success, 1 on failure.

Next steps

  • Add packages to Skyforge and read the lock file after: the exact versions land there immediately.
  • Ship your own reusable system with Publishing packages.
  • See every package command on the CLI reference, and the asset side of content in Assets & packages.