Claude Skill publication runbook
Step-by-step for publishing theaccessible PDF Converter as an
Anthropic Skill bundle. Companion to docs/CUSTOM-GPT-PUBLICATION.md
(OpenAI Custom GPT) and docs/MCP-AND-CUSTOM-GPT.md (MCP server).
The skill source lives in this repo at skills/pdf-converter/. The
public distribution lives at https://github.com/anglinai/theaccessible-skill.
What a Skill is (vs. a Custom GPT)
| Custom GPT | Claude Skill | |
|---|---|---|
| Lives where | OpenAI GPT Store | A folder Claude loads on demand |
| Auth | Action API key, pasted in editor | THEACCESSIBLE_API_KEY env var on the userβs machine |
| Code execution | None β model calls Action endpoints | Yes β model can run bundled bash scripts |
| Discoverability | Public GPT Store | GitHub repo (today); claude.ai upload (when GA) |
| Distribution | One link | Skill bundle (zip / git clone) |
The skill calls the same /api/gpt/* HTTPS surface as the Custom
GPT β no new server-side endpoints required.
Prerequisites
- The OpenAPI spec live at https://api-pdf.theaccessible.org/openapi.yaml.
- A test API key (Settings β API keys in the dashboard).
bash,curl,jqon the test machine.
1. Verify the bundle locally
ls skills/pdf-converter/# SKILL.md README.md scripts/ references/
# Syntax-check the shell scripts:for f in skills/pdf-converter/scripts/*.sh; do bash -n "$f"; done && echo OK2. Smoke-test in Claude Code
mkdir -p ~/.claude/skillsrm -rf ~/.claude/skills/pdf-convertercp -r skills/pdf-converter ~/.claude/skills/pdf-converter
export THEACCESSIBLE_API_KEY=tap_... # your test keyOpen Claude Code in any directory and run all four scenarios:
- Public URL. βMake this PDF accessible:
https://example.com/sample.pdfβ Confirm:convert.sh --url, polling, result with three markdown links +reportUrl. - Local file. βMake
~/Downloads/sample.pdfaccessible.β Confirm the model picksconvert.sh --file(not--urlwith a~/...path). - Known-bad PDF. Use a PDF with no tags / no language. Confirm
conformance.passed=falseand the model lists the failed rules without claiming compliance. - Oversize. Try a 30 MB PDF. Confirm
convert.shexits 65 with the size message, surfaced cleanly to the user.
3. Smoke-test scripts directly
Run each script outside the model to confirm exit codes and JSON shape:
cd ~/.claude/skills/pdf-converter./scripts/convert.sh --url https://example.com/sample.pdf | jq .fid=$(./scripts/convert.sh --url https://example.com/sample.pdf | jq -r .data.fileId)./scripts/poll_status.sh "$fid" | jq .data.status./scripts/get_result.sh "$fid" | jq '.data | keys'./scripts/get_conformance.sh "$fid" | jq '.data.conformance.passed'All four should exit 0 on the happy path. poll_status.sh should
exit 1 on status=failed and 3 on the 5-minute timeout.
4. Publish to the public repo
The public mirror is a separate repo so external users can clone it without pulling our backend source.
# First time only β see step 5 of the original setup, below.cd ~/Projectsgit clone git@github.com:anglinai/theaccessible-skill.gitcd theaccessible-skill
# Sync from the source of truth:rsync -av --delete \ ~/Projects/accessible/skills/pdf-converter/ \ ./
git add -Agit commit -m "Sync from accessible@$(cd ~/Projects/accessible && git rev-parse --short HEAD)"git push origin mainTag a release for users who pin versions:
git tag -a v0.1.0 -m "Initial public release"git push origin v0.1.05. First-time public-repo setup
Done once, then never again. Documented for completeness.
gh repo create anglinai/theaccessible-skill \ --public \ --description "Claude Skill: convert PDFs into WCAG 2.1 AA / PDF/UA-1 compliant deliverables. Uses theaccessible.org." \ --homepage "https://theaccessible.org" \ --license MITRepo settings:
- License: MIT (the bundle is just a thin wrapper around the public API).
- Topics:
claude,claude-code,claude-skill,accessibility,pdf,wcag,pdf-ua,anthropic. - Issues: enabled.
- Discussions: disabled (route to GitHub Issues).
- Branch protection on
main: required PR review for non-admin.
6. Build the .dxt and skill .zip artifacts
We host two installable artifacts at https://pdf.theaccessible.org/downloads/:
| Artifact | What it is | Target surface |
|---|---|---|
theaccessible-pdf-converter-<ver>.dxt | Desktop Extension wrapping our MCP server (api-pdf.theaccessible.org/api/mcp) via mcp-remote | Claude Desktop (one-click install) |
theaccessible-pdf-skill-<ver>.zip | Zip of skills/pdf-converter/ | Claude Code, Agent SDK |
The build script handles both:
# Install the dxt CLI oncenpm install -g @anthropic-ai/dxt
# Build both artifacts./apps/skills/pdf-converter/build.shThis:
- Validates
apps/skills/pdf-converter/dxt/manifest.json. - Runs
dxt packand writestheaccessible-pdf-converter-<ver>.dxtintoapps/web/public/downloads/. - Zips
skills/pdf-converter/(excluding the dev-only smoke tests) intotheaccessible-pdf-skill-<ver>.zipin the same directory.
Cloudflare Pages serves both with Content-Disposition: attachment (configured in apps/web/public/_headers) so users get a clean download flow.
Bump versions independently:
- DXT version β
apps/skills/pdf-converter/dxt/manifest.json - Skill version β reflects the GitHub repo tag (the zip has no embedded version)
Deploy by pushing to main and running the standard apps/web deploy pipeline.
7. Distribute
| Channel | Status | Action |
|---|---|---|
pdf.theaccessible.org/downloads/*.dxt | Day 1 | Built in step 6, deploys with apps/web |
pdf.theaccessible.org/downloads/*.zip | Day 1 | Built in step 6 |
| Public GitHub repo | Day 1 | Done in step 4 |
| Claude Agent SDK skill bundle | Day 1 | Same folder shape β point SDK consumers at the repo |
| claude.ai Skills upload | When GA | Upload the same .zip via the Skills UI |
| Anthropic DXT directory | When GA | Submit theaccessible-pdf-converter-<ver>.dxt once a directory exists |
Promote the repo from:
docs/MCP-AND-CUSTOM-GPT.mdβ add a βSkillsβ section linking to the public repo.apps/homeβToolsβ section on theaccessible.org β add a third card next to Custom GPT and MCP.- The dashboard βAPI keysβ page β surface the install snippet alongside the existing OpenAI / MCP instructions.
8. Versioning + updates
- The skill folder has no version field beyond the git tag β Claude loads the live filesystem copy.
- Bump the tag whenever
SKILL.mdor any script changes:- Patch (
v0.1.x): script bug fix or wording tweak in SKILL.md. - Minor (
v0.x.0): new script, new optional flag, or expanded workflow. Backwards-compatible. - Major (
v1.0.0+): breaking change to script CLI, env-var name, or required workflow steps. Requires user re-install.
- Patch (
- When the API surface changes (new endpoint, breaking schema change),
update
references/api.mdand the relevant script in the same PR that ships the API change. Otherwise the skill silently drifts.
9. Failure modes (post-launch)
| Symptom (user report) | Likely cause | Fix |
|---|---|---|
| βSkill says my key is missingβ | THEACCESSIBLE_API_KEY not exported in the shell Claude Code spawns scripts in | Add the export to ~/.zshrc and restart the terminal |
| βPolling exits with TIMEOUT but the job finishes laterβ | Backend queue backed up | Tell user to re-run poll_status.sh <fileId> β the job is still queued server-side |
| β401 on every callβ | Revoked key, or --header X-API-Key mis-typed | Issue a fresh key |
| Model bypasses scripts and hand-rolls curl | SKILL.md drift after editing | Restore from this repo; the workflow section MUST tell the model to call the scripts |
| Model loops on a failed conversion | Old poll_status.sh without status=failed short-circuit | Update to β₯ v0.1.0 |
10. Monitoring
- API-key dashboard: skill-driven traffic shows up alongside Custom GPT
/ MCP usage on the same key. Thereβs no per-surface attribution today
β if we want it, add a
User-Agent: theaccessible-skill/<ver>header in_lib.shand log it. [gpt-openapi]workers/api logs show every call β filter byuserIdto debug specific user reports.
When to update this doc
- New script added or removed: update steps 1, 2, 3, and the bundle inventory in the README.
- API contract changes: update step 7 and
skills/pdf-converter/references/api.md. - Anthropic ships a registry / claude.ai Skills GA: update step 6.