Routes xEdit automation daemon tasks—plugin inspection, modification, and building for Bethesda games—to the appropriate MCP intent tool, atomic passthrough, or sub-agent delegation. Prevents bypassing the harness.
How this skill is triggered — by the user, by Claude, or both
Slash command
/bgs-modding-superpowers:xedit-automationThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
This skill is the always-loaded entry point for any xEdit work. It is the single source of truth for "which path do I use" and "what must I never do." Specialised task skills (e.g. `xedit-conflict-audit`) inherit its routing, anti-patterns, and verification discipline; they do not restate them.
This skill is the always-loaded entry point for any xEdit work. It is the single source of truth for "which path do I use" and "what must I never do." Specialised task skills (e.g. xedit-conflict-audit) inherit its routing, anti-patterns, and verification discipline; they do not restate them.
The forked xEdit daemon is best treated as a progressive-disclosure surface:
start with the small MCP intent tools, ask the live daemon which r6 capability
blocks it supports, then switch to the richer one-call patterns only when the
corresponding system.capabilities.supports.* key is present.
xedit_session, xedit_list_capabilities. Call
xedit_session first every conversation. Then call xedit_list_capabilities
once to see the command digest, contractVersionExpected, and r6
supports.* anchors.xedit_find_record, xedit_read_record,
xedit_inspect_conflicts. These are the W2 (conflict audit) backbone; branch
to atomic passthrough when W2 needs an r6 response block that no intent tool
exposes yet.xedit_call(command, args). For any native daemon
command that does not have an intent tool yet. Still runs the full pipeline
(validation → state → rules → audit). Use it whenever the intent tools do not
fit.For deep reference material, query the structured BGS KB first (bgs_kb_query
/ bgs_kb_get). Deep reference records live under
knowledge/bgs-kb/packs/core/records/xedit/ (queryable via bgs_kb_query /
bgs_kb_get).
| Task shape | Path |
|---|---|
| High-frequency known intent (audit a conflict, read a record, run a job, write a patch) | MCP intent tool |
| Novel / debugging / free composition of native commands | MCP atomic passthrough: xedit_call(command, args) — still in harness |
| Exploratory atomic-op storm (trial-and-error, repeated read-eval, hypothesis testing) | Delegate to a read-only investigator sub-agent with this skill loaded; the sub-agent burns its own context, returns a distilled summary |
| Large formalisable bulk mutation | MCP xedit_run_script (Batch 4+) with dry-run + snapshot |
| Daemon explicitly in default (non-MCP) mode, manual debug only | Direct xedit-client.ps1 is acceptable — but ONLY when the user has explicitly accepted the risk and the daemon is not in -automation-mcp-mode |
The agent should never have a reason to bypass the MCP. Atomic passthrough exists for that.
Do not assume every daemon is r6. Read xedit_list_capabilities once and branch
on the support keys below. On pre-r6 daemons, fall back to the older explicit
record-list / child-walk / per-record loop patterns; on r6+ daemons, use the
one-call or page-aware form to reduce round-trips and preserve context.
| Capability key | Contract | Prefer this pattern | KB record |
|---|---|---|---|
supports.childGroupNavigation | 0.13 | Navigate CELL/WRLD/DIAL/QUST ChildGroups through elements.children stubs | xedit.childgroup-navigation.v1 |
supports.createParentSpec | 0.16 / 0.18 | Create records directly under parent ChildGroups with records.create parent | xedit.records-create-parent-spec.v1 |
supports.elementsChildrenPagination | 0.17 | Page elements.children with limit / offset | xedit.elements-children-pagination.v1 |
supports.reverseNavigation | 0.19 | Add includeParents:true and read relations.parents | xedit.reverse-navigation.v1 |
For the whole r6 contract delta, query KB record xedit.r6-contract-summary.v1.
supports.childGroupNavigation)On r6+ daemons, elements.children on CELL, WRLD, DIAL, and QUST records
returns a virtual child entry with kind: "child_group". Treat that entry as a
read-only navigation stub, not as a real mutable element.
Use it one generation at a time:
elements.children({ file, formId, path: "\\Child Group" })
elements.children({ file, formId, path: "\\Child Group\\Persistent" })
elements.children({ file, formId, path: "\\Child Group\\Temporary" })
elements.children({ file, formId, path: "\\Child Group\\Visible when Distant" })
elements.children({ file, formId, path: "\\Child Group\\Block X, Y" })
elements.children({ file, formId, path: "\\Child Group\\Block X, Y\\Sub-Block M, N" })
\\Child Group... paths are synthetic and READ-ONLY. Mutation verbs must
use flat FormID locators ({ file, formId }) or a records.create.parent
spec; do not pass synthetic locator paths to mutators.Persistent or the Block/Sub-Block/coordinate route
depending on the target child group.xedit.childgroup-navigation.v1.elements.children pagination (supports.elementsChildrenPagination)On r6+ daemons, elements.children accepts limit and offset:
elements.children({ file, formId, path, limit: 200, offset: 0 })
limit is clamped to 1-1000 and defaults to 200.count, total, offset, and truncated.truncated is true, keep the same limit, add count to offset, and
fetch the next page until covered.00000025
Temporary contains 742 records.xedit.elements-children-pagination.v1.supports.reverseNavigation)On r6+ daemons, add includeParents: true when you need to know ownership or
containment without a second verb. Supported read calls include:
records.getrecords.find_by_form_id / records.find_by_editor_id and MCP wrappers such
as xedit_find_recordrecords.master_or_selfrecords.winning_overrideelements.getelements.childrenThe response may include:
relations.parents: [{ locator, object }, ...]
Parents are nearest-first with a daemon depth cap of 16. This is the preferred
answer to "which CELL owns this REFR?" or "which QUST/DIAL group contains this
child?" Use the parent chain as readback evidence; do not build a custom
reverse-index loop unless the support key is absent. Deep reference:
xedit.reverse-navigation.v1.
records.create parent-spec (supports.createParentSpec)Mutating record creation into ChildGroups is r6-gated and still requires the
normal MCP mutation consent path. When supported, author the target parent
explicitly instead of trying to mutate synthetic \\Child Group paths.
CELL, DIAL, and QUST children:
records.create({
targetFile,
signature,
editorId,
parent: { file, formId, subGroup? }
})
WRLD children:
records.create({
targetFile,
signature,
editorId,
parent: { file, formId, subGroup: "Persistent" }
})
records.create({
targetFile,
signature,
editorId,
parent: { file, formId, coords: [X, Y] }
})
For coords, native xEdit creates the needed Block/Sub-Block groups. Validate
with records.get or elements.children({ includeParents: true }) after the
preview/commit flow, and remember that durability still requires save + daemon
restart + readback. Deep reference: xedit.records-create-parent-spec.v1.
Never do any of the following. Each ban is encoded as an MCP rule or daemon-side refusal, but the skill states them so the agent does not even attempt:
.esp/.esm/.esl files directly. The daemon is the only correct path. If you find yourself reaching for a binary plugin parser, stop and use xedit_call instead.ok: true response as durability. A save with pendingShutdown > 0 is deferred; durability requires a daemon restart and readback (see §10 of the design spec).mcp_mode_required.system.capabilities every session. The digest in xedit_list_capabilities already carries the curated map; only call live capabilities once to check drift.xedit_call records.referenced_by and accepting the consequences. Snapshot does not cleanly recover deletions.-IKnowWhatImDoing)Mutating intent tools (xedit_create_child_record, xedit_call records.create,
xedit_call records.delete, xedit_call records.copy_into, etc.) require the
xEdit daemon to be launched in consent mode — otherwise they fast-fail with
code: "mutation_requires_iknowwhatimdoing" BEFORE the daemon is contacted.
Enable consent at launch time via the MCP arg:
xedit_start({ iKnowWhatImDoing: true, ...other overrides })
xedit_restart({ iKnowWhatImDoing: true, ...other overrides }) # if already running
The flag is forwarded as --i-know-what-im-doing 1 to xedit-client.ps1, which
appends -IKnowWhatImDoing to xEdit's startup argv. Verify post-launch:
xedit_session() # data.consentEnabled === true ?
If consentEnabled is still false after passing iKnowWhatImDoing: true,
the flag did not propagate — check that the MCP is on a build that includes
the consent forwarding (commit xxx and later; see RELEASE-NOTES.md).
Consent is per-launch and explicit only: there is no env-var fallback, no
runtime toggle, and the audit log captures the consent decision at the call
site. To revoke consent, call xedit_stop then xedit_start without the flag.
Before any mutating action:
confirmToken. Read the preview, decide, then commit with the token. Treat the preview as the contract.When delegating, do not hard-code role names — the harness will map them. Use these recipes:
Read-only investigator — for exploratory storms, conflict surveys, and "what's in this plugin" reconnaissance:
Dispatch a read-only investigator sub-agent with this skill loaded. Provide the question, the target files, and the budget (token / time / step count). The sub-agent should return a distilled summary (verdict + key evidence + open questions), not the raw daemon round-trips.
Bounded mutation worker — for well-defined batch edits (Batch 4+):
Dispatch a bounded-execution sub-agent with this skill and the patch-authoring skill loaded. Provide the spec, the snapshot expectations, and the acceptance checks. The sub-agent should perform the mutations through the MCP and return the snapshot IDs + readback proof.
After any session that produced a footgun (an unexpected refusal, a non-obvious recovery, a surprising daemon behavior):
<pack-root>/records/<domain>/<slug>.v1.md with YAML frontmatter that validates against knowledge/bgs-kb/schema/record.schema.json.knowledge/bgs-kb/packs/core/records/; game-specific facts go into the matching per-game pack (bgs-kb-skyrim, bgs-kb-fallout4, bgs-kb-fallout3-fnv, bgs-kb-starfield).node tools/bgs-kb-mcp/dist/cli.js validate <pack-root> and then node tools/bgs-kb-mcp/dist/cli.js build <pack-root> to refresh that pack, unless the current phase explicitly forbids rebuilds and gives a narrower validation path.bgs_kb_query and confirm the new record appears for a query a future agent would actually use.tools/xedit-mcp enforcement.Worked example:
0x-prefixed FormIDs, while the MCP normalizes them at the edge.knowledge/bgs-kb/packs/core/records/xedit/formid-prefix-normalization.v1.md.node tools/bgs-kb-mcp/dist/cli.js validate knowledge/bgs-kb/packs/core then node tools/bgs-kb-mcp/dist/cli.js build knowledge/bgs-kb/packs/core.bgs_kb_query({ query: "0x FormID normalization", domains: ["xedit"] }) and confirm the record is returned..esp/.esm/.esl) for FO4, Skyrim, FO76, Starfield in this repo's MO2 harness.When in doubt, load it.
writing-bgs-load-order — authoritative reference for editing
plugins.txt / loadorder.txt. Use it whenever the task is about
activating, deactivating, reordering, adding, or removing plugins from the
load order. Do NOT edit plugins.txt blindly; xEdit can not change load
order itself (docs 2.3), so the file edit is the only path for those
operations, and the asterisk-format rules + official-master detection rules
are non-obvious.setting-up-bgs-modding-environment — first-run setup including the
MO2 gamePath inspection step you must do before launching xEdit with the
dataPath override.The xedit_start MCP tool accepts optional overrides:
xedit_start({
launcherPath?: string, // xEdit.exe path
gameMode?: string, // "Fallout4", "SkyrimSE", etc.
dataPath?: string, // -D: flag; MO2 <gamePath>\\Data
pluginsFile?: string, // -P: flag; agent-authored plugins.txt
moProfile?: string, // MO2 profile name; defaults to env
})
Always pass dataPath when the user wants xEdit to see the MO2-managed
game tree. Without it, xEdit falls back to the Windows registry, which
returns the raw Steam install path — and your conflict audit will be against
the wrong game data. Read MO2's ModOrganizer.ini gamePath value, append
\\Data, and pass that.
For load-order experimentation (test a subset of plugins to isolate a
conflict, or rehearse a sort), generate a plugins.txt under an
agent-owned artifacts path per writing-bgs-load-order and pass it as
pluginsFile.
The daemon already exposes session.get_dirty_state, and the MCP now
surfaces three helper tools so the agent does not need to remember the raw
daemon verb:
xedit_dirty({}) — returns { dirty, dirtyFiles, unsavedChangeCount } when
ready. This is the safe thing to call before any stop/restart.xedit_stop({ force?: true }) — if the session is dirty and force is not
set, refuses with code: "dirty_state" and the list of unsaved files.xedit_restart({ launcherPath?, gameMode?, dataPath?, pluginsFile?, moProfile?, force?: true })
— same dirty-state safety as stop, then relaunches asynchronously with new
overrides.Use xedit_restart whenever you need to reboot xEdit with a different custom
pluginsFile or dataPath. Do NOT tell the user to reconnect /mcp manually
just to clear a zombie or change launch args.
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