--- name: unity-agent-packages description: "Add, remove, pin, upgrade, or look up Unity Package Manager (UPM) packages from outside the Editor UI: editing Packages/manifest.json safely, the Unity Package Manager Client API run headless (the async poll pattern without -quit), the Pipeline package_add/package_remove commands on a running Editor, OpenUPM and git-URL packages, packages-lock.json, and which AI-related Unity packages are safe on which Unity version. Use whenever the user asks to install or remove a Unity package, add com.unity.something, bump a package version, fix a package resolution error, add an OpenUPM or GitHub package, or says 'refresh unity-agent-packages' / 'is unity-agent-packages stale'. General CLI use is unity-agent-cli; batchmode mechanics are unity-agent-headless." --- # Unity packages (UPM from the command line and scripts) Outcome: the package change is applied through a route that resolves dependencies (Editor API, Pipeline command, or a reviewed manifest edit) and is proven by `Packages/manifest.json` plus a successful resolve (no `upm.log` errors, Editor out of Safe Mode). ## Step 0: freshness (every use, one read) Read `evergreen.json` next to this file. If `verify_at_use` is true, re-check the listed `volatile_claims` before relying on them. If `contradiction` is set or today is on or after `next_due`, tell the user in one line, do the task with the current content, then run the refresh (`evergreen-refresh`) in the same session. If `tests.failing` is non-empty, say so in one line and run `evergreen-tune` after the task. Never block the task on a refresh unless the task depends on the stale claim. ## Step 1: confirm the target and ask before mutating Read `Packages/manifest.json` (dependencies and any `scopedRegistries`) and `ProjectSettings/ProjectVersion.txt`. A package change edits a tracked file and triggers a domain reload in an open Editor, so state the exact change and get a yes unless the user already asked for precisely this. ## Step 2: pick the route | Editor state | Route | |---|---| | Open with `com.unity.pipeline` reachable (check with `unity pipeline list`; if `unity` is not on PATH yet, call `"$env:LOCALAPPDATA\Unity\bin\unity.exe"`) | `unity command package_add --name com.unity.x[@ver]` then poll `unity command package_status`; `package_remove`, `package_resolve`, `package_list` likewise (unity-agent-cli) | | Closed | the Client API script (Step 3), run with `Unity.exe -batchmode -projectPath
-executeMethod ProjectBootstrap.PackageInstaller.Install -logFile -` **without `-quit`** (the request completes on later Editor ticks and the script exits itself); `unity run` cannot be used because it injects `-quit` |
| Closed, simple pin or OpenUPM/git package, user wants a diff they can review | edit `Packages/manifest.json` by hand: add `"com.x.y": "1.2.3"`, a git URL `"https://github.com/org/repo.git?path=/Pkg#v1.2.3"`, or a scoped registry block for OpenUPM (`https://package.openupm.com` with `scopes`); the next Editor open resolves it. Keep `packages-lock.json` (Unity regenerates it; delete it only to force a full re-resolve) |
Unity's own guidance prefers the Client API over hand edits because it resolves compatible versions; hand edits are fine for pinned versions the user chose.
## Step 3: the Client API script
`references/PackageInstaller.cs` (from Unity's `unity-package-management` skill, MIT) goes under an `Editor/` folder, lists packages to add or remove, calls `Client.AddAndRemove` once, polls on `EditorApplication.update`, and ends with `EditorApplication.Exit(0|1|2)`. `PackageSearch.cs` in the same reference lists registry packages and versions the same way. Edit the arrays, run headless as in Step 2, watch the `[PackageInstaller]` lines in the streamed log, then verify.
## Step 4: verify
1. `Packages/manifest.json` contains the id and version.
2. `