docs/cli-provider-settings-descriptor.md

CLI provider settings descriptor

Status: Proposed, not shipped. The last full contract verification used the checksum-verified official Linux CLI 0.56.2 on 2026-09-01. It rejects config providers --descriptors and has no generic config set or config action. See the pinned audit. The scoped 0.57.0 probes confirm descriptor absence and the unchanged generic-command gap. Track settings delivery and onboarding actions in TODO. All command examples and payloads below describe the proposed contract.

This document defines the CLI contract Plasma needs before it can render real provider settings or onboarding flows without duplicating macOS Swift logic in QML.

The Plasma widget consumes this contract when the upstream codexbar CLI exposes it. If a descriptor is absent or unsupported, Plasma keeps enable/disable, supported single-key setup, docs/dashboard/login links, redacted diagnostics, and CLI command hints available.

Command

sh
1codexbar config providers --descriptors --format json --json-only

The command returns the normal provider list plus a provider-specific descriptor. The descriptor is declarative: it names fields and actions, but the CLI remains the only component that knows how to read, validate, write, import, or redact provider settings.

Descriptor writes use local CLI commands such as codexbar config set --provider amp --field sourceMode --value api --json-only. Descriptor actions use local CLI commands such as codexbar config action --provider openai --action openDashboard --json-only.

Top-level shape

json
1[
2 {
3 "provider": "openrouter",
4 "displayName": "OpenRouter",
5 "enabled": true,
6 "descriptor": {
7 "schemaVersion": 1,
8 "fields": [],
9 "actions": []
10 }
11 }
12]

schemaVersion must be incremented for incompatible changes. Plasma should ignore descriptors with an unknown major schema and keep showing CLI command hints.

Fields

Fields are settings the frontend can display or edit. Field order is display order.

json
1{
2 "id": "apiKey",
3 "kind": "secret",
4 "title": "API key",
5 "description": "Stored by codexbar. Paste your OpenRouter API key.",
6 "redactedValue": "sk-...abcd",
7 "required": true,
8 "writeCommand": [
9 "codexbar",
10 "config",
11 "set",
12 "--provider",
13 "openrouter",
14 "--field",
15 "apiKey",
16 "--stdin",
17 "--format",
18 "json",
19 "--json-only"
20 ]
21}

Supported field kinds:

  • "kind": "text": short non-secret string, such as a base URL or workspace id.
  • "kind": "secret": secret input, always written through stdin.
  • "kind": "enum": one of a stable option list.
  • "kind": "boolean": checkbox/toggle.
  • "kind": "number": bounded numeric setting.

Command-like behavior belongs in the descriptor's actions array, not in fields; every field is editable and must provide an allowed writeCommand.

Enum fields include options:

json
1{
2 "id": "sourceMode",
3 "kind": "enum",
4 "title": "Source",
5 "value": "auto",
6 "options": [
7 { "id": "auto", "title": "Automatic" },
8 { "id": "api", "title": "API key" },
9 { "id": "web", "title": "Browser cookies" }
10 ],
11 "writeCommand": [
12 "codexbar",
13 "config",
14 "set",
15 "--provider",
16 "amp",
17 "--field",
18 "sourceMode",
19 "--value",
20 "{value}",
21 "--format",
22 "json",
23 "--json-only"
24 ]
25}

The CLI must validate {value}. Plasma must not infer valid enum values from provider names or config files.

Field, action, and option IDs are machine identifiers. They must match [A-Za-z0-9][A-Za-z0-9._-]* and be no longer than 128 characters. Consumers reject invalid IDs instead of trimming, truncating, or otherwise rewriting them.

Actions

Actions are provider setup flows the CLI knows how to perform.

json
1{
2 "id": "refreshCookies",
3 "kind": "command",
4 "title": "Refresh browser cookies",
5 "description": "Import browser cookies for the selected provider.",
6 "command": [
7 "codexbar",
8 "config",
9 "action",
10 "--provider",
11 "codex",
12 "--action",
13 "refreshCookies",
14 "--format",
15 "json",
16 "--json-only"
17 ]
18}

Useful action categories:

  • browser-cookie import
  • manual cookie save
  • API key save or clear
  • OAuth/device-flow handoff
  • local app/session probe
  • token-account add/edit/remove
  • provider diagnostics refresh
  • open docs/dashboard/login URL

Actions must report structured JSON with status, optional message, and optional refreshed descriptor. status is ok after a completed action, error after a failed action, or cancelled when the user abandons an interactive flow. A failed action may still exit with code zero, so consumers must inspect the structured status before reporting success.

URL-opening actions should still be local CLI actions. For example, codexbar config action --provider openai --action openDashboard --json-only can return { "status": "ok", "url": "https://..." }; Plasma opens the URL only after the CLI reports it.

Redaction and safety

Do not expose raw secrets.

Rules for the CLI:

  • Secret fields must return only redactedValue, never raw values.
  • Writes for secrets must use stdin, not command-line arguments.
  • Descriptors must not include browser cookie values, bearer tokens, API keys, account IDs that are not already user-visible, or raw diagnostic responses.
  • Error messages should be bounded and safe to store in user config.
  • Commands must be local codexbar commands, not remote shell snippets.

Rules for Plasma:

  • Treat descriptor JSON as a contract, not as raw config.
  • Render only supported field kinds.
  • Use writeCommand and action command exactly as arrays of argv-like tokens; quote each token when using Plasma's executable data source.
  • Reject descriptor commands unless they start with codexbar config and use an allowed local subcommand: set/set-api-key for fields, action for actions.
  • Open descriptor-returned URLs only when they are HTTPS URLs.
  • Keep secret fields write-only except for redactedValue.
  • Fall back to current CLI command hints when a descriptor is missing, unsupported, or invalid.
  • Bound rendering work even for malformed descriptors. Plasma inspects at most 32 fields and 32 actions per provider, 64 options per field, and 64 command tokens of at most 2048 characters each. Fields with text values longer than 2048 characters are ignored instead of binding or rewriting the value.

Plasma renderer rules

The first Plasma implementation should be deliberately small:

  • Render fields in the Providers page below the redacted diagnostics summary.
  • Use native controls: text field, password field, checkbox, combo box, spin box, and buttons.
  • Disable controls while their command is in flight.
  • After a successful write/action, reload codexbar config providers --descriptors --format json --json-only.
  • Keep existing provider enable/disable behavior separate from descriptor fields.
  • Do not add provider-specific QML branches for individual settings.

Example descriptor

json
1{
2 "provider": "amp",
3 "displayName": "Amp",
4 "enabled": true,
5 "descriptor": {
6 "schemaVersion": 1,
7 "fields": [
8 {
9 "id": "sourceMode",
10 "kind": "enum",
11 "title": "Source",
12 "value": "auto",
13 "options": [
14 { "id": "auto", "title": "Automatic" },
15 { "id": "api", "title": "API key" },
16 { "id": "web", "title": "Browser cookies" }
17 ],
18 "writeCommand": [
19 "codexbar",
20 "config",
21 "set",
22 "--provider",
23 "amp",
24 "--field",
25 "sourceMode",
26 "--value",
27 "{value}",
28 "--format",
29 "json",
30 "--json-only"
31 ]
32 },
33 {
34 "id": "apiKey",
35 "kind": "secret",
36 "title": "API key",
37 "redactedValue": "amp_...7890",
38 "writeCommand": [
39 "codexbar",
40 "config",
41 "set",
42 "--provider",
43 "amp",
44 "--field",
45 "apiKey",
46 "--stdin",
47 "--format",
48 "json",
49 "--json-only"
50 ]
51 }
52 ],
53 "actions": [
54 {
55 "id": "refreshCookies",
56 "kind": "command",
57 "title": "Refresh browser cookies",
58 "command": [
59 "codexbar",
60 "config",
61 "action",
62 "--provider",
63 "amp",
64 "--action",
65 "refreshCookies",
66 "--format",
67 "json",
68 "--json-only"
69 ]
70 }
71 ]
72 }
73}