@gkorepanov/ccodex 0.5.0-rc.8 → 0.5.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 +159 -157
- package/config/compatibility.json +1 -1
- package/dist/claude/delegation.d.ts +10 -0
- package/dist/claude/delegation.js +41 -0
- package/dist/claude/delegation.js.map +1 -0
- package/dist/claude/native/catalog.d.ts +5 -0
- package/dist/claude/native/catalog.js +26 -17
- package/dist/claude/native/catalog.js.map +1 -1
- package/dist/claude/native/history.js +4 -3
- package/dist/claude/native/history.js.map +1 -1
- package/dist/claude/native/pages.d.ts +2 -0
- package/dist/claude/native/pages.js +6 -1
- package/dist/claude/native/pages.js.map +1 -1
- package/dist/claude/native/projector.js +33 -12
- package/dist/claude/native/projector.js.map +1 -1
- package/dist/claude/native/records.js +19 -0
- package/dist/claude/native/records.js.map +1 -1
- package/dist/claude/native/search.d.ts +7 -0
- package/dist/claude/native/search.js +79 -0
- package/dist/claude/native/search.js.map +1 -0
- package/dist/claude/native/summary.d.ts +6 -1
- package/dist/claude/native/summary.js +24 -6
- package/dist/claude/native/summary.js.map +1 -1
- package/dist/claude/peers.d.ts +2 -0
- package/dist/claude/peers.js +13 -4
- package/dist/claude/peers.js.map +1 -1
- package/dist/claude/processes.d.ts +2 -0
- package/dist/claude/processes.js +15 -0
- package/dist/claude/processes.js.map +1 -1
- package/dist/claude/sdk.d.ts +6 -5
- package/dist/claude/sdk.js +15 -8
- package/dist/claude/sdk.js.map +1 -1
- package/dist/claude/session.d.ts +25 -5
- package/dist/claude/session.js +134 -29
- package/dist/claude/session.js.map +1 -1
- package/dist/claude/threads.d.ts +43 -3
- package/dist/claude/threads.js +255 -60
- package/dist/claude/threads.js.map +1 -1
- package/dist/claude/toolMapper.d.ts +7 -0
- package/dist/claude/toolMapper.js +14 -1
- package/dist/claude/toolMapper.js.map +1 -1
- package/dist/config.d.ts +2 -0
- package/dist/config.js +2 -1
- package/dist/config.js.map +1 -1
- package/dist/daemon/daemon.d.ts +3 -0
- package/dist/daemon/daemon.js +6 -3
- package/dist/daemon/daemon.js.map +1 -1
- package/dist/daemon/supervisor.d.ts +3 -0
- package/dist/daemon/supervisor.js +2 -0
- package/dist/daemon/supervisor.js.map +1 -1
- package/dist/desktop/stdioFrontend.js +1 -1
- package/dist/desktop/stdioFrontend.js.map +1 -1
- package/dist/gateway/catalog.js +35 -20
- package/dist/gateway/catalog.js.map +1 -1
- package/dist/gateway/connection.d.ts +2 -0
- package/dist/gateway/connection.js +14 -2
- package/dist/gateway/connection.js.map +1 -1
- package/dist/gateway/lineage.d.ts +9 -1
- package/dist/gateway/lineage.js +134 -37
- package/dist/gateway/lineage.js.map +1 -1
- package/dist/gateway/server.d.ts +2 -1
- package/dist/gateway/server.js +24 -12
- package/dist/gateway/server.js.map +1 -1
- package/dist/gateway/status.d.ts +15 -5
- package/dist/gateway/status.js +142 -47
- package/dist/gateway/status.js.map +1 -1
- package/dist/gateway/stock.js +17 -2
- package/dist/gateway/stock.js.map +1 -1
- package/dist/instructions.d.ts +4 -0
- package/dist/instructions.js +13 -0
- package/dist/instructions.js.map +1 -0
- package/dist/management/commands.js +19 -2
- package/dist/management/commands.js.map +1 -1
- package/dist/meta.d.ts +39 -11
- package/dist/meta.js +59 -28
- package/dist/meta.js.map +1 -1
- package/dist/protocol/codex.d.ts +1 -3
- package/dist/protocol/codex.js +1 -4
- package/dist/protocol/codex.js.map +1 -1
- package/dist/protocol/turnPagination.d.ts +27 -2
- package/dist/protocol/turnPagination.js +46 -18
- package/dist/protocol/turnPagination.js.map +1 -1
- package/examples/config.toml +6 -2
- package/instructions/ccodex_extra_claude_instructions.md +20 -0
- package/instructions/ccodex_extra_common_instructions.md +23 -0
- package/legal/THIRD_PARTY_NOTICES.md +9 -9
- package/package.json +6 -5
- package/scripts/migrate-0.4-to-0.5.mjs +29 -18
package/README.md
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
**Claude models inside the official Codex App.**
|
|
6
6
|
|
|
7
|
-
*Claude Code'x — or just **CCodex** —
|
|
8
|
-
|
|
7
|
+
*Claude Code'x — or just **CCodex** — lets the Codex desktop app, the ChatGPT mobile app
|
|
8
|
+
and the Codex CLI run Claude models next to GPT.*
|
|
9
9
|
|
|
10
10
|
</div>
|
|
11
11
|
|
|
@@ -26,200 +26,202 @@ curl -fsSL https://github.com/gkorepanov/ccodex/releases/latest/download/install
|
|
|
26
26
|
|
|
27
27
|
---
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
Want Fable and Opus writing your code, but prefer the Codex App and its remote sessions
|
|
30
|
+
from desktop and phone? CCodex puts the **native Claude Code harness** (official Claude
|
|
31
|
+
Agent SDK, your own Claude login) behind that UI. GPT chats still go to your installed
|
|
32
|
+
Codex unchanged. No CCodex servers, no telemetry; MIT-licensed.
|
|
30
33
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
sessions from desktop and mobile that just *work*, from anywhere. CCodex is the
|
|
34
|
-
missing bridge.
|
|
34
|
+
> [!WARNING]
|
|
35
|
+
> CCodex is young. Expect bugs — and please [report them](https://github.com/gkorepanov/ccodex/issues).
|
|
35
36
|
|
|
36
37
|
## What you get
|
|
37
38
|
|
|
38
|
-
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
Claude
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
## Project status
|
|
70
|
-
|
|
71
|
-
> [!WARNING]
|
|
72
|
-
> CCodex is very early and not extensively tested yet. Expect bugs — and please
|
|
73
|
-
> [report them](https://github.com/gkorepanov/ccodex/issues).
|
|
39
|
+
- **Claude models in the model picker**, next to `gpt-*` (ids `claude:…`), with Claude's
|
|
40
|
+
effort levels and Fast mode. Codex's `ultra` effort runs Claude at `max` and has it
|
|
41
|
+
delegate to sub-agents proactively, as stock does for GPT.
|
|
42
|
+
- **Switch providers mid-chat.** Pick a GPT model in a Claude chat (or the other way
|
|
43
|
+
round) and the conversation is compacted into a summary that the other provider
|
|
44
|
+
continues from. The App keeps showing one chat with one history; edits and forks across
|
|
45
|
+
the switch work.
|
|
46
|
+
- **Codex App features on Claude chats**: approvals, Plan mode, `/goal`, `/compact`, fork,
|
|
47
|
+
message edits, steering and queued messages, Stop, side chats (`/side`, served by
|
|
48
|
+
Claude's `/btw`), images, Claude's questions as the App's question prompts, its task
|
|
49
|
+
list as the turn's to-do list, and thinking as reasoning summaries.
|
|
50
|
+
- **Sub-agents and background commands like stock's**: Claude sub-agents open as their
|
|
51
|
+
own threads, background shell commands show as background terminals, and messages
|
|
52
|
+
between Claude chats show as the App's messages between tasks.
|
|
53
|
+
- **Claude skills in the `$` picker**, beside Codex skills, in Claude and GPT chats.
|
|
54
|
+
- **Search**: the sidebar search and find-in-chat cover Claude chats too.
|
|
55
|
+
- **Phone**: turn on remote control in the Codex App (or
|
|
56
|
+
`codex app-server daemon enable-remote-control` on the host) and pair the ChatGPT
|
|
57
|
+
mobile app as usual; it drives Claude chats like GPT ones.
|
|
58
|
+
- **Your `claude` CLI sessions show up** in the App, and chats from the App resume in
|
|
59
|
+
`claude --resume <id>` (a Claude chat's id is its Claude session id). While another live
|
|
60
|
+
Claude process has a chat open, the App can't start a turn in it.
|
|
61
|
+
- **Claude can delegate to Codex** through the `codex-wrapper` agent that setup installs;
|
|
62
|
+
what Codex does streams into the Claude chat.
|
|
63
|
+
- **`/cc` status card** (also `/ccstatus`, `/ccodex`, `/ccstate`, with or without the
|
|
64
|
+
slash, or *CCodex status* in the `/` menu): the chat's model, effort, permission mode,
|
|
65
|
+
context use, session state, and Claude and Codex plan limits. Sent while a turn runs,
|
|
66
|
+
it answers at once and never reaches the model.
|
|
67
|
+
- **Emoji thread titles** from a small GPT model and an editable prompt; Claude chats get
|
|
68
|
+
a ` ✳️` suffix.
|
|
74
69
|
|
|
75
70
|
## Install
|
|
76
71
|
|
|
77
|
-
|
|
78
|
-
|
|
72
|
+
### Requirements
|
|
73
|
+
|
|
74
|
+
| | |
|
|
75
|
+
|---|---|
|
|
76
|
+
| **OS** | macOS 11+ on Apple silicon · Linux x64 or arm64 with glibc ≥ 2.31 (no Alpine/musl) · Bash, Zsh or Fish |
|
|
77
|
+
| **Node.js** | `>=22.13 <27` (22 or 24 LTS recommended), npm `>=10` |
|
|
78
|
+
| **Codex CLI** | any recent version; installed for you if missing. Tested with `0.156` and `0.157` |
|
|
79
|
+
| **Claude Code** | nothing to install: the Agent SDK brings it (`0.3.284` / Claude Code `2.1.284`) |
|
|
80
|
+
|
|
81
|
+
Don't run the installer or setup as root or with `sudo`.
|
|
82
|
+
|
|
83
|
+
### 1. Install
|
|
84
|
+
|
|
85
|
+
Either the script (it checks the platform, installs `@openai/codex` if there is no
|
|
86
|
+
`codex`, then runs `ccodex setup`):
|
|
79
87
|
|
|
80
88
|
```sh
|
|
81
|
-
|
|
82
|
-
npm install -g @gkorepanov/ccodex
|
|
83
|
-
ccodex setup
|
|
89
|
+
curl -fsSL https://github.com/gkorepanov/ccodex/releases/latest/download/install.sh | sh
|
|
84
90
|
```
|
|
85
91
|
|
|
86
|
-
|
|
92
|
+
or npm:
|
|
87
93
|
|
|
88
94
|
```sh
|
|
89
|
-
|
|
90
|
-
ccodex auth claude
|
|
95
|
+
npm install -g @gkorepanov/ccodex
|
|
91
96
|
ccodex setup
|
|
92
97
|
```
|
|
93
98
|
|
|
94
|
-
|
|
99
|
+
### 2. Log in
|
|
100
|
+
|
|
101
|
+
Skip what you are already logged in to; rerun any time:
|
|
95
102
|
|
|
96
103
|
```sh
|
|
97
|
-
ccodex
|
|
98
|
-
ccodex
|
|
99
|
-
ccodex uninstall # preserves config and state; add --purge --yes to wipe
|
|
104
|
+
ccodex auth codex # codex login
|
|
105
|
+
ccodex auth claude # Claude Code login (the SDK's bundled claude)
|
|
100
106
|
```
|
|
101
107
|
|
|
102
|
-
|
|
103
|
-
`PATH` no longer resolves `ccodex`.
|
|
104
|
-
|
|
105
|
-
## How it works
|
|
108
|
+
### 3. Activate
|
|
106
109
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
- **gpt threads are stock, byte for byte.** One stock `codex app-server` serves every App
|
|
110
|
-
connection (each over a connection of its own); CCodex forwards its traffic unchanged.
|
|
111
|
-
No pinned Codex: update Codex whenever you like.
|
|
112
|
-
- **Claude threads are Claude Code sessions.** `claude:*` models run on the official
|
|
113
|
-
Claude Agent SDK, and `~/.claude/projects` is the only source of truth: every session
|
|
114
|
-
(including ones made in the `claude` CLI) is listed at once. Claude's own `/goal`,
|
|
115
|
-
compaction, sub-agents, skills, and background tasks show up as native Codex items.
|
|
116
|
-
Like stock's threads, a Claude chat nobody has open is unloaded after 30 idle minutes,
|
|
117
|
-
unless a command it runs still works (a background command idle for 30 minutes counts
|
|
118
|
-
as hung and is ended).
|
|
119
|
-
- **Provider switch = compaction.** Switching model provider mid-thread compacts the
|
|
120
|
-
conversation with the Codex prompt, then continues in a new native thread of the other
|
|
121
|
-
provider seeded with the summary; the App keeps showing one thread with one history.
|
|
122
|
-
Forks and rollbacks across the switch land in the right segment.
|
|
123
|
-
- Codex approval modes map onto Claude permissions: *Full Access* →
|
|
124
|
-
`bypassPermissions`, *Ask for approval* → `default`, *Approve for me* → `auto`.
|
|
125
|
-
Claude effort and fast mode map from Codex reasoning / priority settings.
|
|
126
|
-
- The only state CCodex keeps is a tiny optional `~/.ccodex/state/meta.json`
|
|
127
|
-
(provider-switch lineages, archive flags and sections of Claude threads).
|
|
128
|
-
- Plain `codex …` commands (TUI, `exec`, login) go straight to your installed Codex.
|
|
129
|
-
`codex mcp-server` (removed from Codex in 0.154) is served by CCodex on top of
|
|
130
|
-
`codex exec`, and Claude threads stream what those Codex sessions do.
|
|
131
|
-
|
|
132
|
-
Setup activates a new version atomically and never restarts a running gateway: the new
|
|
133
|
-
version takes over after `codex app-server daemon restart`.
|
|
134
|
-
|
|
135
|
-
### Upgrading from 0.4
|
|
136
|
-
|
|
137
|
-
0.5 drops the 0.4 databases. `ccodex setup` (also when 0.4's setup hands over to 0.5)
|
|
138
|
-
carries thread ids, provider-switch history, archive flags, sections and names over once,
|
|
139
|
-
before it activates 0.5; a failed migration activates nothing. Claude chats whose
|
|
140
|
-
transcripts Claude's 30-day cleanup deleted come back from 0.4's turns as text. Then:
|
|
110
|
+
Open a new shell, then restart the gateway:
|
|
141
111
|
|
|
142
112
|
```sh
|
|
143
113
|
codex app-server daemon restart
|
|
144
114
|
```
|
|
145
115
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
## Technical details
|
|
116
|
+
- **Codex App over SSH:** reconnect to the host. The App finds CCodex's `codex` first on
|
|
117
|
+
`PATH` (and at `~/.local/bin/codex`).
|
|
118
|
+
- **Local Codex App on macOS:** fully quit the App (`Cmd+Q`) and open it again (or log
|
|
119
|
+
out and back in).
|
|
120
|
+
- **Local Codex App on Linux:** setup doesn't configure it; start the App with
|
|
121
|
+
`CODEX_CLI_PATH=~/.ccodex/bin/codex` in its environment.
|
|
122
|
+
|
|
123
|
+
### What setup changes
|
|
124
|
+
|
|
125
|
+
- Installs the version under `~/.ccodex/versions/` and the `codex` / `ccodex` shims in
|
|
126
|
+
`~/.ccodex/bin`, which a managed block (`# >>> ccodex >>>`) puts first on `PATH` in your
|
|
127
|
+
Bash, Zsh and Fish startup files.
|
|
128
|
+
- Links `~/.local/bin/codex` to the shim; a `codex` found there moves to
|
|
129
|
+
`~/.ccodex/backups/remote-codex` and stays the Codex CCodex runs.
|
|
130
|
+
- macOS: sets `CODEX_CLI_PATH` for the local App (`launchctl setenv` plus a login
|
|
131
|
+
LaunchAgent `dev.ccodex.codex-cli-path`), so the App starts CCodex instead of its bundled
|
|
132
|
+
`codex`. The signed `.app` is never touched, so its auto-updates keep working.
|
|
133
|
+
- Claude Code: sets `cleanupPeriodDays: 36500` in `~/.claude/settings.json` when unset
|
|
134
|
+
(Claude deletes transcripts older than 30 days by default, and with them your Claude
|
|
135
|
+
chats), and installs the `codex-wrapper` agent, the `workforce` skill and the `codex` MCP
|
|
136
|
+
server (user scope).
|
|
137
|
+
- Never restarts a running gateway: a new version takes over after
|
|
138
|
+
`codex app-server daemon restart`.
|
|
139
|
+
|
|
140
|
+
## Update, upgrade from 0.4, uninstall
|
|
173
141
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
| **Runtime** | Node.js `>=22.13 <27`, npm `>=10` |
|
|
180
|
-
| **Platforms** | macOS 11+ (arm64) · Linux arm64 & x64, glibc ≥2.31 (Ubuntu 22.04+, Debian 11+, Fedora/RHEL equivalents). Alpine/musl not supported |
|
|
181
|
-
| **Shells** | Bash, Zsh, Fish |
|
|
182
|
-
| **Relay** | Prebuilt per-platform `@gkorepanov/ccodex-relay-*` optional packages — installs never compile Rust or native addons |
|
|
183
|
-
|
|
184
|
-
Fresh setup writes the editable title prompt to `~/.ccodex/config.toml`:
|
|
185
|
-
|
|
186
|
-
```toml
|
|
187
|
-
rename_prompt = """
|
|
188
|
-
Create a concise, vivid, memorable title for the task.
|
|
189
|
-
Start with exactly one rare, expressive, context-relevant emoji followed by one space.
|
|
190
|
-
Avoid generic decorative emoji when a more specific symbol fits.
|
|
191
|
-
Keep the complete title, including emoji, within 36 characters.
|
|
192
|
-
Return only the title.
|
|
193
|
-
"""
|
|
194
|
-
|
|
195
|
-
# title_model = "gpt-6-luna" # default: a small visible Codex model
|
|
142
|
+
```sh
|
|
143
|
+
ccodex update # to npm latest; --check only reports, --next takes the pre-release
|
|
144
|
+
ccodex doctor # health check (--json available)
|
|
145
|
+
ccodex uninstall # keeps ~/.ccodex/config.toml and ~/.ccodex/state
|
|
146
|
+
ccodex uninstall --purge --yes # also deletes ~/.ccodex
|
|
196
147
|
```
|
|
197
148
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
149
|
+
Uninstall stops CCodex's gateway and undoes the `PATH`, `~/.local/bin/codex` and
|
|
150
|
+
`CODEX_CLI_PATH` changes; what setup added to `~/.claude` stays. If `ccodex` is gone from
|
|
151
|
+
`PATH`, use the release's `uninstall.sh` (`… | sh -s -- --purge` to purge):
|
|
152
|
+
`curl -fsSL https://github.com/gkorepanov/ccodex/releases/latest/download/uninstall.sh | sh`
|
|
153
|
+
|
|
154
|
+
**From 0.4:** run `ccodex update` (or reinstall), then `codex app-server daemon restart`.
|
|
155
|
+
0.5 keeps no databases of its own; setup migrates 0.4's state once before it activates
|
|
156
|
+
0.5 (a failed migration activates nothing). Provider-switch history, archive flags,
|
|
157
|
+
sections and names carry over. Claude chats get their Claude session ids (links to 0.4
|
|
158
|
+
thread ids stop working), 0.4's side chats are archived, and chats whose transcripts
|
|
159
|
+
Claude's 30-day cleanup deleted come back as text. The 0.4 databases move to
|
|
160
|
+
`~/.ccodex.0.4-backup`.
|
|
202
161
|
|
|
203
|
-
|
|
204
|
-
1 GiB) and includes prompts/outputs (`rpc_capture = false` turns it off) — and it never
|
|
205
|
-
leaves your disk.
|
|
162
|
+
## Settings
|
|
206
163
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
164
|
+
Claude chats follow the App's own controls:
|
|
165
|
+
|
|
166
|
+
| Codex App | Claude Code |
|
|
167
|
+
|---|---|
|
|
168
|
+
| *Full Access* / *Ask for approval* / *Approve for me* | permission mode `bypassPermissions` / `default` / `auto` |
|
|
169
|
+
| Plan mode | permission mode `plan` |
|
|
170
|
+
| Reasoning effort | effort (`ultra` = `max` + proactive sub-agents) |
|
|
171
|
+
| Fast | Claude fast mode |
|
|
172
|
+
|
|
173
|
+
`~/.ccodex/config.toml` (every key optional; all of them are in
|
|
174
|
+
[`examples/config.toml`](examples/config.toml)):
|
|
175
|
+
|
|
176
|
+
- `rename_prompt` — the title prompt; remove it for stock Codex titles (manual names
|
|
177
|
+
always win). `title_model` — the model that writes them.
|
|
178
|
+
- `improve_models_formatting_for_codex_app` (default `true`) — adds
|
|
179
|
+
[`instructions/ccodex_extra_common_instructions.md`](instructions/ccodex_extra_common_instructions.md)
|
|
180
|
+
(formulas and plots the App renders) to the App's instructions for Codex models and to
|
|
181
|
+
Claude's; Claude also gets
|
|
182
|
+
[`instructions/ccodex_extra_claude_instructions.md`](instructions/ccodex_extra_claude_instructions.md)
|
|
183
|
+
(what the App shows beyond a terminal).
|
|
184
|
+
- `log_level` — `debug`, `info` (default), `warn`, `error`.
|
|
185
|
+
- `codex_binary`, `delegate_codex`, `claude_binary` — use a specific `codex` or `claude`.
|
|
186
|
+
|
|
187
|
+
## Troubleshooting
|
|
188
|
+
|
|
189
|
+
- `ccodex doctor` checks Node, Codex and Claude and their logins, the prebuilt native
|
|
190
|
+
relay (`@gkorepanov/ccodex-relay-*`), the gateway and the install, and says what to run.
|
|
191
|
+
- `codex app-server daemon restart` restarts the gateway (chats running in it stop).
|
|
192
|
+
- The gateway's log is `~/.codex/app-server-daemon/app-server.stderr.log`, rewritten at
|
|
193
|
+
each gateway start; set `log_level = "debug"` for more.
|
|
194
|
+
- For a bug report, `rpc_capture = true` records every App message to
|
|
195
|
+
`~/.ccodex/state/rpc.jsonl` (mode `0600`, capped at 1 GiB, prompts and outputs
|
|
196
|
+
included). Off by default; it never leaves your disk.
|
|
197
|
+
- The App's built-in `/status` differs by client (Desktop may show only its OpenAI account);
|
|
198
|
+
`/cc` shows the same in every client.
|
|
199
|
+
- On a Mac, the local App replaces a gateway started from a terminal (or by an earlier App
|
|
200
|
+
launch) with its own, so that Browser Use works; chats running in the old one stop.
|
|
201
|
+
|
|
202
|
+
## How it works
|
|
203
|
+
|
|
204
|
+
CCodex is a thin gateway in front of your installed `codex app-server`: the App starts
|
|
205
|
+
CCodex's `codex`, one stock app-server serves every GPT chat unchanged, and `claude:*`
|
|
206
|
+
chats run on the Claude Agent SDK with Claude's transcripts in `~/.claude/projects` as
|
|
207
|
+
their only source of truth. The only state CCodex adds is an optional
|
|
208
|
+
`~/.ccodex/state/meta.json` (provider-switch history, archive flags and sections of Claude
|
|
209
|
+
chats). Plain `codex …` commands (TUI, `exec`, `login`) run your installed Codex; `codex
|
|
210
|
+
mcp-server`, removed from Codex in `0.154`, is served by CCodex on top of `codex exec`.
|
|
210
211
|
|
|
211
212
|
## Development
|
|
212
213
|
|
|
213
214
|
```sh
|
|
214
215
|
npm ci --ignore-scripts
|
|
215
216
|
npm run check
|
|
216
|
-
npm test # black-box gateway tests
|
|
217
|
-
scripts/e2e/run.sh # podman, real models, copies of your credentials
|
|
217
|
+
npm test # unit and black-box gateway tests, relay tests
|
|
218
|
+
scripts/e2e/run.sh # rootless podman, real models, copies of your credentials
|
|
218
219
|
```
|
|
219
220
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
221
|
+
## License
|
|
222
|
+
|
|
223
|
+
MIT — see [`LICENSE`](LICENSE). Third-party licenses and notices:
|
|
224
|
+
[`legal/LICENSES.md`](legal/LICENSES.md), [`legal/THIRD_PARTY_NOTICES.md`](legal/THIRD_PARTY_NOTICES.md).
|
|
223
225
|
|
|
224
226
|
<div align="center">
|
|
225
227
|
<sub>Claude Code'x is an independent open-source project — not affiliated with, sponsored, or endorsed by OpenAI or Anthropic.</sub>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Codex's `ultra` effort on Claude models: Claude's top effort plus proactive delegation to sub-agents. Stock turns the
|
|
3
|
+
* delegation on and off with a mode message in the thread; its guidance lives in the spawn_agent tool, here adapted to
|
|
4
|
+
* Claude Code's Agent tool.
|
|
5
|
+
*/
|
|
6
|
+
export declare const ULTRA = "ultra";
|
|
7
|
+
/** The effort Claude runs at. */
|
|
8
|
+
export declare function claudeEffort(effort: string | null): string | null;
|
|
9
|
+
export declare const DELEGATION_ON = "Proactive multi-agent delegation is active. Any earlier developer instruction requiring an explicit user request before spawning sub-agents no longer applies. This mode remains active until a later multi-agent mode developer message changes it. User requests override this hint.\n\nDelegate with the Agent tool (not the Workflow tool, unless the user asks for a workflow). Sub-agents inherit your model: set `model` only when the user or their instructions ask for another one.\n\n### When to delegate vs. do the subtask yourself\n- First, quickly analyze the overall user task and form a succinct high-level plan. Identify which tasks are immediate blockers on the critical path, and which tasks are sidecar tasks that are needed but can run in parallel without blocking the next local step. As part of that plan, explicitly decide what immediate task you should do locally right now. Do this planning step before delegating to agents so you do not hand off the immediate blocking task to a sub-agent and then waste time waiting on it.\n- Use a sub-agent when a subtask is easy enough for it to handle and can run in parallel with your local work. Prefer delegating concrete, bounded sidecar tasks that materially advance the main task without blocking your immediate next local step.\n- Do not delegate urgent blocking work when your immediate next step depends on that result. If the very next action is blocked on that task, the main thread should usually do it locally to keep the critical path moving.\n- Keep work local when the subtask is too difficult to delegate well and when it is tightly coupled, urgent, or likely to block your immediate next step.\n### Designing delegated subtasks\n- Subtasks must be concrete, well-defined, and self-contained.\n- Delegated subtasks must materially advance the main task.\n- Do not duplicate work between the main thread and delegated subtasks.\n- Avoid issuing multiple delegate calls on the same unresolved thread unless the new delegated task is genuinely different and necessary.\n- Narrow the delegated ask to the concrete output you need next.\n- For coding tasks, prefer delegating concrete code-change worker subtasks over read-only explorer analysis when the sub-agent can make a bounded patch in a clear write scope.\n- When delegating coding work, instruct the sub-agent to edit files directly and list the file paths it changed in the final answer.\n- For code-edit subtasks, decompose work so each delegated task has a disjoint write set.\n### After you delegate\n- Wait for a sub-agent very sparingly. Only wait when you need the result immediately for the next critical-path step and you are blocked until it returns.\n- Do not redo delegated sub-agent tasks yourself; focus on integrating results or tackling non-overlapping work.\n- While the sub-agent is running in the background, do meaningful non-overlapping work immediately.\n- Do not repeatedly wait by reflex.\n- When a delegated coding task returns, quickly review the changes, then integrate or refine them.\n### Parallel delegation patterns\n- Run multiple independent information-seeking subtasks in parallel when you have distinct questions that can be answered independently.\n- Split implementation into disjoint codebase slices and spawn multiple agents for them in parallel when the write scopes do not overlap.\n- Delegate verification only when it can run in parallel with ongoing implementation and is likely to catch a concrete risk before final integration.\n- The key is to find opportunities to spawn multiple independent subtasks in parallel within the same round, while ensuring each subtask is well-defined, self-contained, and materially advances the main task.";
|
|
10
|
+
export declare const DELEGATION_OFF = "Any earlier instruction enabling proactive multi-agent delegation no longer applies. Do not spawn sub-agents unless the user or applicable CLAUDE.md/skill instructions explicitly ask for sub-agents, delegation, or parallel agent work.";
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Codex's `ultra` effort on Claude models: Claude's top effort plus proactive delegation to sub-agents. Stock turns the
|
|
3
|
+
* delegation on and off with a mode message in the thread; its guidance lives in the spawn_agent tool, here adapted to
|
|
4
|
+
* Claude Code's Agent tool.
|
|
5
|
+
*/
|
|
6
|
+
export const ULTRA = "ultra";
|
|
7
|
+
/** The effort Claude runs at. */
|
|
8
|
+
export function claudeEffort(effort) {
|
|
9
|
+
return effort === ULTRA ? "max" : effort;
|
|
10
|
+
}
|
|
11
|
+
export const DELEGATION_ON = `Proactive multi-agent delegation is active. Any earlier developer instruction requiring an explicit user request before spawning sub-agents no longer applies. This mode remains active until a later multi-agent mode developer message changes it. User requests override this hint.
|
|
12
|
+
|
|
13
|
+
Delegate with the Agent tool (not the Workflow tool, unless the user asks for a workflow). Sub-agents inherit your model: set \`model\` only when the user or their instructions ask for another one.
|
|
14
|
+
|
|
15
|
+
### When to delegate vs. do the subtask yourself
|
|
16
|
+
- First, quickly analyze the overall user task and form a succinct high-level plan. Identify which tasks are immediate blockers on the critical path, and which tasks are sidecar tasks that are needed but can run in parallel without blocking the next local step. As part of that plan, explicitly decide what immediate task you should do locally right now. Do this planning step before delegating to agents so you do not hand off the immediate blocking task to a sub-agent and then waste time waiting on it.
|
|
17
|
+
- Use a sub-agent when a subtask is easy enough for it to handle and can run in parallel with your local work. Prefer delegating concrete, bounded sidecar tasks that materially advance the main task without blocking your immediate next local step.
|
|
18
|
+
- Do not delegate urgent blocking work when your immediate next step depends on that result. If the very next action is blocked on that task, the main thread should usually do it locally to keep the critical path moving.
|
|
19
|
+
- Keep work local when the subtask is too difficult to delegate well and when it is tightly coupled, urgent, or likely to block your immediate next step.
|
|
20
|
+
### Designing delegated subtasks
|
|
21
|
+
- Subtasks must be concrete, well-defined, and self-contained.
|
|
22
|
+
- Delegated subtasks must materially advance the main task.
|
|
23
|
+
- Do not duplicate work between the main thread and delegated subtasks.
|
|
24
|
+
- Avoid issuing multiple delegate calls on the same unresolved thread unless the new delegated task is genuinely different and necessary.
|
|
25
|
+
- Narrow the delegated ask to the concrete output you need next.
|
|
26
|
+
- For coding tasks, prefer delegating concrete code-change worker subtasks over read-only explorer analysis when the sub-agent can make a bounded patch in a clear write scope.
|
|
27
|
+
- When delegating coding work, instruct the sub-agent to edit files directly and list the file paths it changed in the final answer.
|
|
28
|
+
- For code-edit subtasks, decompose work so each delegated task has a disjoint write set.
|
|
29
|
+
### After you delegate
|
|
30
|
+
- Wait for a sub-agent very sparingly. Only wait when you need the result immediately for the next critical-path step and you are blocked until it returns.
|
|
31
|
+
- Do not redo delegated sub-agent tasks yourself; focus on integrating results or tackling non-overlapping work.
|
|
32
|
+
- While the sub-agent is running in the background, do meaningful non-overlapping work immediately.
|
|
33
|
+
- Do not repeatedly wait by reflex.
|
|
34
|
+
- When a delegated coding task returns, quickly review the changes, then integrate or refine them.
|
|
35
|
+
### Parallel delegation patterns
|
|
36
|
+
- Run multiple independent information-seeking subtasks in parallel when you have distinct questions that can be answered independently.
|
|
37
|
+
- Split implementation into disjoint codebase slices and spawn multiple agents for them in parallel when the write scopes do not overlap.
|
|
38
|
+
- Delegate verification only when it can run in parallel with ongoing implementation and is likely to catch a concrete risk before final integration.
|
|
39
|
+
- The key is to find opportunities to spawn multiple independent subtasks in parallel within the same round, while ensuring each subtask is well-defined, self-contained, and materially advances the main task.`;
|
|
40
|
+
export const DELEGATION_OFF = "Any earlier instruction enabling proactive multi-agent delegation no longer applies. Do not spawn sub-agents unless the user or applicable CLAUDE.md/skill instructions explicitly ask for sub-agents, delegation, or parallel agent work.";
|
|
41
|
+
//# sourceMappingURL=delegation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delegation.js","sourceRoot":"","sources":["../../src/claude/delegation.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,CAAC,MAAM,KAAK,GAAG,OAAO,CAAC;AAE7B,iCAAiC;AACjC,MAAM,UAAU,YAAY,CAAC,MAAqB;IAChD,OAAO,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;AAC3C,CAAC;AAED,MAAM,CAAC,MAAM,aAAa,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;iNA4BoL,CAAC;AAElN,MAAM,CAAC,MAAM,cAAc,GAAG,4OAA4O,CAAC"}
|
|
@@ -8,6 +8,8 @@ export interface SessionSummary extends TranscriptHeader {
|
|
|
8
8
|
readonly projectKey: string;
|
|
9
9
|
readonly sizeBytes: number;
|
|
10
10
|
readonly hasSubagents: boolean;
|
|
11
|
+
/** Proactive delegation (the `ultra` effort) as the transcript last told Claude. */
|
|
12
|
+
readonly delegating: boolean;
|
|
11
13
|
}
|
|
12
14
|
/** Where the summaries are kept between runs; `key` (the package version) drops them when the summarizer may differ. */
|
|
13
15
|
export interface CatalogCache {
|
|
@@ -23,6 +25,7 @@ export declare class NativeSessionCatalog implements PeerDirectory {
|
|
|
23
25
|
private ordered;
|
|
24
26
|
private bySessionId;
|
|
25
27
|
private refreshInFlight;
|
|
28
|
+
private refreshQueued;
|
|
26
29
|
private readonly projections;
|
|
27
30
|
private readonly pagers;
|
|
28
31
|
private senders;
|
|
@@ -36,6 +39,8 @@ export declare class NativeSessionCatalog implements PeerDirectory {
|
|
|
36
39
|
sender(msgId: string): string | undefined;
|
|
37
40
|
receiver(msgId: string): string | undefined;
|
|
38
41
|
has(sessionId: string): boolean;
|
|
42
|
+
/** Session id → snippet for the sessions whose visible messages hold `term` (see `searchTranscripts`). */
|
|
43
|
+
search(claudeBinary: string, term: string): Promise<Map<string, string>>;
|
|
39
44
|
projection(sessionId: string, leafUuid?: string): Promise<TranscriptProjection>;
|
|
40
45
|
/** Paged reads of a session's transcript (a page of history reads that page's part of the file), per history leaf. */
|
|
41
46
|
pages(sessionId: string, leafUuid?: string): {
|
|
@@ -6,6 +6,7 @@ import { basename, join, resolve } from "node:path";
|
|
|
6
6
|
import { TranscriptPages } from "./pages.js";
|
|
7
7
|
import { projectTranscript } from "./projector.js";
|
|
8
8
|
import { readTranscriptRecords } from "./records.js";
|
|
9
|
+
import { searchTranscripts } from "./search.js";
|
|
9
10
|
import { TranscriptSummarizer, } from "./summary.js";
|
|
10
11
|
const HEAD_BYTES = 4_096;
|
|
11
12
|
const CACHE_WRITE_DELAY_MS = 1_000;
|
|
@@ -35,6 +36,13 @@ function readCache(cache) {
|
|
|
35
36
|
return new Map();
|
|
36
37
|
}
|
|
37
38
|
}
|
|
39
|
+
function summaryOf(file, state) {
|
|
40
|
+
return {
|
|
41
|
+
...new TranscriptSummarizer(state).header(),
|
|
42
|
+
sessionId: file.sessionId, path: file.path, projectKey: file.projectKey, sizeBytes: file.size, hasSubagents: file.hasSubagents,
|
|
43
|
+
delegating: state.delegating,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
38
46
|
async function hashHead(path, length) {
|
|
39
47
|
const handle = await open(path, "r");
|
|
40
48
|
try {
|
|
@@ -55,6 +63,7 @@ export class NativeSessionCatalog {
|
|
|
55
63
|
ordered = [];
|
|
56
64
|
bySessionId = new Map();
|
|
57
65
|
refreshInFlight;
|
|
66
|
+
refreshQueued;
|
|
58
67
|
projections = new Map();
|
|
59
68
|
pagers = new Map();
|
|
60
69
|
senders = new Map();
|
|
@@ -68,8 +77,14 @@ export class NativeSessionCatalog {
|
|
|
68
77
|
this.entries = readCache(cache);
|
|
69
78
|
}
|
|
70
79
|
refresh(_sessionId) {
|
|
71
|
-
|
|
72
|
-
|
|
80
|
+
// A scan in flight may have begun before what the caller just wrote: one more follows it, for all who wait meanwhile.
|
|
81
|
+
if (this.refreshInFlight) {
|
|
82
|
+
this.refreshQueued ??= this.refreshInFlight.catch(() => undefined).then(() => {
|
|
83
|
+
this.refreshQueued = undefined;
|
|
84
|
+
return this.refresh();
|
|
85
|
+
});
|
|
86
|
+
return this.refreshQueued;
|
|
87
|
+
}
|
|
73
88
|
const refresh = this.scan().finally(() => {
|
|
74
89
|
if (this.refreshInFlight === refresh)
|
|
75
90
|
this.refreshInFlight = undefined;
|
|
@@ -86,6 +101,11 @@ export class NativeSessionCatalog {
|
|
|
86
101
|
sender(msgId) { return this.senders.get(msgId); }
|
|
87
102
|
receiver(msgId) { return this.receivers.get(msgId); }
|
|
88
103
|
has(sessionId) { return this.bySessionId.has(sessionId); }
|
|
104
|
+
/** Session id → snippet for the sessions whose visible messages hold `term` (see `searchTranscripts`). */
|
|
105
|
+
async search(claudeBinary, term) {
|
|
106
|
+
const found = await searchTranscripts(claudeBinary, this.projectsDir, term);
|
|
107
|
+
return new Map(this.ordered.flatMap((summary) => found.has(summary.path) ? [[summary.sessionId, found.get(summary.path)]] : []));
|
|
108
|
+
}
|
|
89
109
|
async projection(sessionId, leafUuid) {
|
|
90
110
|
const entry = this.entriesBySessionId.get(sessionId);
|
|
91
111
|
if (!entry)
|
|
@@ -237,7 +257,7 @@ export class NativeSessionCatalog {
|
|
|
237
257
|
this.cacheWrite = setTimeout(() => {
|
|
238
258
|
this.cacheWrite = undefined;
|
|
239
259
|
const temporary = `${cache.path}.${process.pid}.tmp`;
|
|
240
|
-
void writeFile(temporary, JSON.stringify({ key: cache.key, entries: [...this.entries.values()] }), { mode: 0o600 })
|
|
260
|
+
void writeFile(temporary, JSON.stringify({ key: cache.key, entries: [...this.entries.values()].map((entry) => ({ ...entry, summary: undefined })) }), { mode: 0o600 })
|
|
241
261
|
.then(() => rename(temporary, cache.path))
|
|
242
262
|
.catch(() => undefined);
|
|
243
263
|
}, CACHE_WRITE_DELAY_MS);
|
|
@@ -297,12 +317,8 @@ export class NativeSessionCatalog {
|
|
|
297
317
|
}
|
|
298
318
|
async summarize(file) {
|
|
299
319
|
const previous = this.entries.get(file.path);
|
|
300
|
-
if (previous && previous.mtimeMs === file.mtimeMs && previous.size === file.size)
|
|
301
|
-
return {
|
|
302
|
-
...previous,
|
|
303
|
-
summary: { ...previous.summary, hasSubagents: file.hasSubagents },
|
|
304
|
-
};
|
|
305
|
-
}
|
|
320
|
+
if (previous && previous.mtimeMs === file.mtimeMs && previous.size === file.size)
|
|
321
|
+
return { ...previous, summary: summaryOf(file, previous.state) };
|
|
306
322
|
let start = 0;
|
|
307
323
|
let summarizer = new TranscriptSummarizer();
|
|
308
324
|
if (previous && file.size >= previous.offset
|
|
@@ -328,14 +344,7 @@ export class NativeSessionCatalog {
|
|
|
328
344
|
headLength,
|
|
329
345
|
headHash: await hashHead(file.path, headLength),
|
|
330
346
|
state: summarizer.snapshot(),
|
|
331
|
-
summary:
|
|
332
|
-
...summarizer.header(),
|
|
333
|
-
sessionId: file.sessionId,
|
|
334
|
-
path: file.path,
|
|
335
|
-
projectKey: file.projectKey,
|
|
336
|
-
sizeBytes: file.size,
|
|
337
|
-
hasSubagents: file.hasSubagents,
|
|
338
|
-
},
|
|
347
|
+
summary: summaryOf(file, summarizer.snapshot()),
|
|
339
348
|
};
|
|
340
349
|
}
|
|
341
350
|
}
|