Review and triage the X4 mod registry (Phase-A worklist) — scan the ACTUALLY INSTALLED extension folders (the primary source of truth), cross-check against the old profile content.xml (diff/backstop only), refresh upstream mod metadata via the Nexus API, and drive the spot-check loop (confirm/correct identities, ignore junk, mark custom edits). Use when the user wants to triage their modlist for a game version, see what has updates / is obsolete / abandoned, or work the Phase-A modlist rebuild.
Installs into .claude/skills of the current project.
Are you the author of X4 Modlist Review?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/wingedguardian-x4-modlist-review)
---
name: x4-modlist-review
description: Review and triage the X4 mod registry (Phase-A worklist) — scan the ACTUALLY INSTALLED extension folders (the primary source of truth), cross-check against the old profile content.xml (diff/backstop only), refresh upstream mod metadata via the Nexus API, and drive the spot-check loop (confirm/correct identities, ignore junk, mark custom edits). Use when the user wants to triage their modlist for a game version, see what has updates / is obsolete / abandoned, or work the Phase-A modlist rebuild.
allowed-tools: Bash, Read
---
Triage the X4 modlist via the `x4modlist` CLI. **API-FIRST — never scrape Nexus.** Registry: `$X4_MODS/_registry/modlist.yaml` (or `$X4_REGISTRY` if set — the tool resolves it; `x4validate --paths` shows where); human dashboard: `WORKLIST.md` next to it.
**★ SOURCE OF TRUTH: the physically INSTALLED extension folders are PRIMARY** — game-root `extensions\`, profile `extensions\` (if present), Steam Workshop `content\392160\` (if present). That's what the game actually loads. For the INVENTORY, the profile's `content.xml` enabled-list is a **SECONDARY cross-check only** ("did I forget to re-acquire something from my old modlist?") — it keeps entries for mods long gone from disk. For what is ACTIVE it does decide: an installed mod's profile entry overrides its manifest's `enabled`, and a mod with no entry falls back to its manifest (enabled unless the manifest says `enabled="0"`). A mod tracked historically but not found on disk shows up in a separate "OLD MODLIST — NOT CURRENTLY INSTALLED" dashboard section, not in the active lanes.
Run commands via uv from the tool dir:
`cd $CLAUDE_PROJECT_DIR/tools/x4validate && uv run --python 3.13 x4modlist <cmd>`
Needs `X4_NEXUS_KEY` (user env). If a command errors "X4_NEXUS_KEY not set", the user must set it (endpoints, rate budget and how to get a key: `x4validate/_nexus.py`).
## Workflow
1. **Ingest** — `x4modlist ingest` scans the installed folders (reading each mod's OWN `content.xml` for its real `id`/`name`/`version`/`author` — folder names can differ from the manifest `id`, e.g. folder `X4CapturableXenonXL` → id `X4_Capturable_Xenon XL PERSONAL`) and merges that as PRIMARY; the old profile content.xml is a secondary backfill pass so nothing tracked historically is silently dropped. `--installed-only` skips the content.xml pass; `--dirs a,b,c` overrides the scanned directories.
2. **Refresh** — `x4modlist refresh` pulls upstream version/status and auto-resolves identities for installed mods. Identity resolution prefers each mod's REAL manifest name (far more reliable than guessing from the folder/id) over a humanized-id guess, with fallbacks for common author-prefix ("<author>: X" → "X") and suffix-qualifier ("X - Some Edition" / "X <overhaul>" → "X") naming patterns. `--force` bypasses the once-per-day TTL; `--ids a,b,c` targets specific mods (works even for NOT-installed old-list mods, to check upstream status before deciding to re-acquire).
**"Has an update" means one thing, with a grace window:** upstream's newest **MAIN** file was **uploaded more than `UPDATE_GRACE_DAYS` (3) days after the installed copy's manifest `date`** — both dates are printed on every `UPDATE` line and in the dashboard's ⬆ UPDATE AVAILABLE table. A mod pinned to a FILE (`resolve --file`) is judged against that file's newest successor on the page (its `file_updates` chain), or the pinned file itself when it has none. Version strings are **not** compared (Nexus uses several shapes; manifests carry integers). The verdict is `available` / `same-release?` (upload within the 3-day window — **likely the same release, not a new one**, printed with both dates and counted in the tally, but excluded from the UPDATE AVAILABLE table) / `none` / `unknown` (a date is missing or unparseable — never read that as "no update") / `unconfirmed` (the identity is a guess, so the upstream may be another mod). A verdict the current run did not re-check (once-per-day TTL) is labelled **carried over** with its check date; a row that now ends in error/untriaged/off-nexus carries no verdict at all. ⚠ UNMEASURED: authors commonly date the manifest before finishing the upload, which is why the grace window exists — but its own false-positive rate (a `same-release?` that was actually a fast follow-up release) and false-negative rate (a real update landing inside the window) are both unmeasured until the next online refresh checks some by hand. Compare the printed upstream file/version before re-downloading either way.
A refresh that hits a missing/invalid key, a spent rate limit or a dead network **stops** (exit 2), keeps every row it already fetched, and leaves the rest untouched.
3. **Present** — read `WORKLIST.md`; summarize the lanes (✅ ready / ⏸ churning / ⚠ predates-9.0 / 🔧 custom-local / ❌ drop), the **Updates** tally and ⬆ UPDATE AVAILABLE rows (with both dates), the **NEEDS SPOT-CHECK** count, and the **OLD MODLIST — NOT CURRENTLY INSTALLED** count (mods to potentially re-acquire).
4. **Spot-check loop** — `x4modlist needs-review` lists entries needing a human call. For each, show the auto-matched candidate(s) and have the user decide:
- confirm/correct identity → `x4modlist resolve <id> <nexus_id>`
- junk/personal/cheat mod → `x4modlist ignore <id> --reason "..."`
- a mod they locally customized → `x4modlist mark <id> --custom --notes "..."`
**Never guess keep/drop or fabricate a match** — surface candidates, the user decides. Search can return a wrong/deprecated/adoption-patch fork as the top hit (searching a mod's full name can match a niche adoption/compat fork instead of the real, popular mod) — always show the candidate list, don't just trust rank #1.
5. **Deep 9.0-readiness (opt-in only)** — the API gives version/date/status but **NOT "9.0-compatible"** (that gap is real; changelogs are sparse). For churning / predates-9.0 mods the user wants to keep, dispatch the `mod-research` agent (API-first) for changelog/community signal. Only on request.
## The 🔧 CUSTOM-LOCAL FORK lane
If a mod's Nexus status is `removed`/`hidden` AND it's `mark`ed `custom_edited`, it is classified `custom-local` — NOT `drop`. An author temporarily hiding their page mid-update (or a mod you've locally forked/ported yourself, e.g. in `dev\`) doesn't mean abandon it; "drop" would be actively wrong guidance there. This only applies once the user has `mark`ed the mod custom-edited.
## Honest framing
This produces the **auto-resolved worklist + the spot-check queue**. The keep/drop/custom decisions and in-game testing are the user's — it makes Phase A tractable, not instant. **Strategy:** work the ready + churning lanes first (the live mods); let predates-9.0 and unresolved bake, and re-`refresh` later as authors ship 9.0 updates. Periodically re-`ingest` to catch newly-installed/removed folders.