Game asset generation CLI — client/server pipeline for AI-driven 3D game asset production
Project description
assgen
AI-driven game asset generation pipeline — Kubernetes-style client/server architecture for 3D game development.
📖 Full Documentation → aallbrig.github.io/assgen
Architecture
┌───────────────────────────────────────────────────────────┐
│ assgen (client CLI) │
│ ├── visual model create --prompt "sword" --wait │
│ ├── audio sfx generate "laser blast" --wait │
│ └── jobs list / status / wait / cancel │
└───────────────────┬───────────────────────────────────────┘
│ HTTP (REST)
┌───────────────────▼───────────────────────────────────────┐
│ assgen-server │
│ ├── FastAPI REST API (/jobs /models /health) │
│ ├── WorkerThread (polls SQLite queue) │
│ ├── ModelManager (HuggingFace Hub download/cache) │
│ └── Validation (allow-list + HF tag check) │
└───────────────────┬───────────────────────────────────────┘
│
~/.config/assgen/assgen.db (SQLite)
~/.local/share/assgen/models/ (model cache)
The client auto-detects whether a server is configured:
- If
server_urlis set in~/.config/assgen/client.yaml→ use that server. - Otherwise → start a local
assgen-serverprocess (PID-tracked) and use it.
This lets you run the server on a powerful GPU machine and point your laptop's client at it, or just run everything locally.
Installation
pip install assgen
# For GPU inference (RTX 4070 recommended):
pip install "assgen[inference]"
[inference]extra: Installstorch,transformers,diffusers,accelerate, andtrimeshfor local GPU inference. Without it, assgen is a fully functional client that can talk to a remoteassgen-server, but a local server will return stub outputs instead of running real models.For CI environments or machines without a GPU,
pip install assgen(without[inference]) is the right choice.
Development Setup
Clone and run from source:
git clone https://github.com/aallbrig/assgen.git
cd assgen
# Create and activate a virtual environment
python -m venv .venv
source .venv/bin/activate # Linux / macOS
# .venv\Scripts\activate # Windows PowerShell
# Install in editable mode with dev dependencies
pip install -e ".[dev]"
# For GPU inference (optional — needs CUDA-capable GPU):
pip install -e ".[dev,inference]"
# Verify the install
assgen version
assgen-server --help
Run tests: pytest -v (or make test)
Version note: assgen uses
hatch-vcsto derive its version from git tags. If you install without a git tag (fresh clone, no tags), the version will appear as0.1.dev0. Rungit tag v0.1.0to set a version, or ignore the warning — it does not affect functionality.
Quick Start
# Check version
assgen version
# Start local server (optional — client auto-starts if not configured)
assgen-server start --daemon
# Once the server is running, explore the REST API interactively:
# http://127.0.0.1:8432/docs (Swagger UI)
# http://127.0.0.1:8432/redoc (ReDoc)
# http://127.0.0.1:8432/health (health check)
# Generate a 3D model
assgen visual model create --prompt "low-poly medieval sword" --wait
# Generate sound effects
assgen audio sfx generate "laser gun firing" --wait
# Generate background music
assgen audio music compose "epic orchestral battle theme" --duration 30 --wait
# Auto-rig a character
assgen visual rig auto character.glb --wait
# List recent jobs
assgen jobs list
# Point client at a remote GPU server
assgen client config set-server http://my-gpu-machine:8432
# View full game dev task → model catalog
assgen tasks
# Show current server config
assgen server config show
assgen-servervsassgen server:
assgen-server start— runs the inference server directly (the process itself)assgen server start— tells the client to launch a localassgen-serverprocess for youassgen server status/assgen server stop— manage the locally auto-started serverFor a remote GPU machine, run
assgen-server start --daemonthere, then on your laptop:assgen client config set-server http://<gpu-machine>:8432
CLI Command Tree
assgen
├── tasks # View all game dev tasks and their assigned models
│ └── [--domain DOMAIN] # filter by visual / audio / scene / pipeline / qa / support
├── visual # All 3D visual assets
│ ├── concept # AI concept art (SDXL)
│ │ ├── generate # text → concept art
│ │ ├── ref # multi-view reference sheet
│ │ └── style # art style samples
│ ├── blockout # Greybox prototyping
│ │ ├── create # text/image → blockout mesh
│ │ ├── assemble # combine pieces into scene
│ │ └── iterate # quick variation
│ ├── model # 3D mesh generation
│ │ ├── create # text/image → .glb (TripoSR)
│ │ ├── highpoly # high-poly refinement
│ │ ├── retopo # auto-retopology
│ │ ├── splat # Gaussian Splatting (3DGS)
│ │ ├── edit # deform / boolean / combine
│ │ ├── optimize # LOD generation
│ │ └── export # convert to engine format
│ ├── uv # UV unwrapping
│ │ ├── auto # AI smart-unwrap
│ │ ├── manual # seam suggestions
│ │ └── optimize # texel density optimisation
│ ├── texture # PBR texturing & baking
│ │ ├── generate # text → albedo + PBR maps
│ │ ├── apply # project onto mesh
│ │ ├── bake # high-to-low bake
│ │ └── pbr # full PBR material set
│ ├── rig # Character rigging
│ │ ├── auto # auto-skeleton (UniRig)
│ │ ├── skin # skin weight maps
│ │ └── retarget # rig retargeting
│ ├── animate # Animation generation
│ │ ├── keyframe # text → animation (AnimateDiff)
│ │ ├── mocap # video → motion capture
│ │ ├── blend # mix/loop animations
│ │ └── retarget # animation retargeting
│ ├── vfx # VFX & particles
│ │ ├── particle # particle sprite sheets
│ │ ├── decal # dynamic decal textures
│ │ └── sim # physics VFX bake
│ └── ui # UI/HUD elements
│ ├── icon # icons & sprites
│ ├── hud # health bars, minimaps
│ └── overlay # 2D canvas overlays
├── audio # Sound & music
│ ├── sfx # Sound effects (AudioGen)
│ │ ├── generate # text → WAV
│ │ ├── edit # pitch/reverb/layer
│ │ └── library # browse local SFX library
│ ├── music # Music (MusicGen)
│ │ ├── compose # text → music track
│ │ ├── loop # seamless loop generation
│ │ └── adaptive # mood-based stems
│ └── voice # Voice synthesis (Bark)
│ ├── tts # text → speech
│ ├── clone # voice cloning
│ └── dialog # batch NPC dialog
├── scene # Physics + lighting data
│ ├── physics # Collision & simulation
│ │ ├── collider # optimised collision mesh
│ │ ├── rigid # rigid body setup
│ │ ├── cloth # cloth/hair simulation bake
│ │ └── export # engine physics export
│ └── lighting # Lighting assets
│ ├── hdri # text → HDR sky map
│ ├── probes # reflection/irradiance probes
│ ├── volumetrics # fog, clouds, atmosphere
│ └── bake # GI lightmap bake
├── pipeline # Orchestration
│ ├── workflow # Multi-step workflows
│ │ ├── create # define step sequence
│ │ ├── run # execute with inputs
│ │ └── list # browse saved workflows
│ ├── batch # Batch processing
│ │ ├── queue # enqueue from JSON manifest
│ │ ├── variant # style/damage variants
│ │ └── status # batch queue overview
│ └── integrate # Engine integration
│ ├── export # engine-specific export
│ ├── prefab # bundle into prefab
│ └── script # behavior stubs
├── support # Narrative & data
│ ├── narrative
│ │ ├── dialog # NPC dialog trees
│ │ └── lore # world-building text
│ └── data
│ ├── lightmap # AI lightmap baking
│ └── proc # procedural gen scripts
├── qa # Quality assurance
│ ├── validate # mesh/UV/normal checks
│ ├── perf # polygon/VRAM analysis
│ ├── style # art style consistency
│ └── report # full QA report
├── jobs # Job management
│ ├── list # list all jobs
│ ├── status <id> # single job status (8-char prefix ok)
│ ├── wait <id> # wait with progress bar
│ ├── cancel <id> # cancel a job
│ └── clean # remove old jobs from DB
├── models # Model management
│ ├── list # catalog + install status
│ ├── status <id> # single model details
│ └── install [id...] # download from HuggingFace
├── config # Task → model catalog management
│ ├── list [--domain] # browse all job types and their models
│ ├── show <job-type> # detail for one job type
│ ├── set <job-type> # set model for a job type (interactive HF search)
│ ├── remove <job-type> # revert user override → built-in catalog
│ └── search <query> # search HuggingFace for compatible models
├── client # Client-side configuration
│ └── config
│ ├── show # show resolved server URL + health check
│ ├── set-server <url> # point client at a remote server
│ └── unset-server # revert to auto-start local server
└── server # Server management
├── start [--daemon] # start local server
├── stop # stop local server
├── status # server health check
├── config
│ ├── show # show all server settings
│ ├── set <key> <val> # persist a setting to server.yaml
│ └── models [--domain] # view/manage task → model catalog
├── use <url> # (alias for client config set-server)
└── unset # (alias for client config unset-server)
Configuration
Config lives in the OS-appropriate directory (XDG on Linux/macOS, %APPDATA% on Windows):
| File | Purpose |
|---|---|
client.yaml |
Server URL, poll interval, default --wait |
server.yaml |
Host, port, device, security policy |
models.yaml |
User catalog overrides (task → HF model) |
assgen.db |
SQLite job database |
server.pid |
Running local server PID |
# ~/.config/assgen/client.yaml
server_url: null # null = auto-start local server
default_wait: false
poll_interval: 2.0
# ~/.config/assgen/server.yaml
host: "127.0.0.1"
port: 8432
device: "auto" # auto | cuda | cpu
log_level: "info"
# Security / model governance
allow_list: [] # [] = allow all models; restrict with a list:
# allow_list: ["stabilityai/TripoSR", "facebook/audiogen-medium"]
skip_model_validation: false # true = bypass HF pipeline_tag compatibility checks
Task → Model Catalog
Every game-dev task maps to a HuggingFace model. The built-in catalog lives in
src/assgen/catalog.yaml. Users can override any entry:
# Browse all tasks and their models
assgen tasks
# Override the model for a task (interactive HF Hub search)
assgen config set visual.model.create
# Or specify directly
assgen config set visual.model.create --model-id stabilityai/TripoSR
# Revert to built-in
assgen config remove visual.model.create
Client-side overrides are stored in ~/.config/assgen/models.yaml and sent
with each job submission (via the model_id field in the job request).
Model Validation
When a job is submitted the server validates the requested model against the task type using the HuggingFace Hub API:
- Allow-list check — if
allow_listis non-empty inserver.yaml, only models on the list may be downloaded/used. - Pipeline-tag check — the model's
pipeline_tagfrom HF Hub is checked against a compatibility table for the task (e.g., a TTS model will be rejected forvisual.model.createwhich expectsimage-to-3d).
# Restrict downloads to approved models only
assgen server config set allow_list '["stabilityai/TripoSR","facebook/audiogen-medium"]'
# Trust all models (default)
assgen server config set allow_list '[]'
# Skip compatibility checks (useful for research / experimental models)
assgen server config set skip_model_validation true
When skip_model_validation: false (default) and the HF Hub API is
unreachable, the server allows the model (fail-open for offline use).
Running as a systemd Service
# /etc/systemd/system/assgen-server.service
[Unit]
Description=assgen asset generation server
After=network.target
[Service]
Type=simple
User=youruser
ExecStart=/path/to/.venv/bin/assgen-server start
Restart=on-failure
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
systemctl enable --now assgen-server
journalctl -u assgen-server -f # follow JSON-structured logs
Hardware Notes
- RTX 4070 (12GB VRAM): Sufficient for SDXL, TripoSR, MusicGen-Small, AudioGen-Medium
- Set
device: "cuda"inserver.yamlfor GPU acceleration - For lighter models,
device: "cpu"works but is slower - Use
HF_TOKENenv var for authenticated Hub downloads (higher rate limits)
Adding Real Inference Handlers
The worker dispatches each job_type to assgen/server/handlers/<job_type>.py.
Create a module with a run() function:
# src/assgen/server/handlers/visual_model_create.py
from pathlib import Path
from typing import Any, Callable
def run(
job_type: str,
params: dict[str, Any],
model_id: str | None,
model_path: str | None,
device: str,
progress_cb: Callable[[float, str], None],
output_dir: str,
) -> dict[str, Any]:
progress_cb(0.2, "Loading model")
# ... load transformers pipeline from model_path ...
progress_cb(0.8, "Running inference")
# ... write output files to output_dir ...
return {
"files": ["output.glb"],
"metadata": {"model": model_id},
}
Without a handler, jobs run through the stub handler (which simulates steps and returns immediately — useful for development).
Contributing
PRs welcome. CI runs on every push/PR:
ruff check— lintingpytest -v— unit tests (no GPU required)
pip install -e ".[dev]"
ruff check src/ tests/
pytest -v
Architecture
┌───────────────────────────────────────────────────────────┐
│ assgen (client CLI) │
│ ├── visual model create --prompt "sword" --wait │
│ ├── audio sfx generate "laser blast" --wait │
│ └── jobs list / status / wait / cancel │
└───────────────────┬───────────────────────────────────────┘
│ HTTP (REST)
┌───────────────────▼───────────────────────────────────────┐
│ assgen-server │
│ ├── FastAPI REST API (/jobs /models /health) │
│ ├── WorkerThread (polls SQLite queue) │
│ └── ModelManager (HuggingFace Hub download/cache) │
└───────────────────┬───────────────────────────────────────┘
│
~/.config/assgen/assgen.db (SQLite)
~/.local/share/assgen/models/ (model cache)
The client auto-detects whether a server is configured:
- If
server_urlis set in~/.config/assgen/client.yaml→ use that server. - Otherwise → start a local
assgen-serverprocess (PID-tracked) and use it.
This lets you run the server on a powerful GPU machine and point your laptop's client at it, or just run everything locally.
Installation
pip install assgen
# For GPU inference (RTX 4070 recommended):
pip install "assgen[inference]"
Quick Start
# Check version
assgen version
# Start local server (optional — client auto-starts if not configured)
assgen-server start --daemon
# Generate a 3D model
assgen visual model create --prompt "low-poly medieval sword" --wait
# Generate sound effects
assgen audio sfx generate "laser gun firing" --wait
# Generate background music
assgen audio music compose "epic orchestral battle theme" --duration 30 --wait
# Auto-rig a character
assgen visual rig auto character.glb --wait
# List recent jobs
assgen jobs list
# Point client at a remote server
assgen server use http://my-gpu-machine:8432
CLI Command Tree
assgen
├── visual # All 3D visual assets
│ ├── concept # AI concept art (SDXL)
│ │ ├── generate # text → concept art
│ │ ├── ref # multi-view reference sheet
│ │ └── style # art style samples
│ ├── blockout # Greybox prototyping
│ │ ├── create # text/image → blockout mesh
│ │ ├── assemble # combine pieces into scene
│ │ └── iterate # quick variation
│ ├── model # 3D mesh generation
│ │ ├── create # text/image → .glb (TripoSR)
│ │ ├── highpoly # high-poly refinement
│ │ ├── retopo # auto-retopology
│ │ ├── splat # Gaussian Splatting (3DGS)
│ │ ├── edit # deform / boolean / combine
│ │ ├── optimize # LOD generation
│ │ └── export # convert to engine format
│ ├── uv # UV unwrapping
│ │ ├── auto # AI smart-unwrap
│ │ ├── manual # seam suggestions
│ │ └── optimize # texel density optimisation
│ ├── texture # PBR texturing & baking
│ │ ├── generate # text → albedo + PBR maps
│ │ ├── apply # project onto mesh
│ │ ├── bake # high-to-low bake
│ │ └── pbr # full PBR material set
│ ├── rig # Character rigging
│ │ ├── auto # auto-skeleton (UniRig)
│ │ ├── skin # skin weight maps
│ │ └── retarget # rig retargeting
│ ├── animate # Animation generation
│ │ ├── keyframe # text → animation (AnimateDiff)
│ │ ├── mocap # video → motion capture
│ │ ├── blend # mix/loop animations
│ │ └── retarget # animation retargeting
│ ├── vfx # VFX & particles
│ │ ├── particle # particle sprite sheets
│ │ ├── decal # dynamic decal textures
│ │ └── sim # physics VFX bake
│ └── ui # UI/HUD elements
│ ├── icon # icons & sprites
│ ├── hud # health bars, minimaps
│ └── overlay # 2D canvas overlays
├── audio # Sound & music
│ ├── sfx # Sound effects (AudioGen)
│ │ ├── generate # text → WAV
│ │ ├── edit # pitch/reverb/layer
│ │ └── library # browse local SFX library
│ ├── music # Music (MusicGen)
│ │ ├── compose # text → music track
│ │ ├── loop # seamless loop generation
│ │ └── adaptive # mood-based stems
│ └── voice # Voice synthesis (Bark)
│ ├── tts # text → speech
│ ├── clone # voice cloning
│ └── dialog # batch NPC dialog
├── scene # Physics + lighting data
│ ├── physics # Collision & simulation
│ │ ├── collider # optimised collision mesh
│ │ ├── rigid # rigid body setup
│ │ ├── cloth # cloth/hair simulation bake
│ │ └── export # engine physics export
│ └── lighting # Lighting assets
│ ├── hdri # text → HDR sky map
│ ├── probes # reflection/irradiance probes
│ ├── volumetrics # fog, clouds, atmosphere
│ └── bake # GI lightmap bake
├── pipeline # Orchestration
│ ├── workflow # Multi-step workflows
│ │ ├── create # define step sequence
│ │ ├── run # execute with inputs
│ │ └── list # browse saved workflows
│ ├── batch # Batch processing
│ │ ├── queue # enqueue from JSON manifest
│ │ ├── variant # style/damage variants
│ │ └── status # batch queue overview
│ └── integrate # Engine integration
│ ├── export # engine-specific export
│ ├── prefab # bundle into prefab
│ └── script # behavior stubs
├── support # Narrative & data
│ ├── narrative
│ │ ├── dialog # NPC dialog trees
│ │ └── lore # world-building text
│ └── data
│ ├── lightmap # AI lightmap baking
│ └── proc # procedural gen scripts
├── qa # Quality assurance
│ ├── validate # mesh/UV/normal checks
│ ├── perf # polygon/VRAM analysis
│ ├── style # art style consistency
│ └── report # full QA report
├── jobs # Job management
│ ├── list # list all jobs
│ ├── status <id> # single job status
│ ├── wait <id> # wait with progress bar
│ ├── cancel <id> # cancel a job
│ └── clean # remove old jobs from DB
├── models # Model management
│ ├── list # catalog + install status
│ ├── status <id> # single model details
│ └── install [id...] # download from HuggingFace
└── server # Server management
├── start [--daemon] # start local server
├── stop # stop local server
├── status # server health check
├── config # show resolved config
├── use <url> # point client at server
└── unset # revert to auto-start
Configuration
Config lives in the OS-appropriate directory (XDG on Linux/macOS, %APPDATA% on Windows):
| File | Purpose |
|---|---|
client.yaml |
Server URL, poll interval, default --wait |
server.yaml |
Host, port, device (cuda/cpu), log level |
models.yaml |
User catalog overrides |
assgen.db |
SQLite job database |
server.pid |
Running local server PID |
# ~/.config/assgen/client.yaml
server_url: null # null = auto-start local server
default_wait: false
poll_interval: 2.0
# ~/.config/assgen/server.yaml
host: "127.0.0.1"
port: 8432
device: "auto" # auto | cuda | cpu
log_level: "info"
Running as a systemd Service
# /etc/systemd/system/assgen-server.service
[Unit]
Description=assgen asset generation server
After=network.target
[Service]
Type=simple
User=youruser
ExecStart=/path/to/.venv/bin/assgen-server start
Restart=on-failure
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
systemctl enable --now assgen-server
journalctl -u assgen-server -f # follow JSON-structured logs
Hardware Notes
- RTX 4070 (12GB VRAM): Sufficient for SDXL, TripoSR, MusicGen-Small, AudioGen-Medium
- Set
device: "cuda"inserver.yamlfor GPU acceleration - For lighter models,
device: "cpu"works but is slower - Use
HF_TOKENenv var for authenticated Hub downloads (higher rate limits)
Adding Real Inference Handlers
The worker dispatches each job_type to assgen/server/handlers/<job_type>.py.
Create a module with a run() function:
# src/assgen/server/handlers/visual_model_create.py
from pathlib import Path
from typing import Any, Callable
def run(
job_type: str,
params: dict[str, Any],
model_id: str | None,
model_path: str | None,
device: str,
progress_cb: Callable[[float, str], None],
output_dir: str,
) -> dict[str, Any]:
progress_cb(0.2, "Loading model")
# ... load transformers pipeline from model_path ...
progress_cb(0.8, "Running inference")
# ... write output files to output_dir ...
return {
"files": ["output.glb"],
"metadata": {"model": model_id},
}
Without a handler, jobs run through the stub handler (which simulates steps and returns immediately — useful for development).
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file assgen-0.3.2.tar.gz.
File metadata
- Download URL: assgen-0.3.2.tar.gz
- Upload date:
- Size: 337.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
343893cc302c9e6e44ef0e1811ec6b7b6aaf3213e594ebbbbbe89398b0933024
|
|
| MD5 |
d22688dca571a838f3aa8c6514ba33f7
|
|
| BLAKE2b-256 |
0ab0127e7f2f4e1f8c617aac59df114daa8167a85dbca32fb9dd5bf719d23ad7
|
Provenance
The following attestation bundles were made for assgen-0.3.2.tar.gz:
Publisher:
release.yml on aallbrig/assgen
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
assgen-0.3.2.tar.gz -
Subject digest:
343893cc302c9e6e44ef0e1811ec6b7b6aaf3213e594ebbbbbe89398b0933024 - Sigstore transparency entry: 1280272491
- Sigstore integration time:
-
Permalink:
aallbrig/assgen@b11df9e1f113060afba8bb1af44478523245988e -
Branch / Tag:
refs/tags/v0.3.2 - Owner: https://github.com/aallbrig
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@b11df9e1f113060afba8bb1af44478523245988e -
Trigger Event:
push
-
Statement type:
File details
Details for the file assgen-0.3.2-py3-none-any.whl.
File metadata
- Download URL: assgen-0.3.2-py3-none-any.whl
- Upload date:
- Size: 271.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
55f85940e3848cd2ba139767bbf1770daa2b6e714de13544e8fde1b77f0381a7
|
|
| MD5 |
2979d1ce078a5a68bdde800522acc6e7
|
|
| BLAKE2b-256 |
3c44c358335eedfe93c0696f5e1c7742e4eddf1aeae656a236ca522ee264dae3
|
Provenance
The following attestation bundles were made for assgen-0.3.2-py3-none-any.whl:
Publisher:
release.yml on aallbrig/assgen
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
assgen-0.3.2-py3-none-any.whl -
Subject digest:
55f85940e3848cd2ba139767bbf1770daa2b6e714de13544e8fde1b77f0381a7 - Sigstore transparency entry: 1280272521
- Sigstore integration time:
-
Permalink:
aallbrig/assgen@b11df9e1f113060afba8bb1af44478523245988e -
Branch / Tag:
refs/tags/v0.3.2 - Owner: https://github.com/aallbrig
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@b11df9e1f113060afba8bb1af44478523245988e -
Trigger Event:
push
-
Statement type: