cmux-config: the settings schema as a JSON Schema for editors and agents

Merged
TE
18d ago
+258-5

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 (with enumDescriptions), 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-section and x-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.background refused file:/<absolute path>. Swift and the web Settings page accept it, because it's the person's own image.
  • browser.toolbarButtons took any string. It's a Swift choiceSet, exported as a string_list with choices and ordered: 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 accepts sample and default in the settings export passes it;
  • every refuses sample 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_schema passed 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