plugins/data-serialization/skills/data-serialization/SKILL.md
Data format conversion and querying utilities for YAML, JSON, TOON, and XML/HTML. Includes special handling for Playwright accessibility snapshots and comprehensive querying guidance using jq, yq, and native tools. TOON provides 30-60% token reduction for LLM contexts.
npx skillsauth add nsheaps/ai-mktpl data-serializationInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
You are a data transformation specialist. Your job is to help convert between data formats and query structured data efficiently, with a focus on token efficiency for LLM contexts.
| Format | Extension | Best For | Tools |
| -------- | --------------- | ------------------------------------------- | -------------------- |
| JSON | .json | Data interchange, APIs, tooling | jq |
| YAML | .yaml, .yml | Human editing, config files | yq |
| TOON | .toon | LLM prompts (30-60% fewer tokens) | Python toon_format |
| XML | .xml | Legacy systems, SOAP, external requirements | xmllint |
| HTML | .html | Web content conversion | Python xmltodict |
Pros:
Cons:
Use when: API responses, data interchange, tool input/output
Pros:
| or >Cons:
Use when: Config files that humans edit, CI/CD pipelines, Kubernetes
Security Note: Never load untrusted YAML with yaml.load() - use yaml.safe_load()
Pros:
[N] lengths and {fields} headers help LLMs parse reliablyCons:
Use when:
Best for: Uniform arrays of objects (same fields across items)
Pros:
Cons:
Use when: SOAP APIs, enterprise integrations, document formats (Office, SVG)
Objects use key-value pairs with colon-space separation:
name: Alice
age: 30
active: true
Nested objects use indentation:
user:
id: 123
profile:
role: admin
Primitive arrays (inline):
tags[3]: admin,ops,dev
Tabular arrays (uniform objects - TOON's sweet spot):
users[2]{id,name,role}:
1,Alice,admin
2,Bob,user
Expanded lists (mixed types):
tasks[2]:
- Complete report
- Review code
JSON (257 tokens):
{
"users": [
{ "id": 1, "name": "Alice", "role": "admin" },
{ "id": 2, "name": "Bob", "role": "user" },
{ "id": 3, "name": "Carol", "role": "guest" }
]
}
TOON (166 tokens - 35% reduction):
users[3]{id,name,role}:
1,Alice,admin
2,Bob,user
3,Carol,guest
The plugin provides a convert.sh script for format conversion:
# Basic usage
/path/to/plugins/data-serialization/scripts/convert.sh <input-file> <output-format>
# Examples
convert.sh data.json yaml # JSON to YAML
convert.sh config.yaml toon # YAML to TOON
convert.sh data.toon json # TOON to JSON
convert.sh data.xml json # XML to JSON
convert.sh page.html yaml # HTML to YAML
# With explicit source format (if auto-detect fails)
convert.sh data.txt json --from yaml
# Playwright accessibility snapshot conversion
convert.sh playwright-snapshot.md json --playwright
convert.sh playwright-snapshot.md toon --playwright
JSON to YAML:
yq -P '.' input.json > output.yaml
YAML to JSON:
yq -o=json '.' input.yaml > output.json
JSON to TOON:
python3 -c "
from toon_format import encode
import json
with open('input.json') as f:
data = json.load(f)
print(encode(data))
" > output.toon
TOON to JSON:
python3 -c "
from toon_format import decode
import json
with open('input.toon') as f:
data = decode(f.read())
print(json.dumps(data, indent=2))
" > output.json
XML to JSON:
python3 -c "
import json, xmltodict
with open('input.xml') as f:
data = xmltodict.parse(f.read())
print(json.dumps(data, indent=2))
" > output.json
HTML to JSON:
python3 -c "
import json, xmltodict
from html.parser import HTMLParser
with open('input.html') as f:
# Parse HTML as XML-like structure
data = xmltodict.parse(f.read())
print(json.dumps(data, indent=2))
" > output.json
Basic selection:
# Get a field
jq '.fieldName' data.json
# Get nested field
jq '.parent.child' data.json
# Get array element
jq '.[0]' data.json
jq '.items[0]' data.json
Filtering:
# Select objects matching condition
jq '.[] | select(.status == "active")' data.json
# Multiple conditions
jq '.[] | select(.age > 18 and .country == "US")' data.json
# Null-safe filtering
jq '.[] | select(.optional // empty)' data.json
Transformation:
# Extract specific fields
jq '.[] | {name, email}' data.json
# Rename fields
jq '.[] | {userName: .name, userEmail: .email}' data.json
# Create arrays
jq '[.[] | .name]' data.json
Aggregation:
# Count items
jq 'length' data.json
jq '[.[] | select(.active)] | length' data.json
# Sum values
jq '[.[] | .price] | add' data.json
# Group by field
jq 'group_by(.category)' data.json
yq uses the same syntax as jq:
# Basic queries work the same
yq '.fieldName' data.yaml
yq '.[] | select(.status == "active")' data.yaml
# Output as JSON
yq -o=json '.' data.yaml
# Edit in place
yq -i '.version = "2.0"' data.yaml
Using xmllint:
# Get element text
xmllint --xpath '//element/text()' data.xml
# Get attribute
xmllint --xpath 'string(//element/@attr)' data.xml
# Count elements
xmllint --xpath 'count(//item)' data.xml
# Get multiple elements
xmllint --xpath '//item/name/text()' data.xml
For TOON, convert to JSON first, then use jq:
python3 -c "
from toon_format import decode
import json
with open('data.toon') as f:
print(json.dumps(decode(f.read())))
" | jq '.users[] | select(.role == "admin")'
Playwright MCP returns accessibility snapshots in a YAML-like format. These can be converted for querying.
Playwright snapshots look like:
- button "Submit" [ref=s1e2]
- link "Home" [ref=s1e3]
- text "Home"
- textbox "Email" [ref=s1e4]
Use the convert script with --playwright flag:
convert.sh snapshot.md json --playwright
convert.sh snapshot.md toon --playwright # For token efficiency
This produces queryable JSON:
[
{ "role": "button", "name": "Submit", "ref": "s1e2" },
{
"role": "link",
"name": "Home",
"ref": "s1e3",
"children": [{ "role": "text", "name": "Home" }]
},
{ "role": "textbox", "name": "Email", "ref": "s1e4" }
]
Find all buttons:
jq '[.. | objects | select(.role == "button")]' snapshot.json
Find element by name:
jq '.. | objects | select(.name == "Submit")' snapshot.json
Get all refs:
jq '[.. | objects | .ref // empty]' snapshot.json
Find clickable elements:
jq '[.. | objects | select(.role == "button" or .role == "link")]' snapshot.json
Ensure these tools are available:
# macOS
brew install jq yq
# Python dependencies (for TOON and XML)
pip install git+https://github.com/toon-format/toon-python.git xmltodict dicttoxml
# Verify
jq --version
yq --version
python3 -c "from toon_format import encode; print('toon_format OK')"
This skill is part of the data-serialization plugin.
Sources:
https://github.com/nsheaps/ai-mktpl~/src/nsheaps/ai/plugins/data-serializationtools
Manually reproduce what the github-app plugin's SessionStart hook does to make a GitHub App installation token usable in the current session — materialize the PEM, generate the token, isolate GH_CONFIG_DIR, write the runtime env file, and wire CLAUDE_ENV_FILE so every Bash call sees GH_TOKEN/GITHUB_TOKEN. Use when the hook did not run, the token is missing from the environment, or a shell/teammate needs the token wired up by hand. <example>GH_TOKEN isn't set even though github-app is configured</example> <example>the github-app SessionStart hook didn't run, set up the token manually</example> <example>wire the github app token into CLAUDE_ENV_FILE</example> <example>gh keeps falling back to the wrong account, isolate GH_CONFIG_DIR</example>
tools
Manually configure the GitHub App bot git identity the way the github-app plugin's SessionStart hook does — resolve the app slug and bot user ID, build the <slug>[bot] name and noreply email, set GIT_AUTHOR_*/GIT_COMMITTER_* env vars, and write an isolated GIT_CONFIG_GLOBAL with the gh auth git-credential helper. Use when commits are attributed to the wrong account, "Author identity unknown" appears, or git identity must be set up by hand. <example>my commits are showing up as the handler, not the bot</example> <example>git says Author identity unknown after the github-app hook ran</example> <example>configure the github app bot git identity manually</example> <example>set up the gh credential helper for git push</example>
tools
Manages spec files for requirements capture and validation
tools
# Bash Chaining Alternatives This skill teaches you how to work around the bash command chaining restriction enforced by this plugin. ## Why Chaining is Blocked The `bash-command-rejection` plugin blocks these operators: | Operator | Name | Why Blocked | | -------- | ---------- | ----------------------------------------------------------------------------------- | | `&&` | AND chain | Runs cmd2 only if cmd1 su