codex-python 0.2.16__tar.gz → 0.3.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.
@@ -0,0 +1,358 @@
1
+ Metadata-Version: 2.4
2
+ Name: codex-python
3
+ Version: 0.3.0
4
+ Classifier: Programming Language :: Python :: 3
5
+ Classifier: Programming Language :: Python :: 3 :: Only
6
+ Classifier: Programming Language :: Python :: 3.13
7
+ Classifier: License :: OSI Approved :: MIT License
8
+ Classifier: Typing :: Typed
9
+ Classifier: Operating System :: OS Independent
10
+ Requires-Dist: pydantic>=2.11.7
11
+ License-File: LICENSE
12
+ Summary: A minimal Python library scaffold for codex-python
13
+ Keywords: codex,library,scaffold
14
+ Requires-Python: >=3.12
15
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
16
+ Project-URL: Homepage, https://github.com/gersmann/codex-python
17
+ Project-URL: Repository, https://github.com/gersmann/codex-python
18
+ Project-URL: Issues, https://github.com/gersmann/codex-python/issues
19
+
20
+ # codex-python
21
+
22
+ Native Python bindings for Codex (in‑process execution). Distributed as a single package with prebuilt wheels that bundle the native extension.
23
+
24
+ - Python: 3.12–3.13 (CI also attempts 3.14)
25
+ - Import name: `codex`
26
+ - PyPI: https://pypi.org/project/codex-python/
27
+
28
+ ## Table of Contents
29
+
30
+ 1. Install
31
+ 2. Quickstart
32
+ 3. API Overview
33
+ 4. Configuration
34
+ - Common Overrides
35
+ - Examples
36
+ 5. Troubleshooting
37
+ 6. Developing
38
+ 7. CI Integration (Review + Act)
39
+
40
+ ## 1) Install
41
+
42
+ ```
43
+ pip install codex-python
44
+ ```
45
+
46
+ If there’s no prebuilt wheel for your platform/Python, pip will build from source. That requires a Rust toolchain and maturin; see Developing.
47
+
48
+ ## 2) Quickstart
49
+
50
+ Run a prompt and collect structured events (typed):
51
+
52
+ ```python
53
+ from codex import run_exec, CodexClient, CodexNativeError
54
+ from codex.config import CodexConfig, ApprovalPolicy, SandboxMode
55
+
56
+ cfg = CodexConfig(
57
+ model="gpt-5",
58
+ model_provider="openai",
59
+ approval_policy=ApprovalPolicy.ON_REQUEST,
60
+ sandbox_mode=SandboxMode.WORKSPACE_WRITE,
61
+ include_apply_patch_tool=False, # disable apply patch tool by default
62
+ )
63
+
64
+ # One‑shot
65
+ try:
66
+ events = run_exec("Explain this repo", config=cfg)
67
+ for ev in events:
68
+ print(ev.id, ev.msg.type)
69
+ except CodexNativeError as e:
70
+ print("codex-native error:", e)
71
+
72
+ # Conversation (streaming)
73
+ client = CodexClient(config=cfg)
74
+ conv = client.start_conversation()
75
+ conv.submit_user_turn("Add a smoke test")
76
+ for ev in conv:
77
+ print(ev.id, getattr(getattr(ev.msg, "root", ev.msg), "type", "unknown"))
78
+ ```
79
+
80
+ Notes
81
+ - `Event.msg` is a typed union (`EventMsg`). For raw dicts from the native layer, use `codex.native.start_exec_stream`.
82
+
83
+ ### Example: basic_conversation.py
84
+
85
+ Run the interactive example that streams events and prompts for approvals:
86
+
87
+ ```
88
+ python examples/basic_conversation.py "ask me a question"
89
+ ```
90
+
91
+ Flags you may find useful:
92
+ - `--approval on-request` (default) to be asked before running tools
93
+ - `--sandbox workspace-write` to allow writes within the repo
94
+ - `--allow-apply-patch` to include the apply‑patch tool in the session
95
+
96
+ ## 3) API Overview
97
+
98
+ - `codex.run_exec(prompt, *, config=None, load_default_config=True, output_schema=None) -> list[Event]`
99
+ Synchronous one‑shot; returns all events.
100
+
101
+ - `codex.run_review(prompt, *, user_facing_hint=None, config=None, load_default_config=True) -> list[Event]`
102
+ Synchronous review flow; returns all events.
103
+
104
+ - `codex.run_prompt(prompt, *, config=None, load_default_config=True, output_schema=None) -> str | Any`
105
+ Convenience: returns the final assistant message (or parsed JSON when `output_schema` is set).
106
+
107
+ - `codex.CodexClient(config).start_conversation(... ) -> Conversation`
108
+ Creates a stateful session. Iterate over `Conversation` to stream events.
109
+ - `Conversation.submit_user_turn(prompt, *, cwd=None, approval_policy=..., sandbox_mode=..., model=None, effort=..., summary=..., output_schema=None)`
110
+ - `Conversation.submit_review(prompt, user_facing_hint=None)`
111
+ - `Conversation.approve_exec(id, decision)` / `approve_patch(id, decision)`
112
+ - `Conversation.interrupt()`, `Conversation.shutdown()`
113
+ - Utility: `user_input_text`, `override_turn_context`, `add_to_history`, `get_history_entry`, `get_path`, `list_mcp_tools`, `list_custom_prompts`, `compact`
114
+
115
+ - `await codex.CodexClient(...).astart_conversation() -> AsyncConversation`
116
+ Async iterator with the same methods as `Conversation` (async variants).
117
+
118
+ - Exceptions
119
+ - `CodexError` base; `CodexNativeError` wraps native failures / missing extension.
120
+
121
+ - Native helper
122
+ - `codex.native.preview_config(config_overrides, load_default_config)` → compact effective config snapshot (testing aid).
123
+
124
+ ## 4) Configuration
125
+
126
+ Use the Pydantic model `CodexConfig` for strongly‑typed overrides (mirrors the Rust `ConfigOverrides`).
127
+
128
+ ```python
129
+ from codex.config import CodexConfig, ApprovalPolicy, SandboxMode
130
+
131
+ cfg = CodexConfig(
132
+ model="gpt-5",
133
+ model_provider="openai",
134
+ approval_policy=ApprovalPolicy.ON_REQUEST,
135
+ sandbox_mode=SandboxMode.WORKSPACE_WRITE,
136
+ cwd="/path/to/project",
137
+ include_apply_patch_tool=True,
138
+ )
139
+ ```
140
+
141
+ Behavior
142
+ - Precedence matches the CLI: `config.toml` < CLI `-c key=value` < typed overrides (`CodexConfig`).
143
+ - `to_dict()` emits only set fields and serializes enums to kebab‑case as expected by the native core.
144
+ - Set `load_default_config=False` on API calls to avoid reading any on‑disk config and rely purely on overrides you pass in.
145
+
146
+ ### Common Overrides
147
+
148
+ - Model selection: `model`, `review_model`, `model_provider`.
149
+ - Approvals & sandbox: `approval_policy`, `sandbox_mode`, `sandbox_workspace_write` (fine‑tune writeable roots, network, tmpdir behavior for WorkspaceWrite).
150
+ - Shell env policy: `shell_environment_policy` for child process envs: `inherit` (`core|all|none`), `exclude`, `include_only`, `set`, `experimental_use_profile`.
151
+ - Tools: `include_plan_tool`, `include_apply_patch_tool`, `include_view_image_tool`, `tools_web_search_request`.
152
+ - Reasoning & tokens: `model_context_window`, `model_max_output_tokens`, `model_auto_compact_token_limit`, `model_reasoning_effort`, `model_reasoning_summary`, `model_verbosity`, `model_supports_reasoning_summaries`, `model_reasoning_summary_format`.
153
+ - UI/UX: `show_raw_agent_reasoning`, `hide_agent_reasoning`, `disable_paste_burst`, `chatgpt_base_url`, `file_opener`.
154
+ - Providers & MCP: `model_providers` entries support `wire_api` (`responses|chat`), `env_key`, `env_key_instructions`, `http_headers`, `env_http_headers`, retry/timeout tuning; `requires_openai_auth` enables ChatGPT/OAuth auth. Define MCP servers via `mcp_servers`.
155
+
156
+ ### Examples
157
+
158
+ Enable web search and tune sandbox writes:
159
+
160
+ ```python
161
+ from codex.config import CodexConfig, ApprovalPolicy, SandboxMode
162
+
163
+ cfg = CodexConfig(
164
+ model="gpt-5",
165
+ review_model="gpt-5-codex",
166
+ model_provider="openai",
167
+ approval_policy=ApprovalPolicy.ON_REQUEST,
168
+ sandbox_mode=SandboxMode.WORKSPACE_WRITE,
169
+ sandbox_workspace_write={
170
+ "writable_roots": ["/tmp/my-session"],
171
+ "exclude_tmpdir_env_var": True,
172
+ },
173
+ tools_web_search_request=True,
174
+ )
175
+ ```
176
+
177
+ Constrain child process environment for shell tools:
178
+
179
+ ```python
180
+ from codex.config import CodexConfig, ShellEnvironmentPolicy
181
+
182
+ cfg = CodexConfig(
183
+ shell_environment_policy=ShellEnvironmentPolicy(
184
+ inherit="core",
185
+ exclude=["*TOKEN*", "*KEY*"],
186
+ set={"FOO": "bar"},
187
+ include_only=["PATH", "HOME", "FOO"],
188
+ )
189
+ )
190
+ ```
191
+
192
+ Provider entry with OAuth‑style auth:
193
+
194
+ ```python
195
+ from codex.config import CodexConfig
196
+
197
+ cfg = CodexConfig(
198
+ model_provider="openai",
199
+ model_providers={
200
+ "openai": {
201
+ "name": "OpenAI",
202
+ "wire_api": "responses",
203
+ "requires_openai_auth": True,
204
+ "request_max_retries": 4,
205
+ }
206
+ }
207
+ )
208
+ ```
209
+
210
+ ## 5) Troubleshooting
211
+
212
+ - “codex_native extension not installed”
213
+ - Install from PyPI or build locally (see Developing). If building, ensure Rust toolchain + maturin are available.
214
+ - No native wheel for your platform/Python
215
+ - Pip will build from source. If that fails, check your Rust toolchain and try `make dev-native` inside a virtualenv.
216
+ - Missing `OPENAI_API_KEY`
217
+ - Set the environment variable or configure a provider entry (`model_providers`) that uses a different auth method.
218
+
219
+ ## 6) Developing
220
+
221
+ Prerequisites
222
+ - Python 3.12/3.13
223
+ - Rust toolchain (cargo)
224
+ - maturin (native builds)
225
+ - uv (optional, fast Python builds and dev tooling)
226
+
227
+ Common tasks
228
+ - Format: `make fmt`
229
+ - Lint: `make lint` (ruff + mypy)
230
+ - Test: `make test` (pytest)
231
+ - Build native locally: `make dev-native`
232
+ - Generate protocol types from upstream: `make gen-protocol`
233
+
234
+ Protocol types
235
+ - `make gen-protocol` generates TS types + JSON Schema and writes Pydantic v2 models to `codex/protocol/types.py`.
236
+ - Generated models include `model_config = ConfigDict(extra='allow')` at class end.
237
+
238
+ Releasing
239
+ - Bump versions in `codex/__init__.py` and `crates/codex_native/Cargo.toml`.
240
+ - Update `CHANGELOG.md`.
241
+ - Tag and push: `git tag -a vX.Y.Z -m "codex-python X.Y.Z" && git push origin vX.Y.Z`.
242
+ - GitHub Actions builds and publishes wheels and sdist via Trusted Publishing.
243
+
244
+ Project layout
245
+ ```
246
+ .
247
+ ├── codex/ # Python package
248
+ ├── crates/codex_native/ # PyO3 native extension
249
+ ├── scripts/ # generators and helpers
250
+ ├── .github/workflows/ # CI, publish, native wheels
251
+ └── Makefile # common tasks
252
+ ```
253
+
254
+ Links
255
+ - Codex: https://github.com/openai/codex
256
+ - uv: https://docs.astral.sh/uv/
257
+ - maturin: https://www.maturin.rs/
258
+
259
+ ## 7) CI Integration: Review + Act
260
+
261
+ This repo includes a workflow that:
262
+ - Runs autonomous code review on PRs ("Review" job).
263
+ - Listens for `/codex ...` comments and performs autonomous edits ("Act" job), optionally running your tests.
264
+
265
+ Both jobs use `gersmann/codex-review-action@v1`.
266
+
267
+ ### Minimal Review Job
268
+
269
+ ```yaml
270
+ name: Codex Review
271
+ on:
272
+ pull_request:
273
+ types: [opened, synchronize, ready_for_review]
274
+ jobs:
275
+ review:
276
+ name: Review
277
+ permissions:
278
+ contents: read
279
+ pull-requests: write
280
+ issues: read
281
+ env:
282
+ OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
283
+ runs-on: ubuntu-latest
284
+ steps:
285
+ - uses: actions/checkout@v4
286
+ with:
287
+ fetch-depth: 0
288
+ - name: Codex autonomous review
289
+ if: env.OPENAI_API_KEY != ''
290
+ uses: gersmann/codex-review-action@v1
291
+ with:
292
+ mode: review
293
+ openai_api_key: ${{ secrets.OPENAI_API_KEY }}
294
+ model: gpt-5
295
+ reasoning_effort: medium
296
+ debug_level: 1
297
+ ```
298
+
299
+ ### Act on `/codex` Comments
300
+
301
+ ```yaml
302
+ act:
303
+ name: Act on /codex comments
304
+ if: >-
305
+ (
306
+ github.event_name == 'issue_comment' &&
307
+ startsWith(github.event.comment.body, '/codex') &&
308
+ github.event.issue.pull_request &&
309
+ contains(fromJSON('["MEMBER","OWNER","COLLABORATOR"]'), github.event.comment.author_association)
310
+ ) || (
311
+ github.event_name == 'pull_request_review_comment' &&
312
+ startsWith(github.event.comment.body, '/codex') &&
313
+ contains(fromJSON('["MEMBER","OWNER","COLLABORATOR"]'), github.event.comment.author_association)
314
+ )
315
+ && github.actor != 'dependabot[bot]'
316
+ concurrency:
317
+ group: codex-act-${{ github.event.issue.number || github.event.pull_request.number || github.ref }}
318
+ cancel-in-progress: false
319
+ permissions:
320
+ contents: write
321
+ issues: write
322
+ pull-requests: write
323
+ actions: write
324
+ runs-on: ubuntu-latest
325
+ env:
326
+ APP_ENV: test
327
+ CI: true
328
+ steps:
329
+ - uses: actions/checkout@v4
330
+ with:
331
+ fetch-depth: 0
332
+ ref: ${{ github.event.pull_request.head.sha || format('refs/pull/{0}/head', github.event.issue.number) }}
333
+ token: ${{ secrets.REPO_ACCESS_TOKEN }}
334
+ - name: Setup Environment
335
+ uses: ./.github/actions/setup
336
+ with:
337
+ python-version: '3.13'
338
+ node-version: '20'
339
+ - name: Codex autonomous edits
340
+ if: env.OPENAI_API_KEY != ''
341
+ uses: gersmann/codex-review-action@v1
342
+ with:
343
+ mode: act
344
+ openai_api_key: ${{ secrets.OPENAI_API_KEY }}
345
+ model: gpt-5
346
+ debug_level: 1
347
+ ```
348
+
349
+ Common `/codex` patterns
350
+ - `/codex` — propose and apply fixes
351
+ - `/codex focus <path>` — limit scope
352
+ - `/codex redo` — re‑run on latest PR head
353
+
354
+ Secrets
355
+ - `OPENAI_API_KEY` to call the model API
356
+ - `REPO_ACCESS_TOKEN` (write permission) so pushes from Act trigger CI
357
+ - Project‑specific secrets for tests (DB URLs, API keys), when services are enabled
358
+
@@ -0,0 +1,338 @@
1
+ # codex-python
2
+
3
+ Native Python bindings for Codex (in‑process execution). Distributed as a single package with prebuilt wheels that bundle the native extension.
4
+
5
+ - Python: 3.12–3.13 (CI also attempts 3.14)
6
+ - Import name: `codex`
7
+ - PyPI: https://pypi.org/project/codex-python/
8
+
9
+ ## Table of Contents
10
+
11
+ 1. Install
12
+ 2. Quickstart
13
+ 3. API Overview
14
+ 4. Configuration
15
+ - Common Overrides
16
+ - Examples
17
+ 5. Troubleshooting
18
+ 6. Developing
19
+ 7. CI Integration (Review + Act)
20
+
21
+ ## 1) Install
22
+
23
+ ```
24
+ pip install codex-python
25
+ ```
26
+
27
+ If there’s no prebuilt wheel for your platform/Python, pip will build from source. That requires a Rust toolchain and maturin; see Developing.
28
+
29
+ ## 2) Quickstart
30
+
31
+ Run a prompt and collect structured events (typed):
32
+
33
+ ```python
34
+ from codex import run_exec, CodexClient, CodexNativeError
35
+ from codex.config import CodexConfig, ApprovalPolicy, SandboxMode
36
+
37
+ cfg = CodexConfig(
38
+ model="gpt-5",
39
+ model_provider="openai",
40
+ approval_policy=ApprovalPolicy.ON_REQUEST,
41
+ sandbox_mode=SandboxMode.WORKSPACE_WRITE,
42
+ include_apply_patch_tool=False, # disable apply patch tool by default
43
+ )
44
+
45
+ # One‑shot
46
+ try:
47
+ events = run_exec("Explain this repo", config=cfg)
48
+ for ev in events:
49
+ print(ev.id, ev.msg.type)
50
+ except CodexNativeError as e:
51
+ print("codex-native error:", e)
52
+
53
+ # Conversation (streaming)
54
+ client = CodexClient(config=cfg)
55
+ conv = client.start_conversation()
56
+ conv.submit_user_turn("Add a smoke test")
57
+ for ev in conv:
58
+ print(ev.id, getattr(getattr(ev.msg, "root", ev.msg), "type", "unknown"))
59
+ ```
60
+
61
+ Notes
62
+ - `Event.msg` is a typed union (`EventMsg`). For raw dicts from the native layer, use `codex.native.start_exec_stream`.
63
+
64
+ ### Example: basic_conversation.py
65
+
66
+ Run the interactive example that streams events and prompts for approvals:
67
+
68
+ ```
69
+ python examples/basic_conversation.py "ask me a question"
70
+ ```
71
+
72
+ Flags you may find useful:
73
+ - `--approval on-request` (default) to be asked before running tools
74
+ - `--sandbox workspace-write` to allow writes within the repo
75
+ - `--allow-apply-patch` to include the apply‑patch tool in the session
76
+
77
+ ## 3) API Overview
78
+
79
+ - `codex.run_exec(prompt, *, config=None, load_default_config=True, output_schema=None) -> list[Event]`
80
+ Synchronous one‑shot; returns all events.
81
+
82
+ - `codex.run_review(prompt, *, user_facing_hint=None, config=None, load_default_config=True) -> list[Event]`
83
+ Synchronous review flow; returns all events.
84
+
85
+ - `codex.run_prompt(prompt, *, config=None, load_default_config=True, output_schema=None) -> str | Any`
86
+ Convenience: returns the final assistant message (or parsed JSON when `output_schema` is set).
87
+
88
+ - `codex.CodexClient(config).start_conversation(... ) -> Conversation`
89
+ Creates a stateful session. Iterate over `Conversation` to stream events.
90
+ - `Conversation.submit_user_turn(prompt, *, cwd=None, approval_policy=..., sandbox_mode=..., model=None, effort=..., summary=..., output_schema=None)`
91
+ - `Conversation.submit_review(prompt, user_facing_hint=None)`
92
+ - `Conversation.approve_exec(id, decision)` / `approve_patch(id, decision)`
93
+ - `Conversation.interrupt()`, `Conversation.shutdown()`
94
+ - Utility: `user_input_text`, `override_turn_context`, `add_to_history`, `get_history_entry`, `get_path`, `list_mcp_tools`, `list_custom_prompts`, `compact`
95
+
96
+ - `await codex.CodexClient(...).astart_conversation() -> AsyncConversation`
97
+ Async iterator with the same methods as `Conversation` (async variants).
98
+
99
+ - Exceptions
100
+ - `CodexError` base; `CodexNativeError` wraps native failures / missing extension.
101
+
102
+ - Native helper
103
+ - `codex.native.preview_config(config_overrides, load_default_config)` → compact effective config snapshot (testing aid).
104
+
105
+ ## 4) Configuration
106
+
107
+ Use the Pydantic model `CodexConfig` for strongly‑typed overrides (mirrors the Rust `ConfigOverrides`).
108
+
109
+ ```python
110
+ from codex.config import CodexConfig, ApprovalPolicy, SandboxMode
111
+
112
+ cfg = CodexConfig(
113
+ model="gpt-5",
114
+ model_provider="openai",
115
+ approval_policy=ApprovalPolicy.ON_REQUEST,
116
+ sandbox_mode=SandboxMode.WORKSPACE_WRITE,
117
+ cwd="/path/to/project",
118
+ include_apply_patch_tool=True,
119
+ )
120
+ ```
121
+
122
+ Behavior
123
+ - Precedence matches the CLI: `config.toml` < CLI `-c key=value` < typed overrides (`CodexConfig`).
124
+ - `to_dict()` emits only set fields and serializes enums to kebab‑case as expected by the native core.
125
+ - Set `load_default_config=False` on API calls to avoid reading any on‑disk config and rely purely on overrides you pass in.
126
+
127
+ ### Common Overrides
128
+
129
+ - Model selection: `model`, `review_model`, `model_provider`.
130
+ - Approvals & sandbox: `approval_policy`, `sandbox_mode`, `sandbox_workspace_write` (fine‑tune writeable roots, network, tmpdir behavior for WorkspaceWrite).
131
+ - Shell env policy: `shell_environment_policy` for child process envs: `inherit` (`core|all|none`), `exclude`, `include_only`, `set`, `experimental_use_profile`.
132
+ - Tools: `include_plan_tool`, `include_apply_patch_tool`, `include_view_image_tool`, `tools_web_search_request`.
133
+ - Reasoning & tokens: `model_context_window`, `model_max_output_tokens`, `model_auto_compact_token_limit`, `model_reasoning_effort`, `model_reasoning_summary`, `model_verbosity`, `model_supports_reasoning_summaries`, `model_reasoning_summary_format`.
134
+ - UI/UX: `show_raw_agent_reasoning`, `hide_agent_reasoning`, `disable_paste_burst`, `chatgpt_base_url`, `file_opener`.
135
+ - Providers & MCP: `model_providers` entries support `wire_api` (`responses|chat`), `env_key`, `env_key_instructions`, `http_headers`, `env_http_headers`, retry/timeout tuning; `requires_openai_auth` enables ChatGPT/OAuth auth. Define MCP servers via `mcp_servers`.
136
+
137
+ ### Examples
138
+
139
+ Enable web search and tune sandbox writes:
140
+
141
+ ```python
142
+ from codex.config import CodexConfig, ApprovalPolicy, SandboxMode
143
+
144
+ cfg = CodexConfig(
145
+ model="gpt-5",
146
+ review_model="gpt-5-codex",
147
+ model_provider="openai",
148
+ approval_policy=ApprovalPolicy.ON_REQUEST,
149
+ sandbox_mode=SandboxMode.WORKSPACE_WRITE,
150
+ sandbox_workspace_write={
151
+ "writable_roots": ["/tmp/my-session"],
152
+ "exclude_tmpdir_env_var": True,
153
+ },
154
+ tools_web_search_request=True,
155
+ )
156
+ ```
157
+
158
+ Constrain child process environment for shell tools:
159
+
160
+ ```python
161
+ from codex.config import CodexConfig, ShellEnvironmentPolicy
162
+
163
+ cfg = CodexConfig(
164
+ shell_environment_policy=ShellEnvironmentPolicy(
165
+ inherit="core",
166
+ exclude=["*TOKEN*", "*KEY*"],
167
+ set={"FOO": "bar"},
168
+ include_only=["PATH", "HOME", "FOO"],
169
+ )
170
+ )
171
+ ```
172
+
173
+ Provider entry with OAuth‑style auth:
174
+
175
+ ```python
176
+ from codex.config import CodexConfig
177
+
178
+ cfg = CodexConfig(
179
+ model_provider="openai",
180
+ model_providers={
181
+ "openai": {
182
+ "name": "OpenAI",
183
+ "wire_api": "responses",
184
+ "requires_openai_auth": True,
185
+ "request_max_retries": 4,
186
+ }
187
+ }
188
+ )
189
+ ```
190
+
191
+ ## 5) Troubleshooting
192
+
193
+ - “codex_native extension not installed”
194
+ - Install from PyPI or build locally (see Developing). If building, ensure Rust toolchain + maturin are available.
195
+ - No native wheel for your platform/Python
196
+ - Pip will build from source. If that fails, check your Rust toolchain and try `make dev-native` inside a virtualenv.
197
+ - Missing `OPENAI_API_KEY`
198
+ - Set the environment variable or configure a provider entry (`model_providers`) that uses a different auth method.
199
+
200
+ ## 6) Developing
201
+
202
+ Prerequisites
203
+ - Python 3.12/3.13
204
+ - Rust toolchain (cargo)
205
+ - maturin (native builds)
206
+ - uv (optional, fast Python builds and dev tooling)
207
+
208
+ Common tasks
209
+ - Format: `make fmt`
210
+ - Lint: `make lint` (ruff + mypy)
211
+ - Test: `make test` (pytest)
212
+ - Build native locally: `make dev-native`
213
+ - Generate protocol types from upstream: `make gen-protocol`
214
+
215
+ Protocol types
216
+ - `make gen-protocol` generates TS types + JSON Schema and writes Pydantic v2 models to `codex/protocol/types.py`.
217
+ - Generated models include `model_config = ConfigDict(extra='allow')` at class end.
218
+
219
+ Releasing
220
+ - Bump versions in `codex/__init__.py` and `crates/codex_native/Cargo.toml`.
221
+ - Update `CHANGELOG.md`.
222
+ - Tag and push: `git tag -a vX.Y.Z -m "codex-python X.Y.Z" && git push origin vX.Y.Z`.
223
+ - GitHub Actions builds and publishes wheels and sdist via Trusted Publishing.
224
+
225
+ Project layout
226
+ ```
227
+ .
228
+ ├── codex/ # Python package
229
+ ├── crates/codex_native/ # PyO3 native extension
230
+ ├── scripts/ # generators and helpers
231
+ ├── .github/workflows/ # CI, publish, native wheels
232
+ └── Makefile # common tasks
233
+ ```
234
+
235
+ Links
236
+ - Codex: https://github.com/openai/codex
237
+ - uv: https://docs.astral.sh/uv/
238
+ - maturin: https://www.maturin.rs/
239
+
240
+ ## 7) CI Integration: Review + Act
241
+
242
+ This repo includes a workflow that:
243
+ - Runs autonomous code review on PRs ("Review" job).
244
+ - Listens for `/codex ...` comments and performs autonomous edits ("Act" job), optionally running your tests.
245
+
246
+ Both jobs use `gersmann/codex-review-action@v1`.
247
+
248
+ ### Minimal Review Job
249
+
250
+ ```yaml
251
+ name: Codex Review
252
+ on:
253
+ pull_request:
254
+ types: [opened, synchronize, ready_for_review]
255
+ jobs:
256
+ review:
257
+ name: Review
258
+ permissions:
259
+ contents: read
260
+ pull-requests: write
261
+ issues: read
262
+ env:
263
+ OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
264
+ runs-on: ubuntu-latest
265
+ steps:
266
+ - uses: actions/checkout@v4
267
+ with:
268
+ fetch-depth: 0
269
+ - name: Codex autonomous review
270
+ if: env.OPENAI_API_KEY != ''
271
+ uses: gersmann/codex-review-action@v1
272
+ with:
273
+ mode: review
274
+ openai_api_key: ${{ secrets.OPENAI_API_KEY }}
275
+ model: gpt-5
276
+ reasoning_effort: medium
277
+ debug_level: 1
278
+ ```
279
+
280
+ ### Act on `/codex` Comments
281
+
282
+ ```yaml
283
+ act:
284
+ name: Act on /codex comments
285
+ if: >-
286
+ (
287
+ github.event_name == 'issue_comment' &&
288
+ startsWith(github.event.comment.body, '/codex') &&
289
+ github.event.issue.pull_request &&
290
+ contains(fromJSON('["MEMBER","OWNER","COLLABORATOR"]'), github.event.comment.author_association)
291
+ ) || (
292
+ github.event_name == 'pull_request_review_comment' &&
293
+ startsWith(github.event.comment.body, '/codex') &&
294
+ contains(fromJSON('["MEMBER","OWNER","COLLABORATOR"]'), github.event.comment.author_association)
295
+ )
296
+ && github.actor != 'dependabot[bot]'
297
+ concurrency:
298
+ group: codex-act-${{ github.event.issue.number || github.event.pull_request.number || github.ref }}
299
+ cancel-in-progress: false
300
+ permissions:
301
+ contents: write
302
+ issues: write
303
+ pull-requests: write
304
+ actions: write
305
+ runs-on: ubuntu-latest
306
+ env:
307
+ APP_ENV: test
308
+ CI: true
309
+ steps:
310
+ - uses: actions/checkout@v4
311
+ with:
312
+ fetch-depth: 0
313
+ ref: ${{ github.event.pull_request.head.sha || format('refs/pull/{0}/head', github.event.issue.number) }}
314
+ token: ${{ secrets.REPO_ACCESS_TOKEN }}
315
+ - name: Setup Environment
316
+ uses: ./.github/actions/setup
317
+ with:
318
+ python-version: '3.13'
319
+ node-version: '20'
320
+ - name: Codex autonomous edits
321
+ if: env.OPENAI_API_KEY != ''
322
+ uses: gersmann/codex-review-action@v1
323
+ with:
324
+ mode: act
325
+ openai_api_key: ${{ secrets.OPENAI_API_KEY }}
326
+ model: gpt-5
327
+ debug_level: 1
328
+ ```
329
+
330
+ Common `/codex` patterns
331
+ - `/codex` — propose and apply fixes
332
+ - `/codex focus <path>` — limit scope
333
+ - `/codex redo` — re‑run on latest PR head
334
+
335
+ Secrets
336
+ - `OPENAI_API_KEY` to call the model API
337
+ - `REPO_ACCESS_TOKEN` (write permission) so pushes from Act trigger CI
338
+ - Project‑specific secrets for tests (DB URLs, API keys), when services are enabled