cdx-manager 0.20.14 → 0.21.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -1153
- package/VERSION +1 -1
- package/changelogs/CHANGELOGS_0_21_0.md +17 -0
- package/changelogs/CHANGELOGS_0_21_1.md +6 -0
- package/checksums/release-archives.json +22 -0
- package/docs/assets/icon.png +0 -0
- package/docs/assets/list.png +0 -0
- package/docs/assets/next.png +0 -0
- package/docs/assets/stats.png +0 -0
- package/docs/assets/status.png +0 -0
- package/docs/cli.md +411 -0
- package/docs/features.md +102 -0
- package/docs/getting-started.md +183 -0
- package/docs/operations.md +161 -0
- package/docs/sessions-and-notifications.md +138 -0
- package/docs/technical-overview.md +92 -0
- package/docs/tray-local-testing.md +154 -0
- package/package.json +2 -1
- package/pyproject.toml +1 -1
- package/src/cli.py +1 -1
- package/src/cli_args.py +1 -1
- package/src/commands/launch.py +44 -9
- package/src/commands/runs.py +38 -16
- package/src/commands/status.py +22 -35
- package/src/context_store.py +2 -1
- package/src/handoff.py +36 -20
- package/src/provider_background.py +6 -1
- package/src/provider_runtime.py +1 -1
- package/src/run_registry.py +7 -7
- package/src/run_usage.py +61 -30
- package/src/session_backup.py +8 -7
- package/src/update_check.py +7 -1
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.
|
|
1
|
+
0.21.1
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# CDX Manager 0.21.0
|
|
2
|
+
|
|
3
|
+
## Recovery and usage reliability
|
|
4
|
+
|
|
5
|
+
- Preserve imported sessions when an early credential failure triggers forced recovery, and serialize context and run-history appends across independent CLI processes.
|
|
6
|
+
- Attribute headless failover attempts and their usage to the actual session. Keep interactive usage totals at real launch boundaries; overlapping sessions with ambiguous attribution are marked uncertain instead of assigned invented totals.
|
|
7
|
+
- Use the recorded serving model for headless usage pricing. Handle model-specific cache rates and undefined relative weights consistently in stats.
|
|
8
|
+
- Bind handoff recovery to one exact native source file, improve native and terminal transcript discovery, and remove duplicate finalization paths.
|
|
9
|
+
- Add regression coverage for persistence, failover totals, usage boundaries, and handoff source selection.
|
|
10
|
+
|
|
11
|
+
## Documentation
|
|
12
|
+
|
|
13
|
+
- Turn the README into a short product overview and move detailed setup, feature, CLI, operation, and technical guidance into linked guides shipped with the npm package.
|
|
14
|
+
|
|
15
|
+
## Validation
|
|
16
|
+
|
|
17
|
+
- Python tests, project lint, Logics lint/audit, npm package inspection, and Python package build and metadata checks are part of release preparation. Publication and version-specific checksum verification remain separate release gates.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# CDX Manager 0.21.1
|
|
2
|
+
|
|
3
|
+
## Fixes
|
|
4
|
+
|
|
5
|
+
- Stop the macOS tray companion from leaking memory: each poll rebuilt the menu and status icon outside any autorelease pool, so nothing was ever freed and a week-old companion reached a footprint of about 19 GB.
|
|
6
|
+
- Cache a failed cdx-manager release check like a successful one and lower its network timeout from 5 s to 2 s, so a degraded network no longer stalls every `cdx` command on GitHub.
|
|
@@ -463,6 +463,28 @@
|
|
|
463
463
|
"x86_64-pc-windows-msvc": "9c55cab41d489afa77279de219dbc3ad861ad23d3ee50cee55d995033acb0c20",
|
|
464
464
|
"x86_64-unknown-linux-musl": "04794bc12fd5e367cb44af579aa70464f12680945dc92bbe6b0eda275a88141a"
|
|
465
465
|
}
|
|
466
|
+
},
|
|
467
|
+
"v0.20.14": {
|
|
468
|
+
"github_tarball_sha256": "c71b44618e713c245e2cf254f14107a020c0fc04f74c8fa7aee321bf214be9c9",
|
|
469
|
+
"github_zip_sha256": "ebedddf4928d8f6ee9a942e4ab7f03d659bbef9878aa05842bc0280eb8ac14ea",
|
|
470
|
+
"tray_assets": {
|
|
471
|
+
"aarch64-apple-darwin": "44625c2eba446ed4ad02e44ff7f003ffa662de3eea17079227a6055f939cf702",
|
|
472
|
+
"aarch64-unknown-linux-musl": "256389e8b0d9e4c6481a992681ab9fe7c3f037937a4d87bc3b850c136c64b2f4",
|
|
473
|
+
"x86_64-apple-darwin": "8455ba29ad3b08c9ac84516cc0a2f2332c8296586eed302b48cf5e3b30a98717",
|
|
474
|
+
"x86_64-pc-windows-msvc": "d1888eb3d8f34114e36e88821907fae776498b2b03c18158316db61033c94419",
|
|
475
|
+
"x86_64-unknown-linux-musl": "e369163b63bfb5301c985a02cc02755ea90996dc992a8c29c28d6b307b507447"
|
|
476
|
+
}
|
|
477
|
+
},
|
|
478
|
+
"v0.21.0": {
|
|
479
|
+
"github_tarball_sha256": "bee4a300e5de4b31535cebf245e33f73a59be6823dd1c449ebb61711ea7d644d",
|
|
480
|
+
"github_zip_sha256": "c1e8f49b513d5c4c92b298312b865ca3e966954b05b53936699784bf6446343c",
|
|
481
|
+
"tray_assets": {
|
|
482
|
+
"aarch64-apple-darwin": "4c87353837291f562baf0be20c6c1423369924ccda2b670bc328986771082424",
|
|
483
|
+
"aarch64-unknown-linux-musl": "9481632866b7b271483b964633948ec4c43ecbed090e688479afafcfac03bbba",
|
|
484
|
+
"x86_64-apple-darwin": "b0ca64da014846b0cc2eaa5918496b75ff3fc02bd000a9945a9ac7b8fb1f8771",
|
|
485
|
+
"x86_64-pc-windows-msvc": "20af5c24d62b673458c1ad7245df58d3cadb0be27116338fa39f66f896cd3d9f",
|
|
486
|
+
"x86_64-unknown-linux-musl": "4f7bc612c378a6e746a5bd737f89763ddaea0398182b49df28a9954e955fcd63"
|
|
487
|
+
}
|
|
466
488
|
}
|
|
467
489
|
}
|
|
468
490
|
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/docs/cli.md
ADDED
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
# Command reference
|
|
2
|
+
|
|
3
|
+
## All Commands
|
|
4
|
+
|
|
5
|
+
| Command | Description |
|
|
6
|
+
|---|---|
|
|
7
|
+
| `cdx` | List all sessions with last-updated timestamps |
|
|
8
|
+
| `cdx --json` | List all sessions as a machine-readable JSON payload |
|
|
9
|
+
| `cdx <name>` | Launch a session (checks auth first) |
|
|
10
|
+
| `cdx <name> [--json]` | Launch a session; `--json` returns a structured success payload after the interactive run ends |
|
|
11
|
+
| `cdx <name> -r` / `cdx <name> --resume` | Resume the provider-native conversation for a session when supported |
|
|
12
|
+
| `cdx add [provider] <name> [--model MODEL] [--json]` | Register a new session (`provider`: `codex`, `claude`, `antigravity`, or `ollama`; Ollama requires `--model`) |
|
|
13
|
+
| `cdx cp <source> <dest> [--json]` | Copy a session into another session name, overwriting the destination if it exists |
|
|
14
|
+
| `cdx ren <source> <dest> [--json]` | Rename a session and move its auth data |
|
|
15
|
+
| `cdx label <name> <label> [--json]` | Attach one short label to a session; tables show `LABEL` only when at least one label exists |
|
|
16
|
+
| `cdx label <name> --clear [--json]` | Clear a session label |
|
|
17
|
+
| `cdx login <name> [--json]` | Re-authenticate a session (logout + login) |
|
|
18
|
+
| `cdx logout <name> [--json]` | Log out of a session |
|
|
19
|
+
| `cdx auth refresh <name\|all> [--json]` | Make a locked, non-generation Codex auth probe; reports `login_required` when interactive login is needed |
|
|
20
|
+
| `cdx disable <name> [--json]` | Disable a session without deleting it; disabled sessions stay visible and cannot launch |
|
|
21
|
+
| `cdx enable <name> [--json]` | Re-enable a disabled session |
|
|
22
|
+
| `cdx config <name> [--json]` | Show persistent launch settings for a session |
|
|
23
|
+
| `cdx configs [--json]` | Show persistent launch settings for all sessions in one table |
|
|
24
|
+
| `cdx power\|perm\|fast\|model <name\|all\|provider:PROVIDER\|a,b> <value\|default> [--json]` | Shortcut commands for setting or clearing one launch setting |
|
|
25
|
+
| `cdx set <name>\|--sessions all\|a,b\|--provider PROVIDER [--power minimal\|low\|medium\|high\|xhigh] [--permission review\|default\|auto\|full] [--fast on\|off] [--rtk on\|off] [--logics on\|off] [--model MODEL] [--fallback-model MODEL[,MODEL...]] [--budget USD] [--extra-args 'ARGS'] [--priority 0..100] [--json]` | Persist launch settings for one or more sessions |
|
|
26
|
+
| `cdx unset <name>\|--sessions all\|a,b\|--provider PROVIDER (--power\|--permission\|--fast\|--rtk\|--logics\|--model\|--fallback-model\|--budget\|--extra-args\|--priority\|--all) [--json]` | Remove persisted launch settings and fall back to provider defaults |
|
|
27
|
+
| `cdx history [name] [--limit N] [--summary] [--since 7d\|today\|DATE] [--from DATE] [--to DATE] [--json]` | Show recent launch history or aggregate total launch time per assistant, optionally filtered by period |
|
|
28
|
+
| `cdx last [--json]` | Launch the most recent existing session from launch history |
|
|
29
|
+
| `cdx resume <name> [--json]` | Resume the provider-native conversation for a session using the named command form |
|
|
30
|
+
| `cdx can-resume <name> [--json]` | Check whether a session supports native resume without launching the provider |
|
|
31
|
+
| `cdx context show\|path\|init\|edit\|clear\|set\|append [text...] [--json]` | Manage the shared Markdown context for the current workspace |
|
|
32
|
+
| `cdx memory [--global\|--project NAME_OR_PATH] [show\|view\|path\|init\|edit\|clear\|set\|append\|list] [text...] [--json]` | Manage explicit user-controlled memory for the current workspace, global scope, or a named/path project |
|
|
33
|
+
| `cdx handoff <name> [--json]` | Reuse the prepared entry for this target/workspace, or use explicitly labelled notes-only recovery if none exists; launch unless `--json` |
|
|
34
|
+
| `cdx handoff <source> <target> [--source-conversation ID\|--source-native-transcript PATH\|--source-transcript PATH] [--json]` | Prepare an identity-checked transcript entry and launch the target in the verified workspace unless `--json`; exact native selection resolves duplicate IDs, while explicit terminal selection is degraded recovery |
|
|
35
|
+
| `cdx rmv <name> [--force] [--json]` | Remove a session and its auth data (prompts for confirmation unless `--force`) |
|
|
36
|
+
| `cdx clean [name] [--yes] [--json]` | Clear launch transcript logs for one session or all sessions after confirmation |
|
|
37
|
+
| `cdx clean profiles (--tmp\|--old-logs DAYS) [--yes] [--json]` | Remove explicit profile cleanup candidates after confirmation: temporary marketplace/plugin staging caches or old `.log` files |
|
|
38
|
+
| `cdx disk [profiles] [--candidates] [--json]` | Measure `CDX_HOME`; `profiles` includes per-profile breakdown, and `--candidates` reports reclaimable temporary caches and old logs with evidence |
|
|
39
|
+
| `cdx reset <name> [--yes] [--json]` | Explicitly consume one available banked Codex rate-limit reset; confirmation is required unless `--yes` is supplied |
|
|
40
|
+
| `cdx export <file> [--include-auth] [--sessions a,b] [--passphrase-env VAR\|--passphrase-stdin] [--force] [--json]` | Export sessions to a portable bundle; `--include-auth` encrypts auth data with a passphrase |
|
|
41
|
+
| `cdx import <file> [--sessions a,b] [--passphrase-env VAR\|--passphrase-stdin] [--force\|--merge] [--allow-authless-force] [--json]` | Import sessions from a bundle into the current `CDX_HOME` |
|
|
42
|
+
| `cdx doctor [--severity OK|WARN|FAIL[,OK|WARN|FAIL...]] [--check-provider-flags] [--json]` | Inspect CLI dependencies, provider CLI versions/capability hints, CDX_HOME permissions, missing state, orphan profiles, and pending quarantines; optionally filter issue severities. `--check-provider-flags` additionally verifies that the CLI flags cdx maps for each permission are actually accepted by each provider's installed CLI |
|
|
43
|
+
| `cdx repair [--dry-run] [--force] [--json]` | Plan or apply safe repairs for missing state files, quarantines, and orphan profiles |
|
|
44
|
+
| `cdx view [--json] [--lan] [--lan-rw] [--focus <ref>] [--read] [--port <port>] [--host <host>] [--refresh-interval <s>] [--tls] [--tls-cert <path>] [--tls-key <path>] [--open] [--no-open]` | Open the Logics browser/focus viewer by delegating to `logics-manager view`; all viewer flags are forwarded; JSON mode reports diagnostics without launching it |
|
|
45
|
+
| `cdx update [--check] [--yes] [--json] [--version TAG]` | Update cdx-manager using the installer that matches how it was installed |
|
|
46
|
+
| `cdx update all [--yes] [--json]` | Check installed providers, RTK, and Ponytail across Codex profiles; show the plan and ask once before applying safe native/Homebrew updates and missing RTK/Ponytail setup |
|
|
47
|
+
| `cdx ready [--refresh] [--json]` | Schedule an OS notification for the next cooling-down assistant that becomes ready, then return immediately |
|
|
48
|
+
| `cdx notify` | Internal provider hook target for agent alerts; use `cdx set <name> --notify on` to enable it |
|
|
49
|
+
| `cdx next [--json] [--refresh]` | Select the best next assistant using the same priority logic as `cdx status` |
|
|
50
|
+
| `cdx select --provider PROVIDER [--min-reasoning-effort minimal\|low\|medium\|high\|xhigh] [--min-power minimal\|low\|medium\|high\|xhigh] [--require-ready] [--refresh] --json` | Select a suitable session for headless automation |
|
|
51
|
+
| `cdx run [session] --cwd PATH (--prompt-file PATH\|--prompt TEXT\|--prompt-file -) [--provider PROVIDER] [--model MODEL] [--reasoning-effort minimal\|low\|medium\|high\|xhigh] [--power minimal\|low\|medium\|high\|xhigh] [--permission MODE] [--timeout-seconds N] [--detach] [--failover] [--refresh] --json` | Run one headless task and return a stable JSON result; `--detach` returns the `run_id` at launch without waiting, `--failover` continues the task on the next account when this one hits its rate limit, `--prompt-file -` reads the prompt from stdin |
|
|
52
|
+
| `cdx run-report <run_id> --json` | Full report, transcript metadata, and final payload for a run |
|
|
53
|
+
| `cdx run-status <run_id> --json` | Status of one run by id |
|
|
54
|
+
| `cdx run-tail <run_id> [--lines N] --json` | Last lines of a run's own output, while it is still running or after it finished |
|
|
55
|
+
| `cdx runs [--limit N] [--since 7d\|today\|DATE] --json` | List recent runs; `--since` returns every run completed after the cursor and ignores `--limit` |
|
|
56
|
+
| `cdx schema --json` | Publish the enums, mutually-exclusive argument groups, and error codes programmatic callers should validate against |
|
|
57
|
+
| `cdx stats [name] [--since 7d\|today\|DATE] [--from DATE] [--to DATE] [--json]` | Aggregate launch counts, duration, and known token usage by session, for headless and interactive runs alike |
|
|
58
|
+
| `cdx status [--json] [--refresh\|--cached] [--timeout SECONDS]` | Show token usage table for all sessions; empty credits, block, and reset columns are omitted; `--cached` skips live provider probes and returns only stored status |
|
|
59
|
+
| `cdx status --small [--refresh\|--cached] [--timeout SECONDS]` / `cdx status -s [--refresh\|--cached] [--timeout SECONDS]` | Show compact token usage table without provider, blocking quota, credits, and updated columns |
|
|
60
|
+
| `cdx status <name> [--json] [--refresh\|--cached] [--timeout SECONDS]` | Show detailed usage breakdown for one session; `--cached` avoids live provider refreshes |
|
|
61
|
+
| `cdx tray status [--json] [--refresh]` | Emit the tray snapshot: one icon state, one line per enabled session, and how fresh each figure is. Reads stored status by default; `--refresh` is the only path that probes a provider |
|
|
62
|
+
| `cdx tray launch [--json]` | Start the installed tray companion, detached. Reports `tray_companion_not_installed` when nothing is recorded, or `tray_companion_missing` when the recorded companion is gone. `CDX_TRAY_BIN` points it at a locally built one |
|
|
63
|
+
| `cdx tray install [--json] [--yes] [--autostart\|--no-autostart] [--alerts\|--no-alerts]` | Download the companion for this OS and architecture, verify its published checksum before unpacking, record what was written, and start it. It asks whether to launch at login; provider-hook consent is requested separately at the first eligible interactive session launch. Refuses when no checksum is published for the asset |
|
|
64
|
+
| `cdx tray uninstall [--json]` | Remove exactly what `install` recorded, and nothing else |
|
|
65
|
+
| — | `cdx update` also moves an installed companion to the new release, and says so. A companion already running keeps executing the build it started with, so it reports that too rather than leaving you to wonder why the menu looks unchanged |
|
|
66
|
+
| `cdx tray autostart [on\|off\|status] [--json]` | Start the companion at login, or stop doing so. Off until asked, idempotent, and the state is read back from the platform rather than from what CDX last intended |
|
|
67
|
+
| `cdx tray events [--json]` | List agent alerts a running companion has not shown yet. The companion reads these instead of the spool file, so a Windows tray can collect events from CDX in WSL over the same interop it already uses |
|
|
68
|
+
| `cdx tray ack <id>... [--json]` | Mark events as shown, idempotently |
|
|
69
|
+
| `cdx tray heartbeat [--json]` | Record that a companion is alive. `cdx notify` publishes to the tray only while this is fresh, and delivers directly otherwise |
|
|
70
|
+
| `cdx tray terminal [status\|list\|set <app>\|clear] [--json]` | Choose which terminal a tray session row opens; the tray exposes the same candidates plus **System default**. `cdx tray terminal list` reports candidates and the stored choice, and `clear` returns to the platform default. The value is an application name, never a command. A named terminal that disappears is reported unavailable and never silently replaced by another terminal. |
|
|
71
|
+
| `cdx tray sort [status\|set <capacity\|reset\|recent>] [--json]` | Persist the tray session order: current capacity-first order, nearest reset first, or most recently launched first. This affects only the tray menu, never `cdx next` or automatic session selection. |
|
|
72
|
+
| `cdx tray plugin [status\|enable <name>\|disable <name>\|run <action>] [--json]` | Turn a tray integration on or off, and list what is enabled. Opt-in in both directions and reversible; nothing enables one implicitly. `logics` is the only one that exists, and `status` says once when it is installed but not enabled. `run` is what the tray calls back with a card's action id and is not meant to be typed |
|
|
73
|
+
| `cdx tray alerts [on\|off\|status] [--json]` | Silence agent alerts, or let them through again. These commands work with or without a running tray: with one, muted events remain in its menu; without one, delivery falls back directly to the desktop notification channel. In both cases `off` suppresses banners and `on` restores delivery for the next event, including hooks already running with an older launch environment. Distinct from provider-hook consent, which controls configuration writes |
|
|
74
|
+
| `cdx tray doctor [--json]` | Report companion, executable, version, running instance, autostart, and the two capabilities that fail silently — whether this desktop can draw a tray icon at all, and on Windows whether the Start Menu shortcut toasts depend on exists. Reads only; it never repairs |
|
|
75
|
+
| `cdx --help` | Show usage |
|
|
76
|
+
| `cdx --version` | Show version |
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
### Tray snapshot
|
|
81
|
+
|
|
82
|
+
`cdx tray status --json` is the contract an optional desktop tray companion reads. It adds nothing to the quota pipeline: it interprets the status CDX already stores.
|
|
83
|
+
|
|
84
|
+
- **Cached by default.** A tray polls, and a live provider probe serializes on the Codex auth lock, which the launcher holds for a whole interactive session. Polling it would be locked out at best and race a rotating OAuth refresh token at worst. Only `--refresh`, a deliberate user gesture, probes.
|
|
85
|
+
- **Freshness is a value, not an error.** Each session reports `fresh`, `stale`, `auth_locked`, or `unknown`. `auth_locked` means a session is running and its quota cannot be refreshed until it exits — pressing refresh will not help, and the snapshot says so instead of ageing silently.
|
|
86
|
+
- **The icon leaks nothing.** `icon` holds a state, a reason, and a count. Session names, providers, and figures live in `sessions`, which a companion shows only once the user opens the menu.
|
|
87
|
+
- **Versions drift on purpose.** The payload carries `schema.major`. A reader meeting a newer major keeps every field it understands and surfaces one update hint, so upgrading CDX never breaks an installed companion.
|
|
88
|
+
|
|
89
|
+
```json
|
|
90
|
+
{
|
|
91
|
+
"schema": { "name": "cdx.tray.snapshot", "major": 1, "minor": 0 },
|
|
92
|
+
"icon": { "state": "low", "reason": "fresh", "session_count": 2 },
|
|
93
|
+
"sessions": [
|
|
94
|
+
{ "name": "work", "provider": "codex", "available_pct": 18, "state": "low", "freshness": "fresh", "reset_at": "..." }
|
|
95
|
+
],
|
|
96
|
+
"refreshable": true,
|
|
97
|
+
"actions": ["refresh", "open_terminal"]
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Icon states are `ok` at 25% remaining and above, `low` below 25%, `critical` below 5%, and `unknown` when nothing was ever reported. The closed icon shows the most urgent session, and a session that never reported never outranks one with real news.
|
|
102
|
+
|
|
103
|
+
### Setup hints
|
|
104
|
+
|
|
105
|
+
`cdx` and `cdx status` may end with one dim line pointing at an optional surface you have not set up yet — the tray companion, or agent alerts. They exist because neither is discoverable from the output of the commands you already run.
|
|
106
|
+
|
|
107
|
+
They are deliberately hard to become noise. One hint per invocation at most, not again for six hours, and each one retires for good after three showings: if you saw it three times and did not act, that is an answer. A hint never appears in `--json`, never appears alongside an update notice, and is answered entirely from local state — nothing here probes a provider or the network. `CDX_NO_HINTS=1` turns them off outright.
|
|
108
|
+
|
|
109
|
+
### Tray companion: what vouches for it
|
|
110
|
+
|
|
111
|
+
The companion is a native binary distributed as a release asset, not part of the pip package. Its trust model is worth stating plainly rather than leaving you to assume the usual one.
|
|
112
|
+
|
|
113
|
+
- **Where the checksum comes from.** Releases older than the one you are running are vouched for by `checksums/release-archives.json`, committed to the repository before those assets existed. Your own release is a special case: its tray assets are built after the tag, so no package built at tag time can carry their checksums. For that one version CDX reads the ledger the release publishes beside the assets — the publisher's own assertion over the same channel, which catches a truncated download or a wrong-architecture asset but does not defend against someone who can rewrite the release itself.
|
|
114
|
+
- **The checksum is the vouching, not Apple or Microsoft.** The macOS bundle is signed with a *self-signed* certificate. That signature exists because Apple Silicon refuses to execute unsigned arm64 code at all — it is not a claim that Apple reviewed anything. What actually vouches for the asset is the SHA-256 published in `checksums/release-archives.json`, verified before a single byte is unpacked. An asset with no published checksum is refused rather than installed hopefully.
|
|
115
|
+
- **Tray integrations are cards, not plugins.** `cdx tray plugin enable logics` adds one section to the menu: a blocked/ready summary and at most two rows — the first blocked document, because it is what stops work, and the highest-priority task in progress, because it is what to do instead. Clicking a row opens the Logics viewer focused on it. Tray openings ask Logics for a free local port, so an existing viewer is never displaced.
|
|
116
|
+
|
|
117
|
+
- **Alert return path.** When an alert originated in iTerm2, the macOS tray row and native CDX notification focus that exact iTerm session. macOS may ask once for CDX to control iTerm; declining leaves the alert visible but does not focus a different window. Script Editor fallback banners and Windows/Linux notifications remain delivery-only.
|
|
118
|
+
|
|
119
|
+
There is deliberately no marketplace, no discovery, no installation from a URL, and no plugin auto-update. An adapter is a function in this repository, named in a registry CDX owns, so nothing unknown can run. Adapters produce data and never behaviour: a card is a summary, rows, and action ids from a fixed vocabulary, and the tray hands an id back to CDX rather than running anything itself. Adding a capability is a change to CDX, reviewed like any other.
|
|
120
|
+
|
|
121
|
+
A card is built from `logics-manager status --format json` and from nothing else, so nothing about your documents is read or stored. It is refreshed at most once a minute, or on demand from the menu — an integration never pays the tray's polling rate. If `logics-manager` is absent, slow, failing or in a directory that is not a Logics repository, the card is simply not there: an integration cannot degrade the session rows the tray exists to show.
|
|
122
|
+
|
|
123
|
+
- **Install through `cdx tray install`, and no download link is offered.** This is a security property, not a convenience. A file fetched by CDX carries no macOS quarantine attribute and no Windows Mark-of-the-Web, so nothing puts Gatekeeper or SmartScreen between you and a companion you asked for. The same file fetched through a browser would carry both. That is why no direct download URL is published: it would be a worse path wearing the same clothes.
|
|
124
|
+
- **Nothing is silently replaced.** An update downloads, verifies, and *proves the replacement starts* before the working companion is touched. A corrupt asset or one built for the wrong architecture costs an error message, not a tray you can no longer launch. An interrupted update is a named, recoverable state that `cdx tray doctor` reports.
|
|
125
|
+
- **Uninstall removes only what install recorded**, from a record CDX wrote itself. A damaged record reads as absent rather than being guessed at, because that record drives deletion.
|
|
126
|
+
- **Linux carries no C library.** The Linux asset is statically linked against musl, so there is no glibc version to match and no `gtk`, `libxdo`, or `appindicator` package to install. Tray support is resolved at runtime by looking for the `org.kde.StatusNotifierWatcher` D-Bus name — never by matching a distribution or desktop name. A session without it is told so, and nothing is registered to start at login.
|
|
127
|
+
- **Version drift between CDX and the companion is normal**, since pip upgrades one and `cdx tray install` the other. Whichever is older keeps serving every field it understands and shows one update hint.
|
|
128
|
+
- **About stays actionable.** The last tray action before Quit is `About (v<installed CDX version>)`; it opens the project’s GitHub page with the platform’s normal browser launcher.
|
|
129
|
+
|
|
130
|
+
## JSON Output
|
|
131
|
+
|
|
132
|
+
`cdx-manager` can be consumed by other apps through its CLI JSON contract.
|
|
133
|
+
|
|
134
|
+
Commands with machine-readable output:
|
|
135
|
+
|
|
136
|
+
- `cdx --json`
|
|
137
|
+
- `cdx status --json`
|
|
138
|
+
- `cdx status <name> --json`
|
|
139
|
+
- `cdx add ... --json`
|
|
140
|
+
- `cdx cp ... --json`
|
|
141
|
+
- `cdx ren ... --json`
|
|
142
|
+
- `cdx label ... --json`
|
|
143
|
+
- `cdx rmv ... --json`
|
|
144
|
+
- `cdx clean ... --json`
|
|
145
|
+
- `cdx disk ... --json`
|
|
146
|
+
- `cdx reset ... --json`
|
|
147
|
+
- `cdx export ... --json`
|
|
148
|
+
- `cdx import ... --json`
|
|
149
|
+
- `cdx login ... --json`
|
|
150
|
+
- `cdx logout ... --json`
|
|
151
|
+
- `cdx disable ... --json`
|
|
152
|
+
- `cdx enable ... --json`
|
|
153
|
+
- `cdx context ... --json`
|
|
154
|
+
- `cdx memory ... --json`
|
|
155
|
+
- `cdx handoff ... --json`
|
|
156
|
+
- `cdx history ... --json`
|
|
157
|
+
- `cdx stats ... --json`
|
|
158
|
+
- `cdx last --json`
|
|
159
|
+
- `cdx doctor --json`
|
|
160
|
+
- `cdx repair --json`
|
|
161
|
+
- `cdx view --json`
|
|
162
|
+
- `cdx update --json`
|
|
163
|
+
- `cdx ready --json`
|
|
164
|
+
- `cdx select ... --json`
|
|
165
|
+
- `cdx run ... --json`
|
|
166
|
+
|
|
167
|
+
Success payloads follow a shared envelope:
|
|
168
|
+
|
|
169
|
+
```json
|
|
170
|
+
{
|
|
171
|
+
"schema_version": 1,
|
|
172
|
+
"ok": true,
|
|
173
|
+
"action": "add",
|
|
174
|
+
"message": "Created session work (codex)",
|
|
175
|
+
"warnings": [],
|
|
176
|
+
"session": {
|
|
177
|
+
"name": "work"
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Most commands use a shared stderr JSON envelope for errors whenever `--json` is present:
|
|
183
|
+
|
|
184
|
+
```json
|
|
185
|
+
{
|
|
186
|
+
"schema_version": 1,
|
|
187
|
+
"ok": false,
|
|
188
|
+
"error": {
|
|
189
|
+
"code": "invalid_usage",
|
|
190
|
+
"message": "Usage: cdx status [--json] [--refresh|--cached] [--timeout SECONDS] | ...",
|
|
191
|
+
"exit_code": 1
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
`status --json` and similar commands also use the same envelope and place non-fatal issues in `warnings` instead of mixing plain-text diagnostics into `stderr`. `cdx run --json` is the exception: it always writes one final JSON payload to stdout, including cdx-side and provider-start errors, so supervisors can parse a single result stream while provider stdout and stderr are captured to files.
|
|
197
|
+
|
|
198
|
+
This makes `cdx-manager` usable from editor plugins, scripts, and desktop apps without scraping human-readable terminal output.
|
|
199
|
+
|
|
200
|
+
### Headless Runs
|
|
201
|
+
|
|
202
|
+
`cdx run` is designed for supervisors such as Orchestia. In `--json` mode, stdout contains only the final JSON payload; provider stdout and stderr are captured to files.
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
cdx run codex-work \
|
|
206
|
+
--cwd /path/to/workspace \
|
|
207
|
+
--prompt-file task_prompt.md \
|
|
208
|
+
--model gpt-5.3-codex \
|
|
209
|
+
--reasoning-effort low \
|
|
210
|
+
--permission workspace-write \
|
|
211
|
+
--timeout-seconds 1800 \
|
|
212
|
+
--json
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
Use provider-based auto-selection when the caller wants cdx-manager to pick the account:
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
cdx run \
|
|
219
|
+
--provider codex \
|
|
220
|
+
--cwd /path/to/workspace \
|
|
221
|
+
--prompt "Summarize the repo status." \
|
|
222
|
+
--reasoning-effort low \
|
|
223
|
+
--json
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
The result includes `launcher: "cdx"`, `run_id`, selected `session`, `provider`, `exit_code`, `duration_seconds`, absolute `transcript_path`, `stdout_path`, `stderr_path`, and normalized usage token fields. Codex headless runs use `codex exec --json`; Claude headless runs use `claude --print --output-format json`. Token counts are `null` when the provider does not expose a supported JSON or JSONL usage shape.
|
|
227
|
+
|
|
228
|
+
Known headless and completed interactive token usage is persisted in launch history and can be aggregated later. Interactive records are best-effort local data: Codex reads its latest cumulative rollout snapshot, Claude reads its assistant usage records, and Ollama — which writes no transcript of its own — is launched with `--verbose` so its per-response token counts land in the terminal capture cdx already takes. Antigravity reports no usage: its history is schema-less binary protobuf and its logs carry no usage line, so those sessions show no tokens by nature rather than by omission.
|
|
229
|
+
|
|
230
|
+
Every usage record, whichever path produced it, uses one set of definitions:
|
|
231
|
+
|
|
232
|
+
| Field | Meaning |
|
|
233
|
+
| --- | --- |
|
|
234
|
+
| `input_tokens` | Uncached input **only**. Codex reports a cache-inclusive count natively; cdx reduces it to the remainder so the field means the same thing on every provider. |
|
|
235
|
+
| `cache_creation_tokens` | Tokens written to the provider's prompt cache. |
|
|
236
|
+
| `cache_read_tokens` | Tokens served from it. Kept apart from cache creation because the two cost roughly 1.25x and 0.1x of uncached input, a difference no summed figure can recover. |
|
|
237
|
+
| `cached_input_tokens` | `cache_creation_tokens + cache_read_tokens`, derived. The single CACHE column in `cdx stats` shows this. |
|
|
238
|
+
| `output_tokens` | Generated tokens. |
|
|
239
|
+
| `reasoning_tokens` | Reasoning the provider counts separately. Codex reports one; Claude does not, because it bills thinking as output — those tokens are already inside `output_tokens`, so an empty REASON column for Claude is correct rather than missing. |
|
|
240
|
+
| `total_tokens` | `input + cache_creation + cache_read + output`. Cache is typically the bulk of real consumption, so a total that left it out would not be slightly low — it would be a different quantity. |
|
|
241
|
+
|
|
242
|
+
Cached input is counted once: it is excluded from `input_tokens` and reported in the cache fields, never in both. `null` means the provider did not report the figure, which is not the same as zero.
|
|
243
|
+
|
|
244
|
+
`cdx stats` also shows a **`COST~`** column and ranks sessions by it. It weights each token class by what it costs relative to one uncached input token — cache read at the recorded model's ratio (0.1x by default), cache write 1.25x, and output at the recorded model's output/input ratio — and reports the result in uncached-input-equivalent tokens. These are ratios rather than prices. It is **not** a currency amount, and it is not comparable across providers whose own prices differ. The cache-write multiplier assumes the five-minute cache TTL; a one-hour TTL costs 2x and nothing in a transcript says which was used, so long-TTL writes are slightly under-weighted.
|
|
245
|
+
|
|
246
|
+
Ranking on the raw total would put a session that mostly replayed a cache above one that spent far more on generation, because cache reads are typically the overwhelming majority of tokens consumed while costing a fiftieth of an output token.
|
|
247
|
+
|
|
248
|
+
The **`USD~`** column turns that into money for runs whose serving model cdx recorded. It prices each token class directly using the built-in model table. To customize prices: set `CDX_TOKEN_PRICES` to a JSON object mapping model id to dollars per million tokens to override the built-in table, whose last review date is printed with the totals. A run whose model cdx never saw stays unpriced rather than being charged at a default tier, and the totals line says how many runs were actually priced.
|
|
249
|
+
|
|
250
|
+
The table requires `input` and `output` prices in USD per million tokens and accepts an optional `cache_read` price in the same units. Without it, cache reads cost 0.1x input; cache writes assume 1.25x input. GPT-6.1 Sol and Claude Opus 5.5 use 0.05x cache reads, while Claude Fable/Mythos 5.1 use 0.025x. Both `COST~` and `USD~` honor those rates. `CDX_TOKEN_PRICES` replaces the supplied model row: a two-field override keeps the legacy 0.1x fallback; include `cache_read` to override it (including zero).
|
|
251
|
+
|
|
252
|
+
Override rates must be finite and nonnegative. A zero input rate can still yield `USD~`, but ratios relative to input are undefined; `COST~` then shows `-` for an uncovered session. JSON keeps the numeric `weighted_tokens` sum for covered runs and reports `weighted_runs` and `unweighted_runs` so partial coverage is visible.
|
|
253
|
+
|
|
254
|
+
The figure uses standard public list prices, excluding Fast/priority, Batch/Flex, regional premiums, and tool fees — not an invoice. When a run changes models without a measured per-model token split, its USD estimate is unavailable rather than assigning all tokens to one model. OpenAI's long-context tier, which increases rates above a 272K-token request, is **not** modelled: cdx records tokens per run rather than per request, so it cannot tell which requests crossed that line, and long-context Codex work is under-costed.
|
|
255
|
+
|
|
256
|
+
`cdx stats` counts completed history attempts. A headless failover has one logical run in `cdx runs` but one history row per attempted session, including failed attempts that reported usage. Period filtering includes the entire run in every period it overlaps, so adjacent daily results can both include a run crossing midnight; adding daily totals may exceed a combined period. JSON `accounting` names this policy and the current price-table source. `usage_runs` and `priced_runs` show how much of the token total has a dollar estimate. Live runs are absent until their history row is written, and unknown usage is different from measured zero.
|
|
257
|
+
|
|
258
|
+
The built-in price table ships with **cdx-manager**. Run `cdx update` to receive new model prices; updating Codex or Claude alone does not refresh it. Then check `cdx --version` and `cdx stats --json`. Existing runs with a recorded model are recalculated using the new table when stats are read. `CDX_TOKEN_PRICES` overrides still take precedence. Maintainers: follow [the model and pricing update runbook](https://github.com/AlexAgo83/cdx-manager/blob/main/logics/runbook/run_005_maintaining_the_token_price_table.md) for source checks, tests, release preparation and installed-version verification.
|
|
259
|
+
|
|
260
|
+
A model absent from the table stays unpriced rather than being charged a default tier, and the totals line names it — which is exactly the key `CDX_TOKEN_PRICES` wants:
|
|
261
|
+
|
|
262
|
+
```
|
|
263
|
+
Totals: 26 runs, ... ; no price for gpt-6-unreleased)
|
|
264
|
+
CDX_TOKEN_PRICES='{"gpt-6-unreleased": {"input": 3, "output": 18}}' cdx stats
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
**Prices are the only part of this that rots on its own.** A test fails once the table has gone 90 days without review, and `scripts/check_token_prices.py` compares it against published pricing — outside the test suite, since a check that needs the network fails for reasons nobody wants in CI. A row it cannot confirm is reported as unverified, never as passing. When it finds a difference, follow [the pricing runbook](https://github.com/AlexAgo83/cdx-manager/blob/main/logics/runbook/run_005_maintaining_the_token_price_table.md) — which also records where each vendor's numbers actually live.
|
|
268
|
+
|
|
269
|
+
Runs recorded before these definitions existed carry figures that are fictitious rather than imprecise — one real session reported 206.6M cached tokens for a period in which its own conversation consumed 33,608, because the old reader picked whichever transcript had the newest modification time and re-read all of it on every launch. They cannot be recomputed: a run's true usage is the increment its transcript gained while it ran, and nothing recorded that. They are therefore excluded from every total automatically, and the totals line says how many runs that covered — so a period containing only such runs reads as absent rather than as a session that spent nothing. The records themselves are left alone, which keeps them recoverable if the marker ever proves wrong; `cdx repair` clears them from the file for anyone who would rather they were gone:
|
|
270
|
+
|
|
271
|
+
```
|
|
272
|
+
cdx repair --dry-run # says how many records carry unvouched usage
|
|
273
|
+
cdx repair # drops the figures; runs, durations and timestamps stay
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
Records that *are* vouched for but predate the split — headless runs, and anything recorded between the definition landing and the model being captured — are shown as faithfully as their data allows: they carry no creation/read split and no model, so their cached tokens are read as cache reads for weighting and they stay unpriced. `cdx stats` derives each row's `TOTAL` from the columns it displays, so a row always adds up even while history spans both eras.
|
|
277
|
+
|
|
278
|
+
```bash
|
|
279
|
+
cdx stats --since 7d --json
|
|
280
|
+
cdx stats work
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
`cdx select` exposes the same session selection logic directly:
|
|
284
|
+
|
|
285
|
+
```bash
|
|
286
|
+
cdx select --provider codex --min-reasoning-effort low --require-ready --json
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
### How cdx picks a session
|
|
290
|
+
|
|
291
|
+
`cdx select`, `cdx run --provider`, `cdx next`, the `cdx status` recommendation, and `cdx ready` all use one ranking. They used to use two that disagreed, so the answer depended on which command you asked.
|
|
292
|
+
|
|
293
|
+
**Candidate filters** exclude sessions before any ordering happens: disabled sessions, logged-out sessions (they cannot serve work), sessions of another provider when one is requested, sessions below a requested `--min-reasoning-effort`, and — when readiness is required — sessions with no availability left.
|
|
294
|
+
|
|
295
|
+
**Ordering** compares the remaining candidates factor by factor:
|
|
296
|
+
|
|
297
|
+
1. **Usability** — usable now, then blocked with a known upcoming reset, then reset known, then nothing known.
|
|
298
|
+
2. **Priority** — the `--priority` you set with `cdx set <name> --priority 0..100`, highest first.
|
|
299
|
+
3. Then, for a session you can use now: **credits** (sessions *without* credits first, so included quota is spent before paid credits), **availability**, **reset time**. For a session you cannot use now the order is **reset time** first, then credits and availability — when you cannot use it, what matters is when it comes back.
|
|
300
|
+
4. **Reasoning effort** — the lowest configured effort that still clears any requested floor, leaving stronger sessions free for work that needs them.
|
|
301
|
+
5. **Session name**, so the order is deterministic.
|
|
302
|
+
|
|
303
|
+
`--priority` ranks sessions *within* a usability class, never across one. A high-priority session with no quota left does not outrank a usable one: priority expresses which usable session to prefer, not a way to route work somewhere it will fail.
|
|
304
|
+
|
|
305
|
+
`cdx select --json` reports `selection_policy` (built from the ranking itself, so it cannot describe an order the code does not apply) and `deciding_factor`/`reason`, naming the factor that actually separated the winner from the runner-up for that call — or reporting that it was the only candidate. Do not treat `selection_policy` as a stable identifier; it changes when the ranking changes, which is the point.
|
|
306
|
+
|
|
307
|
+
`cdx run --provider` selects from cached status by default. Pass `--refresh` to fetch status first. When a session is auto-selected without any recorded availability, the run payload carries a `session_selected_without_status` warning — that is different from a session known to be low, and on a freshly imported or long-idle set of sessions it is the ordinary case.
|
|
308
|
+
|
|
309
|
+
### Verifying provider flag mappings
|
|
310
|
+
|
|
311
|
+
cdx translates each `--permission` value into concrete provider CLI flags. Those mappings are declarations about someone else's CLI, and a provider can drop or rename a flag without cdx noticing — which is exactly what happened with an `--experimental-yolo` flag mapped for ollama that the ollama CLI never had.
|
|
312
|
+
|
|
313
|
+
`cdx doctor --check-provider-flags` verifies them against the installed provider CLIs:
|
|
314
|
+
|
|
315
|
+
```bash
|
|
316
|
+
cdx doctor --check-provider-flags --json
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
For each configured provider it reports, per permission, whether every mapped flag is accepted. A rejected flag is a `FAIL` naming the provider, the permission, and the flag. A provider whose CLI is not installed, or whose help cannot be read, is a `WARN` — never an `OK`: "could not verify" is precisely the state a stale mapping hides in. A provider that maps no flags at all, such as ollama, reports `OK` with an empty mapping, so having nothing to check is distinguishable from having failed to check.
|
|
320
|
+
|
|
321
|
+
It is opt-in because it costs one provider CLI invocation per configured provider. When it is not requested, the default `cdx doctor` report says so with a `provider_permission_flags_unchecked` warning rather than omitting it, so a green report never implies the mappings were verified.
|
|
322
|
+
|
|
323
|
+
### Programmatic Callers
|
|
324
|
+
|
|
325
|
+
`cdx run` blocks until the provider finishes, which suits a supervisor that can wait. Agents, MCP servers, and watchdogs usually cannot, so the surface below exists specifically for them: launch without waiting, watch progress, react to failures by code, and discover valid values instead of hard-coding them.
|
|
326
|
+
|
|
327
|
+
**Launch without waiting.** `--detach` returns as soon as the run is registered, with the `run_id` already assigned:
|
|
328
|
+
|
|
329
|
+
```bash
|
|
330
|
+
cdx run work --cwd /path/to/repo --prompt-file task.md --detach --json
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
The payload carries `detached: true`, `run_id`, `pid`, and the artifact paths — but no `exit_code`, `duration_seconds`, or `usage`, since the run has not finished. The detached process is put in its own session, so it survives the launcher exiting, including when cdx was invoked over an SSH command that returns immediately. It transitions its own registry entry to a terminal status, so `cdx runs` and `cdx run-status` stay accurate with nobody supervising.
|
|
334
|
+
|
|
335
|
+
Authentication is still resolved before the launch returns, so a login problem surfaces synchronously rather than silently in the background.
|
|
336
|
+
|
|
337
|
+
**Watch a run in progress.** `cdx run-status` reports only running/succeeded/failed; `run-tail` shows what the run is actually doing:
|
|
338
|
+
|
|
339
|
+
```bash
|
|
340
|
+
cdx run-tail <run_id> --lines 50 --json
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
It returns the last lines of the run's own `stdout_path` plus its current status, whether the run is still going or already finished. Lines are raw provider output, not summarized. Undecodable bytes come back with replacement characters rather than failing the call.
|
|
344
|
+
|
|
345
|
+
**Pipe an untrusted prompt.** `--prompt-file -` reads the prompt from standard input, so arbitrary text never has to reach a command line or a temporary file the caller must clean up:
|
|
346
|
+
|
|
347
|
+
```bash
|
|
348
|
+
echo "$UNTRUSTED_PROMPT" | cdx run work --cwd /path/to/repo --prompt-file - --json
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
It fails immediately if standard input is a terminal, rather than blocking at a silent prompt.
|
|
352
|
+
|
|
353
|
+
**Poll for completions with a cursor.** `cdx runs --since` returns every run that completed after the cursor, using the same cursor forms as `cdx history --since`:
|
|
354
|
+
|
|
355
|
+
```bash
|
|
356
|
+
cdx runs --since 15m --json
|
|
357
|
+
cdx runs --since 2026-08-07T09:00:00Z --json
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
A cursor is bounded by time, not by row count: `--limit` is ignored when `--since` is given (and says so in `warnings`). That is deliberate — capping a cursor query by row count would silently drop completions a caller had not yet seen, which is exactly the miss the cursor removes. Runs still in flight are not returned; they appear once they complete. Callers do not need to keep their own set of already-reported run ids.
|
|
361
|
+
|
|
362
|
+
**React to failures by code, not by message.** Argument failures report a specific `error.code` and name the offending arguments as data:
|
|
363
|
+
|
|
364
|
+
| `error.code` | Raised when |
|
|
365
|
+
| --- | --- |
|
|
366
|
+
| `missing_required_argument` | A required argument is absent |
|
|
367
|
+
| `mutually_exclusive_arguments` | Two arguments that cannot be combined were both given |
|
|
368
|
+
| `invalid_argument_value` | A constrained option got a value outside its accepted set |
|
|
369
|
+
| `argument_value_out_of_range` | A numeric argument fell outside its accepted range |
|
|
370
|
+
| `unknown_argument` | An unrecognized flag |
|
|
371
|
+
|
|
372
|
+
```json
|
|
373
|
+
{
|
|
374
|
+
"ok": false,
|
|
375
|
+
"error": {
|
|
376
|
+
"code": "mutually_exclusive_arguments",
|
|
377
|
+
"message": "cdx run: cannot specify both a session name and --provider.",
|
|
378
|
+
"arguments": ["session", "--provider"],
|
|
379
|
+
"allowed_values": null
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
Never branch on `error.message`; it is written for a human reading a terminal and may be reworded.
|
|
385
|
+
|
|
386
|
+
**Discover valid values.** `cdx schema --json` publishes the enums and argument constraints the parser itself validates against:
|
|
387
|
+
|
|
388
|
+
```bash
|
|
389
|
+
cdx schema --json
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
It returns accepted values for `permission` (with its aliases and canonical forms), `reasoning_effort`/`power`, `kind`, and `provider`, plus the declared mutually-exclusive argument groups and the error codes above. Validate against this rather than copying the lists into your own code — a hand-maintained copy drifts, and cdx will not tell you when it does.
|
|
393
|
+
|
|
394
|
+
**Surface run warnings.** The run payload's `warnings` list reports degradations a zero exit code would otherwise hide, on the successful path as much as the failing one:
|
|
395
|
+
|
|
396
|
+
```json
|
|
397
|
+
{
|
|
398
|
+
"ok": true,
|
|
399
|
+
"exit_code": 0,
|
|
400
|
+
"warnings": [
|
|
401
|
+
{
|
|
402
|
+
"code": "network_disabled_by_permission",
|
|
403
|
+
"message": "codex runs at permission 'review' inside a sandbox with no network access, ...",
|
|
404
|
+
"provider": "codex",
|
|
405
|
+
"permission": "review"
|
|
406
|
+
}
|
|
407
|
+
]
|
|
408
|
+
}
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
Codex ties network access to its sandbox, so any permission below `full` leaves the run unable to resolve DNS — `gh`, `curl`, and package installs fail inside an otherwise successful run. Show these warnings to whoever reads your output rather than discarding them; a run that succeeds while quietly doing less is the case they exist for.
|
package/docs/features.md
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# Features
|
|
2
|
+
|
|
3
|
+
## Quota-aware routing
|
|
4
|
+
|
|
5
|
+
The reason `cdx` exists: knowing, across every account you own, which one you can actually use.
|
|
6
|
+
|
|
7
|
+
- **Usage at a glance.** `cdx status` shows token usage, 5-hour window quota, weekly quota, last-updated timestamps, priority guidance, and the last launched session in one aligned table.
|
|
8
|
+
- **Pick for me.** `cdx next` selects the best available assistant from your pinned priorities and the live quota picture, shows the reason, and prints the exact command to run.
|
|
9
|
+
- **Agent notifications.** At the first interactive launch of a supported provider, cdx asks before installing its hook. Delivery starts muted; `cdx tray alerts on` enables the next event globally, with or without the tray running.
|
|
10
|
+
- **Next-ready notification.** `cdx ready` schedules a native system notification for the next assistant that comes back from cooldown, then returns immediately.
|
|
11
|
+
- **Passive status resolution.** Codex status is read from the local Codex app-server rate-limit API when available, with legacy transcript/history parsing kept as a fallback.
|
|
12
|
+
- **Banked reset visibility.** Eligible Codex accounts show the number of manually redeemable bonus resets in `cdx status` and expose reset details in JSON output.
|
|
13
|
+
|
|
14
|
+
## Isolated multi-account sessions
|
|
15
|
+
|
|
16
|
+

|
|
17
|
+
|
|
18
|
+
- **Multiple providers, one tool.** Register as many Codex, Claude, Antigravity, or Ollama sessions as you need. Codex and Claude get isolated auth environments; Antigravity is launchable through `agy` with OS-keyring auth; Ollama runs local models through `ollama run`.
|
|
19
|
+
- **Instant launch.** `cdx work` opens your "work" session. `cdx personal` opens another. No config files to edit mid-flow.
|
|
20
|
+
- **Quick relaunch.** `cdx last` reopens the most recently launched assistant profile.
|
|
21
|
+
- **Resume by identity, not by recency.** Each session records the provider's own conversation id — imposed at launch for Claude, read back from the rollout for Codex — so `cdx resume <name>` reopens *that* conversation regardless of your working directory or of which session ran last. The conversation is looked up before it is named: a recorded id whose transcript the provider never wrote degrades to the provider's own fallback (`--continue`, or `resume --last`) and reports `reason: conversation_not_found`, rather than naming a conversation that does not exist and letting the provider exit with an error. `cdx can-resume --json` reports the strategy and where the id came from, so an automated caller can tell a named resume from a best-effort one.
|
|
22
|
+
- **Auth guardrails.** `cdx` checks authentication before launching. If a session is not logged in, it tells you exactly what to run — no silent failures.
|
|
23
|
+
- **Persistent launch settings.** Pin per-session power, permission, and fast-mode preferences once; `cdx` reapplies them on every launch until you unset them.
|
|
24
|
+
- **Spend ceiling and model fallback.** `cdx set <name> --budget 5` caps what a headless run may spend, and `--fallback-model sonnet,haiku` lets a run continue on the next model when the first is overloaded. Both are Claude Code flags that the provider accepts with `--print` only, so they apply to `cdx run` and not to interactive launches; `cdx configs` says so.
|
|
25
|
+
- **Session control.** Disable a session without deleting it when an account is temporarily out of credits; disabled sessions remain visible and sort last.
|
|
26
|
+
- **Optional session labels.** `cdx label <name> <label>` adds a short human label; list and full status tables show a `LABEL` column only when at least one session has one.
|
|
27
|
+
- **Clean removal.** `cdx rmv` wipes a session and its entire auth directory. No orphaned files, no stale credentials.
|
|
28
|
+
|
|
29
|
+
## Headless automation
|
|
30
|
+
|
|
31
|
+
- **One task, one JSON result.** `cdx run` executes a prompt against a chosen or auto-selected session and returns a stable payload; `--detach` returns a `run_id` immediately.
|
|
32
|
+
- **Survives a rate limit.** `cdx run --failover` notices that a run stopped because its account ran out, moves the task to the next account the ranking allows, and carries on — one `run_id` for the whole task, with every account it occupied listed in `cdx run-report`. A spent account is always confirmed against its own refreshed quota first, so a healthy account is never abandoned. From there two routes migrate a run: the provider said so in words cdx recognises, or — since that wording differs between an enterprise workspace out of credits, a personal plan hitting its 5-hour window, and Claude's own phrasing — simply that the account's quota is gone and the run failed. `cdx run-report` names which route applied. Exhausting every account reports `failover_exhausted`, which a caller can tell apart from the task itself failing.
|
|
33
|
+
- **Native background delegation (opt-in).** With `CDX_EXPERIMENTAL_NATIVE_BG=1`, `cdx run --detach` hands the run to Claude Code's own background agents (`--bg`) instead of cdx's detached launcher. The run keeps its cdx `run_id`, closes out with its token usage and final answer read from the provider's own session transcript, and the parked session is stopped once its task is done. Off by default for one release while it settles; the in-house launcher is unchanged and is what every run takes otherwise. Codex keeps the in-house path while its `cloud`/`exec-server` surfaces are marked experimental.
|
|
34
|
+
- **Observable runs.** `cdx run-status`, `cdx run-tail`, `cdx run-report`, and `cdx runs --since` follow a run while it happens and after it ends.
|
|
35
|
+
- **Selection without launching.** `cdx select --provider ... --require-ready --json` answers "which session should this job use?" for orchestrators.
|
|
36
|
+
- **Escape hatch for unmapped flags.** `cdx set <name> --extra-args "--add-dir ../shared"` passes provider arguments cdx does not model straight through, so a flag your provider shipped last week never forces you to abandon cdx. These arguments are explicitly unvalidated: cdx does not parse or verify them, `cdx schema --json` lists them under `unvalidated` rather than describing them, and `cdx doctor --check-provider-flags` ignores them. They are split into literal argv entries and never passed through a shell.
|
|
37
|
+
- **Validated contract.** `cdx schema --json` publishes the enums, mutually-exclusive argument groups, and error codes programmatic callers should validate against.
|
|
38
|
+
|
|
39
|
+
## Context handoff
|
|
40
|
+
|
|
41
|
+
- **Transcript-first handoff.** Switch accounts or providers using the source conversation's recorded native identity and verified workspace. CDX never chooses a conversation by file modification time. Missing, stale or mismatched identity requires an explicit choice; JSON/non-interactive callers receive candidate diagnostics instead of a launch.
|
|
42
|
+
- **Instructions before action.** The receiving agent is told to read applicable `AGENTS.md`/`CLAUDE.md` and their required references (including Logics instructions), recover the task from bounded portions of the complete transcript, verify current state, then show a concise objective/state/next-action checkpoint before modifying anything. Existing clear authorization still permits continuation. CDX supplies this prompt; it cannot certify that an agent has understood or obeyed it.
|
|
43
|
+
- **Shared notes remain yours.** `cdx context` and `cdx memory` remain explicit notes. Automatic handoff does not overwrite them or copy authentication. A dated reference to workspace notes is supplementary, never a substitute for the native conversation.
|
|
44
|
+
- **Session transcript capture.** Every launch is recorded to a local log file via `script`, giving you a full terminal transcript for each session.
|
|
45
|
+
|
|
46
|
+
Run handoff from the intended project directory:
|
|
47
|
+
|
|
48
|
+
```sh
|
|
49
|
+
cd /path/to/project
|
|
50
|
+
cdx handoff source target --json # prepare only, no provider launch
|
|
51
|
+
cdx handoff target # use that prepared entry and launch
|
|
52
|
+
cdx handoff source target --source-conversation CONVERSATION_ID
|
|
53
|
+
# Exact native file when several transcripts share an identity:
|
|
54
|
+
cdx handoff source target --source-native-transcript /path/to/source/sessions/rollout.jsonl
|
|
55
|
+
# Explicit fallback when only a terminal capture is available:
|
|
56
|
+
cdx handoff source target --source-transcript /path/to/source/log/cdx-session.log
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
The three source-selection options are mutually exclusive and apply only to
|
|
60
|
+
`SOURCE TARGET`. Without a usable recorded identity, an interactive terminal offers
|
|
61
|
+
up to 20 valid conversations from the current workspace, ordered by actual event
|
|
62
|
+
time for inspection, with no default choice. Blank input or Ctrl-C cancels. A stale
|
|
63
|
+
recorded identity never silently falls back, even if there is only one candidate.
|
|
64
|
+
Run from the conversation's original workspace if its metadata names another directory.
|
|
65
|
+
|
|
66
|
+
Each preparation writes a private, unique `<target-auth-home>/handoffs/<uuid>.json`
|
|
67
|
+
entry. `context.target_path` in JSON output names that entry; `handoff` contains its
|
|
68
|
+
metadata, including recovery mode, source conversation ID, transcript path, workspace,
|
|
69
|
+
preparation time, readable byte extent and SHA-256. `source_session`/`target_session`
|
|
70
|
+
contain names/providers only. Transcript bodies and credentials are not emitted.
|
|
71
|
+
Unresolved JSON source selection returns `ok: false`, error code
|
|
72
|
+
`handoff_source_unresolved`, a bounded `candidates` array and a nonzero exit status.
|
|
73
|
+
|
|
74
|
+
The original JSONL remains in place, including early decisions, tool calls/results
|
|
75
|
+
and compaction records. Read it in bounded portions up to `extent_bytes`; there is
|
|
76
|
+
no 120000-character tail replacement. An unfinished final JSONL record is excluded
|
|
77
|
+
from that preparation. Later appends do not change its boundary. Reusing an entry
|
|
78
|
+
checks the original bytes: deletion, truncation or rewriting requires a new handoff,
|
|
79
|
+
not a silent downgrade to notes. Keep the original source profile/transcript available
|
|
80
|
+
until recovery completes. No transcript copy or automatic artifact cleanup is performed;
|
|
81
|
+
entries can be removed after use. A small per-workspace/target pointer chooses the most
|
|
82
|
+
recent preparation for the one-name command; concurrent launches retain their own entry
|
|
83
|
+
path and cannot overwrite each other's entry.
|
|
84
|
+
|
|
85
|
+
Legacy one-name handoff without a prepared entry reads workspace notes in `notes-only`
|
|
86
|
+
mode and explicitly reports that native history was not recovered. Terminal fallback
|
|
87
|
+
requires a named file from that source session's launch logs and is labelled `degraded`:
|
|
88
|
+
it cannot prove complete history or tools, and its workspace is operator-selected rather
|
|
89
|
+
than verified from native metadata. Native resolution currently supports Codex and Claude.
|
|
90
|
+
All modes ask the recipient to report material gaps, and none bypass provider access rules
|
|
91
|
+
or turn historical tool output into new authorization.
|
|
92
|
+
|
|
93
|
+
## Maintenance
|
|
94
|
+
|
|
95
|
+
- **Launch history.** Inspect recent launches with provider, result, duration, working directory, launch settings, and transcript path.
|
|
96
|
+
- **Aggregate usage.** `cdx stats` totals runs, token usage, and time spent per session over any period. Interactive Codex and Claude launches also record provider-native token totals when their local session transcript is available.
|
|
97
|
+
|
|
98
|
+
- **Disk usage and cleanup.** `cdx disk` reports `CDX_HOME` usage, `cdx disk profiles --candidates` identifies reclaimable profile caches/logs with evidence, and `cdx clean profiles ...` applies explicit cleanup actions.
|
|
99
|
+
- **Health and repair.** `cdx doctor` inspects dependencies, permissions, and orphan profiles; `cdx repair` plans or applies safe fixes.
|
|
100
|
+
- **Portable bundles.** `cdx export` / `cdx import` move sessions between machines, with passphrase-encrypted auth data when you ask for it.
|
|
101
|
+
- **Update prompts.** Periodic update checks surface `cdx update` directly in the `cdx`, `cdx status`, and launch output when a newer release is available. When `logics-manager` is installed, `cdx` can also suggest `logics-manager update`.
|
|
102
|
+
- **Logics viewer shortcut.** `cdx view` opens the Logics browser/focus viewer through `logics-manager view` when the companion CLI is installed. All viewer flags are forwarded: `--lan`, `--lan-rw`, `--focus <ref>`, `--read`, `--port`, `--host`, `--refresh-interval`, `--tls`, `--tls-cert`, `--tls-key`, `--open`, `--no-open`. `cdx view --json` reports availability and update diagnostics without opening the viewer.
|