cmux-config: the settings schema as a JSON Schema for editors and agents
Summary
Editors and agents have no machine-readable description of ~/.config/cmux/cmux-next.json. The daemon validates against schemas/settings/settings-schema.json, but that's cmux's own row format, not something VS Code, Zed, Neovim or an agent's JSON tooling can use.
Schema::json_schema() in cmux-config now builds a JSON Schema (draft 2020-12) from the same embedded rows the settings owner validates with:
- each key becomes a nested property with its title, help text and default;
- choices become an
enum(withenumDescriptions), and numbers get their min and max; - colors, time ranges, folder lists and string maps get their exact shapes;
- every leaf carries
x-cmux-key,x-cmux-sectionandx-cmux-agent-settable, so an agent can tell which keys it may set without a confirm sheet.
Keys outside the schema (actions, MCP, shortcuts) stay allowed. Theme, font and sound names are plain strings, because the app checks them against what's installed on the Mac.
The file is not checked in. settings-schema.json is regenerated by the Swift export and the base-autofix bot in almost every settings PR, so a committed copy with a freshness test would break those PRs. The CLI PR stacked on this one adds cmux settings schema, which prints the document for the installed build.
It also fixes two places where the settings owner disagreed with Swift. Both surfaced when the JSON Schema was held to the export's samples:
appearance.backgroundrefusedfile:/<absolute path>. Swift and the web Settings page accept it, because it's the person's own image.browser.toolbarButtonstook any string. It's a SwiftchoiceSet, exported as astring_listwith choices andordered: false, and its items are now checked against the choices.
A new owner conformance test runs every exported accepts and refuses sample through accepts(), so the next drift fails CI. It was committed red first (88a81980bb1), with the fix in 90f434fccc5.
Settings schema: no rows change. This reads the schema and aligns the owner's validation of two rows with Swift.
Part of the dotfiles work (#10081, #3806, #21017): this PR adds the schema, the next one adds the CLI verbs, and a docs page follows.
Testing
cargo test -p cmux-config ran 5 tests on Linux, all passing. They check that:
- the document is a valid 2020-12 schema;
- every
acceptssample and default in the settings export passes it; - every
refusessample for a portable kind fails it; - a realistic file with non-schema keys passes;
- the owner's own
accepts()agrees with every exported sample. This test failed on 88a81980bb1 (the two rows above) and passes on 90f434fccc5.
The refused-sample test caught two shapes the Rust kinds drop: the Swift choiceSet of browser.toolbarButtons, and file: backgrounds. The generator now reads those from the exported row.
A review subagent ran on the stack. Its findings for this PR are fixed here: the owner drift above, and a time-range pattern that was stricter than the owner (111b61fb241).
Hosted runs:
verify-cmux-tui-hosted.sh --filter json_schemapassed on 43a87be1cbf, on Linux and macOS.- A focused hosted run on the head, 111b61fb241, is queued.
Changelog
none
Proof
No UI. It's a library function; the user-facing verb is in the next PR.
Checklist
- Behavior changes have added or updated tests
- Schema change: no user-facing strings added (the English titles and help come from the export)
🤖 Generated with Claude Code