THE FIELD GUIDE
The CLI
reference.
Every command, option, and rule of the Asset Yard CLI. Start with the guide at /docs/.
Commands
Global options go before the command: assetyard --profile my-game generate ....
| Command | Use |
|---|---|
login | Connect this PC to your account in the browser. The person runs it, one time. It makes the default profile. See Restricted access for its options. |
logout | Disconnect this device and remove its local credentials. Agents never run it. |
whoami | Show the account email and name, the profile, the project, the connection, scopes, and spent credits. |
balance | Show the credits that this connection can use. |
capabilities | Show kinds, providers, settings, voices, languages, prices, and limits. |
credits top-up | Check one-off top-up availability. See Credits. |
projects create NAME | Make or reconnect a project. See Profiles and projects. |
projects list | List the account projects on this site. |
projects revoke NAME --yes | Revoke a project on every device. |
configure | Show or change local defaults. See Defaults. |
generate KIND | Submit one request. Kinds: image, music, model, environment, tts, voice, sfx, video. |
estimate KIND | Estimate one request without generation or spending. |
jobs list|status|wait|download | Inspect, wait for, or download an existing request. |
jobs organize REQUEST_UUID | Repeat library actions for a request. See Private library. |
library ... | Manage favorites and named collections. |
assets build MANIFEST | Build or resume an asset pack. See Asset packs. |
voices list|show | Search the published voice catalog. |
| Global option | Use |
|---|---|
--profile NAME | Use this saved sign-in. |
--no-dynamic-defaults | Ignore remembered settings for this command. |
--no-defaults | Ignore configured and remembered settings for this command. |
--reset | Clear all remembered settings for this API origin. |
--api-base URL | Use another API origin. The default is https://uncen.ai. |
--http-timeout SECONDS | Set the HTTP timeout. |
--credential-file PATH | Use a private credential file on a headless host. Not on a shared PC. |
--token-env NAME | Read a short-lived CI access token from an environment variable. Not on a shared PC. |
--state-dir PATH | Keep request journals and locks in another directory. Not on a shared PC. |
--version | Print the CLI version. |
Credits and balance
assetyard balance
assetyard credits top-up
assetyard estimate tts --voice VOICE_KEY --text "The route is clear."Personal access (a login or a project) uses the account balance. Restricted access shows its own allowance, not the complete account balance.
One-off credit top-ups are not available yet. credits top-up returns top_up_unavailable. Its JSON includes subscription_url and funding_note when the server gives them. It does not open a subscription checkout. Use --no-browser to keep the browser closed.
Subscription options are separate. Changing an existing paid plan does not immediately refill credits. Credits added later become available without another login.
The CLI never purchases credits or changes a subscription.
Restricted access
Use restricted access for contractors, hosted agents, or tasks that need fewer permissions. It keeps its own credit allowance, tools, collection restriction, and expiry. It never gives administrator permissions.
assetyard --profile sound-designer login --restricted --max-credits 30 --scope assets:read --scope sfx:generate
assetyard --profile sound-designer whoamiExplicit --restricted, --max-credits, --scope, or login --collection selects restricted access. Restricted access needs a credit allowance. It does not add account credits.
The person approves it in the browser, like a login. A restricted connection cannot create projects, and it does not gain library permissions.
Use CLI connections to change its total limit or expiry without logout. The page also lets you approve conversion to personal access. It does not convert old connections automatically.
Run plain login on that profile to request owner-approved conversion to personal access. Use login --restricted --max-credits N with the required scopes to request a revised allowance. Omitted scopes and collection restrictions stay unchanged. Existing restricted credentials keep their restrictions after a client upgrade.
logout on a restricted profile revokes the restricted connection.
Credentials and headless hosts
The CLI stores desktop credentials in the operating system credential store: Credential Manager on Windows, Keychain on macOS, and Secret Service or KWallet on a Linux desktop. It rejects plaintext keyring back ends. It never prints access or refresh tokens.
Use login --no-browser when another browser must approve the request. The approval URL and code go to stderr. Do not copy browser cookies or Google tokens into the terminal.
A headless Linux or macOS host can use an explicit private credential file outside the repository. A shared PC must not.
mkdir -p "$HOME/.config/asset-yard-auth"
chmod 700 "$HOME/.config/asset-yard-auth"
assetyard --credential-file "$HOME/.config/asset-yard-auth/login.json" login --no-browser
assetyard --credential-file "$HOME/.config/asset-yard-auth/login.json" balanceUse the same flag on later commands. The file supports automatic token refresh. The CLI requires an absolute path outside Git repositories, an owned 0700 directory, and an owned 0600 file. It rejects symbolic links and extra hard links. It never selects file storage without the flag. Windows always uses its native credential store.
The file contains secrets. Keep it out of source control, shared folders, build artifacts, asset packs, and logs.
For CI, supply a scoped access token through your secret manager:
assetyard --token-env UNCEN_ASSET_TOKEN whoamiAn environment token lasts at most 15 minutes and cannot refresh. Do not use it for long jobs. Never put tokens in arguments, source files, manifests, or shell history.
How long a sign-in lasts
A personal connection has no fixed end date. Each device sign-in lasts 90 days from its last token refresh, and each refresh extends it. A profile that you use at least once in 90 days stays signed in.
A sign-in ends when someone revokes it: logout, the owner on CLI connections, projects revoke, or the server's token-reuse protection. Token-reuse protection revokes only the affected device session. projects create NAME then reconnects a project.
logout disconnects this personal device and removes its local credentials. It does not delete assets or disconnect other devices. Downloaded files stay usable.
Sign-in errors
| Error | What to do |
|---|---|
login_required, invalid_token, invalid_grant | The profile is not signed in, or the server rejects it. For a project profile, run the next_command in the error, for example assetyard --profile default projects create NAME. For the default profile, the person runs assetyard login. |
refresh_uncertain | A refresh response was lost. The CLI saved a retry identifier and reuses it. If the recovery window expires, reconnect the profile as above. Do not log out first. |
profile_in_use | The profile name holds another working sign-in. Choose another project name. |
personal_access_required | A restricted connection cannot manage projects. Use the login profile. |
invalid_parent_proof | projects create could not prove the saved sign-in of the parent profile. Run whoami on the parent profile. If that fails too, the person runs assetyard login. |
personal_login_required | The private library needs personal access. Use the login profile or a project. |
Reconnection keeps the request journals. The CLI never resubmits an unconfirmed old request under another identity. Keep your request IDs and resume after reconnection.
Defaults
assetyard configure default-tts-provider PROVIDER_FROM_CAPABILITIES
assetyard configure default-collection my-game
assetyard configure default-category hero
assetyard configure --show
assetyard configure --unset default-collectionConfiguration is local and needs no login. Defaults are separate for each API origin. An explicit argument always wins. Provider settings in --settings, --set, or --model are also explicit.
default-profile sets the profile for every command on the PC. The profile selects the account that pays, so run whoami after a change. Agents must not change it.
default-collection supplies the generation scope label for generate and estimate only. It does not change login permissions or library collections.
default-category, default-gender, default-age, and default-language filter voices list. They do not change generation or a voice's traits.
Remembered choices
Automatic remembering is off by default. This prevents a previous command from changing the account or hiding search results.
assetyard configure --dynamic-defaults
assetyard --profile my-game voices list --category hero --gender male
assetyard voices list
assetyard --reset
assetyard configure --no-dynamic-defaultsWhen you enable it, successful commands remember explicit profiles, generation scope labels, and voice filters. Remembered settings are separate for each working directory and profile. Providers need explicit configuration and are never remembered.
The CLI reports used and changed defaults on stderr. JSON stays on stdout and includes cli_defaults when defaults affect the command. The CLI never remembers prompts, dialogue, references, output paths, seeds, or spending limits.
Precedence is: explicit argument, remembered setting, configured setting, built-in default.
--reset (also --reset-all-dynamic-settings) clears remembered settings in all working directories for the API origin. Configured settings and credentials stay.
Global --no-dynamic-defaults bypasses remembering for one command. Global --no-defaults bypasses both layers. configure --no-dynamic-defaults turns remembering off until you turn it on again.
For repeatable automation, use --profile NAME --no-defaults (or --no-dynamic-defaults) with explicit request settings. Manifest builds do not inherit configured or remembered providers, collections, or voice filters. Retries with an existing request ID keep the saved provider and collection when you omit them.
Speech languages
assetyard voices list --language es
assetyard generate tts --language es --voice VOICE_KEY --text "La señal se perdió." --out narration/es/line.wavgenerate tts --language CODE sends a speech language, for example es, fr, pt-BR, or zh-Hans. The server selects the speech engine of that language. English keeps its current engine.
capabilities lists the available languages under kinds.tts.languages. voices list --language CODE lists the voices whose sample is in that language.
Any catalog voice can speak another listed language. Its accent can move toward the language of its sample, so a native voice is the better choice. A request with --language does not send the default provider. An explicit --provider still applies.
Model settings
Several views of one object
assetyard generate model --prompt "a mining shuttle" \
--reference-image front.png --reference-view front \
--reference-image left.png --reference-view left \
--reference-image back.png --reference-view back \
--out shuttle.glbA 3D model accepts up to four reference images, one for each view of the same object. Give one --reference-view for each image, in the same order: front, left, back, or right. The front view is required and becomes the front of the mesh. Without --reference-view, the images take the views in that order.
Use eye-level pictures, 90 degrees apart, of one object on a plain background. One image uses the single-view pipeline. An environment accepts one image.
Supplied images keep their source orientation. The rigid vehicle profile requires a generated front elevation. To prepare a side elevation, first edit the image with an image editor from capabilities, inspect the result, then use its media ID. Normalization is not automatic.
Orientation details
Select the profile with --orientation-profile rigid_vehicle, with --set orientation_profile=rigid_vehicle, or in a manifest with settings.orientation_profile: rigid_vehicle. All three send the same setting.
The aligned GLB uses +Y up, +Z forward, and a centered pivot. These axes follow the glTF convention, not a camera's viewing direction.
This is not universal front detection. Check orientation.status in the result metadata before you use a vehicle. needs_review means that the geometry is ambiguous. That result preserves the source pose instead of claiming correct alignment.
The vehicle profile also checks bilateral symmetry. Large unmatched wings or other structural defects need review. Small details can differ.
The default source profile preserves the input pose. It does not infer vehicle settings from prompt words. A game that moves along -Z needs one shared 180-degree Y rotation at import. Do not add separate corrections for each ship.
Keep the original setting when you retry. Omit it if the original request omitted it.
Delivery size
Use --target-faces and --texture-resolution (512, 1024, or 2048) to control the delivery size. Each completed GLB keeps its provider license record. See Models and licenses.
Voice catalog details
The catalog returns only voices in the published runtime set. It never returns a private object location. The preview_url needs the same CLI credential.
Each result includes release_basis and human_reviewed. A human_review release passed the listening score gate. A technical_checks release passed batch, trait receipt, storage, format, and loudness checks only.
The three HFY voices above passed technical and transcript checks. Their metadata records human_reviewed: false. They do not clone an actor or imitate a game character.
Age is casting metadata, not a content restriction. Requested traits are not verified identities or accent guarantees.
The CLI never sends a private object URI. The server resolves the published voice key, binds the verified audio checksum, and checks the binding again before the worker uses it.
| Voice mode | Selection | Use |
|---|---|---|
| Asset Yard catalog | A stable voice_key from voices list | Reusable game characters and narrators |
| Provider voice | A provider and voice from tts.providers in capabilities | Built-in voices of one provider |
| Private custom sample | --voice custom --reference-media-id OWNED_AUDIO_MEDIA_ID | A voice design sample (see below) |
A provider uses its default voice when you omit --voice. Repeated catalog pages use a short server cache.
Voice design
Voice design makes a private reference sample for the speech engine. It is a two-stage flow, not another speech provider. Personal access does not include it. After activation, a person approves a new restricted connection with voice and speech scopes. Existing connections do not receive voice:generate.
assetyard --profile voice-work login --max-credits 30 --scope assets:read --scope voice:generate --scope tts:generateFirst, design a sample. The prompt describes the voice. The text is the exact sample transcript, 160 to 500 characters, for a sample of 10 to 30 seconds:
assetyard --profile voice-work generate voice --prompt "A calm space guide with clear diction" --text "Welcome aboard. I will guide your crew through each system check, one clear step at a time. Watch the blue status lights, confirm each green signal, and stay with me until the launch computer reports that every system is ready." --language en --cfg-scale 4 --out assets/guide-voice.wavCopy the completed media ID. Then speak with that private sample:
assetyard --profile voice-work generate tts --text "Navigation is ready. Start the launch sequence when your team is prepared." --voice custom --reference-media-id VOICE_MEDIA_ID --out assets/launch-guide.wavThe server accepts an owned private media ID from the same connection and permitted collection. It does not accept a local path or an arbitrary URL. The sample must last 10 to 30 seconds.
You can steer a new design with owned audio and its exact transcript. Use both options together:
assetyard --profile voice-work generate voice --prompt "Keep the pace, but sound warmer and less formal" --text "You found the hidden route. Stay close, and I will get everyone home safely. Follow the painted stones beside the river, keep your lantern covered, and wait for my signal before the whole group crosses the old wooden bridge." --steering-media-id OWNED_AUDIO_MEDIA_ID --steering-text "The exact transcript spoken in the steering audio." --out assets/warm-guide-voice.wavRun the two stages separately. Manifest version 1 cannot pass a new media ID to a later entry. A later manifest can use a literal reference_media_id after the sample exists.
Private library: favorites and collections
Personal access (a login or a project) can keep favorites and named collections. Restricted connections do not gain these permissions. The library preview first opens to approved accounts.
assetyard generate image --prompt "A painted starport at sunrise" --mark-favorite --add-to "Sector Prime" --out assets/starport.png
assetyard library collections
assetyard library create "Mission briefings"
assetyard library list
assetyard library list --collection COLLECTION_UUID
assetyard library list --favorites --type voice
assetyard library favorite voice ayq1_atlas_narrator_c1
assetyard library add voice ayq1_lyra_vanguard_c1 --to "Sector Prime"
assetyard library favorite media MEDIA_UUID
assetyard library unfavorite media MEDIA_UUIDBoth organization flags wait for generation to finish and use the returned media UUID. Repeat --add-to NAME to use several collections. Names can contain spaces. A repeated name resolves to the same private collection.
--add-to NAME organizes the library. --collection LABEL sets the generation scope label. These are separate. Neither publishes files or changes their visibility.
library list shows favorites by default. Use --collection COLLECTION_UUID for a collection, --type voice or --type media to filter, and --limit and --offset to page (100 items at most). Library commands use a media UUID or a voice key. A request UUID belongs to the jobs commands.
Organization uses idempotent state assignments. A lost response cannot create duplicate favorites or collection names. The CLI retries temporary errors three times.
Favorites and collections stay private. They do not publish files, extend retention, or provide game hosting.
Asset packs
A manifest describes a set of assets. One command builds it and resumes it. See Voidwake: Meridian Run for a small working game and its manifest. That page uses the completed pack by default. Add ?edition=development only to compare the procedural development assets.
version: 1
assets:
- id: crate
kind: model
prompt: One low-poly wooden supply crate with a closed lid
settings:
geometry_profile: prop
out: assets/crate.glb
- id: courier
kind: model
prompt: One symmetric courier spacecraft with a pointed nose and two wings
settings:
geometry_profile: prop
orientation_profile: rigid_vehicle
out: assets/courier.glb
- id: radio_ballad
kind: music
prompt: Irish folk ballad, male baritone, acoustic guitar
settings:
duration_seconds: 75
lyrics: |-
[verse]
Forty one years in a flowerbed.
out: assets/radio-ballad.wav
- id: pop
kind: sfx
prompt: One short cartoon pop, dry recording, no music
settings:
duration_seconds: 1
seed: 42
out: assets/pop.wavSave it as assets.yaml in the game directory. JSON manifests use the same schema. Then build it:
assetyard --profile my-game assets build assets.yaml --run coder-a --jsonThe CLI writes assets.coder-a.lock.json. Without --run, the lock is assets.lock.json. Run the same command to resume. The lock keeps request IDs, payload hashes, resolved settings, metadata, file hashes, credit usage, the account, the API origin, and the stable connection identity. It contains no credentials or signed URLs. It can contain prompts and private game details.
- Builds run one asset at a time.
--max-credits 25limits spending across the whole lock file, including earlier jobs and entries later removed from the manifest. A saved limit stays active on later runs. Give a new limit to change it.- Without a build limit, the server applies the account credits and any restricted allowance.
- A changed prompt or setting for a locked asset is an error. Use a new asset ID, run, or lock file for a new generation.
- Output paths use forward slashes and stay under the manifest directory, or under
--output-dir. Absolute paths, traversal, symbolic links, and duplicate paths are errors. --collection my-gameadds a generation scope label. It does not create a Multiplayers project.- Manifests do not inherit local defaults. Put providers, collections, and filters in the manifest.
Keep the JSON lock file for reproducible assets. Add *.uncen-lock to the game's ignore file.
For a fair coding comparison, give every coder the same completed pack. Use separate runs and budgets to compare generation choices.
Files, credentials, and server storage
| Item | Where it stays |
|---|---|
| Downloaded assets | Normal files in your game directory. The game needs no Asset Yard token at runtime. |
| Generation records and files | Your account, the media database, and private storage. Downloading does not delete the server copy. |
| Asset manifest and JSON lock | Your project directory. They hold prompts and metadata, but no credentials or signed URLs. |
| Access and refresh tokens | The native credential store, or an explicit private file on a headless host. |
| Request journals and locks | The state directory: %LOCALAPPDATA%\Uncen\CLI on Windows. Its jobs/*.uncen-lock files show which request IDs the CLI touched. |
New CLI outputs are private. Website previews need your sign-in. Upload an edited copy when you need a separate version. Temporary retention and delete-on-download are not available. See the storage policy.
The CLI does not provide public hosting or a CDN. Include downloaded assets in your game build or your own delivery service. Never put CLI credentials or authenticated download endpoints in a released game.
Downloads verify SHA-256 and the byte count before the CLI writes the local file. An identical file is reused. A different local file needs another path or explicit --overwrite. The CLI never replaces an edited game asset without that flag. New downloads need a file system with hard-link support.
Read each asset's license metadata before you distribute it. See Models and licenses.
Output and exit codes
Default results and errors use one final JSON document on stdout. Explicit --json uses JSON Lines and emits request_saved before the first POST. Progress and approval details use stderr. Do not merge the two streams in automation.
| Exit code | Meaning |
|---|---|
| 0 | The command succeeded. |
| 2 | The input or budget is invalid. |
| 3 | Sign-in, permission, or credential store error. |
| 4 | The generation failed. |
| 5 | API, network, or integrity error. |
| 6 | A local file conflicts or cannot be accessed. |
| 7 | The wait timed out. The server job can continue. |
| 130 | The caller interrupted the command. |
jobs status reports a failed job as data and exits with 0. jobs wait exits with 4 for the same job.
Bash scripts that pipe through tee must use set -o pipefail. Otherwise a failed CLI command looks successful.
Troubleshooting
A request returns not_found (HTTP 404)
The server has no request with that ID for this account. The request was never submitted, was deleted, or belongs to another account or server.
The error names the request ID and the server. The CLI does not retry a 404, and jobs wait stops at once. Check --api-base and the account in whoami. To create the asset, submit the request again.
Do not run jobs status in a loop on an unknown ID. Many 404 answers in a short time can block your network address for one hour.
The CLI retries only server errors (HTTP 5xx), network failures, and rate limits (HTTP 408 and 429). Each retry has a fixed attempt limit and a wait between attempts.
A profile is signed out
See Sign-in errors. For a project, run assetyard --profile default projects create NAME. For the default profile, the person runs assetyard login. The most common cause is a CLI process that stopped during a token refresh. Never kill a running CLI process.
The command cannot find a credential store
Windows uses Credential Manager. macOS uses Keychain. A Linux desktop needs a working Secret Service or KWallet session. A headless Linux host can use a private credential file.
A provider or asset type is unavailable
Run capabilities. Check both availability and authorization for that kind. An unavailable worker needs server configuration. A restricted connection can lack permission for the tool. The CLI does not choose another model or a paid service without your request.
A command stops with concurrency_limit
Every request slot of the account is busy. The response includes Retry-After, active_requests, and concurrency_limit. The CLI waits and retries with the same request. More credits do not clear it.
A Windows upgrade fails
Stop all running assetyard and uncen commands, then run the install command again. Use python -m uncen_cli only as a temporary recovery command.
Custom clients
A custom client uses the CLI bearer credential in the Authorization header. Never put a credential in a URL, a public game, or a browser bundle. Keep it in your trusted backend or the CLI credential store.
| Endpoint | Use |
|---|---|
GET /api/uncen/v1/cli/assets/REQUEST_UUID/events?timeout=1800 | Server-Sent Events for one request: asset.status, heartbeat, wait.timeout, and stream.error. A reconnect returns current state, not an audit history. This is not a webhook API. Do not build a polling loop around it. |
GET /api/uncen/v1/cli/auth/me | The connection. It includes account_email, account_name, and project_name. |
POST /api/uncen/v1/cli/projects | Body {"name", "device_label", "refresh_token"}, with the bearer access token of a personal connection. The refresh token is the current one of that same saved sign-in. It proves the saved sign-in, so a copied access token alone cannot make a long-lived connection. A wrong or used refresh token gets 401 invalid_parent_proof. The response is a new credential set. Store it in a credential store. Never print it. The CLI does all of this itself. |
GET /api/uncen/v1/cli/projects | List the account projects on this site. |
POST /api/uncen/v1/cli/projects/NAME/revoke | Revoke a project on every device. |
Product keys of an account can also call POST /api/uncen/v1/creative/voice and POST /api/uncen/v1/creative/tts with the same ownership and license checks.
Changes
Run the install command again to upgrade. The newest release is first.
| Version | Change |
|---|---|
0.12.0 | Adds projects create, projects list, and projects revoke. whoami shows the account email, the profile, and the project. A sign-in error names projects create and gives next_command. It no longer tells you to log in. |
0.11.1 | A request with generate tts --language no longer sends the default TTS provider. The language selects its provider. An explicit --provider still applies. |
0.11.0 | Adds generate tts --language CODE and voices list --language CODE. capabilities lists kinds.tts.languages. |
0.10.3 | A 3D model accepts up to four reference images, one for each view, named with --reference-view. |
0.10.2 | A long wait refreshes its 15-minute access token and reconnects. Earlier versions stopped a wait after about 30 minutes with invalid_token. |
0.10.1 | HTTP 404 and 410 are final answers. The CLI asks about a new request ID at most once before it submits the request. |
0.10.0 | Waits use authenticated Server-Sent Events for every asset kind. No status polling. |
0.9.4 | Adds the environment kind: one picture to one 3D place. |
0.9.2 | A 3D model accepts an owned reference image and skips image generation. |
0.8.4 | UTF-8 console output on Windows, including pipes. Music status returns metadata.lyrics and metadata.song_title. |
0.8.3 | Music kind song, curated presets, and the lyric language. |
0.8.2 | Adds --lyrics and --lyrics-file. |
0.8.1 | Retries capacity limits and incomplete dispatches with the same saved request. |
0.6.0 | Private favorites and named collections for personal connections. |
0.4.3 | Adds --orientation-profile rigid_vehicle. 0.4.2 accepted the same setting through --set. |