ueboxai/uebox/ue-project-audit

Claude Code and agent skill by ueboxai/uebox

Trust tier 3
  • community
Source check pending

Checking that the SKILL.md file is still in the repository.

Audits an Unreal project or the open level for size, performance and asset problems, and turns the numbers into a ranked report with concrete fixes. Use when the user asks to analyse or review their project, wants optimisation advice, asks what is taking up space, which assets are heaviest, why the packaged build is large, or says things like "分析一下这个项目"、"给点优化建议"、"哪些资源最占地方"、"这个关卡为什么这么卡"、"帮我看看场景有什么问题". Do not use for organising the World Outliner, for editing or deleting the assets it finds, or f…

Install

npx vskill@latest install ueboxai/uebox/ue-project-audit

SKILL.md

Project and level audit

Verified against UE 5.5.4 with UnrealAgentLink. Eight read-only tools. Nothing here changes the user's project — this skill produces a report, not edits.

Handing part of an audit to a sub-agent? Send it with read_only: true. A sub-agent that can write will "fix" what it finds — a real session had three review subtasks move six actors and save the level, while the prompt said in so many words not to touch anything.

Report format and worked examples: references/report-format.md. Which requests route here and which do not: references/trigger-examples.md. Full performance diagnostic methodology — how a professional actually narrows "it's slow" down to a specific cause, mapped onto the tools below: references/performance-diagnosis.md. Turning a diagnosis into proof — duplicate the level, remove the suspect, measure the delta: references/experimental-verification.md.

The eight tools and what each one answers

ToolAnswersScope
ue_project_asset_rankingwhich assets take up spacewhole project, any class
ue_find_heavy_assetswhich meshes cost frame time herethe open level
ue_asset_size_mapwhy this asset is bigone asset + its dependencies
ue_content_audit_optimizationis the project configured wellproject-wide settings
ue_get_performance_statsis it fast right nowthis instant, this editor
ue_capture_perf_traceis it fast over a stretch of time, and what's the bottleneckN seconds, this editor
ue_insights_trace (action: capture)record a raw Unreal Insights traceN seconds, this editor
ue_insights_trace (action: analyze)which timer ate the most time, per thread (game / render / GPU)one .utrace file
ue_insights_trace (action: compare)did my change make it faster, and which timer movedtwo .utrace files, before and after

ue_project_asset_ranking reads asset-registry tags and file sizes without loading a single asset, so it is safe to run over all of /Game. ue_capture_perf_trace and ue_insights_trace both use engine-native profiling (the CSV Profiler and Unreal Insights respectively) — they are the professional-grade path when a single ue_get_performance_stats snapshot is not enough, see the dedicated section below.

When one instant sample is not enough

ue_get_performance_stats is a snapshot — a rolling average that a single frame spike can easily miss entirely. When the user asks "is there stuttering", "can you stress-test this", or reports something that only happens sometimes, reach for the time-window tools instead:

  • `ue_capture_perf_trace` — samples FrameTime / GameThreadTime / RenderThreadTime / GPUTime

every frame for duration_seconds, using the engine's built-in CSV Profiler. Returns avg/min/max/p50/p95/p99 per stat, the single worst frame's breakdown, and a bottleneck verdict. This is the right default for "is it fast" over a stretch of time — cheap, no external process, answers in one call. The call blocks for the full duration — say so before running a 60+ second capture.

  • `ue_insights_trace`, action: "capture" then action: "analyze" — for when the question

is finer-grained than "which subsystem" — "which specific function or render pass". capture records a full Unreal Insights trace (.utrace); analyze takes that utrace_path and spawns Unreal Insights headlessly to rank timers separately for the game thread, render thread and GPU, plus the game thread's frame times and its longest single calls (hitch suspects). Generic task waits (WaitForTasks and the like) are summed separately, not ranked — a thread waiting on others is not the slow part. start_seconds / end_seconds narrow it to a slice of the trace when the start is loading or entering PIE. compare takes a before (baseline_utrace_path) and an after (utrace_path) trace and lists the biggest per-frame changes; only compare two recordings of the same activity. Slower, and the Insights CLI export path has a documented flaky-empty-output issue (not this tool's bug — say so if it happens, and offer to retry). Reach for ue_capture_perf_trace first; only go here when the user needs event-level detail ue_capture_perf_trace's five stats cannot give.

Both capture tools flag idle_sample the same way ue_get_performance_stats does: if the render thread and GPU are near-zero for the whole capture, the editor viewport was not actually drawing (backgrounded/unfocused). Never report that as a performance finding.

All three tools already try to bring the Unreal Editor window to the foreground before sampling (PowerShell AppActivate on Windows, targeted AppKit activation on macOS; not guaranteed to win focus on every OS/window-manager configuration). So on idle_sample: true, retry once yourself immediately — do not stop and ask the user to alt-tab manually first; that is asking them to do something the tool already attempted. Only surface it to the user if it is still idle after that retry (rare — usually multi-monitor focus quirks), and at that point say plainly what you observed ("auto-focus didn't take, please click the Unreal Editor window and enter PIE") rather than re-explaining the whole mechanism.

Diagnosing "why is it slow" like a professional, not just reporting numbers

A bottleneck verdict alone ("GPU-bound") is not a diagnosis — it is step one of one. Professional UE profiling is a fixed sequence: classify which thread is the bottleneck → confirm it → narrow down to the specific cause within that thread → fix → re-measure, not "run a tool, read whatever field it returns, done." references/performance-diagnosis.md has the full workflow — sourced from Epic's own docs, AMD's GPUOpen guide, and Epic's game-thread optimization blog post, mapped onto exactly which of our tools plays which role (and honest about the one classic step — reading the on-screen stat gpu/stat game overlay — that this toolset genuinely cannot do).

Read it before telling a user "this is GPU-bound" or "this is a CPU problem" — that sentence should come with why, not just a verdict field echoed back. Two parts of it are easy to skip and expensive to skip: §2 (a single capture is not a baseline — warm-up, noise, alternating runs; pass warmup_seconds right after entering PIE) and §6 (on a render-thread or GPU bottleneck, switch whole categories off with ShowFlag.X 0 before touching any asset). Show flags and console variables survive across PIE sessions: finish every diagnosis with ue_run_console_command({ restore_all: true }), which puts back every value the tool changed.

A structural diagnosis ("SM_Grass2 is 53% of the level's triangles and has Nanite off") is still an inference, not proof. When the user pushes back with "what's the real cause" or asks you to back up a claim, that is a request for evidence, not a longer explanation of the same guess — go to references/experimental-verification.md: duplicate the level, remove the suspect, measure the before/after delta. A before/after number is something the user can check themselves; a confident-sounding inference is not.

Workflow

Do not start by asking the user what they want audited. Run steps 1–3, report, then offer depth. A concrete finding is a better question than "what would you like me to look at".

1. Say where you are. ue_get_project_info and ue_get_current_level. One line in the report: which project, which engine version, which level, how many actors. Numbers without a subject are unreadable a week later.

2. Whole project by size. ue_project_asset_ranking with no arguments (defaults to /Game, sorted by disk size). Read by_class first — "textures are 68% of the project" decides where to look before any individual asset does. Then the top rows. Disk size answers "what fills the repository", not the other two questions users actually ask:

  • "包体为什么这么大" — an asset nothing references is usually not cooked at all (maps and

the project's always-cook directories aside). Run ue_content_dependencies with path: "/Game", direction: "unreferenced" first and set those aside (say that assets loaded by path from code or config do not show up as referenced).

  • "内存 / 显存吃紧" — rank with sort_by: "TextureMemory", not disk size. The fix to

recommend is the texture's MaxTextureSize or its texture group (LOD group): the source stays intact and it can be undone. Not re-importing at a lower resolution. Once the user agrees, it is one ue_content_set_properties call per texture ({"MaxTextureSize": 2048} or {"LODGroup": "TEXTUREGROUP_World"}), not a Python script.

3. The open level by cost. ue_find_heavy_assets sorted by TotalTriangles. Read finding_counts and lead with breaks_gameplay: a user chasing frame rate still wants to know their floor has no collision. Then costs_frame_time.

Triangles only measure meshes without Nanite. Nanite draws by screen pixels, so a Nanite mesh's raw triangle count says nearly nothing about its frame cost — its cost is in its material (masked, WPO, translucency pushing it off the fast path) and in overdraw. The triangle ranking already leaves them out: assets holds only non-Nanite meshes, and the highest Nanite ones come back separately in nanite_assets (ranking_note says so). For the top assets rows, mesh_describe shows whether LODs exist and step down, and how many material sections each copy draws (copies × sections is what the CPU submits). For nanite_assets, point at their materials (material_describe reports blend mode), never at their triangle count.

4. Then go deeper on what step 2 or 3 turned up, one thread at a time:

  • biggest asset in the ranking → ue_asset_size_map on it, to see what it drags in
  • lots of high-poly meshes without Nanite → ue_content_audit_optimization for the config side
  • user says it feels slow right now → ue_get_performance_stats
  • user says it stutters, asks for a stress test, or asks why it's slow → ue_capture_perf_trace

over a real stretch of time, then follow references/performance-diagnosis.md to narrow the verdict down to a cause instead of stopping at "GPU-bound"

  • verdict is render thread or GPU → ue_light_census for the lights: per shadow-casting point /

spot / rect light, how many movable, WPO and Nanite shadow casters sit in its radius, and whether it has a max draw distance. Engine facts only — the count is a lead, not proof

Constraints

Never invent a threshold. min_triangles has no default and must not get one. "High poly" is a project decision — a mobile title and an archviz render have nothing in common here. Either ask what counts as heavy, or pass a number and say in the report which number you used and that you chose it. ue_find_heavy_assets will not produce the high_triangles_no_nanite finding without a threshold, and that is deliberate.

Three different "sizes" — never mix them.

  • disk_size — the compressed package on disk. What ships. Nanite meshes and BC7 textures

expand well past this when loaded.

  • resource_bytes — the engine's estimate of resident memory for that asset.
  • texture_bytes — estimated texture memory for the textures one mesh pulls in.

Saying "this mesh uses 40 MB" without saying which of the three is how a user ends up optimising the wrong thing.

A missing field is not a zero. Asset-registry tags are written when an asset is saved. An asset last saved by an older engine may have no triangles or nanite tag at all, so the field is absent from the response. Absent means unknown. Reporting "0 triangles" from an absent tag inverts the conclusion.

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 90 of 100Pattern checks on the skill's files.
  • Model reviewPassed

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
189
Repository forks
17
7-day trend score
0

Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/ueboxai/uebox/ue-project-audit/badge)](https://verified-skill.com/skills/ueboxai/uebox/ue-project-audit)

Something wrong with this skill or its page? Tell us.