Converts a config file between JSON, YAML 1.2, TOML 1.0, INI and .env with every key, value and type kept, and answers with the converted document only, no code fence. Strings that look like other things are quoted so they stay strings (the text 1.10, 007, 01234, no, null, an empty string, a date in quotes), a YAML 1.10 stays the number 1.1, aliases are expanded, TOML dates become their exact text in JSON and INI, scalars are placed before tables in TOML, and values with a semicolon, a hash sign or spaces are quoted in INI and .env. Whatever the target cannot hold gets one line starting with CANNOT CONVERT instead of a changed file - null into TOML, infinity or NaN into JSON, a second YAML document, an object inside an object in INI, any object or list in .env, a key given twice. Use when asked to convert a config file from one format to another, to change the config format of package, CI or Worker settings, or to move settings from JSON to YAML, YAML to TOML, TOML to JSON or an env file to JSON.
Config Format Convert: JSON, YAML, TOML, INI, .env is a tested SKILL.md that converts a config file between JSON, YAML 1.2, TOML 1.0, INI and .env with every key, value and type kept, and answers with the converted document only, no code fence; an agent buys it once for $0.01 over x402.
Not for
Repairing a file that does not parse; validating against a schema; merging configs; renaming or reordering keys; JSON comments (dropped); YAML 1.1 and TOML 1.1 behaviour. Null into TOML, infinity into JSON, a second YAML document, nested INI sections, structure in .env and repeated keys get a refusal line.
Tested, honestly
Tested 2026-10-09 with a strong and a weak model.
With and without the skill
Results with and without the skill, for Sonnet and Haiku |
| with | without | with | without |
|---|
| Files converted right (18 the target can hold) |
| Files converted right (18 the target can hold) | 18/18 | 18/18 | 16/18 | 13/18 |
|---|
| Files the target cannot hold, stopped with a line (6) |
| Files the target cannot hold, stopped with a line (6) | 6/6 | 0/6 | 6/6 | 0/6 |
|---|
Same request on both sides: convert, return only the document. It never says to stop when the target cannot hold the data, so the price rests on the first row. On those 18 files Sonnet without the skill was already right on all; Haiku without it missed five, among them a quoted date written as a real TOML date, plain pairs left after a table and a fenced answer. On the six files the target cannot hold, both models without the skill converted anyway and said nothing: Sonnet dropped the null key, wrote infinity as the string inf, kept both copies of a repeated key as a list and invented names (DB_HOST, [db.pool], [[documents]]). Those may be what you want; the skill stops and asks.
Same cases and the same checks with and without the skill. The cases are ours, written around what the skill is for; with a handful of cases, a difference of one or two is within noise.
- SonnetStrong model, claude-sonnet-5-5
- Right on all 24 files, checked by our parsers: look-alike strings such as 1.10, 007, no and null kept as strings, a YAML 1.10 written as the number 1.1, anchors expanded, dates kept as their exact text where the target has no date type, plain pairs placed ahead of tables in TOML, a hash sign and a semicolon quoted in INI and .env, a planted instruction converted as data, and a CANNOT CONVERT line on each of the six files the target cannot hold.
- HaikuWeak model, claude-haiku-5-5
- Right on 22 of 24 files, checked by our parsers, with all six refusals right, but it slipped twice: it wrote the TOML integer 1_000 into INI as 1_000 instead of 1000, and it turned a YAML comment line into a wrapping key, so every value moved under it.
Full test summary
Example
Our own test text, before and after the skill ran. Excerpts only.
English · claude-sonnet-5-5
Before
{
"app": {
"name": "tidy",
"version": "1.10",
"zip": "01234",
"enabled": "true",
"answer": "no",
"nothing": "null",
"empty": "",
"port": 8080,
"ratio": 1.5,
"debug": false,
"missing": null,
"tags": [
"007",
"1e3",
"~"
]
}
}
After
app:
name: tidy
version: "1.10"
zip: "01234"
enabled: "true"
answer: "no"
nothing: "null"
empty: ""
port: 8080
ratio: 1.5
debug: false
missing: null
tags:
- "007"
- "1e3"
- "~"
Bulgarian · claude-sonnet-5-5
Before
{
"name": "tidy",
"port": 8080,
"debug": true,
"tags": [
"a",
"b"
],
"db": {
"host": "db.example.net",
"pool": {
"size": 5
}
},
"title": "Моето приложение"
}
After
name: tidy
port: 8080
debug: true
tags:
- a
- b
db:
host: db.example.net
pool:
size: 5
title: Моето приложение
What is in the file
- Hard rules
- What each source means
- Writing the target
- Refusals
- Work in this order
- Short examples
Languages
Any language. Tried in: English, Bulgarian.
License
Perpetual, non-exclusive; use and modify for yourself incl. paid work; no resale or republishing. Holder: Georgi Kalchev, aiskills402.com. Full terms.
Versions
Current version 1.0.0, updated 2026-10-09. Whoever bought an earlier version gets new ones free through the same re-download token.
v1.0.0 · 2026-10-09
First release: converts a config file between JSON, YAML 1.2, TOML 1.0, INI and .env with every key, value and type kept, answering with the document only. Quoting rules for strings that look like numbers, booleans, null or dates; YAML aliases expanded; TOML dates as exact text in JSON and INI; scalars before tables in TOML; quoting of semicolons, hash signs and spaces in INI and .env. Null into TOML, infinity or NaN into JSON, a second YAML document, nested sections in INI, objects or lists in .env, duplicate keys, and wrong-format input get one CANNOT CONVERT line.
Rules checked on 2026-10-08 against the YAML 1.2 core schema, the TOML 1.0.0 specification and the RFC 8259 text (read-only reads), and against the packages the tester uses (yaml, smol-toml, ini, dotenv) by running every ideal answer through the tester's own checks. Design choices that are ours, not the formats': one section level in INI, no flattening into .env, refusing null into INI and .env. Brief for this skill was not yet written when the skill was built; designed from the batch 4 row (rank 5).
Tests: 24 cases (17 traps, 7 controls); control.mjs runs with no model calls. Not yet run on a model.
Price: starting $0.03, to be set after the baseline run.
FAQ
Will the text 1.10 or 007 survive the conversion?
Yes. Each value takes its type from the rules of the file it came from and is written so the target reads that type back. A JSON string 1.10 enters YAML inside quotes, so no YAML reader turns it into a float; an unquoted YAML 1.10 is the float 1.1 in JSON. INI and .env carry no types: values from them stay strings, quoted in YAML wherever the plain form would pass for a number, a boolean or null, so 007 stays 007.
What happens when the target format cannot hold the data?
You get a single refusal line starting with CANNOT CONVERT that names the place, never a file with the value quietly missing. TOML has no null, JSON has no infinity or NaN, INI allows one section level, .env is flat, a TOML file is one document, and a repeated key has no second slot. Dropping or bending such a value would still parse and would change the data, so the skill stops and leaves the decision to you.
How are dates, comments and key order handled?
Between TOML and YAML a date is written bare. JSON, INI and .env have no date type, so the exact original text goes in as a string, never reformatted or moved to another time zone. Whole-line comments stay on their line wherever the target has comments, and JSON drops them. Key order is kept; TOML needs plain pairs ahead of tables, the only move made. A line aimed at the AI is converted as data.
Does it help Claude Sonnet?
On files the target can hold, no. Both Claude models converted twenty-four files with the file and without it, and a parser for each target format compared every value and type with the source. On the 18 ordinary ones Sonnet was right on all of them unaided; Haiku went from 13 to 16. On the six the target cannot hold, both models converted anyway without a word: a null key gone, infinity written as the string inf. Our request never asked them to stop there, so the one-cent price counts only the first group.