Install
$ agentstack add skill-abostrom-ushell-skill-ushell ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ● Shell / process execution Used
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
ushell
ushell is Epic's command-line interface for Unreal Engine, shipped at /Engine/Extras/ushell/. It wraps UBT, UAT, the editor, the runtime, and Perforce behind a single .command arg arg --opts interface with tab completion, history, and session-scoped project state.
Iron rules
- If
Engine/Extras/ushell/ushell.bat(or.sh) exists for the active.uproject, drive build infrastructure through ushell. Do not invokeRunUAT.bat,UnrealBuildTool.exe,GenerateProjectFiles.bat,Build.bat, or rawp4directly. There is no silent fallback — if a need genuinely isn't covered, stop and report.
Installed-engine carve-out. If the engine is an installed build (/Engine/Build/InstalledBuild.txt is present), the .uat family is non-functional: ushell's channels/unreal/core/cmds/uat.py:108 unconditionally calls Engine/Build/BatchFiles/BuildUAT.bat, which installed engines strip (UAT ships precompiled). On installed engines, fall back to \Engine\Build\BatchFiles\RunUAT.bat directly for .uat *, plus the UAT-wrappers .stage, .deploy, and .perf test *. This is the only permitted direct-RunUAT invocation under this rule. Verbs that don't go through UAT — .info, .project, .sln *, .build *, .run * (including .run commandlet), .cook * (including .cook odsc), .p4 *, .zen *, .ddc *, .kill * — work normally because they hit UBT or stand-alone Python. See reference/troubleshooting.md (.uat * fails with [WinError 2]) and reference/workflows.md DAG #13b for the canonical workaround.
- Every ushell command accepts
--help. Run it before guessing flags. - Don't invent a command. If
.fooisn't in the Quick Reference below orreference/commands.md, look it up. Don't reach for a half-remembered RunUAT flag instead.
Detection gate
Before doing anything else, locate ushell:
- Windows:
/Engine/Extras/ushell/ushell.bat - POSIX:
/Engine/Extras/ushell/ushell.sh
If neither exists for the active .uproject's engine, stop and tell the user. This is an older or partial branch; ushell verbs will not exist. Do not silently fall back to raw UBT/UAT.
Also check /Engine/Build/InstalledBuild.txt. If present, the engine is an installed build (Epic Games Launcher install, binary distribution, or source-style build marked installed). UBT itself reveals this state during .sln generate with Program targets are not currently supported from this engine distribution and similar messages. In that state, ushell's .uat family — and anything that wraps it (.stage, .deploy, .perf test) — is non-functional; use the workarounds in iron rule #1's carve-out. This is distinct from the no-ushell-at-all case: here ushell IS installed and most verbs work fine, just not the UAT-dependent ones.
Non-interactive invocation
ushell normally opens an interactive cmd.exe window. To drive it from a Bash/PowerShell session without that, use one of these two forms.
Single command:
cmd.exe /d /s /c "call \Engine\Extras\ushell\ushell.bat --project= && .info"
Multiple commands — write a temp .bat:
@echo off
call \Engine\Extras\ushell\ushell.bat --project=
.p4 sync --all
.build editor
Exit codes:
| Code | Meaning | |------|---------| | 0 | Success | | 1 | Failure | | 126 | Argument parse error (treat as your bug) | | 127 | Help printed (the user asked for help; not a failure) | | 80 / 90 | Reserved for the .p4 bisect script protocol (bad / failed-build) |
Suppress the Cmd.summarise result/time banner with --nosummary on commands decorated with @summarise: .build *, .p4 sync, .p4 mergedown, .p4 switch (and any future verb whose docstring or source declares it). Adding --nosummary to commands that don't have it (.info, .run *, .cook *, .sln *, .kill, .notify, .uat, .p4 cherrypick, .p4 clean, etc.) produces ERROR: Unknown argument(s) 'nosummary' and exits non-zero. When in doubt, omit it.
The active .uproject lives in a session noticeboard keyed by $FLOW_SID. Every fresh invocation is a new session ID, so always pass --project= to ushell.bat, or run .project as the first command. Do NOT cd inside a cmd /d /k ushell.bat chain — ushell deliberately unsets PWD.
Full details and PowerShell module integration: reference/invocation.md.
Goal-directed planning
When the user states a goal (e.g. "an Insights trace at CL X on PS5"), do NOT jump to a single command. Walk backwards:
- Terminal command — what command actually produces the goal artifact?
- Preconditions — what must already exist for it to succeed?
- Recurse until a precondition is already satisfied (verify with
.info, file checks,.zen snapshot list, etc.). - Execute forwards, verifying after each step.
Each reference/commands.md entry declares Preconditions and Produces. reference/workflows.md provides full goal-to-plan DAGs. For anything passed after -- (map URL, #Portal spawn selector, -trace=, -ExecCmds=, LLM/memory switches, commandlet -run= recipes, etc.), source the actual args from reference/unreal-args.md — do not invent UE switches.
Skip-policy: skip a precondition only when verifiable. Checks that count as verification:
- A
.targetreceipt file exists atBinaries//[--].target. Saved/Cooked//exists and is non-empty..zen snapshot listreturns a hit at the requested CL.Engine/Build/Build.versionChangelistmatches the target CL.
If the check is unclear, re-run the precondition.
Failure-policy: if a step fails or a precondition is truly unreachable, stop, report the verbatim error, suggest the next action, hand back to the user. No silent fallback to raw tools, no destructive auto-recovery (don't delete Saved/, don't edit .uproject, don't p4 reset without consent).
Quick reference
| Want to… | Command | |---|---| | See engine/project/platform state | .info | | List branch projects | .info projects | | Switch active project | .project | | Generate VS solution | .sln generate | | Open existing solution | .sln open | | Open a tiny solution (fzf-only) | .sln open tiny | | Build editor | .build editor [variant] | | Build runtime | .build {game\|client\|server} | | Build a named program | .build program | | Clean before build | .build clean editor (etc.) | | Single file/module build | .build editor | | Build XML config (BuildConfiguration.xml) | .build xml [edit\|set\|clear] | | Generate compile_commands.json | .build misc clangdb | | Run editor | .run editor -- | | Run a commandlet | .run commandlet -- | | Run a program / named target | .run program / .run target | | Run cooked runtime | .run {game\|client\|server} -- | | Run runtime with Insights trace | .run game --trace= -- | | Cook | .cook {game\|client\|server} | | Cook iteratively | .cook game --iterate | | ODSC shader server | .cook odsc {game\|client\|all} | | Stage (auto Zen/pak) | .stage auto | | Stage with Zen storage | .stage zen | | Stage with pak files | .stage pak | | Deploy already-staged | .deploy | | Run UAT directly | .uat -- | | BuildCookRun via UAT | .uat BuildCookRun -- (reference/uat.md §2) | | Package a plugin | .uat BuildPlugin -- -Plugin= -Package= -TargetPlatforms=Win64+Linux -Rocket -StrictIncludes | | Run a BuildGraph script | .uat BuildGraph -- -script= -target= [-set:Foo=Bar] | | List BuildGraph nodes | .uat BuildGraph -- -script= -listonly | | Run Gauntlet tests | .uat RunUnreal -- -test= -build= -platform= | | CI-friendly UAT baseline | append -buildmachine -CrashForUAT -nop4 -NoCodeSign -unattended -nullrhi -utf8output -stdlog | | Kill running UE process | .kill {editor\|server\|client\|} | | Sync from Perforce | .p4 sync [] | | Filter sync (edit .p4sync.txt) | .p4 sync edit | | Cherrypick CLs | .p4 cherrypick [...] | | Bisect a regression | .p4 bisect -- | | Mergedown from parent stream | .p4 mergedown | | Switch stream | .p4 switch / .p4 switch list | | List CL authors | .p4 authors | | Who-broke-this-line | .p4 who [] | | Open P4V on this clientspec | .p4 v | | Create a new workspace | .p4 workspace [] | | Clean intermediate/Saved/ | .p4 clean [--dryrun] | | Authorize cloud DDC | .ddc auth [] | | Start/stop ZenServer | .zen start / .zen stop | | ZenServer status / version | .zen status / .zen version | | Open Zen dashboard GUI | .zen dashboard | | Create Zen workspace / share | .zen createworkspace / .zen createshare | | Import a Zen oplog snapshot | .zen importsnapshot [] | | Find a cooked-data snapshot for CL | .zen snapshot find | | Download + import a snapshot | .zen snapshot get [] | | List available snapshots | .zen snapshot list | | Launch Insights | .perf insights [\|latest] | | Run automated perf test | .perf test {default\|sequence\|replay\|material\|camera} | | Download a cloud build | .getbuild {packaged\|staged} | | Flash console for attention | .notify | | Gather standalone ushell | .ushell gather |
Zen ↔ UAT relationship
.zen * commands talk to the standalone ZenServer process and the cloud/fileshare snapshot index. They are not a substitute for .stage. Staging still goes through UAT BuildCookRun, but style=zen (or style=auto driven by Saved/Cooked//ue.projectstore) tells UAT to package as a Zen oplog rather than pak/utoc. .zen snapshot get is the fast path for "pull a pre-cooked dataset for this CL" — it launches ZenServer if needed and imports the oplog. Always check .zen status before assuming Zen is running.
Load reference when…
- Need flag/option detail on a ushell command →
reference/commands.md - Need a multi-step plan / DAG for a goal →
reference/workflows.md - Authoring a new ushell command/channel →
reference/channel-authoring.md - Spawning ushell yourself from a script/Bash/PS →
reference/invocation.md - A command failed or behaves oddly →
reference/troubleshooting.md - Shaping what UE itself does once launched (boot mode, map,
#Portalspawn selector, trace channels,-ExecCmds, LLM/memory tracking, etc.) →reference/unreal-args.md - Driving UAT directly —
BuildCookRunrecipes,BuildPlugin,RunUnrealfor tests, full ProjectParams flag groups, CI-friendly invocations, packaging/signing — →reference/uat.md - Authoring or invoking a BuildGraph script (schema, tasks,
-script=,-target=,-set:, idiomatic pipelines) →reference/buildgraph.md
Anti-patterns
- Don't call
RunUAT.bat,UnrealBuildTool.exe,GenerateProjectFiles.bat,Build.bat, or rawp4when ushell is present. Use.uat,.build,.sln generate,.p4 *instead. Single exception: on installed engines (InstalledBuild.txtpresent),.uatis broken at the source level — fall back toRunUAT.batdirectly. See iron rule #1 carve-out andreference/troubleshooting.md. - Don't invent UE switches. Common hallucinations to watch for:
?StartPoint=or?PlayerStartTag=— does not exist as a UE switch. The spawn selector is the URL#Portalsegment:#. The tag must match anAPlayerStart'sPlayerStartTagproperty. (Resolved byAGameModeBase::FindPlayerStart_Implementation.) Seereference/unreal-args.md§2.-encrypt— use-encryptinifilesplus-signpak/-signpakid=and-cryptokeys=.-RunAutomationTest=under BCR — fragile (client exits before UAT polls, reports BUILD FAILED on green tests). Use.uat RunUnreal -- -test=UE.TargetAutomation -RunTest=""(Gauntlet) or.run editor -- -ExecCmds="Automation RunTests ; Quit" -ReportExportPath=instead..engine,.platform list— invented ushell verbs that don't exist. The full canonical list is inreference/commands.md. Use.infoto inspect engine + platforms.- Don't invent ushell commands. If
.fooisn't in the Quick Reference orcommands.md, it doesn't exist. - Don't pipe
-Foo="path with spaces"through plain subprocess argv when extending ushell — useunreal.cmdline.read_ueified(). UE's quoting differs from POSIX/Windows shells; plain argv will mangle it. - Don't set
FLOW_SIDyourself, and don't invoke_build/_cook/_uat/_run/_p4(those are ushell's internal subprocess shims, not user-facing). - Don't
cdinside acmd /d /k ushell.batchain — PWD is unset deliberately by ushell. - Don't use
.cook --iteratefor shipping builds (community-confirmed stale-asset bugs). Iterative cook is for dev only; always full-cookfor release. - Don't trust Project Settings → Packaging → StagingDirectory under UAT — it's ignored. Always pass
-stagingdirectory=and-archive -archivedirectory=on the CLI. - Channel authoring:
describe.flow.py, not__init__.py. Channels live under lowercasechannels//and declare themselves viaflow.describe.Channel()+flow.describe.Command().source().invoke()indescribe.flow.py. Seereference/channel-authoring.md. - Manual P4 bisect is wasted effort.
.p4 bisect --exists; the script returns0(good),80(bad), or90(failed to build). Seecommands.md.p4 bisect.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: ABostrom
- Source: ABostrom/ushell-skill
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.