cdx-manager 0.3.3 → 0.4.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 +183 -13
- package/bin/cdx +5 -2
- package/changelogs/CHANGELOGS_0_3_4.md +31 -0
- package/changelogs/CHANGELOGS_0_4_0.md +36 -0
- package/checksums/release-archives.json +9 -0
- package/install.ps1 +102 -0
- package/install.sh +51 -0
- package/package.json +3 -1
- package/pyproject.toml +1 -1
- package/src/backup_bundle.py +134 -0
- package/src/cli.py +111 -13
- package/src/cli_commands.py +360 -38
- package/src/health.py +13 -1
- package/src/provider_runtime.py +10 -1
- package/src/session_service.py +185 -2
- package/src/session_store.py +11 -0
- package/src/status_source.py +3 -1
- package/src/update_check.py +107 -0
package/README.md
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
# CDX Manager
|
|
2
2
|
|
|
3
|
+
[](LICENSE)  
|
|
4
|
+
|
|
3
5
|
**Run multiple Codex and Claude sessions from one terminal. Switch between accounts instantly.**
|
|
4
6
|
|
|
5
7
|
If you use AI coding tools at scale ; multiple accounts, multiple providers : you know the friction: re-authenticating, losing context, juggling environment variables. `cdx` removes all of that.
|
|
6
8
|
|
|
7
9
|
One command to launch any session. Zero auth juggling.
|
|
8
10
|
|
|
9
|
-
|
|
11
|
+
<img width="213" height="227" alt="image" src="https://github.com/user-attachments/assets/f15f449c-d23e-47fe-a455-17c7386f9be2" />
|
|
12
|
+
<img width="645" height="129" alt="image" src="https://github.com/user-attachments/assets/34bcb395-f832-4da6-9247-3e5022e75e56" />
|
|
10
13
|
|
|
11
14
|
---
|
|
12
15
|
|
|
@@ -16,7 +19,9 @@ One command to launch any session. Zero auth juggling.
|
|
|
16
19
|
- [Technical Overview](#technical-overview)
|
|
17
20
|
- [Getting Started](#getting-started)
|
|
18
21
|
- [All Commands](#all-commands)
|
|
22
|
+
- [JSON Output](#json-output)
|
|
19
23
|
- [Available Scripts](#available-scripts)
|
|
24
|
+
- [Windows Support](#windows-support)
|
|
20
25
|
- [Project Structure](#project-structure)
|
|
21
26
|
- [Data Layout](#data-layout)
|
|
22
27
|
- [Troubleshooting](#troubleshooting)
|
|
@@ -53,6 +58,7 @@ One command to launch any session. Zero auth juggling.
|
|
|
53
58
|
- Fallback: `status-source` scans provider JSONL history files and terminal log transcripts, strips ANSI/OSC sequences, and extracts `usage%`, `5h remaining%`, and `week remaining%` via pattern matching.
|
|
54
59
|
- Claude status refreshes are cached briefly by default; pass `--refresh` to force a live rate-limit probe.
|
|
55
60
|
- If `script` is unavailable, Codex launch falls back to running without transcript capture.
|
|
61
|
+
- On Windows, transcript capture is optional. If no compatible `script` wrapper is installed, Codex still launches normally without transcript capture.
|
|
56
62
|
- Auth probe: synchronous subprocess call to `codex login status` or `claude auth status` before any interactive launch.
|
|
57
63
|
- Signal forwarding: `SIGINT`, `SIGTERM`, and `SIGHUP` are forwarded to the child process and produce clean exit codes.
|
|
58
64
|
- Test stack: Python built-in `unittest` runner with no test framework dependency.
|
|
@@ -87,16 +93,33 @@ With uv:
|
|
|
87
93
|
uv tool install cdx-manager
|
|
88
94
|
```
|
|
89
95
|
|
|
96
|
+
On Windows with PowerShell:
|
|
97
|
+
|
|
98
|
+
```powershell
|
|
99
|
+
npm install -g cdx-manager
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
With the standalone PowerShell installer:
|
|
103
|
+
|
|
104
|
+
```powershell
|
|
105
|
+
Invoke-WebRequest https://raw.githubusercontent.com/AlexAgo83/cdx-manager/main/install.ps1 -OutFile install.ps1
|
|
106
|
+
# Optional: set CDX_SHA256 before running if you have a trusted checksum
|
|
107
|
+
powershell -ExecutionPolicy Bypass -File .\install.ps1
|
|
108
|
+
```
|
|
109
|
+
|
|
90
110
|
With the standalone GitHub installer:
|
|
91
111
|
|
|
92
112
|
```bash
|
|
93
|
-
curl -fsSL https://raw.githubusercontent.com/AlexAgo83/cdx-manager/main/install.sh
|
|
113
|
+
curl -fsSL https://raw.githubusercontent.com/AlexAgo83/cdx-manager/main/install.sh -o install.sh
|
|
114
|
+
# Optional: set CDX_SHA256 before running if you have a trusted checksum
|
|
115
|
+
sh install.sh
|
|
94
116
|
```
|
|
95
117
|
|
|
96
118
|
For a specific version:
|
|
97
119
|
|
|
98
120
|
```bash
|
|
99
|
-
curl -fsSL https://raw.githubusercontent.com/AlexAgo83/cdx-manager/main/install.sh
|
|
121
|
+
curl -fsSL https://raw.githubusercontent.com/AlexAgo83/cdx-manager/main/install.sh -o install.sh
|
|
122
|
+
CDX_VERSION=v0.4.0 sh install.sh
|
|
100
123
|
```
|
|
101
124
|
|
|
102
125
|
From source:
|
|
@@ -107,6 +130,14 @@ cd cdx-manager
|
|
|
107
130
|
make install
|
|
108
131
|
```
|
|
109
132
|
|
|
133
|
+
From source on Windows:
|
|
134
|
+
|
|
135
|
+
```powershell
|
|
136
|
+
git clone <repo>
|
|
137
|
+
cd cdx-manager
|
|
138
|
+
npm install -g .
|
|
139
|
+
```
|
|
140
|
+
|
|
110
141
|
`cdx` is now available globally. Changes to the source take effect immediately — no reinstall needed.
|
|
111
142
|
|
|
112
143
|
To uninstall:
|
|
@@ -115,12 +146,25 @@ To uninstall:
|
|
|
115
146
|
make uninstall
|
|
116
147
|
```
|
|
117
148
|
|
|
149
|
+
To uninstall on Windows after `npm install -g`:
|
|
150
|
+
|
|
151
|
+
```powershell
|
|
152
|
+
npm uninstall -g cdx-manager
|
|
153
|
+
```
|
|
154
|
+
|
|
118
155
|
Alternatively, for a non-symlinked global source install:
|
|
119
156
|
|
|
120
157
|
```bash
|
|
121
158
|
npm install -g .
|
|
122
159
|
```
|
|
123
160
|
|
|
161
|
+
Security note:
|
|
162
|
+
|
|
163
|
+
- The standalone installers try to resolve official release checksums from `checksums/release-archives.json`.
|
|
164
|
+
- You can still override verification explicitly through `CDX_SHA256`.
|
|
165
|
+
- Prefer `npm`, `pipx`, or `uv` when you want registry-backed install flows.
|
|
166
|
+
- If you use the standalone script, download it first, inspect it, and prefer a release with an official checksum entry.
|
|
167
|
+
|
|
124
168
|
### Environment
|
|
125
169
|
|
|
126
170
|
By default, `cdx` stores all data under `~/.cdx/`. Override with:
|
|
@@ -137,6 +181,24 @@ export CDX_SCRIPT_BIN=script
|
|
|
137
181
|
export CDX_SCRIPT_ARGS='-q -F {transcript}'
|
|
138
182
|
```
|
|
139
183
|
|
|
184
|
+
PowerShell equivalents:
|
|
185
|
+
|
|
186
|
+
```powershell
|
|
187
|
+
$env:CDX_HOME = "C:\cdx-data"
|
|
188
|
+
$env:CDX_CLAUDE_STATUS_MODEL = "claude-haiku-4-5-20251001"
|
|
189
|
+
$env:CDX_SCRIPT_BIN = "script"
|
|
190
|
+
$env:CDX_SCRIPT_ARGS = "-q -F {transcript}"
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Command Prompt equivalents:
|
|
194
|
+
|
|
195
|
+
```cmd
|
|
196
|
+
set CDX_HOME=C:\cdx-data
|
|
197
|
+
set CDX_CLAUDE_STATUS_MODEL=claude-haiku-4-5-20251001
|
|
198
|
+
set CDX_SCRIPT_BIN=script
|
|
199
|
+
set CDX_SCRIPT_ARGS=-q -F {transcript}
|
|
200
|
+
```
|
|
201
|
+
|
|
140
202
|
### Quick Start
|
|
141
203
|
|
|
142
204
|
```bash
|
|
@@ -163,19 +225,23 @@ cdx status
|
|
|
163
225
|
| Command | Description |
|
|
164
226
|
|---|---|
|
|
165
227
|
| `cdx` | List all sessions with last-updated timestamps |
|
|
228
|
+
| `cdx --json` | List all sessions as a machine-readable JSON payload |
|
|
166
229
|
| `cdx <name>` | Launch a session (checks auth first) |
|
|
167
|
-
| `cdx
|
|
168
|
-
| `cdx
|
|
169
|
-
| `cdx
|
|
170
|
-
| `cdx
|
|
171
|
-
| `cdx
|
|
172
|
-
| `cdx
|
|
173
|
-
| `cdx
|
|
230
|
+
| `cdx <name> [--json]` | Launch a session; `--json` returns a structured success payload after the interactive run ends |
|
|
231
|
+
| `cdx add [provider] <name> [--json]` | Register a new session (`provider`: `codex` or `claude`, default: `codex`) |
|
|
232
|
+
| `cdx cp <source> <dest> [--json]` | Copy a session into another session name, overwriting the destination if it exists |
|
|
233
|
+
| `cdx ren <source> <dest> [--json]` | Rename a session and move its auth data |
|
|
234
|
+
| `cdx login <name> [--json]` | Re-authenticate a session (logout + login) |
|
|
235
|
+
| `cdx logout <name> [--json]` | Log out of a session |
|
|
236
|
+
| `cdx rmv <name> [--force] [--json]` | Remove a session and its auth data (prompts for confirmation unless `--force`) |
|
|
237
|
+
| `cdx clean [name] [--json]` | Clear launch transcript logs for one session or all sessions |
|
|
238
|
+
| `cdx export <file> [--include-auth] [--sessions a,b] [--passphrase-env VAR] [--force] [--json]` | Export sessions to a portable bundle; `--include-auth` encrypts auth data with a passphrase |
|
|
239
|
+
| `cdx import <file> [--sessions a,b] [--passphrase-env VAR] [--force] [--json]` | Import sessions from a bundle into the current `CDX_HOME` |
|
|
174
240
|
| `cdx doctor [--json]` | Inspect CLI dependencies, CDX_HOME permissions, missing state, orphan profiles, and pending quarantines |
|
|
175
241
|
| `cdx repair [--dry-run] [--force] [--json]` | Plan or apply safe repairs for missing state files, quarantines, and orphan profiles |
|
|
176
|
-
| `cdx notify <name> --at-reset [--poll seconds] [--once]` | Wait for a session reset time and send a desktop notification when due |
|
|
177
|
-
| `cdx notify --next-ready [--poll seconds] [--once]` | Wait until the recommended session is usable or needs a refresh after reset |
|
|
178
|
-
| `cdx status [--json] [--refresh]` | Show token usage table for all sessions; JSON
|
|
242
|
+
| `cdx notify <name> --at-reset [--poll seconds] [--once] [--json]` | Wait for a session reset time and send a desktop notification when due |
|
|
243
|
+
| `cdx notify --next-ready [--poll seconds] [--once] [--json]` | Wait until the recommended session is usable or needs a refresh after reset |
|
|
244
|
+
| `cdx status [--json] [--refresh]` | Show token usage table for all sessions; JSON returns a versioned payload with structured warnings |
|
|
179
245
|
| `cdx status --small [--refresh]` / `cdx status -s [--refresh]` | Show compact token usage table without provider, blocking quota, credits, and updated columns |
|
|
180
246
|
| `cdx status <name> [--json] [--refresh]` | Show detailed usage breakdown for one session |
|
|
181
247
|
| `cdx --help` | Show usage |
|
|
@@ -183,6 +249,90 @@ cdx status
|
|
|
183
249
|
|
|
184
250
|
---
|
|
185
251
|
|
|
252
|
+
## JSON Output
|
|
253
|
+
|
|
254
|
+
`cdx-manager` can be consumed by other apps through its CLI JSON contract.
|
|
255
|
+
|
|
256
|
+
Commands with machine-readable output:
|
|
257
|
+
|
|
258
|
+
- `cdx --json`
|
|
259
|
+
- `cdx status --json`
|
|
260
|
+
- `cdx status <name> --json`
|
|
261
|
+
- `cdx add ... --json`
|
|
262
|
+
- `cdx cp ... --json`
|
|
263
|
+
- `cdx ren ... --json`
|
|
264
|
+
- `cdx rmv ... --json`
|
|
265
|
+
- `cdx clean ... --json`
|
|
266
|
+
- `cdx export ... --json`
|
|
267
|
+
- `cdx import ... --json`
|
|
268
|
+
- `cdx login ... --json`
|
|
269
|
+
- `cdx logout ... --json`
|
|
270
|
+
- `cdx doctor --json`
|
|
271
|
+
- `cdx repair --json`
|
|
272
|
+
- `cdx notify ... --json`
|
|
273
|
+
|
|
274
|
+
Success payloads follow a shared envelope:
|
|
275
|
+
|
|
276
|
+
```json
|
|
277
|
+
{
|
|
278
|
+
"schema_version": 1,
|
|
279
|
+
"ok": true,
|
|
280
|
+
"action": "add",
|
|
281
|
+
"message": "Created session work (codex)",
|
|
282
|
+
"warnings": [],
|
|
283
|
+
"session": {
|
|
284
|
+
"name": "work"
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
Errors use a shared stderr JSON envelope whenever `--json` is present:
|
|
290
|
+
|
|
291
|
+
```json
|
|
292
|
+
{
|
|
293
|
+
"schema_version": 1,
|
|
294
|
+
"ok": false,
|
|
295
|
+
"error": {
|
|
296
|
+
"code": "invalid_usage",
|
|
297
|
+
"message": "Usage: cdx status [--json] [--refresh] | ...",
|
|
298
|
+
"exit_code": 1
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
`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`.
|
|
304
|
+
|
|
305
|
+
This makes `cdx-manager` usable from editor plugins, scripts, and desktop apps without scraping human-readable terminal output.
|
|
306
|
+
|
|
307
|
+
---
|
|
308
|
+
|
|
309
|
+
## Backup And Restore
|
|
310
|
+
|
|
311
|
+
You can move sessions between machines with portable bundles:
|
|
312
|
+
|
|
313
|
+
```bash
|
|
314
|
+
cdx export backup.cdx
|
|
315
|
+
cdx import backup.cdx
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
To migrate auth and avoid logging in again, include auth data in an encrypted bundle:
|
|
319
|
+
|
|
320
|
+
```bash
|
|
321
|
+
export CDX_BUNDLE_PASSPHRASE='choose-a-strong-passphrase'
|
|
322
|
+
cdx export backup-auth.cdx --include-auth --passphrase-env CDX_BUNDLE_PASSPHRASE
|
|
323
|
+
cdx import backup-auth.cdx --passphrase-env CDX_BUNDLE_PASSPHRASE
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
Notes:
|
|
327
|
+
|
|
328
|
+
- `--include-auth` is encrypted and requires a passphrase.
|
|
329
|
+
- Without `--passphrase-env`, `cdx` prompts in an interactive terminal.
|
|
330
|
+
- `--sessions work,perso` exports or imports only a subset.
|
|
331
|
+
- `--force` allows overwriting existing destination sessions during import or replacing an existing bundle file during export.
|
|
332
|
+
- Auth bundles contain credentials. Treat them like secrets and delete them after transfer.
|
|
333
|
+
|
|
334
|
+
---
|
|
335
|
+
|
|
186
336
|
## Available Scripts
|
|
187
337
|
|
|
188
338
|
- `npm test`: run the Python test suite
|
|
@@ -193,6 +343,24 @@ cdx status
|
|
|
193
343
|
|
|
194
344
|
---
|
|
195
345
|
|
|
346
|
+
## Windows Support
|
|
347
|
+
|
|
348
|
+
- Supported install paths on Windows:
|
|
349
|
+
- `npm install -g cdx-manager`
|
|
350
|
+
- `pipx install cdx-manager`
|
|
351
|
+
- `uv tool install cdx-manager`
|
|
352
|
+
- `install.ps1`
|
|
353
|
+
- `install.sh` is Unix-only.
|
|
354
|
+
- `make install` and `make uninstall` are Unix-oriented convenience commands, not the default Windows path.
|
|
355
|
+
- `cdx` isolates Claude sessions on Windows by setting `HOME`, `USERPROFILE`, `HOMEDRIVE`, and `HOMEPATH`.
|
|
356
|
+
- Desktop notifications use PowerShell on Windows.
|
|
357
|
+
- Codex transcript capture is optional on Windows:
|
|
358
|
+
- if a compatible `script` command is available and exposed via `CDX_SCRIPT_BIN`, `cdx` uses it
|
|
359
|
+
- otherwise Codex launches without transcript capture and the session still works normally
|
|
360
|
+
- `cdx doctor` reports the transcript-capture fallback explicitly so missing `script` on Windows is visible without being treated as a hard failure.
|
|
361
|
+
|
|
362
|
+
---
|
|
363
|
+
|
|
196
364
|
## Project Structure
|
|
197
365
|
|
|
198
366
|
```text
|
|
@@ -203,6 +371,7 @@ src/
|
|
|
203
371
|
cli.py # Top-level command router
|
|
204
372
|
cli_commands.py # Command handlers and argument handling
|
|
205
373
|
cli_render.py # Terminal formatting, tables, colors, and errors
|
|
374
|
+
backup_bundle.py # Portable session bundle encoding/decoding + auth encryption
|
|
206
375
|
status_view.py # Status table/detail rendering and priority ranking
|
|
207
376
|
provider_runtime.py # Provider launch/auth commands, transcripts, signals
|
|
208
377
|
claude_refresh.py # Claude usage refresh orchestration
|
|
@@ -255,6 +424,7 @@ Session names are URL-encoded when used as directory or file names. CLI command
|
|
|
255
424
|
- **`cdx rmv` says "Removal requires confirmation in an interactive terminal"** — pass `--force` to bypass the prompt in non-interactive environments (scripts, CI).
|
|
256
425
|
- **`cdx login` hangs** — the provider's login flow requires a browser or device code. Follow the on-screen instructions in the terminal that opened.
|
|
257
426
|
- **`make install` says `npm link` is not found** — ensure Node.js and npm are installed and in your PATH.
|
|
427
|
+
- **On Windows, `doctor` warns that `script` is missing** — this is expected on many setups. Codex still launches, but transcript capture stays disabled unless you point `CDX_SCRIPT_BIN` to a compatible wrapper.
|
|
258
428
|
|
|
259
429
|
---
|
|
260
430
|
|
package/bin/cdx
CHANGED
|
@@ -8,7 +8,7 @@ ROOT = Path(__file__).resolve().parent.parent
|
|
|
8
8
|
if str(ROOT) not in sys.path:
|
|
9
9
|
sys.path.insert(0, str(ROOT))
|
|
10
10
|
|
|
11
|
-
from src.cli import format_error, main # noqa: E402
|
|
11
|
+
from src.cli import format_error, format_json_error, main, wants_json # noqa: E402
|
|
12
12
|
from src.errors import CdxError # noqa: E402
|
|
13
13
|
|
|
14
14
|
|
|
@@ -16,5 +16,8 @@ if __name__ == "__main__":
|
|
|
16
16
|
try:
|
|
17
17
|
raise SystemExit(main(sys.argv[1:]))
|
|
18
18
|
except CdxError as error:
|
|
19
|
-
sys.
|
|
19
|
+
if wants_json(sys.argv[1:]):
|
|
20
|
+
sys.stderr.write(f"{format_json_error(error)}\n")
|
|
21
|
+
else:
|
|
22
|
+
sys.stderr.write(f"{format_error(error)}\n")
|
|
20
23
|
raise SystemExit(error.exit_code)
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# CHANGELOGS_0_3_4
|
|
2
|
+
|
|
3
|
+
Release date: 2026-04-16
|
|
4
|
+
|
|
5
|
+
## CDX Manager 0.3.4
|
|
6
|
+
|
|
7
|
+
CDX Manager 0.3.4 makes the CLI consumable by other applications through a structured JSON contract and rounds out the Windows release surface.
|
|
8
|
+
|
|
9
|
+
### JSON CLI API
|
|
10
|
+
|
|
11
|
+
- Added `cdx --json` to list known sessions as a machine-readable payload.
|
|
12
|
+
- Added `--json` support for session-management commands: `add`, `cp`, `ren`, `rmv`, `clean`, `login`, and `logout`.
|
|
13
|
+
- Added a shared success envelope for JSON responses with `ok`, `action`, `message`, and `warnings`.
|
|
14
|
+
- Added a shared stderr error envelope for JSON mode with machine-readable `code`, `message`, and `exit_code`.
|
|
15
|
+
- Documented the JSON contract in the README so editor plugins and desktop apps can integrate without scraping human-readable terminal output.
|
|
16
|
+
|
|
17
|
+
### Windows release hardening
|
|
18
|
+
|
|
19
|
+
- Added a native `install.ps1` installer for Windows.
|
|
20
|
+
- Documented supported Windows install paths and the optional transcript-capture fallback.
|
|
21
|
+
- Added targeted `win32` unit coverage for CLI startup, provider environment isolation, notifications, and session-store locking.
|
|
22
|
+
- Added a Windows CI smoke flow that installs the package and exercises core CLI commands with shimmed providers.
|
|
23
|
+
|
|
24
|
+
### Validation
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm run lint
|
|
28
|
+
npm test
|
|
29
|
+
npm_config_cache=/tmp/cdx-npm-cache npm pack --dry-run
|
|
30
|
+
python3 logics/skills/logics.py lint --require-status
|
|
31
|
+
```
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# CHANGELOGS_0_4_0
|
|
2
|
+
|
|
3
|
+
Release date: 2026-04-16
|
|
4
|
+
|
|
5
|
+
## CDX Manager 0.4.0
|
|
6
|
+
|
|
7
|
+
CDX Manager 0.4.0 adds portable session backup and restore, surfaces cached release-update notices inside the CLI, and tightens Codex status isolation across multiple accounts.
|
|
8
|
+
|
|
9
|
+
### Portable session bundles
|
|
10
|
+
|
|
11
|
+
- Added `cdx export <file>` and `cdx import <file>` for moving sessions between machines.
|
|
12
|
+
- Added optional encrypted auth export with `--include-auth` and interactive or environment-driven passphrase handling.
|
|
13
|
+
- Added subset export/import support with `--sessions`.
|
|
14
|
+
- Preserved per-session state alongside session records so imported environments keep their local metadata.
|
|
15
|
+
- Added bundle schema validation and integrity checks during import.
|
|
16
|
+
|
|
17
|
+
### Update awareness and installer hardening
|
|
18
|
+
|
|
19
|
+
- Added cached GitHub release checks so the CLI can warn when a newer `cdx-manager` release is available without hitting the network on every command.
|
|
20
|
+
- Surfaced update notices in interactive output and structured JSON warnings.
|
|
21
|
+
- Hardened the standalone install scripts to consume official release-archive checksums when available.
|
|
22
|
+
- Documented the checksum-backed installer flow and backup/restore usage in the README.
|
|
23
|
+
|
|
24
|
+
### Status isolation fix
|
|
25
|
+
|
|
26
|
+
- Fixed Codex status parsing so boxed blank lines in TUI transcripts no longer drop the `Account:` context line.
|
|
27
|
+
- Restored account-aware status selection when multiple sessions contain similar `/status` blocks.
|
|
28
|
+
- Added regression coverage for mixed-account transcript selection and bundle export/import flows.
|
|
29
|
+
|
|
30
|
+
### Validation
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npm run lint
|
|
34
|
+
npm test
|
|
35
|
+
python3 -m build --no-isolation
|
|
36
|
+
```
|
package/install.ps1
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
param(
|
|
2
|
+
[string]$Version = $env:CDX_VERSION,
|
|
3
|
+
[string]$Prefix = $env:CDX_PREFIX,
|
|
4
|
+
[string]$Sha256 = $env:CDX_SHA256,
|
|
5
|
+
[string]$ChecksumsUrl = $env:CDX_CHECKSUMS_URL
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
$ErrorActionPreference = "Stop"
|
|
9
|
+
|
|
10
|
+
$repo = "AlexAgo83/cdx-manager"
|
|
11
|
+
if (-not $ChecksumsUrl) {
|
|
12
|
+
$ChecksumsUrl = "https://raw.githubusercontent.com/$repo/main/checksums/release-archives.json"
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function Require-Command {
|
|
16
|
+
param([string]$Name)
|
|
17
|
+
if (-not (Get-Command $Name -ErrorAction SilentlyContinue)) {
|
|
18
|
+
throw "cdx install: missing required command: $Name"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
Require-Command python
|
|
23
|
+
|
|
24
|
+
if (-not $Prefix) {
|
|
25
|
+
$Prefix = Join-Path $env:LOCALAPPDATA "cdx-manager"
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
$binDir = Join-Path $Prefix "bin"
|
|
29
|
+
$installRoot = Join-Path $Prefix "versions"
|
|
30
|
+
|
|
31
|
+
if (-not $Version) {
|
|
32
|
+
$release = Invoke-RestMethod -Uri "https://api.github.com/repos/$repo/releases/latest"
|
|
33
|
+
$Version = $release.tag_name
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if ($Version.StartsWith("v")) {
|
|
37
|
+
$tag = $Version
|
|
38
|
+
} else {
|
|
39
|
+
$tag = "v$Version"
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
$tmpRoot = Join-Path ([System.IO.Path]::GetTempPath()) ("cdx-install-" + [guid]::NewGuid().ToString("N"))
|
|
43
|
+
$archivePath = Join-Path $tmpRoot "cdx-manager.zip"
|
|
44
|
+
$extractRoot = Join-Path $tmpRoot "extract"
|
|
45
|
+
$targetDir = Join-Path $installRoot $tag.TrimStart("v")
|
|
46
|
+
$archiveUrl = "https://github.com/$repo/archive/refs/tags/$tag.zip"
|
|
47
|
+
|
|
48
|
+
New-Item -ItemType Directory -Force -Path $tmpRoot, $extractRoot, $binDir, $installRoot | Out-Null
|
|
49
|
+
|
|
50
|
+
try {
|
|
51
|
+
Invoke-WebRequest -Uri $archiveUrl -OutFile $archivePath
|
|
52
|
+
if (-not $Sha256) {
|
|
53
|
+
try {
|
|
54
|
+
$checksums = Invoke-RestMethod -Uri $ChecksumsUrl
|
|
55
|
+
$Sha256 = $checksums.releases.$tag.github_zip_sha256
|
|
56
|
+
} catch {
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if ($Sha256) {
|
|
60
|
+
$actualSha256 = (Get-FileHash -Algorithm SHA256 -Path $archivePath).Hash.ToLowerInvariant()
|
|
61
|
+
if ($actualSha256 -ne $Sha256.ToLowerInvariant()) {
|
|
62
|
+
throw "cdx install: checksum mismatch for $tag`nexpected: $Sha256`nactual: $actualSha256"
|
|
63
|
+
}
|
|
64
|
+
} else {
|
|
65
|
+
Write-Warning "No official checksum available for $tag; continuing without verification."
|
|
66
|
+
}
|
|
67
|
+
Expand-Archive -Path $archivePath -DestinationPath $extractRoot -Force
|
|
68
|
+
|
|
69
|
+
$sourceDir = Get-ChildItem -Path $extractRoot -Directory | Select-Object -First 1
|
|
70
|
+
if (-not $sourceDir) {
|
|
71
|
+
throw "cdx install: failed to extract release archive"
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (Test-Path $targetDir) {
|
|
75
|
+
Remove-Item -Recurse -Force $targetDir
|
|
76
|
+
}
|
|
77
|
+
New-Item -ItemType Directory -Force -Path $targetDir | Out-Null
|
|
78
|
+
Copy-Item -Path (Join-Path $sourceDir.FullName "*") -Destination $targetDir -Recurse -Force
|
|
79
|
+
|
|
80
|
+
$launcherPath = Join-Path $binDir "cdx.cmd"
|
|
81
|
+
$launcher = @"
|
|
82
|
+
@echo off
|
|
83
|
+
set SCRIPT=%~dp0..\versions\${($tag.TrimStart("v"))}\bin\cdx
|
|
84
|
+
where py >nul 2>nul
|
|
85
|
+
if %ERRORLEVEL%==0 (
|
|
86
|
+
py -3 "%SCRIPT%" %*
|
|
87
|
+
exit /b %ERRORLEVEL%
|
|
88
|
+
)
|
|
89
|
+
python "%SCRIPT%" %*
|
|
90
|
+
"@
|
|
91
|
+
Set-Content -Path $launcherPath -Value $launcher -Encoding ascii
|
|
92
|
+
|
|
93
|
+
Write-Host "Installed cdx $tag to $targetDir"
|
|
94
|
+
Write-Host "Created launcher $launcherPath"
|
|
95
|
+
if (-not (($env:PATH -split ";") -contains $binDir)) {
|
|
96
|
+
Write-Warning "Add $binDir to PATH to run cdx from anywhere."
|
|
97
|
+
}
|
|
98
|
+
} finally {
|
|
99
|
+
if (Test-Path $tmpRoot) {
|
|
100
|
+
Remove-Item -Recurse -Force $tmpRoot
|
|
101
|
+
}
|
|
102
|
+
}
|
package/install.sh
CHANGED
|
@@ -6,6 +6,7 @@ VERSION="${CDX_VERSION:-}"
|
|
|
6
6
|
PREFIX="${PREFIX:-$HOME/.local}"
|
|
7
7
|
BIN_DIR="${BIN_DIR:-$PREFIX/bin}"
|
|
8
8
|
INSTALL_ROOT="${CDX_INSTALL_ROOT:-$PREFIX/share/cdx-manager}"
|
|
9
|
+
CHECKSUMS_URL="${CDX_CHECKSUMS_URL:-https://raw.githubusercontent.com/$REPO/main/checksums/release-archives.json}"
|
|
9
10
|
|
|
10
11
|
need() {
|
|
11
12
|
if ! command -v "$1" >/dev/null 2>&1; then
|
|
@@ -18,6 +19,38 @@ need curl
|
|
|
18
19
|
need tar
|
|
19
20
|
need python3
|
|
20
21
|
|
|
22
|
+
sha256_file() {
|
|
23
|
+
if command -v sha256sum >/dev/null 2>&1; then
|
|
24
|
+
sha256sum "$1" | awk '{print $1}'
|
|
25
|
+
return
|
|
26
|
+
fi
|
|
27
|
+
if command -v shasum >/dev/null 2>&1; then
|
|
28
|
+
shasum -a 256 "$1" | awk '{print $1}'
|
|
29
|
+
return
|
|
30
|
+
fi
|
|
31
|
+
echo "cdx install: missing checksum tool (sha256sum or shasum)" >&2
|
|
32
|
+
exit 1
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
resolve_expected_sha256() {
|
|
36
|
+
curl -fsSL "$CHECKSUMS_URL" |
|
|
37
|
+
python3 - "$1" <<'PY'
|
|
38
|
+
import json
|
|
39
|
+
import sys
|
|
40
|
+
|
|
41
|
+
tag = sys.argv[1]
|
|
42
|
+
try:
|
|
43
|
+
payload = json.load(sys.stdin)
|
|
44
|
+
except Exception:
|
|
45
|
+
raise SystemExit(1)
|
|
46
|
+
|
|
47
|
+
release = (payload.get("releases") or {}).get(tag) or {}
|
|
48
|
+
value = release.get("github_tarball_sha256")
|
|
49
|
+
if value:
|
|
50
|
+
print(value)
|
|
51
|
+
PY
|
|
52
|
+
}
|
|
53
|
+
|
|
21
54
|
if [ -z "$VERSION" ]; then
|
|
22
55
|
VERSION="$(
|
|
23
56
|
curl -fsSL "https://api.github.com/repos/$REPO/releases/latest" |
|
|
@@ -38,6 +71,24 @@ trap cleanup EXIT INT TERM
|
|
|
38
71
|
|
|
39
72
|
ARCHIVE_URL="https://github.com/$REPO/archive/refs/tags/$TAG.tar.gz"
|
|
40
73
|
curl -fsSL "$ARCHIVE_URL" -o "$TMP_DIR/cdx-manager.tar.gz"
|
|
74
|
+
|
|
75
|
+
EXPECTED_SHA256="${CDX_SHA256:-}"
|
|
76
|
+
if [ -z "$EXPECTED_SHA256" ]; then
|
|
77
|
+
EXPECTED_SHA256="$(resolve_expected_sha256 "$TAG" 2>/dev/null || true)"
|
|
78
|
+
fi
|
|
79
|
+
|
|
80
|
+
if [ -n "$EXPECTED_SHA256" ]; then
|
|
81
|
+
ACTUAL_SHA256="$(sha256_file "$TMP_DIR/cdx-manager.tar.gz")"
|
|
82
|
+
if [ "$ACTUAL_SHA256" != "$EXPECTED_SHA256" ]; then
|
|
83
|
+
echo "cdx install: checksum mismatch for $TAG" >&2
|
|
84
|
+
echo "expected: $EXPECTED_SHA256" >&2
|
|
85
|
+
echo "actual: $ACTUAL_SHA256" >&2
|
|
86
|
+
exit 1
|
|
87
|
+
fi
|
|
88
|
+
else
|
|
89
|
+
echo "cdx install: warning: no official checksum available for $TAG; continuing without verification" >&2
|
|
90
|
+
fi
|
|
91
|
+
|
|
41
92
|
tar -xzf "$TMP_DIR/cdx-manager.tar.gz" -C "$TMP_DIR"
|
|
42
93
|
|
|
43
94
|
SRC_DIR="$(find "$TMP_DIR" -mindepth 1 -maxdepth 1 -type d | head -n 1)"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cdx-manager",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Terminal session manager for Codex and Claude accounts.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Alexandre Agostini",
|
|
@@ -25,9 +25,11 @@
|
|
|
25
25
|
},
|
|
26
26
|
"files": [
|
|
27
27
|
"bin",
|
|
28
|
+
"checksums",
|
|
28
29
|
"changelogs",
|
|
29
30
|
"src",
|
|
30
31
|
"install.sh",
|
|
32
|
+
"install.ps1",
|
|
31
33
|
"pyproject.toml",
|
|
32
34
|
"README.md",
|
|
33
35
|
"LICENSE"
|
package/pyproject.toml
CHANGED