patch-cc 0.1.3__tar.gz → 0.2.0__tar.gz

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.
Files changed (43) hide show
  1. {patch_cc-0.1.3 → patch_cc-0.2.0}/.github/workflows/ci.yml +1 -1
  2. {patch_cc-0.1.3 → patch_cc-0.2.0}/.gitignore +4 -0
  3. patch_cc-0.2.0/AGENTS.md +18 -0
  4. patch_cc-0.2.0/CLAUDE.md +1 -0
  5. {patch_cc-0.1.3 → patch_cc-0.2.0}/PKG-INFO +84 -15
  6. patch_cc-0.2.0/README.md +183 -0
  7. {patch_cc-0.1.3 → patch_cc-0.2.0}/docs/CONDUCT.md +5 -3
  8. {patch_cc-0.1.3 → patch_cc-0.2.0}/docs/INTERNALS.md +19 -3
  9. {patch_cc-0.1.3 → patch_cc-0.2.0}/docs/PLAYBOOK.md +179 -15
  10. {patch_cc-0.1.3 → patch_cc-0.2.0}/pyproject.toml +3 -2
  11. {patch_cc-0.1.3 → patch_cc-0.2.0}/src/patch_cc/__init__.py +1 -1
  12. {patch_cc-0.1.3 → patch_cc-0.2.0}/src/patch_cc/bun/blob.py +8 -3
  13. {patch_cc-0.1.3 → patch_cc-0.2.0}/src/patch_cc/bun/container.py +10 -0
  14. {patch_cc-0.1.3 → patch_cc-0.2.0}/src/patch_cc/bun/macho.py +0 -12
  15. {patch_cc-0.1.3 → patch_cc-0.2.0}/src/patch_cc/cache.py +32 -6
  16. patch_cc-0.2.0/src/patch_cc/cli.py +1090 -0
  17. patch_cc-0.2.0/src/patch_cc/codex/__init__.py +62 -0
  18. patch_cc-0.2.0/src/patch_cc/codex/gateway.py +407 -0
  19. patch_cc-0.2.0/src/patch_cc/codex/models.py +334 -0
  20. patch_cc-0.2.0/src/patch_cc/codex/oauth.py +361 -0
  21. patch_cc-0.2.0/src/patch_cc/codex/translate.py +855 -0
  22. {patch_cc-0.1.3 → patch_cc-0.2.0}/src/patch_cc/doctor.py +29 -8
  23. {patch_cc-0.1.3 → patch_cc-0.2.0}/src/patch_cc/locate.py +29 -17
  24. {patch_cc-0.1.3 → patch_cc-0.2.0}/src/patch_cc/menu.py +503 -67
  25. {patch_cc-0.1.3 → patch_cc-0.2.0}/src/patch_cc/patcher.py +99 -45
  26. {patch_cc-0.1.3 → patch_cc-0.2.0}/src/patch_cc/patches/__init__.py +12 -13
  27. {patch_cc-0.1.3 → patch_cc-0.2.0}/src/patch_cc/patches/agents.py +45 -8
  28. {patch_cc-0.1.3 → patch_cc-0.2.0}/src/patch_cc/patches/base.py +48 -18
  29. {patch_cc-0.1.3 → patch_cc-0.2.0}/src/patch_cc/patches/chrome.py +18 -9
  30. patch_cc-0.2.0/src/patch_cc/patches/codex.py +523 -0
  31. {patch_cc-0.1.3 → patch_cc-0.2.0}/src/patch_cc/patches/streaming.py +2 -2
  32. {patch_cc-0.1.3 → patch_cc-0.2.0}/src/patch_cc/patches/thinking.py +2 -2
  33. patch_cc-0.2.0/src/patch_cc/ui.py +108 -0
  34. {patch_cc-0.1.3 → patch_cc-0.2.0}/uv.lock +1 -1
  35. patch_cc-0.1.3/README.md +0 -115
  36. patch_cc-0.1.3/src/patch_cc/cli.py +0 -416
  37. patch_cc-0.1.3/src/patch_cc/ui.py +0 -53
  38. {patch_cc-0.1.3 → patch_cc-0.2.0}/.github/workflows/release.yml +0 -0
  39. {patch_cc-0.1.3 → patch_cc-0.2.0}/LICENSE +0 -0
  40. {patch_cc-0.1.3 → patch_cc-0.2.0}/src/patch_cc/bun/__init__.py +0 -0
  41. {patch_cc-0.1.3 → patch_cc-0.2.0}/src/patch_cc/bun/elf.py +0 -0
  42. {patch_cc-0.1.3 → patch_cc-0.2.0}/src/patch_cc/bun/errors.py +0 -0
  43. {patch_cc-0.1.3 → patch_cc-0.2.0}/src/patch_cc/patches/output.py +0 -0
@@ -11,7 +11,7 @@ jobs:
11
11
  strategy:
12
12
  fail-fast: false
13
13
  matrix:
14
- python-version: ["3.11", "3.12", "3.13"]
14
+ python-version: ["3.11", "3.12", "3.13", "3.14"]
15
15
  steps:
16
16
  - uses: actions/checkout@v4
17
17
 
@@ -20,3 +20,7 @@ build/
20
20
  *.patched
21
21
  content*.js
22
22
  claude-*.bin
23
+ .opencode/
24
+
25
+ # Build journal, not documentation (see docs/PLAYBOOK.md for the shipped "why")
26
+ CODEX-PLAN.md
@@ -0,0 +1,18 @@
1
+ # patch-cc
2
+
3
+ Interactive patcher for the Claude Code native binary. What it does and how to
4
+ use it: [README.md](README.md).
5
+
6
+ Before changing anything, read [docs/CONDUCT.md](docs/CONDUCT.md) — how we
7
+ build here: the mindset, the guardrails, and who commits (the user does). Then:
8
+
9
+ - [docs/PLAYBOOK.md](docs/PLAYBOOK.md) — matcher rules, the patch reference,
10
+ how to repair a patch after a Claude update, and the map of the bundle's
11
+ native surfaces (the model registry and its consumers).
12
+ - [docs/INTERNALS.md](docs/INTERNALS.md) — the Bun container format and how
13
+ the binary is rewritten in place.
14
+
15
+ Verify with `uv run patch-cc doctor` (every patch against a clean bundle;
16
+ point it at the pristine copies in `~/.local/share/patch-cc/backups/` to sweep
17
+ older builds). There is no test suite by design — doctor against real bundles
18
+ is the check.
@@ -0,0 +1 @@
1
+ AGENTS.md
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: patch-cc
3
- Version: 0.1.3
3
+ Version: 0.2.0
4
4
  Summary: Interactive patcher for the Claude Code native binary
5
5
  Project-URL: Homepage, https://github.com/anfreire/patch-cc
6
6
  Project-URL: Repository, https://github.com/anfreire/patch-cc
@@ -8,7 +8,7 @@ Project-URL: Issues, https://github.com/anfreire/patch-cc/issues
8
8
  Author-email: André Freire Ferreira <anfreire.dev@gmail.com>
9
9
  License-Expression: MIT
10
10
  License-File: LICENSE
11
- Keywords: bun,claude,claude-code,cli,patch,tui
11
+ Keywords: bun,claude,claude-code,cli,codex,gpt,openai,patch,tui
12
12
  Classifier: Development Status :: 3 - Alpha
13
13
  Classifier: Environment :: Console
14
14
  Classifier: Intended Audience :: Developers
@@ -18,6 +18,7 @@ Classifier: Programming Language :: Python :: 3
18
18
  Classifier: Programming Language :: Python :: 3.11
19
19
  Classifier: Programming Language :: Python :: 3.12
20
20
  Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Programming Language :: Python :: 3.14
21
22
  Classifier: Topic :: Software Development
22
23
  Classifier: Topic :: Utilities
23
24
  Requires-Python: >=3.11
@@ -52,12 +53,12 @@ uvx patch-cc # fullscreen menu, no install needed
52
53
  ```
53
54
 
54
55
  The menu is a single centered panel: move with `↑ ↓`, toggle with `space`,
55
- press `s` to save. Patches that carry a setting — subagent models, the startup
56
- name, the `--version` marker — open a centered modal on `enter`, and the row
57
- then shows what you chose. Everything choosable is a picker: the agent names
58
- and model aliases are **discovered from your binary itself**, so the menu can
59
- never offer something your build would reject. Typing exists only for the two
60
- genuinely free-text values.
56
+ press `s` to save. Patches that carry a setting — subagent models, Codex models,
57
+ the startup name, the `--version` marker — open a centered modal on `enter`, and
58
+ the row then shows what you chose. Everything choosable is a picker: the agent
59
+ names and model aliases are **discovered from your binary itself** (and the
60
+ Codex ones from your plan), so the menu can never offer something your build
61
+ would reject. Typing exists only for the genuinely free-text values.
61
62
 
62
63
  A patched binary records what was applied inside itself, so the menu always
63
64
  comes up showing the real current state, and `patch-cc status` answers
@@ -76,14 +77,15 @@ patch-cc # then just run it
76
77
  |---|---|---|
77
78
  | Output & diffs | Detailed tool calls | Show full read/search calls, not collapsed summaries |
78
79
  | | Colour new files as diffs | Created files render with `+` lines and green |
79
- | Thinking | Opt out of server-side experiments | Some accounts land in one that empties every thinking block |
80
+ | Thinking | Fix blank thinking blocks | Opt out of the server-side experiment that can empty every thinking block |
80
81
  | | Always show thinking | Thinking blocks stay inline — no `ctrl+o` |
81
- | Live thinking | Stream thinking live | See reasoning as it is generated, inline and in order |
82
+ | | Stream thinking live | See reasoning as it is generated, inline and in order |
82
83
  | Subagents | Show subagent prompts | Prompt blocks visible during normal use |
83
84
  | | Override subagent models | Pick the model per built-in agent (discovered from your binary) |
84
85
  | Chrome | Disable spinner tips | No rotating tips on the spinner |
85
86
  | | Custom startup name | Defaults to `<your username>'s Code` |
86
87
  | | Mark `--version` | Appends `(patched)` — or any marker you choose |
88
+ | Codex | Codex models | Use OpenAI/Codex-plan models in Claude Code — see [Codex models](#codex-models) |
87
89
 
88
90
  ## Usage
89
91
 
@@ -97,21 +99,83 @@ uvx patch-cc apply --brand # + branding as <username>'s Code
97
99
  uvx patch-cc apply --brand "Ada's Code" # + branding, explicit name
98
100
  uvx patch-cc apply --model Explore=haiku --model general-purpose=opus
99
101
  uvx patch-cc apply --suffix "(mine)" # custom --version marker
102
+ uvx patch-cc apply --codex gpt-5.6-sol # + a Codex model (see below)
103
+ uvx patch-cc apply --from-cache # replay your last remembered selection
100
104
  uvx patch-cc status # exactly what is applied
101
105
  uvx patch-cc doctor # do all patches match this build?
102
106
  uvx patch-cc doctor path/to/claude # ...or match some other binary
103
- uvx patch-cc list # patches + your binary's agents/models
107
+ uvx patch-cc list # every patch, described
104
108
  uvx patch-cc restore # put the original back
105
109
  ```
106
110
 
107
- `--model` and `--brand` imply their patches; agents and models are validated
108
- against what your installed binary actually ships.
111
+ `--brand`, `--model` and `--codex` imply their patches; agents and models are
112
+ validated against what your installed binary actually ships, and Codex model ids
113
+ against what your plan offers. `apply --help` lists all three.
114
+
115
+ ## Codex models
116
+
117
+ Bring your **ChatGPT/Codex-plan** models (GPT-5.x) into Claude Code and use them
118
+ alongside your Claude ones — in the `/model` picker, as a subagent override,
119
+ with `/effort` driving how hard they think. It is two halves: a patch that
120
+ teaches your binary to accept and route the models you pick, and a small
121
+ localhost **gateway** that translates between Claude Code and OpenAI. Only the
122
+ models you pick are diverted — every Anthropic request stays byte-identical,
123
+ so your Claude plan is untouched. Nothing extra to install: the gateway is pure
124
+ Python and ships with patch-cc; you just sign in to a ChatGPT or Codex plan.
125
+
126
+ ```bash
127
+ uvx patch-cc codex login # sign in to your ChatGPT/Codex plan
128
+ uvx patch-cc # Codex models → pick models → save with `s`
129
+ uvx patch-cc codex serve # start the gateway; keep it running
130
+ ```
131
+
132
+ Which models you want is a patch setting like the startup name, so the menu's
133
+ **Codex models** row is where you pick them — it lists what your plan offers,
134
+ live. Everything the menu does the command line does too:
135
+
136
+ ```bash
137
+ uvx patch-cc apply --codex gpt-5.6-sol --codex gpt-5.5
138
+ uvx patch-cc apply --help # lists the model ids your plan offers
139
+ uvx patch-cc apply --from-cache # replay your last selection
140
+ ```
141
+
142
+ Then pick a model like any other:
143
+
144
+ ```bash
145
+ claude --model sol # shortcut → newest gpt-5.6-sol
146
+ claude --model gpt-5.6-sol # the full id also works, as does /model
147
+ ```
148
+
149
+ - **Shortcuts** (`sol`, `terra`, `luna`, …) are the last word of the model id;
150
+ the newest in a family wins, the way `opus` means the latest Claude Opus. They
151
+ are derived from the ids you picked — there is nothing to configure.
152
+ - **Your binary is the record.** The models and the port live in the patched
153
+ binary, so `patch-cc status` names exactly what is registered, and
154
+ `codex serve` finds the right port with nothing to tell it.
155
+ - **They read as native everywhere.** A registered model is added to the
156
+ binary's own model table, so its real name shows in the status line and the
157
+ welcome banner, its plan-reported effort levels are declared, and
158
+ `/advisor sol` works like any other model. Ask for an effort the model
159
+ doesn't run and the gateway quietly runs the closest lower one — the same
160
+ clamping Claude Code documents for its own models.
161
+ - **The gateway has to be running.** Every surface that names it says whether it
162
+ is — the apply report as soon as you bake, `patch-cc status`, and `codex
163
+ status` — so you never learn it from a request that hangs instead.
164
+ - The gateway holds *your* OpenAI token and listens only on localhost. No
165
+ Anthropic-model request is ever diverted to it. The Codex ones that *are*
166
+ still carry Claude Code's own auth header — the gateway ignores it and never
167
+ forwards it, but treat the port as trusted: whatever binds it first sees it.
168
+ - After a Claude update, **re-bake** — the patch reverts with the binary — but
169
+ the gateway is separate and keeps running. Until you do, a Codex model you had
170
+ saved as your default reads as unavailable; the models live in the patch.
171
+ Change the port and the gateway needs a restart to follow it.
109
172
 
110
173
  ## After a Claude update
111
174
 
112
175
  Claude auto-updates roughly daily and replaces the binary, which reverts the
113
- patch. Re-run `patch-cc` — the menu remembers your last selection — or re-apply
114
- your set explicitly:
176
+ patch. Re-run `patch-cc` — the menu remembers your last selection — replay it
177
+ without the menu via `patch-cc apply --from-cache`, or re-apply your set
178
+ explicitly:
115
179
 
116
180
  ```bash
117
181
  uvx patch-cc apply --brand --model Explore=haiku
@@ -130,6 +194,8 @@ binary is *smaller* than the original (≈113 MB vs 267 MB), not larger.
130
194
 
131
195
  See [docs/INTERNALS.md](docs/INTERNALS.md) for the container format and
132
196
  [docs/PLAYBOOK.md](docs/PLAYBOOK.md) for repairing a patch after an update.
197
+ Changing anything here starts at [docs/CONDUCT.md](docs/CONDUCT.md) — how this
198
+ is built, and what a patch has to prove before it ships.
133
199
 
134
200
  ## Credits
135
201
 
@@ -137,6 +203,9 @@ The patch set is a Python port of
137
203
  [a-connoisseur/patch-claude-code](https://github.com/a-connoisseur/patch-claude-code),
138
204
  with the subagent-model override idea from
139
205
  [aleks-apostle/claude-code-patches](https://github.com/aleks-apostle/claude-code-patches).
206
+ Registering Codex models inside the bundle follows
207
+ [clodex](https://github.com/gxjansen/clodex); the routing here is done in the
208
+ bundle rather than with clodex's TLS interception.
140
209
 
141
210
  ## License
142
211
 
@@ -0,0 +1,183 @@
1
+ # patch-cc
2
+
3
+ [![CI](https://github.com/anfreire/patch-cc/actions/workflows/ci.yml/badge.svg)](https://github.com/anfreire/patch-cc/actions/workflows/ci.yml)
4
+ [![PyPI](https://img.shields.io/pypi/v/patch-cc)](https://pypi.org/project/patch-cc/)
5
+
6
+ An interactive patcher for the **Claude Code native binary**. Pick the tweaks
7
+ you want — inline and live thinking, detailed tool calls, subagent model
8
+ overrides, your own startup name — and apply them to your installed `claude`
9
+ in one keystroke. Pure Python; no Node, no Bun.
10
+
11
+ ## Requirements
12
+
13
+ - **Linux or macOS**
14
+ - **Python 3.11+**
15
+ - **[uv](https://docs.astral.sh/uv/)** — how patch-cc is run and installed
16
+ below. Install it with `curl -LsSf https://astral.sh/uv/install.sh | sh`.
17
+ Not using uv? `pipx install patch-cc` (or `pip install patch-cc`) works too;
18
+ it is an ordinary PyPI package.
19
+ - **macOS only:** the Xcode command line tools, for `codesign` — a patched
20
+ binary has to be re-signed or macOS refuses to run it.
21
+
22
+ ```bash
23
+ uvx patch-cc # fullscreen menu, no install needed
24
+ ```
25
+
26
+ The menu is a single centered panel: move with `↑ ↓`, toggle with `space`,
27
+ press `s` to save. Patches that carry a setting — subagent models, Codex models,
28
+ the startup name, the `--version` marker — open a centered modal on `enter`, and
29
+ the row then shows what you chose. Everything choosable is a picker: the agent
30
+ names and model aliases are **discovered from your binary itself** (and the
31
+ Codex ones from your plan), so the menu can never offer something your build
32
+ would reject. Typing exists only for the genuinely free-text values.
33
+
34
+ A patched binary records what was applied inside itself, so the menu always
35
+ comes up showing the real current state, and `patch-cc status` answers
36
+ exactly.
37
+
38
+ Prefer it always available on your PATH? Install it:
39
+
40
+ ```bash
41
+ uv tool install patch-cc
42
+ patch-cc # then just run it
43
+ ```
44
+
45
+ ## What it can do
46
+
47
+ | Group | Patch | |
48
+ |---|---|---|
49
+ | Output & diffs | Detailed tool calls | Show full read/search calls, not collapsed summaries |
50
+ | | Colour new files as diffs | Created files render with `+` lines and green |
51
+ | Thinking | Fix blank thinking blocks | Opt out of the server-side experiment that can empty every thinking block |
52
+ | | Always show thinking | Thinking blocks stay inline — no `ctrl+o` |
53
+ | | Stream thinking live | See reasoning as it is generated, inline and in order |
54
+ | Subagents | Show subagent prompts | Prompt blocks visible during normal use |
55
+ | | Override subagent models | Pick the model per built-in agent (discovered from your binary) |
56
+ | Chrome | Disable spinner tips | No rotating tips on the spinner |
57
+ | | Custom startup name | Defaults to `<your username>'s Code` |
58
+ | | Mark `--version` | Appends `(patched)` — or any marker you choose |
59
+ | Codex | Codex models | Use OpenAI/Codex-plan models in Claude Code — see [Codex models](#codex-models) |
60
+
61
+ ## Usage
62
+
63
+ Everything the menu does is also a non-interactive subcommand (shown with
64
+ `uvx`; drop it if you installed the tool):
65
+
66
+ ```bash
67
+ uvx patch-cc apply # the default patch set
68
+ uvx patch-cc apply tool-calls live-thinking # just these
69
+ uvx patch-cc apply --brand # + branding as <username>'s Code
70
+ uvx patch-cc apply --brand "Ada's Code" # + branding, explicit name
71
+ uvx patch-cc apply --model Explore=haiku --model general-purpose=opus
72
+ uvx patch-cc apply --suffix "(mine)" # custom --version marker
73
+ uvx patch-cc apply --codex gpt-5.6-sol # + a Codex model (see below)
74
+ uvx patch-cc apply --from-cache # replay your last remembered selection
75
+ uvx patch-cc status # exactly what is applied
76
+ uvx patch-cc doctor # do all patches match this build?
77
+ uvx patch-cc doctor path/to/claude # ...or match some other binary
78
+ uvx patch-cc list # every patch, described
79
+ uvx patch-cc restore # put the original back
80
+ ```
81
+
82
+ `--brand`, `--model` and `--codex` imply their patches; agents and models are
83
+ validated against what your installed binary actually ships, and Codex model ids
84
+ against what your plan offers. `apply --help` lists all three.
85
+
86
+ ## Codex models
87
+
88
+ Bring your **ChatGPT/Codex-plan** models (GPT-5.x) into Claude Code and use them
89
+ alongside your Claude ones — in the `/model` picker, as a subagent override,
90
+ with `/effort` driving how hard they think. It is two halves: a patch that
91
+ teaches your binary to accept and route the models you pick, and a small
92
+ localhost **gateway** that translates between Claude Code and OpenAI. Only the
93
+ models you pick are diverted — every Anthropic request stays byte-identical,
94
+ so your Claude plan is untouched. Nothing extra to install: the gateway is pure
95
+ Python and ships with patch-cc; you just sign in to a ChatGPT or Codex plan.
96
+
97
+ ```bash
98
+ uvx patch-cc codex login # sign in to your ChatGPT/Codex plan
99
+ uvx patch-cc # Codex models → pick models → save with `s`
100
+ uvx patch-cc codex serve # start the gateway; keep it running
101
+ ```
102
+
103
+ Which models you want is a patch setting like the startup name, so the menu's
104
+ **Codex models** row is where you pick them — it lists what your plan offers,
105
+ live. Everything the menu does the command line does too:
106
+
107
+ ```bash
108
+ uvx patch-cc apply --codex gpt-5.6-sol --codex gpt-5.5
109
+ uvx patch-cc apply --help # lists the model ids your plan offers
110
+ uvx patch-cc apply --from-cache # replay your last selection
111
+ ```
112
+
113
+ Then pick a model like any other:
114
+
115
+ ```bash
116
+ claude --model sol # shortcut → newest gpt-5.6-sol
117
+ claude --model gpt-5.6-sol # the full id also works, as does /model
118
+ ```
119
+
120
+ - **Shortcuts** (`sol`, `terra`, `luna`, …) are the last word of the model id;
121
+ the newest in a family wins, the way `opus` means the latest Claude Opus. They
122
+ are derived from the ids you picked — there is nothing to configure.
123
+ - **Your binary is the record.** The models and the port live in the patched
124
+ binary, so `patch-cc status` names exactly what is registered, and
125
+ `codex serve` finds the right port with nothing to tell it.
126
+ - **They read as native everywhere.** A registered model is added to the
127
+ binary's own model table, so its real name shows in the status line and the
128
+ welcome banner, its plan-reported effort levels are declared, and
129
+ `/advisor sol` works like any other model. Ask for an effort the model
130
+ doesn't run and the gateway quietly runs the closest lower one — the same
131
+ clamping Claude Code documents for its own models.
132
+ - **The gateway has to be running.** Every surface that names it says whether it
133
+ is — the apply report as soon as you bake, `patch-cc status`, and `codex
134
+ status` — so you never learn it from a request that hangs instead.
135
+ - The gateway holds *your* OpenAI token and listens only on localhost. No
136
+ Anthropic-model request is ever diverted to it. The Codex ones that *are*
137
+ still carry Claude Code's own auth header — the gateway ignores it and never
138
+ forwards it, but treat the port as trusted: whatever binds it first sees it.
139
+ - After a Claude update, **re-bake** — the patch reverts with the binary — but
140
+ the gateway is separate and keeps running. Until you do, a Codex model you had
141
+ saved as your default reads as unavailable; the models live in the patch.
142
+ Change the port and the gateway needs a restart to follow it.
143
+
144
+ ## After a Claude update
145
+
146
+ Claude auto-updates roughly daily and replaces the binary, which reverts the
147
+ patch. Re-run `patch-cc` — the menu remembers your last selection — replay it
148
+ without the menu via `patch-cc apply --from-cache`, or re-apply your set
149
+ explicitly:
150
+
151
+ ```bash
152
+ uvx patch-cc apply --brand --model Explore=haiku
153
+ ```
154
+
155
+ `uvx patch-cc status` tells you whether the current binary is patched, and the
156
+ startup name / `--version` marker are visible tells too.
157
+
158
+ ## Why native-only, and why it stays small
159
+
160
+ Claude Code now ships only as a Bun single-file executable; the npm package is a
161
+ wrapper that downloads it. patch-cc edits the JavaScript bundle embedded in the
162
+ binary's `.bun` section in place. It also drops the module's 154 MB of stale
163
+ precompiled bytecode — editing the source invalidates it anyway — so a patched
164
+ binary is *smaller* than the original (≈113 MB vs 267 MB), not larger.
165
+
166
+ See [docs/INTERNALS.md](docs/INTERNALS.md) for the container format and
167
+ [docs/PLAYBOOK.md](docs/PLAYBOOK.md) for repairing a patch after an update.
168
+ Changing anything here starts at [docs/CONDUCT.md](docs/CONDUCT.md) — how this
169
+ is built, and what a patch has to prove before it ships.
170
+
171
+ ## Credits
172
+
173
+ The patch set is a Python port of
174
+ [a-connoisseur/patch-claude-code](https://github.com/a-connoisseur/patch-claude-code),
175
+ with the subagent-model override idea from
176
+ [aleks-apostle/claude-code-patches](https://github.com/aleks-apostle/claude-code-patches).
177
+ Registering Codex models inside the bundle follows
178
+ [clodex](https://github.com/gxjansen/clodex); the routing here is done in the
179
+ bundle rather than with clodex's TLS interception.
180
+
181
+ ## License
182
+
183
+ MIT
@@ -29,9 +29,11 @@ shape that already absorbs every case, found rather than bolted on.
29
29
  brick.
30
30
 
31
31
  - **Explicit invocations are hermetic.** A non-interactive command's arguments
32
- are its whole input; no saved state may silently change what it does, so the
33
- same command always yields the same result. Persisted choices belong to the
34
- interactive UI alone they pre-fill a prompt, never trigger an action.
32
+ are its whole input; no saved state may *silently* change what it does.
33
+ Persisted choices pre-fill the interactive UI and never act on their own — the
34
+ lone exception is `apply --from-cache`, which takes the cache as its *named*
35
+ input, so the state it reads is declared in the arguments, not hidden behind a
36
+ default. Absent that flag, the same command still always yields the same result.
35
37
 
36
38
  - **Anchor matchers on meaning.** String literals, `case` labels, prop names,
37
39
  control-flow shape — never a minified local that changes every build. A new
@@ -88,10 +88,12 @@ edit is followed by an ad-hoc `codesign` (mandatory on Apple Silicon).
88
88
 
89
89
  ## The manifest
90
90
 
91
- Every patched bundle ends with a single comment line:
91
+ Every patched bundle ends with a single comment line — the one description of
92
+ its shape; [PLAYBOOK.md](PLAYBOOK.md) covers what it means for matcher health:
92
93
 
93
94
  ```
94
- //patch-cc {"v":1,"tool":"0.1.0","patches":[...],"brand":...,"models":{...}}
95
+ //patch-cc {"v":1,"tool":"<version>","patches":[...],"brand":...,"models":{...},
96
+ "codex":{"port":8817,"models":["gpt-5.6-sol", ...]}}
95
97
  ```
96
98
 
97
99
  That line is why `patch-cc status` can name exactly what is applied: several
@@ -100,6 +102,18 @@ can't collide with code and travels with the bundle through extract/repack.
100
102
  The menu also reads it to pre-select the current patch set — the binary is the
101
103
  state.
102
104
 
105
+ Every key after `patches` belongs to a patch and is written only when *that*
106
+ patch landed, so `status` can never assert a name, marker, or model the bundle
107
+ does not contain.
108
+
109
+ Each key records what was *asked for*, never what was derived from it. `codex`
110
+ carries model ids and a port and nothing else: a Codex model's display name and
111
+ context window are already baked into the bundle, and repeating them here would
112
+ be a second copy — one that a relabelling upstream could make disagree with the
113
+ binary it claims to describe. That is also what makes the manifest the single
114
+ home for the gateway port: `codex serve` and `codex status` read it from here
115
+ rather than from a store of their own.
116
+
103
117
  ## Safety
104
118
 
105
119
  - Before the first patch of a version, the pristine binary is copied to
@@ -112,4 +126,6 @@ state.
112
126
  - Every write is verified: patch-cc re-extracts the JS from the binary it just
113
127
  wrote and asserts it equals what it meant to write.
114
128
  - Patching a binary that is already marked, when no pristine backup exists, is
115
- refused unless `--force` — there is nothing clean to start from.
129
+ refused outright — there is nothing clean to start from, and our edits change
130
+ lengths, so a second pass would corrupt rather than update. `restore` or a
131
+ reinstall are the only honest fixes; there is deliberately no override.