Reads, edits, and generates BGS load-order files (plugins.txt) for Fallout 4, Skyrim, Fallout 76, Starfield. Covers asterisk-prefix format and xEdit integration.
How this skill is triggered — by the user, by Claude, or both
Slash command
/bgs-modding-superpowers:writing-bgs-load-orderThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
> Sources for every claim in this skill: `Ortham/libloadorder` (the library
Sources for every claim in this skill:
Ortham/libloadorder(the library behind LOOT),ModOrganizer2/modorganizer/src/profile.cpp,ModOrganizer2/modorganizer-basic_games/.../game_plugins.py, and xEdit's official docs Section 2.8.1.
| Format | Games | File | Activation marker |
|---|---|---|---|
| Asterisk format (modern) | Fallout 4, Skyrim SE/AE/VR, Fallout 4 VR, Starfield | plugins.txt | leading * = active |
| Textfile-only (legacy) | Skyrim LE, Oblivion, Fallout 3, Fallout NV | plugins.txt (active only) + sibling loadorder.txt (full order) | presence in plugins.txt = active |
This skill covers the asterisk format in depth. If your target is Skyrim LE / Oblivion / FO3 / FNV, the rules are different — see the "Legacy format" section at the bottom.
| Context | Path |
|---|---|
| Vanilla install (no MO2) | %LOCALAPPDATA%\<GameFolder>\plugins.txt (e.g. Fallout4, Skyrim Special Edition, Starfield) |
| MO2-managed | <MO2_Root>\profiles\<ProfileName>\plugins.txt |
| MO2-managed sibling | <MO2_Root>\profiles\<ProfileName>\loadorder.txt (full order including inactive; MO2 keeps both) |
| Agent-authored (experiments) | an agent-owned artifacts path — generate your own, pass to xedit_start({ pluginsFile }) |
Ownership in MO2 use: MO2 writes plugins.txt whenever the user toggles
plugin checkboxes in the GUI. LOOT can also write it. If you mutate it under
MO2, do it while MO2 is closed OR via mobase's IPluginList API — live edits
while MO2 is open get overwritten on its next save.
# This file was automatically generated by Mod Organizer.
*Unofficial Fallout 4 Patch.esp ← * = ACTIVE; loads first among non-vanilla
ArmorKeywords.esm ← no * = present-but-INACTIVE; position preserved
*HUDFramework.esm
SomeDisabledMod.esp
*MyMod.esp ← bottom = loads LAST = wins conflicts
Verbatim parser rules (from libloadorder/src/load_order/asterisk_based.rs):
# (column 0) → comment, ignored.* → plugin name follows; active.# must be at column 0.The engine loads each game's official plugins at fixed positions before reading
the user-managed plugins.txt. The exact set depends on the target game,
installed DLC, and any Creation Club / verified-content bundles.
Do not hardcode a per-game vanilla-master list in your workflow. Instead, derive the official masters from the user's actual MO2-managed runtime:
<MO2_Root>\ModOrganizer.ini to learn gameName and gamePath.xedit_call({ command: "files.list", args: {} })
and look at the earliest, auto-loaded official plugins. Treat those as the
immutable official master set.<gamePath>\Data)
and known official DLC/content files there. Do not add, remove, or reorder
them in your generated plugins.txt.libloadorder's writer skips these early-loading official plugins on save; MO2 re-injects them as active at read time. So whether they appear in the file or not, they load first.
Practical rule for agent-authored plugins.txt: omit the official masters you inferred from the actual target runtime. Start your file with user-managed plugins instead.
Prefix the line with *. Position unchanged.
Before:
ArmorKeywords.esm
After:
*ArmorKeywords.esm
Strip the leading *. Position preserved (the plugin stays in the file).
Before:
*HUDFramework.esm
After:
HUDFramework.esm
Delete the whole line. Position is dropped. (MO2 will re-append it as inactive
at the end of loadorder.txt on next read — plugins.txt itself stays clean.)
Cut the line, paste it after Y. Mirror the change in loadorder.txt if it
exists (MO2 maintains both files; out-of-sync state confuses MO2).
Append at the bottom with * if you want it active.
*MyExistingMod.esp
*JustInstalledMod.esp ← new line at the end
The bottom = loads last = wins conflicts with everything above. If you don't want it to win conflicts, move it higher.
Do NOT do this by editing plugins.txt. The light-plugin flag lives in
the plugin's file header, not in the load-order file. Route through the xEdit
daemon:
xedit_call({ command: "plugin.esl.analyze", args: { file: "MyMod.esp" } }) — checks whether the plugin's FormIDs fit in the ESL FE-slot range.xedit_call({ command: "plugin.esl.apply", args: { file: "MyMod.esp" } }) — sets the light-plugin flag in the file header.After flagging, the file extension stays .esp. The engine reads the new
flag at load time and remaps the plugin into the shared FE slot.
plugins.txt does NOT change as part of ESL conversion.
| Operation | Right path | Why |
|---|---|---|
| Activate / deactivate a plugin | Edit plugins.txt (toggle *) | No daemon verb exists for activation; the daemon manipulates plugin contents, not the activation file. |
| Reorder plugins | Edit plugins.txt + mirror in loadorder.txt | xEdit docs 2.3 (verbatim): "Load order cannot be changed with xEdit." |
| Remove a plugin entry | Edit plugins.txt | Same reason. |
| Add new plugin to load order | Edit plugins.txt (append) | Daemon doesn't write the activation file. MO2 will project the mod's .esp via VFS once the file references it. |
| Check a plugin's masters | xedit_call({command:"files.get_masters", args:{file:"..."}}) | Reads the plugin header. |
| Add a missing master to a plugin | xedit_call({command:"files.add_required_masters", args:{...}}) | Mutates the file header. |
| Convert ESP → ESL | plugin.esl.analyze → plugin.esl.apply | Sets header flag; load-order file unchanged. |
| Clean ITM / UDR | xEdit launcher with -quickAutoClean OR daemon files.clean_masters | Both work; CLI faster for batch. |
| Sort the load order | External LOOT | Neither xEdit nor MO2 sorts; LOOT does, then writes plugins.txt. |
| Verify a load order is valid | Combine: read plugins.txt, then daemon files.list to confirm each *-prefixed file exists with required masters present. | Two-sided: file presence (libloadorder) + header consistency (xEdit). |
The rule of thumb: plugins.txt is an activation surface owned by MO2 (or
LOOT, or the agent). The xEdit daemon never touches it. The daemon's domain
ends at the file header of individual plugins.
When you want xEdit to load only a subset of mods (e.g., to isolate a
conflict between two specific plugins), generate a custom plugins.txt under
an agent-owned artifacts path and pass it to xedit_start:
// 1. Write the file
const customPlugins = `# Agent-generated for conflict isolation between PluginA + PluginB
*<PrimaryGameMaster>.esm
*<OptionalCommunityFix>.esp
*PluginA.esp
*PluginB.esp
`;
await writeFile("<agent-owned-artifacts-path>/foo-vs-bar/plugins.txt", customPlugins);
// 2. Start xEdit pointing at the custom file + the right Data dir
await xedit_start({
pluginsFile: "<agent-owned-artifacts-path>/foo-vs-bar/plugins.txt",
dataPath: "<MO2_Root>/<managed game root>/Data",
gameMode: "<GameMode>",
});
Notes for the experimental file:
| File | What it lists | Prefix convention | Where |
|---|---|---|---|
plugins.txt | .esp/.esm/.esl plugin filenames | * = active, no prefix = inactive | <profile>/plugins.txt |
modlist.txt | MO2 mod folder names (under mods/) | + = enabled, - = disabled, * = foreign | <profile>/modlist.txt |
The * in modlist.txt means "foreign mod" (MO2-managed but externally
owned), NOT "active." Mixing the two formats is the #1 way to corrupt a
profile. Never copy/paste between them.
Before launching xEdit via the agent, read MO2's config to learn the managed game path:
# <MO2_Root>\ModOrganizer.ini contains lines like:
gameName=Fallout 4
gamePath=@ByteArray(D:\\awesome-bgs-mod-master\\.artifacts\\mo2\\Stock Game\\Fallout 4)
The gamePath value (strip the @ByteArray(...) wrapper) is where the
agent's xedit_start({ dataPath: ... }) should point. Specifically, the Data
directory is <gamePath>\Data. Without an explicit dataPath, xEdit falls
back to the Windows registry — which points at the platform install path,
not necessarily the MO2-managed game root. That's the source of "wrong Data"
bugs.
Three options for catching a malformed plugins.txt before launching xEdit
into a broken state:
-quickAutoClean against the
file. Non-zero exit = a master is missing or a *-prefixed plugin doesn't
resolve. Cheap and authoritative.
xEdit.exe -fo4 -D:"...\Data\" -P:"...\plugins.txt" -veryquickshowconflicts
*-prefixed plugin must exist as a file in the
Data dir; no duplicate lines; under 255 active full plugins + under 4096
active light plugins (.esl + flagged-ESP).What makes a file invalid:
*-prefixed line whose file does not exist in the Data dir.The OLD format used by pre-asterisk games:
* prefix. Presence of a plugin line in plugins.txt means it's
active. Absence means it's not loaded.loadorder.txt is the canonical full-order file (active + inactive).
plugins.txt contains only active plugins.plugins.txt uses Windows-1252 encoding; loadorder.txt uses UTF-8
without BOM.This format does NOT apply to FO4 / SSE / Starfield. If you're targeting one of these older games, use this section's rules; for everything else, use the asterisk format above.
xedit-automation — hub skill for all xEdit work; routing doctrine,
anti-patterns, sub-agent recipes.knowledge/bgs-kb/packs/core/records/ — daemon command,
error-code, save-semantics, and glossary facts formerly kept in the retired
xedit-automation/xedit-knowledgebase.md redirect.setting-up-bgs-modding-environment — explains how to inspect MO2's
ModOrganizer.ini for gamePath before launching xEdit.-P:,
-D:, and friends.Ortham/libloadorder documentation — the authoritative source for the
asterisk format semantics.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