feat(codex): create and customize Codex config from /settings
Adds the Codex config panel (skills/agents/rules/memory/config editing, mcp/plugins/marketplaces add-remove via the codex CLI) as the last piece of parity with the Claude Code settings tab, plus the codex_config_changed WebSocket type the client was missing, and docs for the new /api/codex-config surface.
This commit is contained in:
+31
@@ -1619,6 +1619,37 @@ The dashboard **cannot log an account in** — only `claude auth login` mints to
|
||||
|
||||
Backup paths look like `<root>/cc-config-backups/<type>/<base>.<ISO>.bak[.dir]` — outside the directories Claude Code scans, so a deleted skill cannot resurface as a backup-named one. The Backups modal in the UI auto-builds `mv` restore commands.
|
||||
|
||||
### Codex Config Explorer
|
||||
|
||||
The `/api/codex-config/*` namespace powers the **Codex** tab of Settings (`/settings?tool=codex`) — the Codex CLI counterpart of the Claude Config Explorer above. Codex has a narrower scope union than Claude Code: `"user"` or `"project"` only, no `"project-local"` and no per-project file-based memory. Reads for skills/agents/rules/memory/config are pure file reads (`server/lib/codex-discovery.js`); MCP servers, plugins, and marketplaces have no on-disk reader and are read *and* mutated entirely through the `codex` CLI (`server/lib/codex-cli.js`), because the CLI owns `config.toml`'s schema.
|
||||
|
||||
```http
|
||||
GET /api/codex-config/overview
|
||||
GET /api/codex-config/skills?scope=user|project|all
|
||||
GET /api/codex-config/agents?scope=user|project|all
|
||||
GET /api/codex-config/rules?scope=user|project|all
|
||||
GET /api/codex-config/memory
|
||||
GET /api/codex-config/config
|
||||
GET /api/codex-config/file?path=<absolute-path>
|
||||
PUT /api/codex-config/file Body: { scope, type, name?, content }
|
||||
DELETE /api/codex-config/file Body: { scope, type, name? }
|
||||
GET /api/codex-config/backups[?scope=&type=]
|
||||
GET /api/codex-config/mcp
|
||||
GET /api/codex-config/plugins
|
||||
GET /api/codex-config/marketplaces
|
||||
POST /api/codex-config/mcp/add Body: { name, url, bearerTokenEnvVar? } | { name, command, args?, env? }
|
||||
POST /api/codex-config/mcp/remove Body: { name }
|
||||
POST /api/codex-config/plugins/action Body: { spec, action: add|remove }
|
||||
POST /api/codex-config/marketplaces/add Body: { url }
|
||||
POST /api/codex-config/marketplaces/action Body: { name, action: remove }
|
||||
```
|
||||
|
||||
`type` is one of `skills`, `agents`, `rules`, `memory`, `config`. `name` is required for `skills`/`agents`/`rules` and forbidden for `memory`/`config` (each is a single fixed file per scope — `AGENTS.md` and `config.toml` respectively). `PUT`/`DELETE` always back the previous content up first (`server/lib/codex-mutate.js`) and always resolve `project` scope against the **dashboard server's own cwd** — unlike the read routes, there is no `?cwd=` override on a write, for the same reason `cc-config.js`'s `PATCH /settings` refuses one. Mutation errors: `EBADTYPE`/`EBADSCOPE`/`EBADNAME`/`EBADCONTENT`/`EOUTOFROOT` (400), `ETOOLARGE` (413), `ENOTFOUND` (404). Every successful write/delete broadcasts `codex_config_changed`.
|
||||
|
||||
`GET /mcp`, `/plugins`, `/marketplaces` proxy `codex mcp list --json` / `codex plugin list --json` / `codex marketplace list --json`; a fresh install with none of a kind returns `{ mcp: [] }` etc. rather than a parse error, and the client further coerces a non-array response to `[]` defensively. The add/remove routes shell out to `codex …` with an explicit argv array (never a shell string); a non-zero CLI exit is reported as **422 `ECLIEXIT`** with `stdout`/`stderr` preserved, never a 500. `POST /mcp/add` takes either `{ name, url, bearerTokenEnvVar? }` (HTTP transport) or `{ name, command, args?, env? }` (stdio transport) — never both, mirroring `codex mcp add`'s own mutually-exclusive flags. Other CLI errors: `EBADARG` (400), `ECLINOTFOUND` (503 — the `codex` binary isn't on `PATH`), `ETIMEOUT` (504).
|
||||
|
||||
Because `CodexMcpServer`/`CodexPlugin`/`CodexMarketplace` are opaque JSON blobs from the CLI (`[key: string]: unknown`) rather than a shape the dashboard controls, the Codex tab renders them as generic key/value cards instead of the richly-typed plugin/MCP cards the Claude Code tab shows.
|
||||
|
||||
### Run Claude via tmux+PTY
|
||||
|
||||
The `/api/run/*` namespace starts and manages `claude` subprocesses in tmux-backed pseudoterminals, one session per lane. The Workspace page renders an interactive xterm.js terminal attached to the session over `/ws-pty/:runId` (binary PTY frames, not JSON). Every route enforces a same-origin / loopback-Origin guard; browser requests must come from `localhost`, `127.0.0.1`, `::1`, or `0.0.0.0`. CLI / curl requests with no `Origin` header pass through. When `DASHBOARD_TOKEN` is set, a valid token is also required here (like the rest of `/api/*` — see [Authentication](#authentication)). **`tmux` must be installed on the dashboard server** (same operational requirement as better-sqlite3's native module).
|
||||
|
||||
Reference in New Issue
Block a user