Unity CLI
SkillFiles & storageUse when interacting with Unity CLI from the terminal, or to control a running/connected Unity Editor from the command line — create or modify GameObjects, edit scenes and assets, inspect the hierarchy, and run C# in a live Editor instead of hand-editing scene or asset files. Also install, upgrade or uninstall editors, create, list or open projects, manage modules, manage licenses, check auth status, read logs, browse Unity releases, build/test projects, configure the Unity MCP server for AI agents, or run any other Unity CLI operation. For a guided idea-to-running-project flow for a brand-new game, use the new-unity-project skill instead.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Unity CLI skill
What this skill tells your AI
The instructions your AI receives, as published by unity-technologies/skills in skills/unity-cli/SKILL.md and read by ahel’s review.
Drive a running Unity Editor (if one is open)
If a Unity Editor is open on this machine, this CLI can control it live — create and modify GameObjects, edit scenes and assets, inspect the hierarchy, and run arbitrary C# — through the project's Pipeline package (com.unity.pipeline). This runs entirely on your local machine, in your own user account, against your own open Editor: it is not remote access and grants no privilege you don't already have at your own terminal. When an Editor is available, drive it instead of hand-editing scene or asset files.
unity status # confirm a connected Editor (look for state "ready")
unity command # list the commands the Editor exposes
unity command editor_play # run one — e.g. enter Play mode
# Run arbitrary C# — e.g. add a GameObject named "Joe" — when the Editor exposes eval:
unity command eval 'new UnityEngine.GameObject("Joe");'
More than one Editor open? Pass --project-path
Every Editor-driving command takes --project-path <path>. Pass it whenever more than one Editor may be running — without it the CLI targets the Editor whose project contains the current directory, so the target follows the shell's cwd:
unity command editor_play --project-path /path/to/MyProject
A unity status instance's project field is what --project-path takes. For unity command/list/job/mcp, matching no running project fails with AMBIGUOUS_EDITOR and lists the candidates. Details.
Requires the project's com.unity.pipeline package (Unity 6.0+) — add it once with unity pipeline install. Full details — launching a headless Editor to drive, unity list tool discovery, and authoring custom [CliCommand] tools — are in integration-advanced.md.
The package also ships a deeper unity-pipeline agent skill, invisible to clients inside Library/PackageCache — in a project with the package, run unity skill install <client> --local once to mirror it beside this skill.
Can't connect / commands time out? Check for Safe Mode first. When a project has C# compile errors, the Editor boots into Safe Mode, where the Pipeline package doesn't load — so
unity command,unity status, andunity listcan't connect at all. Don't fall back to blind file-editing: rununity pipeline listto confirm, then fix the compile errors and restart Unity. Full recovery loop in integration-advanced.md → Recovering from Safe Mode.
Running as a sandboxed coding agent and
unity statusreports no instances? A restrictive sandbox can hide an Editor that is genuinely running from this CLI's view of it — don't treat that alone as proof the Editor is down. Full detail in integration-advanced.md → Sandboxed agent tooling can hide a running Editor.
Install the CLI (if not already installed)
First check if the CLI is available:
which unity && unity --version
If not found, install it:
macOS / Linux
curl -fsSL https://public-cdn.cloud.unity3d.com/hub/prod/cli/install.sh | UNITY_CLI_CHANNEL=beta bash
Windows (PowerShell)
$env:UNITY_CLI_CHANNEL='beta'; irm https://public-cdn.cloud.unity3d.com/hub/prod/cli/install.ps1 | iex
After installing, open a new shell so unity is on PATH, then verify with unity --version. If the install script fails or the binary is still not found, tell the user and stop; if the command itself fails with a permissions error or crash, the installation may be broken — suggest re-running the install script.
Global flags
These work on every command:
| Flag | Description |
|---|---|
--format <fmt> | Output format: human (default), json, tsv, ndjson, github. Also via UNITY_FORMAT env var. |
--json | Global shorthand for --format json, accepted on every command (e.g. unity status --json, unity doctor --json). --format takes precedence when both are supplied. |
--no-banner | Suppress the branded header — use in scripts |
--no-pager | Turn off paging. Governs both pagers: the external one over the long listings (unity command, releases, editors, changelog, logs) and the interactive one in unity projects list. Also via UNITY_NO_PAGER (presence-based — any value, including 0, disables it). |
--non-interactive | Disable all interactive prompts — use in CI |
--quiet | Suppress non-essential output |
--verbose | Print full error details (stack trace + cause chain) on failure. Also via UNITY_VERBOSE. |
--proxy <url> | HTTP/HTTPS/SOCKS/PAC proxy URL for this invocation. Also via UNITY_PROXY. Takes precedence over standard HTTPS_PROXY/HTTP_PROXY/ALL_PROXY env vars and the persisted proxy.json setting. |
--proxy-disable | Disable proxy for this invocation, ignoring all sources (env vars, persisted config, system settings). |
--log-proxy | Log one redacted entry per outbound request to proxy-request.json — for reproducing proxy issues. Also via UNITY_LOG_PROXY=1 or the proxyRequestLogging setting. |
--no-log-proxy | Opt a single invocation out of proxy request logging when it's enabled globally. |
--color <auto|always|never> | Control colored output for this invocation, overriding NO_COLOR/FORCE_COLOR and TTY auto-detection. Governs every ANSI-emitting surface (help, tables, spinners, errors), not just human output. |
--no-color | Shorthand for --color never. Whichever of --color/--no-color appears last on the line wins. |
Always use --format json when you need to parse output programmatically.
unity projects list is the only command that pages IN-PROCESS. It shows 10 projects per screen and waits for a keypress between screens, and only when stdout is a terminal. Paging is off for redirected stdout, under --format json and --format ndjson, and under --all, --watch, or --no-pager / UNITY_NO_PAGER.
Not every machine format bypasses that one. Only json and ndjson get their own non-interactive rendering; on a terminal, --format tsv and --format github fall through to the human table and page like human does — so --format tsv on a TTY yields neither TSV nor unpaged output. Redirect stdout (the usual case for a machine format) or pass --no-pager. Note this is the opposite of the external pager below, which is human-only: the two mechanisms differ here, and projects list is the surprising one.
The long listings page through an external pager, like git log. unity command (the bare listing), unity releases, unity editors, unity changelog, and unity logs pipe human output through less -RFX on a terminal — colors kept, no screen clear, and -F quits by itself when the output already fits one screen, so short listings show no pager UI. $UNITY_PAGER then $PAGER override the choice and run through a shell, so PAGER="less -S" works; a blank value is ignored rather than treated as an opt-out. Quitting with q exits cleanly with the command's own exit code. Unlike projects list's pager this one is human-only, and it never engages for redirected stdout, any machine format (json, tsv, ndjson, github), --quiet, TERM=dumb, the streaming modes (editors --watch, logs --follow), a named unity command <name>, or inside unity shell. A broken pager costs the paging, not the output: a $PAGER naming something that is not there is resolved before anything spawns, and one that spawns and then dies has its output reprinted to the terminal, decided from the pager's exit status (a clean exit is a normal q and discards; a failure status reprints). The exception is a pager that exits successfully without reading — PAGER=true, or anything that lingers and then exits 0 — which nothing distinguishes from a q, and which git loses too. A pager that starts and merely waits is not treated as broken, so the CLI waits with it.
A branded Unity header (logo, wordmark, CLI version) renders on the landing surfaces — bare unity, unity --help / -h, unity help, and above the first-run consent prompt. It's shown only on a TTY, prints at most once, and degrades to compact, uncolored text on narrow terminals, without Unicode, or under NO_COLOR. Piped output is unaffected. Use --no-banner to suppress it in scripts. Bare unity prints usage and exits 0.
Environment variables
All CLI env vars use the UNITY_ prefix. A CLI flag always overrides the corresponding env var.
| Variable | Mirrors flag | Description |
|---|---|---|
UNITY_FORMAT | --format | Output format (human, json, tsv, ndjson, github). HUB_FORMAT is a deprecated alias. |
UNITY_EDITOR_VERSION | --editor-version | Editor version (e.g. 2023.3.0f1, latest, lts). |
UNITY_ARCHITECTURE | --architecture | Chip architecture (x86_64, arm64). |
UNITY_PROJECT_PATH | path argument | Project path — used by open, and also honored by status and the cloud commands. |
UNITY_QUIET | --quiet | Suppress non-essential output. |
UNITY_VERBOSE | --verbose | Show full error details on failure. |
UNITY_NON_INTERACTIVE | --non-interactive | Disable interactive prompts. |
UNITY_NO_BANNER | --no-banner | Suppress the branded banner. |
UNITY_NO_PAGER | --no-pager | Turn off paging — both the external pager over the long listings and unity projects list's interactive one. Presence-based: any value counts, including 0. |
UNITY_PAGER | — | The pager to use for the long listings, overriding $PAGER and the less -RFX default. Runs through a shell, so flags work (less -S). A blank value is ignored, not an opt-out. |
PAGER | — | Same as UNITY_PAGER, consulted only when that is unset or blank. |
LESS / LV / LESSCHARSET / MORE | — | Passed to the pager only when you have not set them, defaulting to FRX, -c, utf-8, and FRX. LESSCHARSET keeps multi-byte glyphs readable where the locale does not declare UTF-8; MORE exists because more on macOS/BSD is less under another name and reads $MORE, so without it PAGER=more waits for a keypress even for one line. |
UNITY_RUN_TIMEOUT | --timeout | Timeout for unity run in seconds. |
UNITY_TEST_TIMEOUT | --timeout | Timeout for unity test in seconds. |
UNITY_CLOUD_ORG | --cloud-org | Active Unity Cloud organization id or name for a single call. |
UNITY_SERVICE_ACCOUNT_ID | — | Service account client ID for non-interactive (CI) auth. |
UNITY_SERVICE_ACCOUNT_SECRET | — | Service account client secret for non-interactive (CI) auth. |
UNITY_PROXY | --proxy | HTTP/HTTPS/SOCKS/PAC proxy URL. Takes precedence over HTTPS_PROXY/HTTP_PROXY/ALL_PROXY and the persisted proxy.json setting. |
UNITY_NO_UPDATE_CHECK | — | Disable the background "update available" check (see unity config update-check). |
UNITY_NO_CONSENT_PROMPT | — | Suppress the one-time first-run analytics consent prompt without recording a choice — for wrapper scripts on an interactive terminal that must never absorb the prompt. Analytics stay off until you run unity analytics opt-in. Unlike UNITY_NON_INTERACTIVE, it changes nothing else about command behavior. |
UNITY_NO_CRASH_REPORT | — | Disable anonymous crash/error reporting (Sentry) entirely. |
UNITY_LOG_PROXY | --log-proxy | Log one redacted entry per outbound request to proxy-request.json. Truthy values: 1, true. |
UNITY_NO_ELEVATE | --no-elevate | Windows: skip the elevated (UAC) install helper for install / install-modules, so the install service runs unelevated. The Editor's NSIS installer still asks for elevation on demand if Windows requires it for your account — an administrator token always does; a standard user never does. |
UNITY_INSTALL_RETRIES | --retries | Number of times install-modules retries a module whose download/validation fails. 0 disables retries. |
CI service account auth: Set both UNITY_SERVICE_ACCOUNT_ID and UNITY_SERVICE_ACCOUNT_SECRET to skip the browser OAuth flow — this keeps the secret out of the process argument list and shell history. These map to the --client-id / --secret-from-stdin inputs of unity auth login, but reading the credentials from the environment isn't a full login: it doesn't run the interactive flow or persist credentials to the keyring.
Getting help
Append -h or --help to any command or subcommand, at any level: unity --help, unity projects create --help.
Exit codes
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | General error |
| 2 | Bad arguments |
| 3 | Authentication failure |
| 4 | Precondition not met (e.g. no license active, floating server not configured) |
| 6 | Command-specific failure |
| 8 | unity test only — the tests ran and one or more failed. Every other way a test run fails (compile error, unavailable license, editor crash, --timeout) keeps 6, so CI can retry an infrastructure failure and never retry a failing test. |
| 130 | Interrupted — Ctrl+C / SIGINT (128 + 2) |
| 143 | Terminated by SIGTERM (128 + 15) — e.g. kill or a CI/runner timeout. Emitted by long-running commands that install a signal handler to clean up first (currently unity build, which scrubs the temporary Android keystore). |
The cloud and auth commands map an authentication failure (expired/missing session, rejected sign-in) to 3, and any other operational failure (network, server error) to 6 — so scripts can reliably tell "sign in again" apart from a genuine command failure.
Commands
The full per-command reference — syntax, flags, and examples — lives in grouped files under
references/. Read the file for the command group you need; all the global
flags, environment variables, and exit codes above apply throughout. Every command also supports
-h / --help (see Getting help).
| Commands | Reference file |
|---|---|
auth (login / logout / status / list / switch / default / consumers / revoke), license (activate / return / server), cloud (org / project) | auth-license-cloud.md |
editors (list / running / add / default / path / install-path / info / upgrade / prune / verify / module), install, uninstall, modules, install-modules | editors-install.md |
projects (list / create / new / clone / open / link / require / upgrade / export / import / pin / size / clean / exec), releases, templates (list / info / create / pack / delete) | projects-templates.md |
config (proxy / update-check / get / set / list / unset), hub install | config-hub.md |
run, test, build | build-run-test.md |
logs, doctor, env, version, cache, ci init, analytics, changelog, language, completion, bug, self-update, self-uninstall, diagnose proxy | diagnostics-maintenance.md |
mcp (+ configure), skill (install / refresh / show), plugin (install / remove / upgrade / list / changelog), connected editors (pipeline / command / status / list), shell | integration-advanced.md |
vcs — setup / status / sync / switch / doctor / providers / merge-setup / conflicts / explain / resolve / diff / blame / summarize / affected / hooks, vcs git (migrate-lfs / worktree), vcs uvcs (locks / changesets / review) | version-control.md |
collaboration (alias collab) — annotations / attachments / thumbnail / reactions / read / subscribe / jira | collaboration.md |
Common workflows
Edit a scene, GameObject, or asset — unity status first
Before editing any scene, GameObject, prefab, or asset, run unity status to detect a connected Editor. If one is reachable, drive it with live commands instead of touching project files — the Editor applies changes to the actual active scene and keeps its in-memory state in sync.
unity status # is an Editor connected? (look for state "ready")
unity command # discover the scene/GameObject commands THIS Editor exposes
# then drive it with the commands it lists — for example, if your Editor exposes them:
unity command create_gameobject # act on the live, active scene
unity command save_scene # persist the active scene
Command names are defined by the Editor, so run unity command (or unity list) to see the exact set — don't assume a name.
Never hand-edit
.unity,.prefab, or.assetYAML while a live Editor is reachable. Raw-file edits are:
- error-prone — fileIDs and GUIDs are assigned by hand and easy to get wrong;
- invisible to the running Editor until a reimport, so the change silently fails to take effect; and
- prone to hitting the wrong file — e.g. writing to
SampleScene.unitywhile the Editor's active scene is actuallyDemo2.unity, producing valid-looking YAML that changes nothing the user sees.
Rule out two false negatives before concluding no Editor is reachable — both look identical to a genuinely closed Editor, and both are easy to get wrong under time pressure:
- Safe Mode. If an Editor is running for this project but
unity status/unity commandwon't connect, it may be stuck in Safe Mode from a compile error rather than genuinely absent. Rununity pipeline list— if it reports Safe Mode, editing the C# source to fix the compile errors (and then restarting Unity) is the correct move, not a fallback. See integration-advanced.md → Recovering from Safe Mode. - A sandboxed agent shell. If your own shell commands run inside a restrictive sandbox — the normal case for a coding agent like this one — the sandbox can hide a genuinely running Editor from
unity statusthe same way. This applies to every scene/GameObject/prefab/asset task that reaches this preflight, not only ones that obviously need a live Editor: a task you could otherwise finish without any CLI involvement (e.g. generating an asset through ordinary Editor APIs) can still get funneled into "no Editor" here and derailed. Don't treat "no instances" as proof the Editor is down, and don't quietly improvise a third path — like driving a separate headless Editor process to approximate what a live connection would have done — as a substitute for a disclosed file edit. Say plainly that your sandbox may be blocking your view of a real Editor, and ask whether one is actually open before falling back. Full detail: integration-advanced.md → Sandboxed agent tooling can hide a running Editor.
Only fall back to editing files directly once you've ruled out both of the above — and say so explicitly ("no live Editor detected, editing the file directly").
Bootstrap a new project from scratch
For a guided end-to-end experience — concept questions, installing the Editor in the background while you plan, package selection, and monetization handoff — use the
new-unity-projectskill. This section is the raw CLI recipe that skill builds on; use it directly when you just want the commands.
Take an idea to a running, version-controlled project using only the CLI. Decide the target
platforms first — they determine which Editor modules you install in step 2. You can add
modules later (unity install-modules), but a project can't build for a platform until that
platform's module is installed, so it's simplest to decide up front.
# 1. Confirm the CLI works and you're signed in and licensed (see references/auth-license-cloud.md).
unity --version
unity auth status --format json # if signed out: unity auth login
unity license status --format json # if none active: unity license activate
# 2. Pick and install an Editor with the modules your target platforms need.
# Default to the latest LTS (most stable, ~2 years of patches). Reach for a Tech-stream
# release (--stream tech) only for a feature not yet in LTS; treat --stream beta/alpha as
# evaluation-only, never for a project you intend to ship. A deadline argues for LTS.
# (lts / latest aliases work wherever a version is accepted.)
unity releases --stream lts --limit 5 --format json
unity install lts --module android --module ios --yes --accept-eula # add --module webgl, etc.
unity editors --installed --format json # confirm it landed
# 3. List the real template ids this Editor offers — don't guess them.
unity templates list --editor lts --format json
# Common ids: com.unity.template.3d, com.unity.template.2d, and a URP template (id varies by version).
# 4. Create the project. The first positional arg is the NAME; --path sets the parent directory.
# All options supplied, so it won't prompt; add --non-interactive in CI.
unity projects create "MyGame" --path ~/UnityProjects \
--editor-version lts --template com.unity.template.3d
Source control — let the user choose. The CLI publishes the new project to a fresh remote in
one step for any provider. Always pass tokens on stdin (--git-token-stdin) so secrets never
land in shell history or the process list. Pick based on the project — don't default to one:
- Git — GitHub / GitLab (
--vcs github/--vcs gitlab). Ubiquitous. For asset-heavy games add Git LFS (--git-lfs) so large binaries don't bloat history. - Unity Version Control — UVCS (
--vcs uvcs). Unity's own VCS, built for large binary game assets: it handles them natively (no LFS needed) and supports file locking — often the better fit for art-heavy projects or larger teams. Auth uses your Unity sign-in;--vcs-regionselects the region.
# Git (GitHub) — drop --git-lfs if the game isn't asset-heavy. Add --no-initial-commit if you
# want to add packages/assets BEFORE the first commit (see the new-unity-project flow).
unity projects create "MyGame" --path ~/UnityProjects \
--editor-version lts --template com.unity.template.3d \
--vcs github --git-namespace my-org --git-repo my-game \
--git-visibility private --git-default-branch main --git-token-stdin --git-lfs
# Unity Version Control (UVCS) — handles binaries natively, so no LFS:
unity projects create "MyGame" --path ~/UnityProjects \
--editor-version lts --template com.unity.template.3d \
--vcs uvcs --git-namespace my-org --git-repo my-game --vcs-region <region>
Feed the token to --git-token-stdin from a secret store, never a literal — e.g.
… --git-token-stdin <<<"$GIT_TOKEN" where $GIT_TOKEN comes from your CI/secret manager
(UVCS uses your Unity sign-in, so no token is needed).
Working with a UVCS workspace day to day: a few wrapped reads, everything else straight through
to cm. The split is deliberate and worth teaching, because guessing wrong wastes a user's time:
Shortened here. Read the whole file on GitHub.
Signals
- GitHub stars
- 876
- Forks
- 50
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
unity-cli- Source
- github.com/unity-technologies/skills