generate-keyrefs
Skill2 starsChanged 6 months agoMITView on GitHub
Scans one or more DITA 1.3 topics and automatically generates keydef entries and keyref suggestions. Use this skill when you want to enforce reuse-first authoring, detect repeated inline text or repeated hrefs that should be centralised in the map, or migrate a set of topics to use keyrefs instead of hard-coded values. Returns ready-to-paste keydef XML plus a change list showing exactly which elements to update.
In this repository18 other files it gives its agents.
- .github/copilot-instructions.mdCopilot instructions
- context-setupSkill
- dita-best-practicesSkill
- ditaval-helperSkill
- error-handlingSkill
- generate-bookmapSkill
- generate-ditamapSkill
- generate-dita-topicSkill
- keyspace-debugSkill
- map-resolveSkill
- pdf-to-ditaSkill
- refactor-dita-contentSkill
- review-dita-guideSkill
- validate-bookmapSkill
- validate-ditamapSkill
- validate-dita-topicSkill
- visitor-extendSkill
- xslt-dita-helperSkill
The file
We split this skill into the rules it gives an agent
1 rule. About 0 are common, 0 are distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈0
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 90
When --apply is used, the response also includes:
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Overview
generate-keyrefs analyses a set of DITA topics and produces:
keydefs— suggested<keydef>entries to add to your root ditamapchanges— a per-file list of elements to replace withkeyref=attributeskeydef_block— a ready-to-paste XML snippet for your map--applymode — rewrites files in place, addingkeyref=attrs and removing hard-coded values
Candidate detection rules
| Category | Elements scanned | Condition |
| Text keys | <ph>, <term>, <keyword>, <prodname>, <varname>, <wintitle>, <cmdname>, <option>, <parmname>, <apiname>, <filepath>, <userinput>, <systemoutput> | Same text appears ≥ N times across all files |
| External URL keys | <xref href="http…">, <link href="http…"> | Same URL appears ≥ N times |
| Image keys | <image href="…"> | Same image path appears ≥ N times |
| Code ref keys | <coderef href="…"> | Same path appears ≥ N times |
Elements that already carry a keyref= attribute are skipped.
Usage
# Scan a directory, show suggestions (dry run)
python generate-keyrefs/scripts/generate_keyrefs.py topics/
# Raise the threshold — only suggest if text appears 3+ times
python generate-keyrefs/scripts/generate_keyrefs.py topics/ --min-occurrences 3
# Scan specific files
python generate-keyrefs/scripts/generate_keyrefs.py overview.dita install.dita reference.dita
# Save keydef XML to a file for pasting into your map
python generate-keyrefs/scripts/generate_keyrefs.py topics/ --keydef-output keydefs.xml
# Rewrite topics in place (adds keyref= attrs, removes old values)
python generate-keyrefs/scripts/generate_keyrefs.py topics/ --applyOutput schema
{
"summary": {
"files_scanned": 3,
"keydefs_suggested": 4,
"changes_suggested": 9
},
"keydefs": [
{
"key": "acme-product",
"type": "text",
"value": "ACME Product",
"occurrences": 6,
"files": ["topics/overview.dita", "topics/install.dita"]
},
{
"key": "ext-docs-acme-com-api",
"type": "href",
"href": "https://docs.acme.com/api",
"scope": "external",
"occurrences": 3,
"files": ["topics/overview.dita"]
}
],
"changes": [
{
"file": "topics/overview.dita",
"element": "ph",
"change": "add_keyref",
"old_text": "ACME Product",
"new_keyref": "acme-product",
"description": "<ph>ACME Product</ph> → <ph keyref=\"acme-product\"/>"
}
],
"keydef_block": "<keydef key=\"acme-product\">\n <topicmeta>…</topicmeta>\n</keydef>\n\n<keydef key=\"ext-docs-acme-com-api\" href=\"https://docs.acme.com/api\" scope=\"external\" format=\"html\"/>"
}When --apply is used, the response also includes:
{
"applied": {
"topics/overview.dita": 3,
"topics/install.dita": 2
},
"summary": {
"files_rewritten": 2
}
}Keydef XML produced
Text key
<keydef key="acme-product">
<topicmeta>
<keywords>
<keyword>ACME Product</keyword>
</keywords>
</topicmeta>
</keydef>Usage in topic after --apply:
<!-- Before -->
<ph>ACME Product</ph>
<!-- After -->
<ph keyref="acme-product"/>External URL key
<keydef key="ext-docs-acme-com-api"
href="https://docs.acme.com/api"
scope="external"
format="html"/>Usage in topic:
<!-- Before -->
<xref href="https://docs.acme.com/api">API docs</xref>
<!-- After -->
<xref keyref="ext-docs-acme-com-api">API docs</xref>Image key
<keydef key="img-header-logo" href="images/header-logo.png" format="png"/>Usage in topic:
<!-- Before -->
<image href="images/header-logo.png" alt="Logo"/>
<!-- After -->
<image keyref="img-header-logo" alt="Logo"/>Integration into a map
Paste the keydef_block output (or the file written by --keydef-output) before your first <topicref>:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE map PUBLIC "-//OASIS//DTD DITA Map//EN" "map.dtd">
<map>
<title>Product Guide</title>
<!-- ── Key definitions ─────────────────────────────────── -->
<keydef key="acme-product">
<topicmeta>
<keywords><keyword>ACME Product</keyword></keywords>
</topicmeta>
</keydef>
<keydef key="ext-docs-acme-com-api"
href="https://docs.acme.com/api"
scope="external" format="html"/>
<!-- ── Topics ──────────────────────────────────────────── -->
<topicref href="topics/overview.dita"/>
<topicref href="topics/install.dita"/>
</map>Common pitfalls
| Pitfall | Cause | Fix |
| Key name collision | Two different values slug to the same key | Script auto-appends -2, -3 suffixes; review and rename if needed |
--apply breaks round-trip | ET serialisation drops CDATA / processing instructions | Back up topics before running --apply; check git diff |
| Short text over-matched | Single letters or numbers meet the threshold | Raise --min-occurrences or post-filter the change list |
| Scope wrong for local images | Image path treated as external | Script detects http:// prefix; local paths always get format=<ext> |
| keyref resolution at build time | Keys must be defined before first reference in map order | Place all <keydef> elements at the top of the map |
See also
validate-ditamap— validates that all keyrefs in a map resolve to defined keysvalidate-dita-topic— catches malformed keyref attributes in topicsdita-best-practices— flags topics that have hard-coded values instead of keyrefsrefactor-dita-content— broader refactoring including conref extraction
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

