From gamedev-log-analyzer
Analyze an editor, build, or structured trace log (Unreal Engine Saved/Logs, Unity Editor.log, Godot output, MSVC/UBT/MSBuild build output, JSONL / structured `.jsonl` traces, or any text log) token-efficiently. Use when the user mentions checking, reading, searching, summarizing, or diffing a log; investigating editor/engine errors, warnings, crashes, asserts, callstacks, or log spam; or asks "what's flooding the log" / "what changed since the last run". Parses, deduplicates, classifies by severity/category, and extracts decisive fields via the `gamedev-log` CLI instead of dumping the raw file (logs can be tens of MB).
How this skill is triggered — by the user, by Claude, or both
Slash command
/gamedev-log-analyzer:logsThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Read logs through the **`gamedev-log` CLI**, never `cat`/`grep`/`Get-Content` the raw file — these logs
Read logs through the gamedev-log CLI, never cat/grep/Get-Content the raw file — these logs
are routinely tens of MB and will flood the context. The CLI parses → classifies → deduplicates →
returns a compact, token-capped summary (often ~99% smaller than the raw log).
Format coverage: Unreal runtime + MSVC/UBT/MSBuild/Unity-C# build + JSONL are live-verified (JSONL on a real UE
AIMovementDebug.jsonl). For JSONL,fieldsalso extractsKey=value/Key=(x,y,z)from inside themessageplus top-level keys, so per-frame scalar tracking over a--windowworks. Unity-deep, Godot, Python-logging, and bracketed-level parsing are best-effort from public docs and NOT verified against a specific app's real logs — say so if you report results for those, and rungamedev-log learningsto see what went unparsed.
Invoke via Bash using the plugin-root absolute path (no PATH/setup needed; pure Node, no deps):
node "${CLAUDE_PLUGIN_ROOT}/server/cli.js" <command> [--flags]
Quote every path argument (Windows paths/spaces). --help lists everything.
detect — find editor logs (newest first). --projectPath <dir> (UE: scans <dir>/Saved/Logs,
one subdir deep; Unity: Editor.log). Run this first if you don't have a path.summary — severity counts + top categories, no message bodies. --path | --projectPath.search — parse + dedup into templated groups with ×count + locations, severity-sorted, capped.
--severityMin Error|Warning|Display (default Warning) · --query <substr> · --category <Cat>--file <pathfrag> · --groupBy template|callsite|code (callsite = roll up by file:line, best
for "which callsite floods the log"; code = roll up by diagnostic code like C4996/LNK2019,
collapsing a noisy build to one line per code) · --maxGroups Ndiff — compare two logs, emit ONLY the delta (new / gone / count-changed groups; unchanged
omitted). --pathA <before> --pathB <after>, or omit both to auto-pick the two newest detected
logs. Same filters as search plus --minDelta N. Token-cheap "what changed since last run?".locate — jump list: just the distinct file:line of matched entries (no message bodies), ranked
by severity then count. --severityMin Error (default) · --basename (strip to filename, for
Rider's name search) · --query --category --file --max. The compact handoff for opening source.fields — pull just decisive scalars from dense per-frame trace logs into a compact table.
--fields Pawn,Alpha,ts,Pos.x,step:Pos,d:Yaw (forms: Key, Key.x|.y|.z, Key.Y|.P|.R, ts,
dts, d:Key, step:Key) · --query · --window t0,t1 · --max N. Biggest win on per-frame logs.
Add --stats to collapse to per-column min/max/avg/first/last/Δ (one line per field) instead of
rows — use it for "what's the range/trend of X over this window?" (even fewer tokens than the table).tail — last N raw lines (escape hatch). --lines N.setup / config — persist/show settings (~/.gamedev-log-analyzer/config.json). Keys: --projectPath --logPath --logMaxBytes --maxGroups --maxLineChars.learnings / learnings-reset — local sanitized parse-coverage report + top unparsed line shapes
(new-parser candidates). See Growing format coverage below; a low-coverage file also auto-nudges.savings / savings-reset — local cumulative report of how many tokens you've saved vs dumping raw
logs into context. Each analysis also appends a one-line ✓ Saved ~N tokens (M× smaller) for big logs.enforce <block|warn|off> (or no arg = status) — log-read enforcement. A PreToolUse hook
intercepts raw Bash log reads (grep/tail/cat/… over .log/.jsonl/Logs) and unbounded
Reads of large (≥ 200 KB) logs, steering them here. A sliced Read (offset/limit) always
passes — that's the one-step escape when you truly need raw bytes or when a format parses poorly.
warn (default) allows + nudges; block denies + nudges; off disables. Env: GDLOG_ENFORCE. If a
user hits the block and genuinely wants raw bytes, tell them to re-Read with offset/limit, or
gamedev-log enforce warn|off.log-analyst subagentlog-analyst subagent in one call. It runs every pass in its own context and returns one compact
answer, so the raw output never piles up in yours.node "${CLAUDE_PLUGIN_ROOT}/server/cli.js" detect --projectPath "<project>"
node "${CLAUDE_PLUGIN_ROOT}/server/cli.js" summary --path "<log>"
node "${CLAUDE_PLUGIN_ROOT}/server/cli.js" search --path "<log>" --severityMin Error
Then report the errors with their file:line locations. For per-frame/trace noise use fields; for
regression triage across two runs use diff.
Log entries carry file:line. When the user wants to open / fix the offending code and
rider-mcp-enforcer is installed, use this token-frugal loop instead of reading whole files:
node "${CLAUDE_PLUGIN_ROOT}/server/cli.js" locate --path "<log>" --severityMin Error --basename
--basename strips paths to Foo.cpp:123 so Rider's filename search can resolve them.find_files_by_name_keyword (or search_file)
with the basename. Logs often carry partial/relative paths; Rider's index has the real one.read_file (a small line range around the
number), or get_symbol_info for the enclosing symbol — never dump the whole file.Skip locate and read directly only when there's a single known location. For many errors, locate
first so you batch-resolve the distinct callsites instead of re-scanning the log per file.
The analyzer keeps a local, sanitized learnings ledger (~/.gamedev-log-analyzer/learnings.json):
every run records parse coverage + templated shapes of UNPARSED lines (variable parts masked; never
transmitted). When a log barely parses, summary/search/fields print a one-line nudge
(⚠ Only N% of lines parsed …). That is the signal to grow a new format — and you (Claude) are the
right layer to do it, not a heuristic. The loop:
gamedev-log learnings for the top unparsed shapes.server/logs.js parseLine (or a JSON-key alias / --window
field) that covers the shape. Match the existing style; mark it best-effort / ⚠️ unverified in
comments unless you have a real sample to verify against.eval/run.mjs's engineCases (or a field-extraction
case) asserting the new shape's severity/category/location, so it can't silently regress.enhancement), bump gamedev minor, tag gamedev-v<x.y.z> to publish to npm.This is how JSONL support was added: a real .jsonl log tripped the low-coverage path, the ledger
showed the {"<q>":…} shape, and that became the JSON branch + eval guard. Prefer this over inventing a
CLI "auto-propose" command — the LLM writes better parsers than a regex heuristic, and the eval gate
keeps it honest.
The CLI carries no always-on context cost — nothing sits in the prompt until you run it — whereas an MCP server injects its tool schemas into every session. The ~99% output reduction is identical either way. Users who prefer typed MCP tools can opt in (see the README), but the CLI is the default.
Provides behavioral guidelines to reduce common LLM coding mistakes, focusing on simplicity, surgical changes, assumption surfacing, and verifiable success criteria.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
npx claudepluginhub jsungmin/vs-token-safer --plugin gamedev-log-analyzer