
Building a Claude Skill for DDEX Validation: Automate Music Metadata Checks with AI
A step-by-step guide to creating a Claude Code skill that validates DDEX ERN XML files against official schemas - catching metadata errors before they reach distributors.
Key takeaways
- A Claude skill validates DDEX ERN XML files on demand with no external services required.
- Progressive disclosure loads domain knowledge only when needed, keeping token usage low.
- The skill catches common rejection causes like hyphenated ISRCs and missing territory codes.
If you distribute music digitally, you've dealt with DDEX. The Electronic Release Notification (ERN) standard is how labels and distributors exchange release metadata - track titles, ISRC codes, territory rights, audio file references, and more. Get it wrong, and your release gets rejected. Get it right, and it flows seamlessly to Spotify, Apple Music, and hundreds of other platforms.
The problem? DDEX XML files are complex, deeply nested, and easy to break. Validation usually means uploading files to web tools, running CLI scripts, or waiting for your distributor to reject your submission.
In this tutorial, you'll build a Claude skill that validates DDEX ERN files on demand - right inside Claude Code or Claude.ai. Type /ddex-validate, paste your XML, and get instant feedback with actionable error messages.
This is a proof of concept - an experiment in using AI to streamline daily routines when working with music industry data. The full skill is open source on GitHub.
What is a Claude skill?
A skill is a folder with a SKILL.md file that teaches Claude how to handle a specific workflow. Think of it as a reusable prompt template with structure:
ddex-validate/
├── SKILL.md # Instructions + YAML frontmatter
├── references/
│ └── ern-structure.md # DDEX domain knowledge
└── assets/
└── ern382-sample.xml # Example file for testing
Skills use progressive disclosure - Claude loads the frontmatter first (to decide if the skill is relevant), then the full instructions only when triggered. This keeps token usage low while maintaining deep domain expertise.
Prerequisites
- Claude Code installed (or Claude.ai with skills support)
- Basic familiarity with XML and DDEX concepts
- About 15–30 minutes
Step 1: Plan the use cases
Before writing any code, define what the skill should handle:
Parse XML, detect ERN version, fetch XSD schema, validate, and report errors with line numbers.
Verify required elements exist and check ISRC/UPC format without full schema validation.
Analyze each error, suggest a specific fix, and show corrected XML snippets the user can copy-paste.
Step 2: Create the skill folder
Create the skill directory in your Claude Code skills location:
mkdir -p ~/.claude/skills/ddex-validate/references
mkdir -p ~/.claude/skills/ddex-validate/assets
Step 3: Write the SKILL.md
This is the core of the skill. The YAML frontmatter tells Claude when to load it, and the Markdown body tells Claude what to do.
Create ~/.claude/skills/ddex-validate/SKILL.md:
The frontmatter
The frontmatter is the most important part - it's how Claude decides whether to load your skill:
name: ddex-validate
description: Validates DDEX ERN XML files against official schemas.
Checks structure, required fields (ISRC, UPC, MessageHeader), and
schema conformance. Use when user uploads .xml files, mentions
"DDEX", "ERN", "validate release", "check metadata", or
"release notification".
A good description follows the pattern: What it does + When to use it + Key capabilities. Include specific trigger phrases users might say - Claude uses these to decide if the skill is relevant.
The validation workflow
The body of SKILL.md contains step-by-step instructions. Here's the core - the Python validation function that fetches the official DDEX XSD and validates against it:
from lxml import etree
import requests
def validate_ddex(xml_content: str, version: str) -> dict:
"""Validate DDEX XML against official ERN schema."""
xsd_url = (
f"https://service.ddex.net/xml/ern/"
f"{version}/release-notification.xsd"
)
# Fetch and compile schema
response = requests.get(xsd_url, timeout=10)
response.raise_for_status()
schema_root = etree.fromstring(response.content)
schema = etree.XMLSchema(schema_root)
# Parse and validate
xml_tree = etree.fromstring(xml_content.encode())
is_valid = schema.validate(xml_tree)
errors = []
if not is_valid:
for error in schema.error_log:
errors.append({
"line": error.line,
"column": error.column,
"message": error.message,
"level": error.level_name,
})
return {"valid": is_valid, "errors": errors, "version": version}
Music industry checks
Beyond schema validation, the skill checks for issues that cause real distributor rejections:
| Check | Rule | Example |
|---|---|---|
| ISRC | Exactly 12 alphanumeric chars, no hyphens | USSM12345678 |
| UPC/EAN | 12 or 13 digits | 123456789012 |
| Territory | ISO 3166-1 alpha-2 or Worldwide | US, GB, Worldwide |
| Duration | ISO 8601 format | PT3M30S |
| Resource refs | Every ReleaseResourceReference must match a ResourceReference | A1 links to A1 |
| ParentalWarning | Must be present | NotExplicit, Explicit |
ISRC codes use hyphens for display (US-SM1-23-45678) but never in XML. This is one of the most common validation errors I see.
Output format
The skill defines exactly how Claude should present results:
DDEX ERN 382 - Valid
Summary:
- Releases: 1
- Sound Recordings: 3
- Images: 1
- Territory: Worldwide
- Message Type: LiveMessage
And when errors are found:
DDEX ERN 382 - 2 error(s) found
| # | Line | Error | Suggested Fix |
|---|------|---------------------------------|----------------------------------|
| 1 | 36 | Element 'ISRC': '' is not valid | Add 12-char ISRC: CCXXXYYNNNNN |
| 2 | 45 | Missing element 'TerritoryCode' | Add <TerritoryCode>Worldwide</…> |
The full SKILL.md also includes a Common Issues section with pre-documented fixes for namespace errors, resource reference mismatches, and territory code problems. See the complete file in the GitHub repo.
Step 4: Add supporting files
The skill needs two more pieces:
references/ern-structure.md - the complete ERN element hierarchy (MessageHeader, ResourceList, ReleaseList, DealList), field format rules, and version differences between ERN 3.8.2 and 4.1.1+. Claude loads this on demand when it needs deeper context during validation.
assets/ern382-sample.xml - a minimal but valid ERN 3.8.2 file with a MessageHeader, one SoundRecording (ISRC, artist, genre, technical details), one Image, and one Release.
You don't need to write these from scratch. Clone the GitHub repo and the full skill is ready to use:
git clone https://github.com/musictechlab/ddex-validate.git ~/.claude/skills/ddex-validate
Step 5: Test the skill
Once installed, test it from three angles:
Should trigger - try prompts like these:
"Validate this DDEX file"
"Check my ERN XML for errors"
"Is this release metadata valid?"
Error detection - introduce common mistakes and verify the skill catches them:
<!-- Missing ISRC -->
<SoundRecordingId>
<CatalogNumber Namespace="PADPIDA2023001">CAT001</CatalogNumber>
</SoundRecordingId>
<!-- Invalid territory code -->
<TerritoryCode>United States</TerritoryCode>
<!-- Mismatched resource reference -->
<ReleaseResourceReference>A99</ReleaseResourceReference>
<!-- when ResourceReference is "A1" -->
Should NOT trigger - prompts like "Write a Python function" or "Help me with CSS" should not activate the skill.
How it works under the hood
When you type a prompt that matches the skill's description triggers, Claude's progressive disclosure system kicks in:
graph LR
A[User prompt] --> B{Match?}
B -->|Yes| C[Level 1: Frontmatter]
B -->|No| D[Skip skill]
C --> E[Level 2: SKILL.md body]
E --> F{Need more context?}
F -->|Yes| G[Level 3: references/]
F -->|No| H[Execute validation]
G --> H
This three-level system keeps token usage minimal for non-DDEX conversations while providing deep expertise when needed:
Claude reads `name` and `description`. Just enough to decide: "is this a DDEX request?"
The full 5-step workflow: parse, validate, check industry rules, report results.
Deep ERN structure docs, field formats, version differences. Loaded only when needed.
What's next
This skill covers standalone validation - no external services required. But there are natural extensions:
- MCP integration - connect to your distributor's API to validate and submit in one workflow
- Batch validation - process an entire directory of ERN files before a bulk delivery
- DSRF support - extend to Digital Sales Report Format flat files (tab-separated, not XML)
- Auto-fix mode - instead of just reporting errors, have Claude rewrite the XML with fixes applied
You could also combine this with an AudioSalad or Revelator delivery skill - validate the DDEX, then push it to your distributor, all from one conversation. I've already built similar Claude integrations: a SignNow MCP server for e-signatures and a Bandcamp MCP server for revenue analytics.
Wrapping up
DDEX validation is a perfect fit for a Claude skill: it's a well-defined workflow, requires domain knowledge that doesn't change often, and benefits from consistent execution. Instead of context-switching to a web tool or remembering CLI flags, you type /ddex-validate and get expert-level feedback in seconds.
The full skill is open source - clone it and start validating:
git clone https://github.com/musictechlab/ddex-validate.git ~/.claude/skills/ddex-validate
FAQ
What is a Claude skill?
A Claude skill is a folder containing instructions (SKILL.md) that teaches Claude how to handle specific tasks or workflows. Skills are reusable across Claude.ai, Claude Code, and the API.
What is DDEX ERN?
DDEX ERN (Electronic Release Notification) is the music industry standard XML format for communicating metadata about music releases between labels, distributors, and digital service providers like Spotify and Apple Music.
Do I need an MCP server for this skill?
No. This is a standalone skill that uses Claude's built-in code execution capabilities. No MCP server or external integrations are required.
BeatBuddy Replay: Video Analysis App Challenges
A deep-dive into how I built a Flutter video analysis app for swimmers. From MVP architecture to cross-platform challenges - my lessons from two weeks of development.
DIY MIDI Controller for Ableton with Arduino
Build a physical MIDI volume controller for Ableton Live using Arduino Leonardo. Covers hardware setup, MIDI protocol, and USB communication.