Install
$ agentstack add skill-frostyleaves-nsight-graphics-analyzer-nsight-graphics-analyzer ✓ 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 No
- ✓ 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.
About
Nsight Graphics 2026 Skill
Wrapper around NVIDIA Nsight Graphics 2026.1+. The agent captures GPU frames, gets 3 small JSON artifacts, and uses drill-down subcommands to answer follow-up questions without ever loading the raw 300+ MB TSV bundle.
When to use
User intents that should trigger this skill:
- "Why is this frame slow on the GPU?" / "Profile GPU performance" / "Grab a frame to inspect"
- "Capture a frame from this game" / "frame trace" / "GPU Trace"
- "What draw calls does this frame make?" / "API stream"
- "How fast does this
.ngfx-capturereplay?" / "replay perf" - "Inspect markers / stages / metrics in this
.ngfx-gputrace" - "Generate a C++ capture so I can edit and replay it"
Trigger keywords: nsight, ngfx, nsight graphics, GPU trace, frame capture, frame trace, gpu profiling, frame profiling.
Quick start (90% case)
# 1. capture a 200 ms GPU Trace 30 s after launch (game must already be loaded)
python "/scripts/nsight.py" gputrace-capture \
--exe "C:\Game\game.exe" --wd "C:\Game" \
--start-after-ms 30000 --max-duration-ms 200 \
--architecture Ada --metric-set-name "Throughput Metrics" \
--time-every-action \
--out "D:\captures\game.ngfx-gputrace"
# 2. the wrapper writes 3 small JSON next to the .ngfx-gputrace:
# /game.gputrace.summary.json (~50 KB)
# /game.gputrace.stages.json (~3 KB)
# /game.gputrace.actions.json (~15 KB)
# 3. drill into the dominant stage from summary.json's analysis.hotspots
python "/scripts/nsight.py" gputrace-stages \
"/game.ngfx-gputrace" --parent "Render Camera" --top 10
Replace ` with the directory containing this SKILL.md. For any subcommand's full flag list run python scripts/nsight.py --help`.
Three rules to never break:
GPUTRACE_REGIMES.xlsis 300+ MB — never Read it directly. Drill
through gputrace-stages / gputrace-actions / gputrace-metric.
- Anti-cheat games (EAC/BattlEye/Vanguard) refuse capture and exit with
code 4. Try cpp-capture or disable the anti-cheat per game policy.
- If a capture fails with a permission error, re-run from an elevated
PowerShell. doctor reports is_admin.
Tool layout
A single Python entry point dispatches to 25 subcommands. Full flag list for any subcommand: python "/scripts/nsight.py" --help.
| Group | Subcommands | Purpose | |---|---|---| | Env | locate / doctor / capabilities / kill | Detect install, self-check, dump per-binary flags, kill residuals | | Run no-capture | launch / attach | Run game under ngfx with no capture taken | | Capture | capture / cpp-capture / gputrace-capture | Graphics Capture / C++ Capture / GPU Trace + 3 JSON | | Trigger | trigger-hotkey | Synthesize F11 (or another F-key) into a target window so the agent — not a human — fires a --start-after-hotkey capture | | Post-process | gputrace | Rebuild 3 JSON from existing trace | | Drill | gputrace-stages / gputrace-actions / gputrace-metric | Stage tree / leaf-marker top-N / metric aggregate | | Diagnose (7) | gputrace-{stalls,bandwidth,shader-bound,texture-cache,overdraw,geometry,draws} | Focused verdict[]-producing diagnostic commands | | Replay | export-{metadata,functions,screenshot} / replay-perf / replay-analyze | Metadata / API stream / PNG extraction; replay timing; combined |
Exit codes: 0 success, 2 user error, 3 Nsight not found, 4 underlying tool failed, 5 wrapper-side timeout. stdout is JSON for query commands; pass --out FILE to redirect.
Parameter Decision Guide
For decisions beyond the Quick Start path — picking a start trigger, tuning trace quality vs cost, navigating drill-down after capture, or reaching for an advanced ngfx flag — Read references/parameters.md. That file contains five decision tables:
- A. User goal → command → required flags → what to read
- B. GPU Trace start trigger choice (
--start-after-msvs
--start-after-frames vs --start-after-hotkey vs SDK)
- C. Trace quality vs cost trade-off (
--time-every-action,
--set-gpu-clocks, --real-time-shader-profiler, etc.)
- D. Drill-down workflow once the three JSON artifacts are written
- E. Advanced 1:1 ngfx flags (rare; skip unless asked)
⚠️ One red-line warning that belongs in the body, not the reference: --multi-pass-metrics is unusable through this wrapper (Nsight 2025.3 + 2026.1, verified May 2026). Combined with the mandatory --auto-export it deterministically writes an unloadable .ngfx-gputrace. The wrapper still accepts the flag for forensic / bug-report purposes but emits a runtime WARNING and returns bundle_complete=False. Full investigation in DESIGN.md → Investigations.
Capabilities-driven feature gating
The wrapper checks every conditional flag against the live ngfx install and exits with code 4 + a clear message if your build lacks that flag — preventing cryptic ngfx parse errors. Run python scripts/nsight.py capabilities to see what's available locally; wrapper_features. maps each wrapper flag to its underlying ngfx flag.
Subcommand reference
Full flag list for any subcommand: python scripts/nsight.py --help. This section is the agent-facing purpose only; flag detail lives in --help.
gputrace-capture
Wraps ngfx.exe --activity "GPU Trace Profiler" --auto-export .... Always writes /.ngfx-gputrace + BASE/ + 3 JSON artifacts. Use --dry-run to preview the ngfx command line.
trigger-hotkey
Synthesize a function-key press (default F11) into a target window via Win32 SendInput. Pair with gputrace-capture --start-after-hotkey run in the background to let the agent — not a human — fire the trigger once an external workflow has reached the desired scene. See the Agent-triggered capture workflow pattern below.
gputrace
Re-runs the parser pipeline against an existing trace + BASE/. Use after a skill upgrade to regenerate JSON without re-launching the game.
gputrace-stages
Stage-tree drill. --parent REGEX returns children of all matching parents grouped by name. --depth N restricts to a specific depth.
gputrace-actions
Top-N leaf markers (deepest D3DPERF_EVENTS nodes). --filter matches the leaf's own name; --in-marker matches any ancestor in the path. --with-metrics adds the headline block via one streaming REGIMES pass (~1-2 s). Important: read the definition field — actions are leaf markers, not raw draw calls.
gputrace-metric
Aggregate one metric. --name PATTERN is a regex over the metric catalog; --all-matches allows multi-match output. --in-marker REGEX returns per-marker windows in addition to the global aggregate.
Diagnostic command family (7 commands)
gputrace-stalls, gputrace-bandwidth, gputrace-shader-bound, gputrace-overdraw, gputrace-geometry, gputrace-texture-cache, gputrace-draws — focused diagnostic commands. Each returns a verdict[] array of {tag, severity, message}, severity ∈ {info, medium, high}. Thresholds are heuristics; treat verdicts as investigation starters, not absolute judgments. Most accept --in-marker REGEX to scope to a subtree (gputrace-stalls and gputrace-draws are whole-frame only).
Recommended investigation order on an unknown frame:
gputrace-stalls— rule out CPU-bound / pipeline-bubble first; if
the GPU isn't busy, the rest of the analysis doesn't matter.
gputrace-bandwidth— memory-bound vs compute-bound axis.- Branch:
- memory-bound →
gputrace-texture-cacheto localize - compute-bound →
gputrace-shader-boundfor SM utilization detail
gputrace-overdraw— opaque-pass quality.gputrace-geometry— vertex/primitive frontend.gputrace-draws— CPU-side state-churn / small-batch signals.
replay-perf
Replays a .ngfx-capture N times via ngfx-replay -n N --perf-report-dir and parses iteration_times.csv. Useful for replay-cost regression; not for original-app GPU performance (that's gputrace-capture).
How to read the artifacts
Read summary.json first. Four fields that matter:
analysis.frame_budget.verdict→ 60fps / 30fps / below_30fpsanalysis.throughput.dominant→ most loaded subsystemanalysis.hotspots.slowest_stage→ where to drillanalysis.warnings→ natural-language flags
Then pick a drill direction: stage > 50% GPU → drill it; throughput dominated by dram/pcie → memory-heavy; sm dominant → shaders. Always drill via subcommands, never by reading BASE/*.xls directly (REGIMES is 300+ MB).
Top-level JSON shapes:
summary.json: source, session, summary{frame/marker/metric counts},
analysis{frame_budget, throughput, hotspots, warnings},
headline_metrics, metrics[], hardware_context
stages.json: source, headline_metrics, roots[], top_stages[]
each: name, depth, total_duration_ns, fraction_of_gpu, headline
actions.json: source, definition, top_20_slowest_actions[]
each: name, path, instance_count, duration fields, headline
Diagnostic verdict thresholds — use these to interpret verdict[] beyond just severity:
| Command | Key signal | Healthy | Red | |---|---|---|---| | overdraw | overdraw_ratio | ~1.0 (1.5-3 typical) | > 3 | | overdraw | zcull_rejection_rate | > 0.3 | 80%).
Deep bottleneck dive (single stage > 80% of frame time)
gputrace-stages --parent "" --top 20
gputrace-actions --in-marker "" --top 20 --with-metrics
gputrace-metric --name "dramc__throughput" --in-marker ""
gputrace-metric --name "sm__throughput" --in-marker ""
Capture-once-then-iterate
gputrace-capture --exe ... --out trace.ngfx-gputrace
# now drill repeatedly; no re-launch needed
gputrace-stages "/trace.ngfx-gputrace" ...
gputrace-actions "/trace.ngfx-gputrace" ...
Reanalyze an old trace
gputrace "/old-trace.ngfx-gputrace" # rebuilds 3 JSON
cpp-capture for repro (deterministic C++ replay code)
cpp-capture --exe ... --wait-seconds 10 --out D:\repro
Attach to a running game (can't relaunch, e.g. multiplayer)
attach --activity "GPU Trace Profiler" --pid 12345
# user presses F11 in the running app
Agent-triggered capture in a larger workflow
Use this when: the agent is orchestrating a wider workflow — launching the game, running automated tests / bot actions / other skills, then deciding when to capture — and only the agent (not a human at the keyboard) knows when the target scene is on screen. Timer-based triggers (--start-after-ms / --start-after-frames) don't fit because the runtime of the surrounding workflow is unpredictable.
Why F11 simulation is the only option: ngfx's GPU Trace activity exposes exactly five start triggers (--start-after-ms / --start-after-frames / --start-after-submits / --start-after-hotkey / --start-with-ngfx-sdk / --start-on-replay-begin). ngfx-rpc.exe is the UI↔replayer IPC, not a trace-trigger RPC, and --start-with-ngfx-sdk requires the game to link the NGFX SDK and call NGFX_GPUTrace_StartTrace. For an unmodified target, hotkey is the only externally addressable trigger, and trigger-hotkey synthesizes it without a human.
Pattern:
# 1. Launch ngfx + game in the background, armed for F11 trigger.
# DO NOT wait on this command — it blocks until the trace is written.
python scripts/nsight.py gputrace-capture \
--exe "C:\Game\game.exe" --wd "C:\Game" \
--start-after-hotkey \
--max-duration-ms 200 \
--architecture --metric-set-name "Throughput Metrics" \
--time-every-action \
--out "D:\captures\game.ngfx-gputrace"
# (Run via your harness's background-task primitive; capture the task ID.)
# 2. Attach a streaming watcher to the background task's output so the
# agent is notified when the bundle is written. The wrapper prints
# "GPU Trace report saved to ..." then "bundle_complete=True". Watch
# for those lines (and also for "error", "fatal", "denied" to fail fast).
# 3. The agent now runs the rest of the workflow (other skills, automated
# tests, scripted gameplay) — no polling. The capture is dormant in
# the game process; F11 has not been pressed yet.
# 4. When the workflow signals "ready to capture":
python scripts/nsight.py trigger-hotkey --process game
# Returns JSON with foreground_ok / sent fields. exit 0 = key delivered.
# 5. ngfx hook receives F11, runs the 200 ms trace, writes the bundle,
# wrapper post-processes into 3 JSON. The streaming watcher from step 2
# fires; the agent reads summary.json and drills as usual.
Notes:
- Background launch is mandatory.
gputrace-captureblocks until the
bundle is written, which is "forever" from the agent's point of view (it depends on when step 4 fires). The agent must run step 1 asynchronously.
- Watch for completion, do not poll. The wrapper writes
bundle_complete=True - the saved path to its stdout/stderr; pipe that into your harness's
streaming notification primitive so the agent reacts to the event rather than guessing.
- Windowed/borderless mode preferred.
SendInputis reliable against
windowed and borderless-window games. Exclusive-fullscreen + DRM combinations can swallow synthetic keystrokes; if trigger-hotkey reports sent=true but no trace appears, switch the game to borderless-window and retry.
- Foreground stealing is restricted on Windows.
trigger-hotkey
calls AllowSetForegroundWindow(ASFW_ANY) + SetForegroundWindow, which works from an elevated shell (doctor reports is_admin=true) and usually from a non-elevated shell that recently saw user input. If it can't bring the window forward it still sends the key (ngfx's hook is global) and emits a stderr WARNING. Pass --no-foreground to skip the foreground step entirely if you'd rather not steal focus.
- Use
--use-scancodeif the default fails. Some engines / DRM
shims only honour hardware scancodes (KEYEVENTF_SCANCODE). The flag toggles the wParam encoding without other changes.
- ngfx 2026.1.x cleanup-phase crash is benign. After the trace is
written, ngfx exits with rc 0xC0000409 after trace_written=True and bundle_complete=True. The wrapper detects this and still produces the 3 JSON. Don't treat the non-zero rc as failure; check bundle_complete instead.
- Disambiguating multiple instances. If
tasklistfinds more than
one process matching --process, trigger-hotkey refuses and lists the PIDs; re-run with --pid . Always use --pid when ngfx itself launched the game (you have the PID from the capture-task output).
Out of scope
- Per-API-call timing (no
vkCmdDrawdurations — Nsight 2026.1
removed GPUTrace.pyd; actions in this skill are leaf markers, not raw draw calls). Use RenderDoc/PIX for per-API timing.
- HTML/PDF report generation — agent writes Markdown directly.
- Capture diff (compare two runs) — future work.
- Cross-platform — Windows only.
- Auto-installing Nsight —
doctoronly detects. - Remote capture (ngfx-rpc) — use
ngfx-rpc.exemanually if needed. - NVTX marker injection — game-side, not skill-side.
- GUI launching — open
ngfx-ui.exemanually for visual inspection.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: FrostyLeaves
- Source: FrostyLeaves/nsight-graphics-analyzer
- 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.