Skip to content

Commit ef00a8d

Browse files
Merge remote-tracking branch 'origin/main' into nornagon/fix-transcript
# Conflicts: # codex-rs/tui/src/render/mod.rs # codex-rs/tui/src/render/renderable.rs
2 parents 2118255 + a0d5654 commit ef00a8d

File tree

220 files changed

+14670
-4038
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

220 files changed

+14670
-4038
lines changed

.github/ISSUE_TEMPLATE/4-feature-request.yml

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ name: 🎁 Feature Request
22
description: Propose a new feature for Codex
33
labels:
44
- enhancement
5-
- needs triage
65
body:
76
- type: markdown
87
attributes:
@@ -19,11 +18,6 @@ body:
1918
label: What feature would you like to see?
2019
validations:
2120
required: true
22-
- type: textarea
23-
id: author
24-
attributes:
25-
label: Are you interested in implementing this feature?
26-
description: Please wait for acknowledgement before implementing or opening a PR.
2721
- type: textarea
2822
id: notes
2923
attributes:

.github/workflows/ci.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,6 @@ jobs:
6060
run: ./scripts/asciicheck.py codex-cli/README.md
6161
- name: Check codex-cli/README ToC
6262
run: python3 scripts/readme_toc.py codex-cli/README.md
63+
64+
- name: Prettier (run `pnpm run format:fix` to fix)
65+
run: pnpm run format

.github/workflows/issue-deduplicator.yml

Lines changed: 49 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414
permissions:
1515
contents: read
1616
outputs:
17-
codex_output: ${{ steps.codex.outputs.final_message }}
17+
codex_output: ${{ steps.codex.outputs.final-message }}
1818
steps:
1919
- uses: actions/checkout@v4
2020

@@ -44,11 +44,38 @@ jobs:
4444
- id: codex
4545
uses: openai/codex-action@main
4646
with:
47-
openai_api_key: ${{ secrets.CODEX_OPENAI_API_KEY }}
48-
prompt_file: .github/prompts/issue-deduplicator.txt
49-
require_repo_write: false
50-
codex_version: 0.43.0-alpha.16
51-
codex_args: -m gpt-5
47+
openai-api-key: ${{ secrets.CODEX_OPENAI_API_KEY }}
48+
allow-users: "*"
49+
model: gpt-5
50+
prompt: |
51+
You are an assistant that triages new GitHub issues by identifying potential duplicates.
52+
53+
You will receive the following JSON files located in the current working directory:
54+
- `codex-current-issue.json`: JSON object describing the newly created issue (fields: number, title, body).
55+
- `codex-existing-issues.json`: JSON array of recent issues (each element includes number, title, body, createdAt).
56+
57+
Instructions:
58+
- Compare the current issue against the existing issues to find up to five that appear to describe the same underlying problem or request.
59+
- Focus on the underlying intent and context of each issue—such as reported symptoms, feature requests, reproduction steps, or error messages—rather than relying solely on string similarity or synthetic metrics.
60+
- After your analysis, validate your results in 1-2 lines explaining your decision to return the selected matches.
61+
- When unsure, prefer returning fewer matches.
62+
- Include at most five numbers.
63+
64+
output-schema: |
65+
{
66+
"type": "object",
67+
"properties": {
68+
"issues": {
69+
"type": "array",
70+
"items": {
71+
"type": "string"
72+
}
73+
},
74+
"reason": { "type": "string" }
75+
},
76+
"required": ["issues", "reason"],
77+
"additionalProperties": false
78+
}
5279
5380
comment-on-issue:
5481
name: Comment with potential duplicates
@@ -66,22 +93,33 @@ jobs:
6693
with:
6794
github-token: ${{ github.token }}
6895
script: |
69-
let numbers;
96+
const raw = process.env.CODEX_OUTPUT ?? '';
97+
let parsed;
7098
try {
71-
numbers = JSON.parse(process.env.CODEX_OUTPUT);
99+
parsed = JSON.parse(raw);
72100
} catch (error) {
73101
core.info(`Codex output was not valid JSON. Raw output: ${raw}`);
102+
core.info(`Parse error: ${error.message}`);
74103
return;
75104
}
76105
77-
if (numbers.length === 0) {
106+
const issues = Array.isArray(parsed?.issues) ? parsed.issues : [];
107+
const currentIssueNumber = String(context.payload.issue.number);
108+
109+
console.log(`Current issue number: ${currentIssueNumber}`);
110+
console.log(issues);
111+
112+
const filteredIssues = issues.filter((value) => String(value) !== currentIssueNumber);
113+
114+
if (filteredIssues.length === 0) {
78115
core.info('Codex reported no potential duplicates.');
79116
return;
80117
}
81118
82119
const lines = [
83-
'Potential duplicates detected:'
84-
...numbers.map((value) => `- #${value}`),
120+
'Potential duplicates detected. Please review them and close your issue if it is a duplicate.',
121+
'',
122+
...filteredIssues.map((value) => `- #${String(value)}`),
85123
'',
86124
'*Powered by [Codex Action](https://github.com/openai/codex-action)*'];
87125

.github/workflows/issue-labeler.yml

Lines changed: 50 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,23 +13,60 @@ jobs:
1313
runs-on: ubuntu-latest
1414
permissions:
1515
contents: read
16-
env:
17-
ISSUE_NUMBER: ${{ github.event.issue.number }}
18-
ISSUE_TITLE: ${{ github.event.issue.title }}
19-
ISSUE_BODY: ${{ github.event.issue.body }}
20-
REPO_FULL_NAME: ${{ github.repository }}
2116
outputs:
22-
codex_output: ${{ steps.codex.outputs.final_message }}
17+
codex_output: ${{ steps.codex.outputs.final-message }}
2318
steps:
2419
- uses: actions/checkout@v4
2520

2621
- id: codex
2722
uses: openai/codex-action@main
2823
with:
29-
openai_api_key: ${{ secrets.CODEX_OPENAI_API_KEY }}
30-
prompt_file: .github/prompts/issue-labeler.txt
31-
require_repo_write: false
32-
codex_version: 0.43.0-alpha.16
24+
openai-api-key: ${{ secrets.CODEX_OPENAI_API_KEY }}
25+
allow-users: "*"
26+
prompt: |
27+
You are an assistant that reviews GitHub issues for the repository.
28+
29+
Your job is to choose the most appropriate existing labels for the issue described later in this prompt.
30+
Follow these rules:
31+
- Only pick labels out of the list below.
32+
- Prefer a small set of precise labels over many broad ones.
33+
34+
Labels to apply:
35+
1. bug — Reproducible defects in Codex products (CLI, VS Code extension, web, auth).
36+
2. enhancement — Feature requests or usability improvements that ask for new capabilities, better ergonomics, or quality-of-life tweaks.
37+
3. extension — VS Code (or other IDE) extension-specific issues.
38+
4. windows-os — Bugs or friction specific to Windows environments (always when PowerShell is mentioned, path handling, copy/paste, OS-specific auth or tooling failures).
39+
5. mcp — Topics involving Model Context Protocol servers/clients.
40+
6. codex-web — Issues targeting the Codex web UI/Cloud experience.
41+
8. azure — Problems or requests tied to Azure OpenAI deployments.
42+
9. documentation — Updates or corrections needed in docs/README/config references (broken links, missing examples, outdated keys, clarification requests).
43+
10. model-behavior — Undesirable LLM behavior: forgetting goals, refusing work, hallucinating environment details, quota misreports, or other reasoning/performance anomalies.
44+
45+
Issue number: ${{ github.event.issue.number }}
46+
47+
Issue title:
48+
${{ github.event.issue.title }}
49+
50+
Issue body:
51+
${{ github.event.issue.body }}
52+
53+
Repository full name:
54+
${{ github.repository }}
55+
56+
output-schema: |
57+
{
58+
"type": "object",
59+
"properties": {
60+
"labels": {
61+
"type": "array",
62+
"items": {
63+
"type": "string"
64+
}
65+
}
66+
},
67+
"required": ["labels"],
68+
"additionalProperties": false
69+
}
3370
3471
apply-labels:
3572
name: Apply labels from Codex output
@@ -53,12 +90,12 @@ jobs:
5390
exit 0
5491
fi
5592
56-
if ! printf '%s' "$json" | jq -e 'type == "array"' >/dev/null 2>&1; then
57-
echo "Codex output was not a JSON array. Raw output: $json"
93+
if ! printf '%s' "$json" | jq -e 'type == "object" and (.labels | type == "array")' >/dev/null 2>&1; then
94+
echo "Codex output did not include a labels array. Raw output: $json"
5895
exit 0
5996
fi
6097
61-
labels=$(printf '%s' "$json" | jq -r '.[] | tostring')
98+
labels=$(printf '%s' "$json" | jq -r '.labels[] | tostring')
6299
if [ -z "$labels" ]; then
63100
echo "Codex returned an empty array. Nothing to do."
64101
exit 0

AGENTS.md

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,16 @@ In the codex-rs folder where the rust code lives:
88
- Never add or modify any code related to `CODEX_SANDBOX_NETWORK_DISABLED_ENV_VAR` or `CODEX_SANDBOX_ENV_VAR`.
99
- You operate in a sandbox where `CODEX_SANDBOX_NETWORK_DISABLED=1` will be set whenever you use the `shell` tool. Any existing code that uses `CODEX_SANDBOX_NETWORK_DISABLED_ENV_VAR` was authored with this fact in mind. It is often used to early exit out of tests that the author knew you would not be able to run given your sandbox limitations.
1010
- Similarly, when you spawn a process using Seatbelt (`/usr/bin/sandbox-exec`), `CODEX_SANDBOX=seatbelt` will be set on the child process. Integration tests that want to run Seatbelt themselves cannot be run under Seatbelt, so checks for `CODEX_SANDBOX=seatbelt` are also often used to early exit out of tests, as appropriate.
11+
- Always collapse if statements per https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_if
12+
- Always inline format! args when possible per https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args
13+
- Use method references over closures when possible per https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure_for_method_calls
14+
- When writing tests, prefer comparing the equality of entire objects over fields one by one.
1115

1216
Run `just fmt` (in `codex-rs` directory) automatically after making Rust code changes; do not ask for approval to run it. Before finalizing a change to `codex-rs`, run `just fix -p <project>` (in `codex-rs` directory) to fix any linter issues in the code. Prefer scoping with `-p` to avoid slow workspace‑wide Clippy builds; only run `just fix` without `-p` if you changed shared crates. Additionally, run the tests:
17+
1318
1. Run the test for the specific project that was changed. For example, if changes were made in `codex-rs/tui`, run `cargo test -p codex-tui`.
1419
2. Once those pass, if any changes were made in common, core, or protocol, run the complete test suite with `cargo test --all-features`.
15-
When running interactively, ask the user before running `just fix` to finalize. `just fmt` does not require approval. project-specific or individual tests can be run without asking the user, but do ask the user before running the complete test suite.
20+
When running interactively, ask the user before running `just fix` to finalize. `just fmt` does not require approval. project-specific or individual tests can be run without asking the user, but do ask the user before running the complete test suite.
1621

1722
## TUI style conventions
1823

@@ -28,6 +33,7 @@ See `codex-rs/tui/styles.md`.
2833
- Desired: vec![" └ ".into(), "M".red(), " ".dim(), "tui/src/app.rs".dim()]
2934

3035
### TUI Styling (ratatui)
36+
3137
- Prefer Stylize helpers: use "text".dim(), .bold(), .cyan(), .italic(), .underlined() instead of manual Style where possible.
3238
- Prefer simple conversions: use "text".into() for spans and vec![].into() for lines; when inference is ambiguous (e.g., Paragraph::new/Cell::from), use Line::from(spans) or Span::from(text).
3339
- Computed styles: if the Style is computed at runtime, using `Span::styled` is OK (`Span::from(text).set_style(style)` is also acceptable).
@@ -39,6 +45,7 @@ See `codex-rs/tui/styles.md`.
3945
- Compactness: prefer the form that stays on one line after rustfmt; if only one of Line::from(vec![]) or vec![].into() avoids wrapping, choose that. If both wrap, pick the one with fewer wrapped lines.
4046

4147
### Text wrapping
48+
4249
- Always use textwrap::wrap to wrap plain strings.
4350
- If you have a ratatui Line and you want to wrap it, use the helpers in tui/src/wrapping.rs, e.g. word_wrap_lines / word_wrap_line.
4451
- If you need to indent wrapped lines, use the initial_indent / subsequent_indent options from RtOptions if you can, rather than writing custom logic.
@@ -60,8 +67,34 @@ This repo uses snapshot tests (via `insta`), especially in `codex-rs/tui`, to va
6067
- `cargo insta accept -p codex-tui`
6168

6269
If you don’t have the tool:
70+
6371
- `cargo install cargo-insta`
6472

6573
### Test assertions
6674

6775
- Tests should use pretty_assertions::assert_eq for clearer diffs. Import this at the top of the test module if it isn't already.
76+
77+
### Integration tests (core)
78+
79+
- Prefer the utilities in `core_test_support::responses` when writing end-to-end Codex tests.
80+
81+
- All `mount_sse*` helpers return a `ResponseMock`; hold onto it so you can assert against outbound `/responses` POST bodies.
82+
- Use `ResponseMock::single_request()` when a test should only issue one POST, or `ResponseMock::requests()` to inspect every captured `ResponsesRequest`.
83+
- `ResponsesRequest` exposes helpers (`body_json`, `input`, `function_call_output`, `custom_tool_call_output`, `call_output`, `header`, `path`, `query_param`) so assertions can target structured payloads instead of manual JSON digging.
84+
- Build SSE payloads with the provided `ev_*` constructors and the `sse(...)`.
85+
86+
- Typical pattern:
87+
88+
```rust
89+
let mock = responses::mount_sse_once(&server, responses::sse(vec![
90+
responses::ev_response_created("resp-1"),
91+
responses::ev_function_call(call_id, "shell", &serde_json::to_string(&args)?),
92+
responses::ev_completed("resp-1"),
93+
])).await;
94+
95+
codex.submit(Op::UserTurn { ... }).await?;
96+
97+
// Assert request body if needed.
98+
let request = mock.single_request();
99+
// assert using request.function_call_output(call_id) or request.json_body() or other helpers.
100+
```

README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
<p align="center"><code>npm i -g @openai/codex</code><br />or <code>brew install codex</code></p>
32

43
<p align="center"><strong>Codex CLI</strong> is a coding agent from OpenAI that runs locally on your computer.
@@ -62,8 +61,7 @@ You can also use Codex with an API key, but this requires [additional setup](./d
6261

6362
### Model Context Protocol (MCP)
6463

65-
Codex CLI supports [MCP servers](./docs/advanced.md#model-context-protocol-mcp). Enable by adding an `mcp_servers` section to your `~/.codex/config.toml`.
66-
64+
Codex can access MCP servers. To configure them, refer to the [config docs](./docs/config.md#mcp_servers).
6765

6866
### Configuration
6967

@@ -83,9 +81,11 @@ Codex CLI supports a rich set of configuration options, with preferences stored
8381
- [**Authentication**](./docs/authentication.md)
8482
- [Auth methods](./docs/authentication.md#forcing-a-specific-auth-method-advanced)
8583
- [Login on a "Headless" machine](./docs/authentication.md#connecting-on-a-headless-machine)
86-
- [**Non-interactive mode**](./docs/exec.md)
84+
- **Automating Codex**
85+
- [GitHub Action](https://github.com/openai/codex-action)
86+
- [TypeScript SDK](./sdk/typescript/README.md)
87+
- [Non-interactive mode (`codex exec`)](./docs/exec.md)
8788
- [**Advanced**](./docs/advanced.md)
88-
- [Non-interactive / CI mode](./docs/advanced.md#non-interactive--ci-mode)
8989
- [Tracing / verbose logging](./docs/advanced.md#tracing--verbose-logging)
9090
- [Model Context Protocol (MCP)](./docs/advanced.md#model-context-protocol-mcp)
9191
- [**Zero data retention (ZDR)**](./docs/zdr.md)

0 commit comments

Comments
 (0)