cdx-manager 0.6.4 → 0.7.0
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 +48 -8
- package/changelogs/CHANGELOGS_0_6_5.md +35 -0
- package/changelogs/CHANGELOGS_0_7_0.md +49 -0
- package/checksums/release-archives.json +8 -0
- package/install.sh +2 -2
- package/package.json +1 -1
- package/pyproject.toml +2 -2
- package/src/backup_bundle.py +40 -11
- package/src/claude_refresh.py +1 -0
- package/src/cli.py +15 -4
- package/src/cli_commands.py +453 -29
- package/src/provider_runtime.py +174 -10
- package/src/session_service.py +19 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# CDX Manager
|
|
2
2
|
|
|
3
|
-
[](LICENSE) ](LICENSE)  
|
|
4
4
|
|
|
5
5
|
**Run multiple Codex, Claude, Antigravity, and Ollama sessions from one terminal. Switch between accounts instantly.**
|
|
6
6
|
|
|
@@ -51,7 +51,7 @@ One command to launch any session. Zero auth juggling.
|
|
|
51
51
|
|
|
52
52
|
## Technical Overview
|
|
53
53
|
|
|
54
|
-
- Python 3.9
|
|
54
|
+
- Python 3.9+.
|
|
55
55
|
- Environment isolation per session:
|
|
56
56
|
- Codex sessions override `CODEX_HOME` to a dedicated profile directory.
|
|
57
57
|
- Claude sessions override `HOME` to a dedicated profile directory and disable Claude Code commit co-author attribution by default.
|
|
@@ -134,7 +134,7 @@ For a specific version:
|
|
|
134
134
|
|
|
135
135
|
```bash
|
|
136
136
|
curl -fsSL https://raw.githubusercontent.com/AlexAgo83/cdx-manager/main/install.sh -o install.sh
|
|
137
|
-
CDX_VERSION=v0.
|
|
137
|
+
CDX_VERSION=v0.7.0 sh install.sh
|
|
138
138
|
```
|
|
139
139
|
|
|
140
140
|
From source:
|
|
@@ -263,6 +263,7 @@ cdx set work --power medium --permission full --fast off
|
|
|
263
263
|
cdx set personal --power low --permission review
|
|
264
264
|
cdx set --sessions all --permission auto
|
|
265
265
|
cdx set --provider ollama --model llama3.2
|
|
266
|
+
cdx set work --priority 80
|
|
266
267
|
cdx power all low
|
|
267
268
|
cdx perm provider:claude review
|
|
268
269
|
cdx model provider:ollama llama3.2
|
|
@@ -275,12 +276,13 @@ Those values are stored on the session and reapplied every time you run `cdx wor
|
|
|
275
276
|
cdx unset work --power
|
|
276
277
|
cdx unset --sessions work,personal --fast
|
|
277
278
|
cdx unset --provider claude --permission
|
|
279
|
+
cdx unset work --priority
|
|
278
280
|
cdx unset work --all
|
|
279
281
|
cdx power all default
|
|
280
282
|
cdx model provider:ollama default
|
|
281
283
|
```
|
|
282
284
|
|
|
283
|
-
`--power` maps to Codex `model_reasoning_effort` and Claude `--effort`. `--permission` maps to provider-native permission flags. `--fast on` uses low effort when no explicit power is set.
|
|
285
|
+
`--power` maps to Codex `model_reasoning_effort` and Claude `--effort`. `--permission` maps to provider-native permission flags. `--fast on` uses low effort when no explicit power is set. `--priority` is a 0..100 selector preference used as a tie-breaker after readiness and availability.
|
|
284
286
|
|
|
285
287
|
### Launch History
|
|
286
288
|
|
|
@@ -317,8 +319,8 @@ cdx history --summary --from 2026-05-01 --to 2026-05-28
|
|
|
317
319
|
| `cdx enable <name> [--json]` | Re-enable a disabled session |
|
|
318
320
|
| `cdx config <name> [--json]` | Show persistent launch settings for a session |
|
|
319
321
|
| `cdx power\|perm\|fast\|model <name\|all\|provider:PROVIDER\|a,b> <value\|default> [--json]` | Shortcut commands for setting or clearing one launch setting |
|
|
320
|
-
| `cdx set <name>\|--sessions all\|a,b\|--provider PROVIDER [--power low\|medium\|high\|xhigh\|max] [--permission review\|default\|auto\|full] [--fast on\|off] [--model MODEL] [--json]` | Persist launch settings for one or more sessions |
|
|
321
|
-
| `cdx unset <name>\|--sessions all\|a,b\|--provider PROVIDER (--power\|--permission\|--fast\|--model\|--all) [--json]` | Remove persisted launch settings and fall back to provider defaults |
|
|
322
|
+
| `cdx set <name>\|--sessions all\|a,b\|--provider PROVIDER [--power low\|medium\|high\|xhigh\|max] [--permission review\|default\|auto\|full] [--fast on\|off] [--model MODEL] [--priority 0..100] [--json]` | Persist launch settings for one or more sessions |
|
|
323
|
+
| `cdx unset <name>\|--sessions all\|a,b\|--provider PROVIDER (--power\|--permission\|--fast\|--model\|--priority\|--all) [--json]` | Remove persisted launch settings and fall back to provider defaults |
|
|
322
324
|
| `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 |
|
|
323
325
|
| `cdx last [--json]` | Launch the most recent existing session from launch history |
|
|
324
326
|
| `cdx context show\|path\|init\|edit\|clear\|set [text...] [--json]` | Manage the shared Markdown context for the current workspace |
|
|
@@ -334,6 +336,8 @@ cdx history --summary --from 2026-05-01 --to 2026-05-28
|
|
|
334
336
|
| `cdx ready [--refresh] [--json]` | Schedule an OS notification for the next cooling-down assistant that becomes ready, then return immediately |
|
|
335
337
|
| `cdx notify <name> --at-reset [--poll seconds] [--once] [--schedule] [--refresh] [--json]` | Wait for a session reset time or schedule an OS wake-up notification when due |
|
|
336
338
|
| `cdx notify --next-ready [--poll seconds] [--once] [--schedule] [--refresh] [--json]` | Wait until the recommended session is usable, or schedule the next known reset notification |
|
|
339
|
+
| `cdx select --provider PROVIDER [--min-reasoning-effort low\|medium\|high] [--min-power low\|medium\|high] [--require-ready] [--refresh] --json` | Select a suitable session for headless automation |
|
|
340
|
+
| `cdx run [session] --cwd PATH (--prompt-file PATH\|--prompt TEXT) [--provider PROVIDER] [--model MODEL] [--reasoning-effort low\|medium\|high] [--power low\|medium\|high] [--permission MODE] [--timeout-seconds N] --json` | Run one headless task and return a stable JSON result |
|
|
337
341
|
| `cdx status [--json] [--refresh]` | Show token usage table for all sessions; JSON returns a versioned payload with structured warnings |
|
|
338
342
|
| `cdx status --small [--refresh]` / `cdx status -s [--refresh]` | Show compact token usage table without provider, blocking quota, credits, and updated columns |
|
|
339
343
|
| `cdx status <name> [--json] [--refresh]` | Show detailed usage breakdown for one session |
|
|
@@ -371,6 +375,8 @@ Commands with machine-readable output:
|
|
|
371
375
|
- `cdx update --json`
|
|
372
376
|
- `cdx ready --json`
|
|
373
377
|
- `cdx notify ... --json`
|
|
378
|
+
- `cdx select ... --json`
|
|
379
|
+
- `cdx run ... --json`
|
|
374
380
|
|
|
375
381
|
Success payloads follow a shared envelope:
|
|
376
382
|
|
|
@@ -387,7 +393,7 @@ Success payloads follow a shared envelope:
|
|
|
387
393
|
}
|
|
388
394
|
```
|
|
389
395
|
|
|
390
|
-
|
|
396
|
+
Most commands use a shared stderr JSON envelope for errors whenever `--json` is present:
|
|
391
397
|
|
|
392
398
|
```json
|
|
393
399
|
{
|
|
@@ -401,10 +407,44 @@ Errors use a shared stderr JSON envelope whenever `--json` is present:
|
|
|
401
407
|
}
|
|
402
408
|
```
|
|
403
409
|
|
|
404
|
-
`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`.
|
|
410
|
+
`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.
|
|
405
411
|
|
|
406
412
|
This makes `cdx-manager` usable from editor plugins, scripts, and desktop apps without scraping human-readable terminal output.
|
|
407
413
|
|
|
414
|
+
### Headless Runs
|
|
415
|
+
|
|
416
|
+
`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.
|
|
417
|
+
|
|
418
|
+
```bash
|
|
419
|
+
cdx run codex-work \
|
|
420
|
+
--cwd /path/to/workspace \
|
|
421
|
+
--prompt-file task_prompt.md \
|
|
422
|
+
--model gpt-5.3-codex \
|
|
423
|
+
--reasoning-effort low \
|
|
424
|
+
--permission workspace-write \
|
|
425
|
+
--timeout-seconds 1800 \
|
|
426
|
+
--json
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
Use provider-based auto-selection when the caller wants cdx-manager to pick the account:
|
|
430
|
+
|
|
431
|
+
```bash
|
|
432
|
+
cdx run \
|
|
433
|
+
--provider codex \
|
|
434
|
+
--cwd /path/to/workspace \
|
|
435
|
+
--prompt "Summarize the repo status." \
|
|
436
|
+
--reasoning-effort low \
|
|
437
|
+
--json
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
The result includes `run_id`, selected `session`, `provider`, `exit_code`, `duration_seconds`, absolute `transcript_path`, `stdout_path`, `stderr_path`, and normalized usage token fields. Token counts are `null` when the provider does not expose them.
|
|
441
|
+
|
|
442
|
+
`cdx select` exposes the same session selection logic directly:
|
|
443
|
+
|
|
444
|
+
```bash
|
|
445
|
+
cdx select --provider codex --min-reasoning-effort low --require-ready --json
|
|
446
|
+
```
|
|
447
|
+
|
|
408
448
|
---
|
|
409
449
|
|
|
410
450
|
## Backup And Restore
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Changelog (`0.6.4 -> 0.6.5`)
|
|
2
|
+
|
|
3
|
+
Release date: 2026-05-29
|
|
4
|
+
|
|
5
|
+
## Installer Integrity
|
|
6
|
+
|
|
7
|
+
- Fixed standalone installer checksum resolution so the Unix installer can validate published GitHub archive checksums correctly.
|
|
8
|
+
- Added regression coverage for the release checksum lookup path used by the standalone installer.
|
|
9
|
+
|
|
10
|
+
## Claude Authentication
|
|
11
|
+
|
|
12
|
+
- Preserved the captured Claude setup-token transcript when token extraction fails, making failed login setup recoverable and easier to inspect.
|
|
13
|
+
- Reordered Claude status handling so authentication is checked before refreshing usage, avoiding noisy usage refresh failures when Claude credentials are absent or invalid.
|
|
14
|
+
|
|
15
|
+
## Codex Authentication
|
|
16
|
+
|
|
17
|
+
- Hardened Codex auth detection so an empty or unusable `auth.json` is no longer treated as an authenticated session.
|
|
18
|
+
- Added coverage for usable-token validation instead of relying on file presence alone.
|
|
19
|
+
|
|
20
|
+
## Auth Bundle Security
|
|
21
|
+
|
|
22
|
+
- Replaced the previous homegrown auth bundle encryption with AEAD encryption via `cryptography`.
|
|
23
|
+
- Added wrong-passphrase and auth bundle regression tests for the new encrypted bundle format.
|
|
24
|
+
- Updated CI and publish workflows to install Python package dependencies before running Python-backed lint, tests, and version validation.
|
|
25
|
+
|
|
26
|
+
## Release Metadata and Documentation
|
|
27
|
+
|
|
28
|
+
- Updated package metadata, CLI version output, README badge, pinned installer example, and release changelog to `v0.6.5`.
|
|
29
|
+
|
|
30
|
+
## Validation and Regression Evidence
|
|
31
|
+
|
|
32
|
+
- `npm run lint`
|
|
33
|
+
- `npm test`
|
|
34
|
+
- `python -m build --sdist --wheel`
|
|
35
|
+
- `npm pack --dry-run`
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Changelog (`0.6.5 -> 0.7.0`)
|
|
2
|
+
|
|
3
|
+
Release date: 2026-05-29
|
|
4
|
+
|
|
5
|
+
## Headless Automation
|
|
6
|
+
|
|
7
|
+
- Added `cdx run --json` as a headless execution contract for automation clients such as Orchestia.
|
|
8
|
+
- Added explicit session execution, provider-based auto-selection, inline prompt and prompt-file support, working-directory validation, timeout handling, and stable run metadata.
|
|
9
|
+
- Kept JSON mode stdout reserved for the final response so callers can parse command output without terminal UI noise.
|
|
10
|
+
- Returned structured cdx-side and provider-side error envelopes for missing provider CLIs, invalid launch inputs, provider start failures, disabled sessions, and reasoning validation errors.
|
|
11
|
+
|
|
12
|
+
## Session Selection
|
|
13
|
+
|
|
14
|
+
- Added `cdx select --json` with deterministic ranking from provider match, readiness, cooldown, quota health, configured priority, reasoning capability, and session name.
|
|
15
|
+
- Reused the same selector from `cdx run --provider ...`.
|
|
16
|
+
- Added priority handling improvements, including configured-priority tie-breaking and clearing selection priority.
|
|
17
|
+
- Allowed ready selection for local providers where remote quota signals are not applicable.
|
|
18
|
+
|
|
19
|
+
## Reasoning Effort
|
|
20
|
+
|
|
21
|
+
- Added provider-neutral `--reasoning-effort low|medium|high` handling.
|
|
22
|
+
- Kept `--power` as a compatibility alias and rejected conflicting values with cdx-sourced JSON errors.
|
|
23
|
+
- Mapped normalized effort into Codex launch options while leaving clear extension points for other providers.
|
|
24
|
+
|
|
25
|
+
## Artifacts and Diagnostics
|
|
26
|
+
|
|
27
|
+
- Added transcript, stdout, and stderr artifact reporting for headless runs.
|
|
28
|
+
- Returned absolute artifact paths and normalized nullable token usage fields on success and failure responses.
|
|
29
|
+
- Hardened artifact and timeout tests to cover provider failures and unknown usage.
|
|
30
|
+
|
|
31
|
+
## Documentation and Release Readiness
|
|
32
|
+
|
|
33
|
+
- Documented the Orchestia headless delivery, headless CLI options, selection reasons, and JSON error stream behavior.
|
|
34
|
+
- Completed Logics release-gate documentation with rollback coverage, project changelog, release notes, duplicate triage, and release gate artifacts.
|
|
35
|
+
- Carried forward the `v0.6.5` release checksum metadata so standalone installer integrity checks can resolve the previous release.
|
|
36
|
+
|
|
37
|
+
## Release Metadata
|
|
38
|
+
|
|
39
|
+
- Updated package metadata, CLI version output, README badge, pinned installer example, and release changelog to `v0.7.0`.
|
|
40
|
+
|
|
41
|
+
## Validation and Regression Evidence
|
|
42
|
+
|
|
43
|
+
- `python -m py_compile bin/cdx src/*.py test/test_*_py.py`
|
|
44
|
+
- `python -m unittest discover -s test -p 'test_*_py.py'`
|
|
45
|
+
- `npm run lint`
|
|
46
|
+
- `npm test`
|
|
47
|
+
- `npm pack --dry-run`
|
|
48
|
+
- `python -m build`
|
|
49
|
+
- `python -m twine check dist/*`
|
|
@@ -20,6 +20,14 @@
|
|
|
20
20
|
"v0.6.3": {
|
|
21
21
|
"github_tarball_sha256": "539bc299fe2211cddcbe58db71a859ebbd1cb76aec254f6feef501fc038d7c62",
|
|
22
22
|
"github_zip_sha256": "138c7c67ea1b512d71ed745559f8eed395accb9a06b3ed9d82c3ccc454aba12b"
|
|
23
|
+
},
|
|
24
|
+
"v0.6.4": {
|
|
25
|
+
"github_tarball_sha256": "f7c83dd1ae7506cf1ae6420e718a285f4dc96a10fb3a19e24cc17e79d75a46b4",
|
|
26
|
+
"github_zip_sha256": "d602800cf6b54f1e0adea751cc6b686ab2fc4a224715ade94f761df2ff7da2af"
|
|
27
|
+
},
|
|
28
|
+
"v0.6.5": {
|
|
29
|
+
"github_tarball_sha256": "f2280917ea75b5ae1e99a99b011f09704d89b1a7ae42497f5093e6fff9f814d9",
|
|
30
|
+
"github_zip_sha256": "0b8491037310ed82cf44419d0de887bc0f768c6690c69153992fc4d5cda69676"
|
|
23
31
|
}
|
|
24
32
|
}
|
|
25
33
|
}
|
package/install.sh
CHANGED
|
@@ -34,7 +34,7 @@ sha256_file() {
|
|
|
34
34
|
|
|
35
35
|
resolve_expected_sha256() {
|
|
36
36
|
curl -fsSL "$CHECKSUMS_URL" |
|
|
37
|
-
python3 -
|
|
37
|
+
python3 -c '
|
|
38
38
|
import json
|
|
39
39
|
import sys
|
|
40
40
|
|
|
@@ -48,7 +48,7 @@ release = (payload.get("releases") or {}).get(tag) or {}
|
|
|
48
48
|
value = release.get("github_tarball_sha256")
|
|
49
49
|
if value:
|
|
50
50
|
print(value)
|
|
51
|
-
|
|
51
|
+
' "$1"
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
if [ -z "$VERSION" ]; then
|
package/package.json
CHANGED
package/pyproject.toml
CHANGED
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "cdx-manager"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.7.0"
|
|
8
8
|
description = "Terminal session manager for Codex and Claude accounts."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.9"
|
|
@@ -26,7 +26,7 @@ classifiers = [
|
|
|
26
26
|
"Topic :: Software Development",
|
|
27
27
|
"Topic :: Terminals",
|
|
28
28
|
]
|
|
29
|
-
dependencies = []
|
|
29
|
+
dependencies = ["cryptography>=42"]
|
|
30
30
|
|
|
31
31
|
[project.urls]
|
|
32
32
|
Homepage = "https://github.com/AlexAgo83/cdx-manager"
|
package/src/backup_bundle.py
CHANGED
|
@@ -11,10 +11,13 @@ from .errors import CdxError
|
|
|
11
11
|
BUNDLE_SCHEMA_VERSION = 1
|
|
12
12
|
_SALT_BYTES = 16
|
|
13
13
|
_NONCE_BYTES = 16
|
|
14
|
+
_AEAD_NONCE_BYTES = 12
|
|
14
15
|
_SCRYPT_N = 2 ** 14
|
|
15
16
|
_SCRYPT_R = 8
|
|
16
17
|
_SCRYPT_P = 1
|
|
17
18
|
_PBKDF2_ITERATIONS = 200000
|
|
19
|
+
_AEAD_ALGORITHM = "aes-256-gcm"
|
|
20
|
+
_LEGACY_ALGORITHM = "sha256-xor-hmac"
|
|
18
21
|
|
|
19
22
|
|
|
20
23
|
def _now_iso():
|
|
@@ -68,6 +71,22 @@ def _derive_keys(passphrase, salt):
|
|
|
68
71
|
return key_material[:32], key_material[32:]
|
|
69
72
|
|
|
70
73
|
|
|
74
|
+
def _derive_aead_key(passphrase, salt):
|
|
75
|
+
enc_key, _mac_key = _derive_keys(passphrase, salt)
|
|
76
|
+
return enc_key
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def _load_aesgcm():
|
|
80
|
+
try:
|
|
81
|
+
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
|
|
82
|
+
except ImportError as error:
|
|
83
|
+
raise CdxError(
|
|
84
|
+
"Auth bundle encryption requires the Python package 'cryptography'. "
|
|
85
|
+
"Install cdx-manager through pipx/uv/pip, or install cryptography for the Python used by cdx."
|
|
86
|
+
) from error
|
|
87
|
+
return AESGCM
|
|
88
|
+
|
|
89
|
+
|
|
71
90
|
def _xor_keystream(data, key, nonce):
|
|
72
91
|
output = bytearray()
|
|
73
92
|
counter = 0
|
|
@@ -90,14 +109,14 @@ def encode_bundle(payload, include_auth=False, passphrase=None):
|
|
|
90
109
|
}
|
|
91
110
|
if include_auth:
|
|
92
111
|
salt = os.urandom(_SALT_BYTES)
|
|
93
|
-
nonce = os.urandom(
|
|
94
|
-
|
|
95
|
-
ciphertext =
|
|
96
|
-
mac = hmac.new(mac_key, nonce + ciphertext, hashlib.sha256).digest()
|
|
112
|
+
nonce = os.urandom(_AEAD_NONCE_BYTES)
|
|
113
|
+
aesgcm = _load_aesgcm()(_derive_aead_key(passphrase, salt))
|
|
114
|
+
ciphertext = aesgcm.encrypt(nonce, payload_bytes, None)
|
|
97
115
|
wrapper.update({
|
|
116
|
+
"encryption": _AEAD_ALGORITHM,
|
|
117
|
+
"kdf": "scrypt" if hasattr(hashlib, "scrypt") else "pbkdf2-hmac-sha256",
|
|
98
118
|
"salt": _b64_encode(salt),
|
|
99
119
|
"nonce": _b64_encode(nonce),
|
|
100
|
-
"hmac_sha256": _b64_encode(mac),
|
|
101
120
|
"payload": _b64_encode(ciphertext),
|
|
102
121
|
})
|
|
103
122
|
else:
|
|
@@ -116,13 +135,23 @@ def decode_bundle(data, passphrase=None):
|
|
|
116
135
|
if encrypted:
|
|
117
136
|
salt = _b64_decode(wrapper.get("salt", ""))
|
|
118
137
|
nonce = _b64_decode(wrapper.get("nonce", ""))
|
|
119
|
-
expected_mac = _b64_decode(wrapper.get("hmac_sha256", ""))
|
|
120
138
|
ciphertext = _b64_decode(payload_b64)
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
139
|
+
algorithm = wrapper.get("encryption") or _LEGACY_ALGORITHM
|
|
140
|
+
if algorithm == _AEAD_ALGORITHM:
|
|
141
|
+
aesgcm = _load_aesgcm()(_derive_aead_key(passphrase, salt))
|
|
142
|
+
try:
|
|
143
|
+
payload_bytes = aesgcm.decrypt(nonce, ciphertext, None)
|
|
144
|
+
except Exception as error:
|
|
145
|
+
raise CdxError("Invalid bundle passphrase or corrupted bundle.") from error
|
|
146
|
+
elif algorithm == _LEGACY_ALGORITHM:
|
|
147
|
+
expected_mac = _b64_decode(wrapper.get("hmac_sha256", ""))
|
|
148
|
+
enc_key, mac_key = _derive_keys(passphrase, salt)
|
|
149
|
+
actual_mac = hmac.new(mac_key, nonce + ciphertext, hashlib.sha256).digest()
|
|
150
|
+
if not hmac.compare_digest(actual_mac, expected_mac):
|
|
151
|
+
raise CdxError("Invalid bundle passphrase or corrupted bundle.")
|
|
152
|
+
payload_bytes = _xor_keystream(ciphertext, enc_key, nonce)
|
|
153
|
+
else:
|
|
154
|
+
raise CdxError("Unsupported bundle encryption algorithm.")
|
|
126
155
|
else:
|
|
127
156
|
payload_bytes = _b64_decode(payload_b64)
|
|
128
157
|
|
package/src/claude_refresh.py
CHANGED
|
@@ -38,6 +38,7 @@ def _refresh_claude_sessions(service, refresh_fn=None, target_names=None, force=
|
|
|
38
38
|
s for s in sessions
|
|
39
39
|
if s["provider"] == PROVIDER_CLAUDE
|
|
40
40
|
and s.get("enabled", True) is not False
|
|
41
|
+
and (s.get("auth") or {}).get("status") != "logged_out"
|
|
41
42
|
and (not target_names or s["name"] in target_names)
|
|
42
43
|
and (force or _is_stale(s, ttl_seconds=ttl_seconds))
|
|
43
44
|
]
|
package/src/cli.py
CHANGED
|
@@ -28,6 +28,8 @@ from .cli_commands import (
|
|
|
28
28
|
handle_remove,
|
|
29
29
|
handle_repair,
|
|
30
30
|
handle_rename,
|
|
31
|
+
handle_run,
|
|
32
|
+
handle_select,
|
|
31
33
|
handle_status,
|
|
32
34
|
handle_set,
|
|
33
35
|
handle_unset,
|
|
@@ -55,7 +57,7 @@ from .status_view import (
|
|
|
55
57
|
)
|
|
56
58
|
from .update_check import check_for_update
|
|
57
59
|
|
|
58
|
-
VERSION = "0.
|
|
60
|
+
VERSION = "0.7.0"
|
|
59
61
|
|
|
60
62
|
|
|
61
63
|
# ---------------------------------------------------------------------------
|
|
@@ -72,11 +74,13 @@ def _print_help(use_color=False):
|
|
|
72
74
|
f" {_style('cdx status [--json] [--refresh]', '36', use_color)}",
|
|
73
75
|
f" {_style('cdx status --small|-s [--refresh]', '36', use_color)}",
|
|
74
76
|
f" {_style('cdx status <name> [--json] [--refresh]', '36', use_color)}",
|
|
77
|
+
f" {_style('cdx select --provider PROVIDER [--min-reasoning-effort low|medium|high] [--min-power low|medium|high] [--require-ready] [--refresh] --json', '36', use_color)}",
|
|
78
|
+
f" {_style('cdx run [session] --cwd PATH (--prompt-file PATH|--prompt TEXT) [--provider PROVIDER] [--model MODEL] [--reasoning-effort low|medium|high] [--power low|medium|high] [--permission review|default|auto|full|workspace-write|read-only|danger-full-access] [--timeout-seconds N] --json', '36', use_color)}",
|
|
75
79
|
f" {_style('cdx context show|path|init|edit|clear|set [text...] [--json]', '36', use_color)}",
|
|
76
80
|
f" {_style('cdx config <name> [--json]', '36', use_color)}",
|
|
77
81
|
f" {_style('cdx power|perm|fast|model <name|all|provider:PROVIDER|a,b> <value|default> [--json]', '36', use_color)}",
|
|
78
|
-
f" {_style('cdx set <name>|--sessions all|a,b|--provider PROVIDER [--power low|medium|high|xhigh|max] [--permission review|default|auto|full] [--fast on|off] [--model MODEL] [--json]', '36', use_color)}",
|
|
79
|
-
f" {_style('cdx unset <name>|--sessions all|a,b|--provider PROVIDER (--power|--permission|--fast|--model|--all) [--json]', '36', use_color)}",
|
|
82
|
+
f" {_style('cdx set <name>|--sessions all|a,b|--provider PROVIDER [--power low|medium|high|xhigh|max] [--permission review|default|auto|full] [--fast on|off] [--model MODEL] [--priority 0..100] [--json]', '36', use_color)}",
|
|
83
|
+
f" {_style('cdx unset <name>|--sessions all|a,b|--provider PROVIDER (--power|--permission|--fast|--model|--priority|--all) [--json]', '36', use_color)}",
|
|
80
84
|
f" {_style('cdx history [name] [--limit N] [--summary] [--since 7d|today|DATE] [--from DATE] [--to DATE] [--json]', '36', use_color)}",
|
|
81
85
|
f" {_style('cdx last [--json]', '36', use_color)}",
|
|
82
86
|
f" {_style('cdx handoff <name> [--json]', '36', use_color)}",
|
|
@@ -228,12 +232,13 @@ def main(argv, options=None):
|
|
|
228
232
|
"service": service,
|
|
229
233
|
"signal_emitter": signal_emitter,
|
|
230
234
|
"spawn": spawn,
|
|
235
|
+
"spawn_headless": options.get("spawn_headless"),
|
|
231
236
|
"spawn_sync": spawn_sync,
|
|
232
237
|
"stdin_is_tty": stdin_is_tty,
|
|
233
238
|
"version": VERSION,
|
|
234
239
|
"cwd": options.get("cwd") or os.getcwd(),
|
|
235
240
|
"update_notice": _get_update_notice(service, env, options) if command not in (
|
|
236
|
-
"add", "cp", "ren", "rename", "mv", "rmv", "clean", "doctor", "repair", "update", "ready", "notify", "context", "config", "set", "unset", "power", "perm", "fast", "model", "history", "handoff", "login", "logout", "disable", "enable", "export", "import", "help", "version"
|
|
241
|
+
"add", "cp", "ren", "rename", "mv", "rmv", "clean", "doctor", "repair", "update", "ready", "notify", "context", "config", "set", "unset", "power", "perm", "fast", "model", "history", "handoff", "login", "logout", "disable", "enable", "export", "import", "select", "run", "help", "version"
|
|
237
242
|
) else None,
|
|
238
243
|
"use_color": use_color,
|
|
239
244
|
}
|
|
@@ -309,6 +314,12 @@ def main(argv, options=None):
|
|
|
309
314
|
if command == "status":
|
|
310
315
|
return handle_status(rest, ctx)
|
|
311
316
|
|
|
317
|
+
if command == "select":
|
|
318
|
+
return handle_select(rest, ctx)
|
|
319
|
+
|
|
320
|
+
if command == "run":
|
|
321
|
+
return handle_run(rest, ctx)
|
|
322
|
+
|
|
312
323
|
if command == "login":
|
|
313
324
|
return handle_login(rest, ctx)
|
|
314
325
|
|