Bootstraps BGS modding environment: detects MO2, deploys control-plane plugin, optionally downloads xEdit, initializes changelog. First-run bootstrap for new modpack projects.
How this skill is triggered — by the user, by Claude, or both
Slash command
/bgs-modding-superpowers:setting-up-bgs-modding-environmentThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
This is the first-run bootstrap. Use it when:
This is the first-run bootstrap. Use it when:
bgs-modding-superpowers and this is the first conversation
in their project directory.xedit-automation) finds the environment incomplete
and routes back here.<Steam>/steamapps/common/<Game>/Data/). All overlays go through MO2.profiles/<Profile>/plugins.txt, modlist.txt, INIs, or load order.scripts/start-mo2.ps1 enforces this and surfaces "zombie" MO2 processes
(running but no window) so they can be cleaned up before a fresh start.The "MO2 control plane" we deploy in step 4 is a Python MO2 plugin plus a PowerShell broker:
tools/mo2-control-plane/live-bridge/mo2_agent_control.py — the actual MO2
plugin. When MO2 loads it, the plugin opens a named pipe and starts publishing
bootstrap runtime files. This is what the agent harness talks to.tools/mo2-control-plane/broker/ — PowerShell IPC client used by
xedit-client.ps1. Runs from the plugin checkout; no install step.There is no C++ DLL to build or deploy at v0.1. A C++ kernel skeleton lives
under docs/internal/future-c-kernel/ as a design note for later perf-critical
paths; it is intentionally unbuilt. If a previous agent told you to "build
Mo2AgentControl.dll first" — that was wrong. The Python plugin is the
integration.
Search for ModOrganizer.exe in common locations:
$env:LOCALAPPDATA\ModOrganizer*\ModOrganizer.exeD:\ModOrganizer*\ModOrganizer.exe, E:\ModOrganizer*\ModOrganizer.exe,
C:\ModOrganizer*\ModOrganizer.exeIf exactly one MO2 install is found, propose it to the user for confirmation. If multiple, list them with paths and ask which is the target. If none, go to step 2.
Persist the confirmed install root in conversation context as MO2_Root. All
subsequent steps reference this variable.
Also surface the BGS_MO2_ROOT env-var requirement. The xedit MCP server
needs to know MO2_Root so it can resolve <MO2_Root>/tools/xEdit/xEdit.exe
and <MO2_Root>/profiles/<profile>/plugins.txt. Without it, the MCP either
falls back to a stale dev-sandbox path (silent wrong-answer on dev clones) or
errors with a "MO2 sandbox root is not configured" message (on end-user
installs). Tell the user where to set it for their harness:
xedit MCP entry's env block in opencode.json:
{ "mcp": { "xedit": { "env": { "BGS_MO2_ROOT": "<MO2_Root>" } } } }
~/.codex/config.toml:
[mcp_servers.xedit.env]
BGS_MO2_ROOT = "<MO2_Root>"
<plugin-root>/.mcp.json to add an env block on the xedit entry.After the user sets it, the user must restart their harness session so the
MCP server picks up the new env. Confirm by calling xedit_status({}) and
checking that the returned hint no longer mentions BGS_MO2_ROOT.
Per-call override is also available: xedit_start({ moRoot: "<MO2_Root>", ... }).
Useful for one-off testing, but the env-var path is what makes restarts and
subsequent sessions work without re-passing it.
Surface a [BLOCKED] notice and offer THREE paths, in order of preference:
(a) Default - human install. Provide the official MO2 release URL: https://github.com/ModOrganizer2/modorganizer/releases/latest. Give the user a brief setup outline (download installer, pick an install root outside Program Files, launch once to initialize). Wait for the user to install and come back with the path.
(b) Agent-handled install (explicit user consent required). Only if the
user says something like "yes, install MO2 for me, go ahead": download the
official MO2 installer to a temp location, run it (silent install where
supported), register the resulting path as MO2_Root. Surface every step
("downloading from ...", "installing to ...", "MO2 ready at ..."). Never
proceed without the explicit verbal consent.
(c) No-MO2 mode. If the user says "I do not need MO2 for this project"
(e.g., they are writing modpack docs / planning without a runtime), record
MO2_Root = none, continue through step 3 for KB target selection, then skip to
step 9 (dev-log / changelog init). Mark that any MO2-bound or xEdit-bound work
will be unavailable until they revisit this skill.
Ask which target games the modpack should support. Use the exact game codes
when talking to KB tools where possible: SkyrimLE, SkyrimSE, SkyrimAE,
SkyrimVR, Fallout4, Fallout4VR, Fallout3, FalloutNV, Starfield.
The bundled bgs-kb-core pack is materialized inside the plugin tree at
plugins/bgs-modding-superpowers/knowledge/bgs-kb/packs/core/. No action is
needed for it; it appears in bgs_kb_status even before MO2 or xEdit are
configured.
Per-game packs (bgs-kb-skyrim, bgs-kb-fallout4, bgs-kb-fallout3-fnv,
bgs-kb-starfield) are published as GitHub Release artifacts on the
BB-84C/bgs-modding-superpowers repo. The KB MCP wraps the entire fetch +
sha256 verify + cache install in two tools — do not download zips by hand:
Map the chosen games to pack IDs:
SkyrimLE / SkyrimSE / SkyrimAE / SkyrimVR -> bgs-kb-skyrimFallout4 / Fallout4VR -> bgs-kb-fallout4Fallout3 / FalloutNV -> bgs-kb-fallout3-fnvStarfield -> bgs-kb-starfieldAdditionally, if the user has indicated a translation/localization workflow
for any of these games (intent to run xtl batch against the game), add the
corresponding localization pack. Today's released localization packs:
Starfield + Simplified Chinese -> bgs-l10n-starfield-zhhans
(151k Bethesda-official terminology entries; RAG retrieval inside xtl
depends on this pack — see using-bgs-translator.)These follow the same install path (bgs_kb_check_updates ->
bgs_kb_install_pack) and the same on-disk cache layout as the per-game
packs. Do not assume a localization pack is present just because the
per-game pack is installed; check bgs_kb_status after install.
List what is available from the live release manifest:
bgs_kb_check_updates({})
This reads the published manifest-index.json and returns the latest
{ packId, version, sha256, url, breakingChange } for every official pack.
Surface the per-game-pack rows that match the chosen games before doing
anything else.
Get explicit user consent before installing each pack ("yes, install
bgs-kb-skyrim"). Pack install mutates ~/.bgs-modding-superpowers/kb/packs/<packId>/<version>/
(legacy %LOCALAPPDATA%/bgs-modding-superpowers/kb/packs is no longer used; the cache
root is unified with xtl).
For each consented pack:
bgs_kb_install_pack({ packId: "bgs-kb-skyrim", version: "<from check_updates>", dryRun: true })
Verify the dry-run reports the expected version + sha256, then re-run
without dryRun to actually install. The MCP downloads from the official
release URL, verifies sha256, and lays the pack out in the versioned cache.
If bgs_kb_check_updates returns an empty or partial list for a game the
user wanted (network failure, release not yet published), say so and
continue with the bundled core pack. Do not improvise a download URL or
iwr into the cache by hand.
Smoke test after selection / install:
bgs_kb_status({})
bgs_kb_query({ query: "plugins", games: ["<chosen-game>"], maxResults: 3 })
Success criterion: bgs_kb_status lists every pack that was just installed
plus bgs-kb-core, and bgs_kb_query returns at least one hit. If only the
core pack is available, a core-pack hit is enough for first-run.
For routine update / prune / version-pinning work after first-run, route to
maintaining-modding-environments — it documents the full ongoing-care flow
on top of the same two MCP tools.
xtl for AI translation workflowsIf the user plans to translate mods, or a downstream workflow routes into
using-bgs-translator, make sure the standalone translator CLI is available.
xtl is distributed on PyPI as the bgs-translator package; do not assume it
is present in a fresh machine just because this plugin is installed.
Start with a readback:
# Check whether the translator CLI is already installed and can report capabilities.
xtl version
If xtl is missing, choose one install path:
# Preferred user-level CLI install when pipx is available.
pipx install bgs-translator==0.9.0rc1
# Fallback when pipx is unavailable, or when the user wants xtl inside the active Python environment.
py -3.12 -m pip install bgs-translator==0.9.0rc1
For a future stable release, the same commands can omit the exact prerelease
pin, for example pipx install bgs-translator or
py -3.12 -m pip install bgs-translator. Do not use broad
pip install --pre bgs-translator as routine setup; it can opt unrelated
dependencies into prerelease builds. Pin an exact release candidate only when
that exact version is the intended runtime.
Verify after install:
# Confirm xtl is on PATH and exposes the expected command surface.
xtl version
# Inspect the top-level help before choosing subcommands or options.
xtl --help
# Inspect provider-profile options instead of assuming a single SDK kind.
xtl profile add --help
# Inspect GUI launch options if the user wants the web translator.
xtl gui --help
If xtl version fails after a pipx install, surface the pipx PATH warning and
ask the user to reopen the shell/session, then retry. Once it passes, route
actual translation work to using-bgs-translator; this setup skill only
installs and smoke-checks the CLI.
Once MO2_Root is known (path a or b), deploy the Python plugin:
& "<plugin-root>/scripts/install-mo2-control-plane.ps1" -MO2Root "<MO2_Root>"
This deploys:
tools/mo2-control-plane/live-bridge/mo2_agent_control.py -> <MO2_Root>/plugins/Mo2AgentControl/ support tree -> <MO2_Root>/plugins/ModOrganizer.ini lock_gui=false normalization.After the script returns, list <MO2_Root>/plugins/ and confirm
mo2_agent_control.py is present. The script will NOT install a .dll — that
is intentional (see "What the control plane actually is" above). If the script
errors, stop and surface it; do not continue.
& "<plugin-root>/scripts/start-mo2.ps1" -MO2Root "<MO2_Root>" -Profile "<Profile>"
The launcher script:
-KillStale to skip the prompt.-WindowStyle Normal so the GUI is visible.Verify after launch: the user should see the MO2 GUI on their desktop. The
plugin's bootstrap runtime files should appear at
<MO2_Root>/plugins/Mo2AgentControl/bootstrap/runtime/ within a few seconds:
status.json -> { schemaVersion, state: "ok", mo2Pid }endpoint.json -> { transport: "named-pipe", endpoint: "mo2-control-plane-<pid>" }capabilities.json -> lists launch.*, system.* methods.If those don't appear, the Python plugin didn't load. Check MO2's plugin
settings to confirm mo2_agent_control is enabled.
xEdit is optional but high-value. Describe what it does so the user can make an informed choice:
"xEdit is the canonical editor for Bethesda plugin files (.esp / .esm / .esl). Modpack curators use it to resolve conflicts between mods, generate compatibility patches, flag plugins as ESL (light) to free up load-order slots, clean stray edits (ITM / UDR), and run Pascal-based bulk edits. With this plugin's bundled
xeditMCP, your agent can drive xEdit programmatically - no GUI clicks required."
Then ask: "Would you like me to install xEdit?" - explicit consent gate.
If the user declines, skip to step 9.
The forked, agent-friendly xEdit lives at https://github.com/BB-84C/TES5Edit. Fetch its latest release into the MO2 tools tree:
& "<plugin-root>/scripts/fetch-xedit-release.ps1" -MO2Root "<MO2_Root>"
This downloads the latest release zip, extracts into
<MO2_Root>/tools/xEdit/, and verifies xEdit.exe exists post-extract. For
ongoing version pinning after first install, route to
maintaining-modding-environments.
xEditHookBridge.dll ships with THIS plugin (it is OWNED by
bgs-modding-superpowers, NOT by the xEdit fork). Co-locate it with
xEdit.exe:
& "<plugin-root>/scripts/install-xedit-hook-bridge.ps1" -MO2Root "<MO2_Root>"
This copies tools/xedit-hook-bridge/dist/xEditHookBridge.dll into
<MO2_Root>/tools/xEdit/. The xEdit daemon will find it there at runtime.
Ask the user for their modpack project root. This is usually one of:
<MO2_Root>/profiles/<ProfileName>/ (if the profile is the unit of work).Once <project_root> is known, route to:
writing-modpack-devlog skill - creates <project_root>/docs/dev-log.md with
the project name and start date as the first entry.writing-modpack-changelog skill - creates
<project_root>/docs/release-changelog.md skeleton.From here on, those two skills maintain the files at runtime; do not template or pre-fill them in this skill.
The xEdit MCP is fully non-blocking. Do NOT call a single blocking tool and wait — that will time out. Instead:
0. Read MO2's managed gamePath before launching xEdit. xEdit's default
game discovery uses the Windows registry, which points at the Steam install
— NOT MO2's Stock Game. To force xEdit to see MO2's projected game tree,
read <MO2_Root>\ModOrganizer.ini and extract the gamePath value:
gameName=<Target Game>
gamePath=@ByteArray(<MO2 managed game root>)
Strip the @ByteArray(...) wrapper; the Data dir is <gamePath>\Data.
Pass this to xedit_start as dataPath in the next step. See
writing-bgs-load-order for the full reasoning + alternative load-order
workflows.
Kick off the daemon launch.
xedit_start({
dataPath: "<gamePath>\\Data", // from step 0 above
})
Without an explicit dataPath, xEdit will discover the game via registry
and may open the wrong Data directory.
Expect { ok: true, data: { status: "starting" } } (or "ready" if it was
already up). If you want to use a custom subset of plugins (load-order
experimentation), also pass pluginsFile:
xedit_start({
dataPath: "<gamePath>\\Data",
pluginsFile: "<agent-owned-artifacts-path>/plugins.txt",
})
The writing-bgs-load-order skill explains how to author the file.
Poll xedit_status until ready. The first launch takes 60-240s because
xEdit must parse the active load order. Sleep 5-15s between polls.
xedit_status({}) -> { status: "starting", elapsedSeconds: N }
xedit_status({}) -> { status: "starting", elapsedSeconds: N+5 }
...
xedit_status({}) -> { status: "ready", pid: N, readySince: timestamp }
If status: "failed", surface data.error exactly and STOP. Do not declare
success. Common reasons: MO2 not running, MO2 not loading the Python plugin,
xEdit binary missing, xEdit's automation-serve mode tripping on the active
load order.
Confirm with xedit_health — sends a real system.ping to the daemon
to catch zombies. Expect { status: "ready", responsive: true }.
Confirm domain tools work.
xedit_list_capabilities({}) -> ~49 commands, empty drift.onlyInDigest
xedit_session({}) -> { gameMode: "Fallout4", loadOrderSize: N, daemonPid: N }
If all four pass: surface [OK] BGS modding environment ready with the recorded
MO2_Root, xEdit path (if installed), and project root.
The setup is complete only when ALL of the following hold. Do not declare success otherwise:
<MO2_Root> is known and <MO2_Root>/ModOrganizer.exe exists.bgs_kb_status sees the bundled core pack; and at
least one bgs_kb_query smoke for the chosen game returns a hit.xtl version succeeds from the
user's shell, and xtl --help lists the translator command surface.<MO2_Root>/plugins/mo2_agent_control.py exists (skipped only in no-MO2 mode).MainWindowHandle != 0) and
<MO2_Root>/plugins/Mo2AgentControl/bootstrap/runtime/status.json reports
state: "ok" with a current mo2Pid (skipped only in no-MO2 mode).<MO2_Root>/tools/xEdit/xEdit.exe AND
<MO2_Root>/tools/xEdit/xEditHookBridge.dll both exist.<project_root>/docs/dev-log.md and
<project_root>/docs/release-changelog.md both exist (or user explicitly
declined - record the decline in conversation context).xedit_status eventually reports status: "ready", and
xedit_health.data.responsive is true, and
xedit_list_capabilities returns a non-empty digest. (Skipped only if xEdit
was declined or no-MO2 mode.)In no-MO2 mode, only the KB target selection / smoke and the dev-log / changelog steps need to pass.
Mo2AgentControl.dll from docs/internal/future-c-kernel/.
That is a skeleton, not a real MO2 plugin. The Python plugin IS the
integration. Build the C++ kernel only if you are deliberately moving
perf-critical paths out of Python in a future release.xedit_session or any domain tool and blocking on the response.
Every tool returns immediately. If you see status: "starting", poll
xedit_status; do not call the same tool again in a tight loop./mcp reconnect as the normal way to relaunch xEdit.
Prefer xedit_dirty, xedit_stop, and xedit_restart so the agent can
decide whether to save or abandon unsaved edits before clearing state.Start-Process -WindowStyle Hidden (or any other
invisible/background mode). Always use the start-mo2.ps1 helper, which
forces a visible window.using-bgs-modding-superpowers rule 1.pip install --pre bgs-translator during setup. Prefer an exact
package version such as bgs-translator==0.9.0rc1, or use the stable package
name once a stable release is published.For ongoing care after first-run, see maintaining-modding-environments.
using-bgs-modding-superpowers - the per-session bootstrap; lists the full
skill inventory and hard rules.xedit-automation - hub skill for all xEdit work; load after this skill
succeeds.writing-modpack-devlog, writing-modpack-changelog - runtime asset skills
invoked from step 9.scripts/: install-mo2-control-plane.ps1,
start-mo2.ps1, fetch-xedit-release.ps1, install-xedit-hook-bridge.ps1.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.
Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub bb-84c/bgs-modding-superpowers --plugin bgs-modding-superpowers