Skip to main content
Glama

addon-auditor

A deterministic auditor for World of Warcraft addons, built to be called by AI coding agents while they write code (and by humans and CI).

It focuses on performance and usability, and also covers luacheck, the TOC, API existence per client, taint and security, SavedVariables, packaging, and runtime data from an in-game probe. Findings come back ranked, with a rule ID, a confidence level, a fix_hint, and a documentation page for each rule. The tool makes no LLM calls and needs no API keys; the agent does the triage and fixing.

Supported clients: WoW Forever (16xxx), Classic Era (11xxx), Classic progression, and Mainline / Midnight (11xxxx–12xxxx). These are detected from ## Interface lines, per-client TOC files (_Mainline.toc, _Vanilla.toc, …), and AllowLoadGameType.

Install

pip install "addon-auditor[mcp]"        # or: uv tool install "addon-auditor[mcp]"
luarocks install luacheck               # optional, enables the LINT pack

From a checkout: uv venv && uv pip install -e ".[dev,mcp]".

If luacheck is not on PATH, set ADDON_AUDITOR_LUACHECK=/path/to/luacheck.

Related MCP server: groundtruth-mcp

Use it from the command line

addon-auditor audit MyAddon                      # full audit, Markdown report, exit 1 if the gate fails
addon-auditor diff MyAddon                       # only lines changed vs HEAD (plus untracked files)
addon-auditor audit MyAddon --format sarif -o audit.sarif
addon-auditor audit MyAddon --category perf --category ux --min-severity warn
addon-auditor explain PERF001                    # why, bad/good example, references
addon-auditor rules                              # every rule with severity and client scope
addon-auditor api C_Container.GetContainerItemInfo   # does it exist on each client?
addon-auditor luacheckrc MyAddon --write         # compact .luacheckrc tailored to the addon
addon-auditor baseline MyAddon                   # accept current findings once (legacy adoption)
addon-auditor learn MyAddon UX004 false_positive "HUD frame is re-anchored to the screen on every login"

Example output:

# addon-auditor: MyAddon
**Gate:** FAIL (fails on `error`) · **Score:** 71/100 · **Profiles:** forever, mainline
- **ERROR** `API001` core.lua:41 — `C_Container.GetItemInfoz` does not exist on forever, mainline
- **WARN** `PERF001` ui.lua:88 — OnUpdate handler runs every frame without a throttle
  - fix: self.t = (self.t or 0) + elapsed; if self.t < 0.1 then return end; self.t = 0

Use it from an agent (MCP)

Run addon-auditor-mcp (stdio). Tools:

Tool

Purpose

audit_changes

Fast diff audit after each edit batch (git ref or explicit files)

audit_addon

Full audit with gate and scores; optional probe_path for runtime rules

explain_rule, list_rules

Rule rationale and catalogue

check_api, check_toc

Per-client API existence; parsed TOC, profiles and load order

ingest_probe

Summarise AuditorProbe runtime data

suppress_finding, update_baseline

Reasoned inline suppression; legacy baseline

record_learning, memory_hints

Learning loop (see below)

Set ADDON_AUDITOR_ROOTS (paths separated by :) to limit the folders the server may read and write.

Cursor: scripts/install-cursor-plugin.sh installs the MCP server and the agent skill as a local plugin. --dev makes the plugin follow your checkout.

Other agents: point your MCP config at addon-auditor-mcp. Then give the agent skills/addon-auditor/SKILL.md, which describes the workflow: recall, audit changes, fix by severity, gate, remember.

Rule packs

Category

Examples

lint

luacheck syntax errors, undefined or accidental globals, overwriting Blizzard globals, shadowing; .luacheckrc files that turn global checks off

toc

TOC name vs folder, Interface per client, missing or unlisted files, SavedVariables declared vs used, game-type sanity, 1024-character lines

api

APIs that are hallucinated or missing on a targeted client, deprecated APIs, Forever-specific restrictions

perf

unthrottled OnUpdate, allocation in hot paths, frame churn, timers that are never cancelled, RegisterUnitEvent opportunities, unbounded SavedVariables growth

security

taint from replacing Blizzard functions or scripts, combat lockdown, loadstring on external data, global namespace hygiene, chat spam

savedvars

SavedVariables initialised before they load, functions or frames stored in SavedVariables, wholesale resets

ux

Esc to close, clamping, saved positions, slash command help, options panel, login spam, BackdropTemplate, tooltips

packaging

dev files that would ship, .pkgmeta, size, LICENSE and CHANGELOG

runtime

memory size and growth, CPU ms/s, frame hitches, event storms (needs probe data)

Every rule has a page in rules-docs/.

Configuration

To configure the auditor for one addon, add .addon-auditor.toml to the addon folder:

profiles = ["forever", "mainline"]     # override detection
exclude = ["Generated/**"]
fail_on = "error"                       # gate threshold: error | warn | info
min_severity = "info"
disabled_categories = ["packaging"]

[rules]
UX007 = "off"
PERF008 = { severity = "warn" }

[thresholds]
runtime_cpu_ms_per_sec_warn = 0.5

You can also suppress inline. A suppression without a reason is itself reported, as META001.

frame:SetScript("OnUpdate", Tick) -- auditor:ignore PERF001 Tick self-throttles via its own timer
-- auditor:ignore-file UX010 developer build announces itself on purpose

The .addon-auditor/ folder in each addon holds baseline.json (accepted legacy findings) and learnings.jsonl (recorded verdicts).

Runtime data: AuditorProbe

probe/AuditorProbe is a small in-game addon. It records per-addon memory, CPU time, and event deliveries:

  1. Copy probe/AuditorProbe into Interface/AddOns/. For CPU data, enable the AddOn profiler (Mainline and Forever), or run /console scriptProfile 1 and /reload.

  2. In game: /probe start. Play normally for a few minutes, then /probe stop and /reload.

  3. Run addon-auditor audit MyAddon --probe "<WoW>/WTF/Account/<ACCOUNT>/SavedVariables/AuditorProbe.lua".

The probe only post-hooks RegisterEvent (hooksecurefunc), so it does not taint secure code. Any events an addon registers before AuditorProbe loads are not counted.

Learning loop

memory_hints returns search queries to run before an audit, and a lessons document to store afterwards when ingest_recommended is true. The lessons cover recurring findings, confirmed false positives, accepted trade-offs, and suppressions with reasons. The tool works with any memory service; the skill shows how to use it with Hindsight. With no memory service, learnings.jsonl still works: a false_positive verdict downgrades matching findings to info and keeps them out of the gate.

Development

uv venv && uv pip install -e ".[dev,mcp]"
.venv/bin/ruff check src tests scripts && .venv/bin/mypy && .venv/bin/python -m pytest -q

Every rule needs a rules-docs/<ID>.md page plus tests/fixtures/<category>/<ID>/{bad,good}/ fixtures; pytest enforces this. See CONTRIBUTING.md and AGENTS.md.

License

MIT. See LICENSE.

Related MCP Connectors

Related MCP Servers