Commit Graph

66 Commits

Author SHA1 Message Date
Fouad Matin
cabf83f2ed add: session history viewer (#912)
- A new “/sessions” command is available for browsing previous sessions,
as shown in the updated slash command list

- The CLI now documents and parses a new “--history” flag to browse past
sessions from the command line

- A dedicated `SessionsOverlay` component loads session metadata and
allows toggling between viewing and resuming sessions

- When the sessions overlay is opened during a chat, selecting a session
can either show the saved rollout or resume it
2025-05-16 12:28:22 -07:00
hanson-openai
7edfbae062 fix: diff command for filenames with special characters (#954)
## Summary
- fix quoting issues in `/diff` to correctly handle files with special
characters
- add regression test for `getGitDiff` when filenames contain `$`
- relax timeout in raw-exec-process-group test

Fixes https://github.com/openai/codex/issues/943

## Testing
- `pnpm test`
2025-05-16 09:10:44 -07:00
Fouad Matin
070499f534 add: codex-mini-latest (#951)
💽

---------

Co-authored-by: Trevor Creech <tcreech@openai.com>
2025-05-16 08:04:00 -07:00
Michael Bolin
a786c1d188 feat: auto-approve nl and support piping to sed (#920)
Auto-approved:

```
["nl", "-ba", "README.md"]
["sed", "-n", "1,200p", "filename.txt"]
["bash", "-lc", "sed -n '1,200p' filename.txt"]
["bash", "-lc", "nl -ba README.md | sed -n '1,200p'"]
```

Not auto approved:

```
["sed", "-n", "'1,200p'", "filename.txt"]
["sed", "-n", "1,200p", "file1.txt", "file2.txt"]
```
2025-05-13 13:06:35 -07:00
Michael Bolin
0ac7e8d55b fix: tweak the label for citations for better rendering (#919)
Adds a space so that sequential citations have some more breathing room.

As I had to update the tests for this change, I also introduced a
`toDiffableString()` helper to make the test easier to update as we make
formatting changes to the output.
2025-05-13 12:46:21 -07:00
Michael Bolin
1ff3e14d5a fix: patch in #366 and #367 for marked-terminal (#916)
This PR uses [`pnpm
patch`](https://www.petermekhaeil.com/til/pnpm-patch/) to pull in the
following proposed fixes for `marked-terminal`:

* https://github.com/mikaelbr/marked-terminal/pull/366
* https://github.com/mikaelbr/marked-terminal/pull/367

This adds a substantial test to `codex-cli/tests/markdown.test.tsx` to
verify the new behavior.

Note that one of the tests shows two citations being split across a line
even though the rendered version would fit comfortably on one line.
Changing this likely requires a subtle fix to `marked-terminal` to
account for "rendered length" when determining line breaks.
2025-05-13 12:29:17 -07:00
Michael Bolin
557f608f25 fix: add support for fileOpener in config.json (#911)
This PR introduces the following type:

```typescript
export type FileOpenerScheme = "vscode" | "cursor" | "windsurf";
```

and uses it as the new type for a `fileOpener` option in `config.json`.
If set, this will be used to linkify file annotations in the output
using the URI-based file opener supported in VS Code-based IDEs.

Currently, this does not pass:

Updated `codex-cli/tests/markdown.test.tsx` to verify the new behavior.
Note it required mocking `supports-hyperlinks` and temporarily modifying
`chalk.level` to yield the desired output.
2025-05-13 09:45:46 -07:00
Michael Bolin
05bb5d7d46 fix: always load version from package.json at runtime (#909)
Note the high-level motivation behind this change is to avoid the need
to make temporary changes in the source tree in order to cut a release
build since that runs the risk of leaving things in an inconsistent
state in the event of a failure. The existing code:

```
import pkg from "../../package.json" assert { type: "json" };
```

did not work as intended because, as written, ESBuild would bake the
contents of the local `package.json` into the release build at build
time whereas we want it to read the contents at runtime so we can use
the `package.json` in the tree to build the code and later inject a
modified version into the release package with a timestamped build
version.

Changes:

* move `CLI_VERSION` out of `src/utils/session.ts` and into
`src/version.ts` so `../package.json` is a correct relative path both
from `src/version.ts` in the source tree and also in the final
`dist/cli.js` build output
* change `assert` to `with` in `import pkg` as apparently `with` became
standard in Node 22
* mark `"../package.json"` as external in `build.mjs` so the version is
not baked into the `.js` at build time

After using `pnpm stage-release` to build a release version, if I use
Node 22.0 to run Codex, I see the following printed to stderr at
startup:

```
(node:71308) ExperimentalWarning: Importing JSON modules is an experimental feature and might change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
```

Note it is a warning and does not prevent Codex from running.

In Node 22.12, the warning goes away, but the warning still appears in
Node 22.11. For Node 22, 22.15.0 is the current LTS version, so LTS
users will not see this.

Also, something about moving the definition of `CLI_VERSION` caused a
problem with the mocks in `check-updates.test.ts`. I asked Codex to fix
it, and it came up with the change to the test configs. I don't know
enough about vitest to understand what it did, but the tests seem
healthy again, so I'm going with it.
2025-05-12 21:27:15 -07:00
Anil Karaka
76a979007e fix: increase output limits for truncating collector (#575)
This Pull Request addresses an issue where the output of commands
executed in the raw-exec utility was being truncated due to restrictive
limits on the number of lines and bytes collected. The truncation caused
the message [Output truncated: too many lines or bytes] to appear when
processing large outputs, which could hinder the functionality of the
CLI.

Changes Made

Increased the maximum output limits in the
[createTruncatingCollector](https://github.com/openai/codex/pull/575)
utility:
Bytes: Increased from 10 KB to 100 KB.
Lines: Increased from 256 lines to 1024 lines.
Installed the @types/node package to resolve missing type definitions
for [NodeJS](https://github.com/openai/codex/pull/575) and
[Buffer](https://github.com/openai/codex/pull/575).
Verified and fixed any related errors in the
[createTruncatingCollector](https://github.com/openai/codex/pull/575)
implementation.

Issue Solved: 

This PR ensures that larger outputs can be processed without truncation,
improving the usability of the CLI for commands that generate extensive
output. https://github.com/openai/codex/issues/509

---------

Co-authored-by: Michael Bolin <bolinfest@gmail.com>
2025-05-05 10:26:55 -07:00
Fouad Matin
985fd44ec0 fix: input keyboard shortcut opt+delete (#685) 2025-04-30 17:17:13 -07:00
moppywhip
bc4e6db749 feat: @mention files in codex (#701)
Solves #700

## State of the World Before

Prior to this PR, when users wanted to share file contents with Codex,
they had two options:
- Manually copy and paste file contents into the chat
- Wait for the assistant to use the shell tool to view the file

The second approach required the assistant to:
1. Recognize the need to view a file
2. Execute a shell tool call
3. Wait for the tool call to complete
4. Process the file contents

This consumed extra tokens and reduced user control over which files
were shared with the model.

## State of the World After

With this PR, users can now:
- Reference files directly in their chat input using the `@path` syntax
- Have file contents automatically expanded into XML blocks before being
sent to the LLM

For example, users can type `@src/utils/config.js` in their message, and
the file contents will be included in context. Within the terminal chat
history, these file blocks will be collapsed back to `@path` format in
the UI for clean presentation.

Tag File suggestions:
<img width="857" alt="file-suggestions"
src="https://github.com/user-attachments/assets/397669dc-ad83-492d-b5f0-164fab2ff4ba"
/>

Tagging files in action:
<img width="858" alt="tagging-files"
src="https://github.com/user-attachments/assets/0de9d559-7b7f-4916-aeff-87ae9b16550a"
/>

Demo video of file tagging:
[![Demo video of file
tagging](https://img.youtube.com/vi/vL4LqtBnqt8/0.jpg)](https://www.youtube.com/watch?v=vL4LqtBnqt8)

## Implementation Details

This PR consists of 2 main components:

1. **File Tag Utilities**:
- New `file-tag-utils.ts` utility module that handles both expansion and
collapsing of file tags
- `expandFileTags()` identifies `@path` tokens and replaces them with
XML blocks containing file contents
- `collapseXmlBlocks()` reverses the process, converting XML blocks back
to `@path` format for UI display
- Tokens are only expanded if they point to valid files (directories are
ignored)
   - Expansion happens just before sending input to the model

2. **Terminal Chat Integration**:
- Leveraged the existing file system completion system for tabbing to
support the `@path` syntax
   - Added `updateFsSuggestions` helper to manage filesystem suggestions
- Added `replaceFileSystemSuggestion` to replace input with filesystem
suggestions
- Applied `collapseXmlBlocks` in the chat response rendering so that
tagged files are shown as simple `@path` tags

The PR also includes test coverage for both the UI and the file tag
utilities.

## Next Steps

Some ideas I'd like to implement if this feature gets merged:

- Line selection: `@path[50:80]` to grab specific sections of files
- Method selection: `@path#methodName` to grab just one function/class
- Visual improvements: highlight file tags in the UI to make them more
noticeable
2025-04-30 16:19:55 -07:00
Michael Bolin
033d379eca fix: remove unused _writableRoots arg to exec() function (#762)
I suspect this was done originally so that `execForSandbox()` had a
consistent signature for both the `SandboxType.NONE` and
`SandboxType.MACOS_SEATBELT` cases, but that is not really necessary and
turns out to make the upcoming Landlock support a bit more complicated
to implement, so I had Codex remove it and clean up the call sites.
2025-04-30 14:08:27 -07:00
Kevin Alwell
a6ed7ff103 Fixes issue #726 by adding config to configToSave object (#728)
The saveConfig() function only includes a hardcoded subset of properties
when writing the config file. Any property not explicitly listed (like
disableResponseStorage) will be dropped.
I have added `disableResponseStorage` to the `configToSave` object as
the immediate fix.

[Linking Issue this fixes.](https://github.com/openai/codex/issues/726)
2025-04-29 13:10:16 -04:00
Rashim
892242ef7c feat: add --reasoning CLI flag (#314)
This PR adds a new CLI flag: `--reasoning`, which allows users to
customize the reasoning effort level (`low`, `medium`, or `high`) used
by OpenAI's `o` models.
By introducing the `--reasoning` flag, users gain more flexibility when
working with the models. It enables optimization for either speed or
depth of reasoning, depending on specific use cases.
This PR resolves #107

- **Flag**: `--reasoning`
- **Accepted Values**: `low`, `medium`, `high`
- **Default Behavior**: If not specified, the model uses the default
reasoning level.

## Example Usage

```bash
codex --reasoning=low "Write a simple function to calculate factorial"

---------

Co-authored-by: Fouad Matin <169186268+fouad-openai@users.noreply.github.com>
Co-authored-by: yashrwealthy <yash.rastogi@wealthy.in>
Co-authored-by: Thibault Sottiaux <tibo@openai.com>
2025-04-29 07:30:49 -07:00
Thibault Sottiaux
d09dbba7ec feat: lower default retry wait time and increase number of tries (#720)
In total we now guarantee that we will wait for at least 60s before
giving up.

---------

Signed-off-by: Thibault Sottiaux <tibo@openai.com>
2025-04-28 21:11:30 -07:00
Tomas Cupr
bc500d3009 feat: user config api key (#569)
Adds support for reading OPENAI_API_KEY (and other variables) from a
user‑wide dotenv file (~/.codex.config). Precedence order is now:
  1. explicit environment variable
  2. project‑local .env (loaded earlier)
  3. ~/.codex.config

Also adds a regression test that ensures the multiline editor correctly
handles cases where printable text and the CSI‑u Shift+Enter sequence
arrive in the same input chunk.

House‑kept with Prettier; removed stray temp.json artifact.
2025-04-26 10:13:30 -07:00
moppywhip
9b0ccf9aeb fix: duplicate messages in quiet mode (#680)
Addressing #600 and #664 (partially)

## Bug
Codex was staging duplicate items in output running when the same
response item appeared in both the streaming events. Specifically:

1. Items would be staged once when received as a
`response.output_item.done` event
2. The same items would be staged again when included in the final
`response.completed` payload

This duplication would result in each message being sent several times
in the quiet mode output.

## Changes
- Added a Set (`alreadyStagedItemIds`) to track items that have already
been staged
- Modified the `stageItem` function to check if an item's ID is already
in this set before staging it
- Added a regression test (`agent-dedupe-items.test.ts`) that verifies
items with the same ID are only staged once

## Testing
Like other tests, the included test creates a mock OpenAI stream that
emits the same message twice (once as an incremental event and once in
the final response) and verifies the item is only passed to `onItem`
once.
2025-04-26 09:14:50 -07:00
Thibault Sottiaux
44d68f9dbf fix: remove outdated copy of text input and external editor feature (#670)
Signed-off-by: Thibault Sottiaux <tibo@openai.com>
2025-04-25 16:11:16 -07:00
Tomas Cupr
4760aa1eb9 perf: optimize token streaming with balanced approach (#635)
- Replace setTimeout(10ms) with queueMicrotask for immediate processing
- Add minimal 3ms setTimeout for rendering to maintain readable UX
- Reduces per-token delay while preserving streaming experience
- Add performance test to verify optimization works correctly

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Thibault Sottiaux <tibo@openai.com>
2025-04-25 10:49:38 -07:00
Thibault Sottiaux
866626347b fix: only allow going up in history when not already in history if input is empty (#654)
\+ cleanup below input help to be "ctrl+c to exit | "/" to see commands
| enter to send" now that we have command autocompletion
\+ minor other drive-by code cleanups

---------

Signed-off-by: Thibault Sottiaux <tibo@openai.com>
2025-04-25 09:39:24 -07:00
Luci
a9ecb2efce chore: upgrade prettier to v3 (#644)
## Description

This PR addresses the following improvements:

**Unify Prettier Version**: Currently, the Prettier version used in
`/package.json` and `/codex-cli/package.json` are different. In this PR,
we're updating both to use Prettier v3.

- Prettier v3 introduces improved support for JavaScript and TypeScript.
(e.g. the formatting scenario shown in the image below. This is more
aligned with the TypeScript indentation standard).

<img width="1126" alt="image"
src="https://github.com/user-attachments/assets/6e237eb8-4553-4574-b336-ed9561c55370"
/>

**Add Prettier Auto-Formatting in lint-staged**: We've added a step to
automatically run prettier --write on JavaScript and TypeScript files as
part of the lint-staged process, before the ESLint checks.

- This will help ensure that all committed code is properly formatted
according to the project's Prettier configuration.
2025-04-25 07:21:50 -07:00
Luci
c38c2a59c7 fix(utils): save config (#578)
## Description

When `saveConfig` is called, the project doc is incorrectly saved into
user instructions. This change ensures that only user instructions are
saved to `instructions.md` during saveConfig, preventing data
corruption.

close: #576

---------

Co-authored-by: Thibault Sottiaux <tibo@openai.com>
2025-04-24 17:32:33 -07:00
sooraj
36a5a02d5c feat: display error on selection of invalid model (#594)
Up-to-date of #78 

Fixes #32

addressed requested changes @tibo-openai :) made sense to me


though, previous rationale with passing the state up was assuming there
could be a future need to have a shared state with all available models
being available to the parent
2025-04-24 16:56:00 -07:00
Misha Davidov
9b102965b9 feat: more loosely match context for apply_patch (#610)
More of a proposal than anything but models seem to struggle with
composing valid patches for `apply_patch` for context matching when
there are unicode look-a-likes involved. This would normalize them.

```
top-level          # ASCII
top-level          # U+2011 NON-BREAKING HYPHEN
top–level          # U+2013 EN DASH
top—level          # U+2014 EM DASH
top‒level          # U+2012 FIGURE DASH
```

thanks unicode.
2025-04-24 09:05:19 -07:00
kshern
146a61b073 feat: add support for custom provider configuration in the user config (#537)
### What

- Add support for loading and merging custom provider configurations
from a local `providers.json` file.
- Allow users to override or extend default providers with their own
settings.

### Why

This change enables users to flexibly customize and extend provider
endpoints and API keys without modifying the codebase, making the CLI
more adaptable for various LLM backends and enterprise use cases.

### How

- Introduced `loadProvidersFromFile` and `getMergedProviders` in config
logic.
- Added/updated related tests in [tests/config.test.tsx]


### Checklist

- [x] Lint passes for changed files
- [x] Tests pass for all files
- [x] Documentation/comments updated as needed

---------

Co-authored-by: Thibault Sottiaux <tibo@openai.com>
2025-04-23 01:45:56 -04:00
Daniel Nakov
23f0887df3 bug: non-openai mode - fix for gemini content: null, fix 429 to throw before stream (#563)
Gemini's API is finicky, it 400's without an error when you pass
content: null
Also fixed the rate limiting issues by throwing outside of the iterator.
I think there's a separate issue with the second isRateLimit check in
agent-loop - turnInput is cleared by that time, so it retries without
the last message.
2025-04-22 20:37:48 -04:00
Misha Davidov
20b6ef0de8 feat: create parent directories when creating new files. (#552)
apply_patch doesn't create parent directories when creating a new file
leading to confusion and flailing by the agent. This will create parent
directories automatically when absent.

---------

Co-authored-by: Thibault Sottiaux <tibo@openai.com>
2025-04-22 19:45:17 -04:00
chunterb
750d97e8ad feat: add openai model info configuration (#551)
In reference to [Issue 548](https://github.com/openai/codex/issues/548)
- part 1.
2025-04-22 17:31:25 -04:00
Michael Bolin
7c1f2d7deb when a shell tool call invokes apply_patch, resolve relative paths against workdir, if specified (#556)
Previously, we were ignoring the `workdir` field in an `ExecInput` when
running it through `canAutoApprove()`. For ordinary `exec()` calls, that
was sufficient, but for `apply_patch`, we need the `workdir` to resolve
relative paths in the `apply_patch` argument so that we can check them
in `isPathConstrainedTowritablePaths()`.

Likewise, we also need the workdir when running `execApplyPatch()`
because the paths need to be resolved again.

Ideally, the `ApplyPatchCommand` returned by `canAutoApprove()` would
not be a simple `patch: string`, but the parsed patch with all of the
paths resolved, in which case `execApplyPatch()` could expect absolute
paths and would not need `workdir`.
2025-04-22 14:07:47 -07:00
Michael Bolin
3eba86a553 include fractional portion of chunk that exceeds stdout/stderr limit (#497)
I saw cases where the first chunk of output from `ls -R` could be large
enough to exceed `MAX_OUTPUT_BYTES` or `MAX_OUTPUT_LINES`, in which case
the loop would exit early in `createTruncatingCollector()` such that
nothing was appended to the `chunks` array. As a result, the reported
`stdout` of `ls -R` would be empty.

I asked Codex to add logic to handle this edge case and write a unit
test. I used this as my test:

```
./codex-cli/dist/cli.js -q 'what is the output of `ls -R`'
```

now it appears to include a ton of stuff whereas before this change, I
saw:

```
{"type":"function_call_output","call_id":"call_a2QhVt7HRJYKjb3dIc8w1aBB","output":"{\"output\":\"\\n\\n[Output truncated: too many lines or bytes]\",\"metadata\":{\"exit_code\":0,\"duration_seconds\":0.5}}"}
```
2025-04-21 19:06:03 -07:00
Michael Bolin
12ec57b330 do not auto-approve the find command if it contains options that write files or spawn commands (#482)
Updates `isSafeCommand()` so that an invocation of `find` is not
auto-approved if it contains any of: `-exec`, `-execdir`, `-ok`,
`-okdir`, `-delete`, `-fls`, `-fprint`, `-fprint0`, `-fprintf`.
2025-04-21 10:29:58 -07:00
Michael Bolin
d36d295a1a revert #386 due to unsafe shell command parsing (#478)
Reverts https://github.com/openai/codex/pull/386 because:

* The parsing logic for shell commands was unsafe (`split(/\s+/)`
instead of something like `shell-quote`)
* We have a different plan for supporting auto-approved commands.
2025-04-21 12:52:11 -04:00
nerdielol
797eba4930 fix: /clear now clears terminal screen and resets context left indicator (#425)
## What does this PR do?
* Implements the full `/clear` command in **codex‑cli**:
  * Resets chat history **and** wipes the terminal screen.
  * Shows a single system message: `Context cleared`.
* Adds comprehensive unit tests for the new behaviour.

## Why is it needed?
* Fixes user‑reported bugs:  
  * **#395**  
  * **#405**

## How is it implemented?
* **Code** – Adds `process.stdout.write('\x1b[3J\x1b[H\x1b[2J')` in
`terminal.tsx`. Removed reference to `prev` in `
        setItems((prev) => [
          ...prev,
` in `terminal-chat-new-input.tsx` & `terminal-chat-input.tsx`.

## CI / QA
All commands pass locally:
```bash
pnpm test      # green
pnpm run lint  # green
pnpm run typecheck  # zero TS errors
```

## Results



https://github.com/user-attachments/assets/11dcf05c-e054-495a-8ecb-ac6ef21a9da4

---------

Co-authored-by: Thibault Sottiaux <tibo@openai.com>
2025-04-21 12:39:46 -04:00
Thibault Sottiaux
3c4f1fea9b chore: consolidate model utils and drive-by cleanups (#476)
Signed-off-by: Thibault Sottiaux <tibo@openai.com>
2025-04-21 12:33:57 -04:00
Benny Yen
3e71c87708 refactor(updates): fetch version from registry instead of npm CLI to support multiple managers (#446)
## Background  
Addressing feedback from
https://github.com/openai/codex/pull/333#discussion_r2050893224, this PR
adds support for Bun alongside npm, pnpm while keeping the code simple.

## Summary  
The update‑check flow is refactored to use a direct registry lookup
(`fast-npm-meta` + `semver`) instead of shelling out to `npm outdated`,
and adds a lightweight installer‑detection mechanism that:

1. Checks if the invoked script lives under a known global‑bin directory
(npm, pnpm, or bun)
2. If not, falls back to local detection via `getUserAgent()` (the
`package‑manager‑detector` library)

## What’s Changed  
- **Registry‑based version check**  
- Replace `execFile("npm", ["outdated"])` with `getLatestVersion()` and
`semver.gt()`
- **Multi‑manager support**  
- New `renderUpdateCommand` handles update commands for `npm`, `pnpm`,
and `bun`.
  - Detect global installer first via `detectInstallerByPath()`  
  - Fallback to local detection via `getUserAgent()`  
- **Module cleanup**  
- Extract `detectInstallerByPath` into
`utils/package-manager-detector.ts`
- Remove legacy `checkOutdated`, `getNPMCommandPath`, and child‑process
JSON parsing
- **Flow improvements in `checkForUpdates`**  
  1. Short‑circuit by `UPDATE_CHECK_FREQUENCY`  
  3. Fetch & compare versions  
  4. Persist new timestamp immediately  
  5. Render & display styled box only when an update exists  
- **Maintain simplicity**
- All multi‑manager logic lives in one small helper and a concise lookup
rather than a complex adapter hierarchy
- Core `checkForUpdates` remains a single, easy‑to‑follow async function
- **Dependencies added**  
- `fast-npm-meta`, `semver`, `package-manager-detector`, `@types/semver`

## Considerations
If we decide to drop the interactive update‑message (`npm install -g
@openai/codex`) rendering altogether, we could remove most of the
installer‑detection code and dependencies, which would simplify the
codebase further but result in a less friendly UX.

## Preview

* npm

![refactor-update-check-flow-npm](https://github.com/user-attachments/assets/57320114-3fb6-4985-8780-3388a1d1ec85)

* bun

![refactor-update-check-flow-bun](https://github.com/user-attachments/assets/d93bf0ae-a687-412a-ab92-581b4f967307)

## Simple Flow Chart

```mermaid
flowchart TD
  A(Start) --> B[Read state]
  B --> C{Recent check?}
  C -- Yes --> Z[End]
  C -- No --> D[Fetch latest version]
  D --> E[Save check time]
  E --> F{Version data OK?}
  F -- No --> Z
  F -- Yes --> G{Update available?}
  G -- No --> Z
  G -- Yes --> H{Global install?}
  H -- Yes --> I[Select global manager]
  H -- No --> K{Local install?}
  K -- No --> Z
  K -- Yes --> L[Select local manager]
  I & L --> M[Render update message]
  M --> N[Format with boxen]
  N --> O[Print update]
  O --> Z
```
2025-04-21 00:00:20 -07:00
Aiden Cline
ee7ce5b601 feat: tab completions for file paths (#279)
Made a PR as was requested in the #113
2025-04-20 22:34:27 -07:00
Jordan Docherty
f6b12aa994 refactor(history-overlay): split into modular functions & add tests (fixes #402) (#403)
## What
This PR targets #402 and refactors the `history-overlay.tsx`component to
reduce cognitive complexity by splitting the `buildLists` function into
smaller, focused helper functions. It also adds comprehensive test
coverage to ensure the functionality remains intact.

## Why
The original `buildLists` function had high cognitive complexity due to
multiple nested conditionals, complex string manipulation, and mixed
responsibilities. This refactor makes the code more maintainable and
easier to understand while preserving all existing functionality.

## How
- Split `buildLists` into focused helper functions
- Added comprehensive test coverage for all functionality
- Maintained existing behavior and keyboard interactions
- Improved code organization and readability

## Testing
All tests pass, including:
- Command mode functionality
- File mode functionality
- Keyboard interactions
- Error handling
2025-04-20 22:27:06 -07:00
Brayden Moon
8dd1125681 fix: command pipe execution by improving shell detection (#437)
## Description
This PR fixes Issue #421 where commands with pipes (e.g., `grep -R ...
-n | head -n 20`) were failing to execute properly after PR #391 was
merged.

## Changes
- Modified the `requiresShell` function to only enable shell mode when
the command is a single string containing shell operators
- Added logic to handle the case where shell operators are passed as
separate arguments
- Added comprehensive tests to verify the fix

## Root Cause
The issue was that the `requiresShell` function was detecting shell
operators like `|` even when they were passed as separate arguments,
which caused the command to be executed with `shell: true`
unnecessarily. This was causing syntax errors when running commands with
pipes.

## Testing
- Added unit tests to verify the fix
- Manually tested with real commands using pipes
- Ensured all existing tests pass

Fixes #421
2025-04-20 21:11:19 -07:00
Daniel Nakov
eafbc75612 feat: support multiple providers via Responses-Completion transformation (#247)
https://github.com/user-attachments/assets/9ecb51be-fa65-4e99-8512-abb898dda569

Implemented it as a transformation between Responses API and Completion
API so that it supports existing providers that implement the Completion
API and minimizes the changes needed to the codex repo.

---------

Co-authored-by: Thibault Sottiaux <tibo@openai.com>
Co-authored-by: Fouad Matin <169186268+fouad-openai@users.noreply.github.com>
Co-authored-by: Fouad Matin <fouad@openai.com>
2025-04-20 20:59:34 -07:00
Jordan Docherty
693bd59ecc fix(raw-exec-process-group): improve test reliability (#434)
This PR improves the reliability of `raw-exec-process-group.test`,
addressing [#415](https://github.com/openai/codex/issues/415)

Before: The test would fail sporadically in CI because it checked for
process termination immediately after abort, without accounting for the
time it takes for processes to fully terminate.

Now: We've added a robust `ensureProcessGone` helper that:
- Polls the process status with a 500ms timeout
- Retries every 50ms if the process is still alive
- Provides clear error messages if termination takes too long

We now wait for the child process to fully exit after sending abort
signals, instead of assuming instant death, fixing flakiness caused by
asynchronous process termination.

Changes:
- Added `ensureProcessGone` helper function with retry logic
- Improved error handling and timeout management

See [this bash
demo](https://gist.github.com/jdocherty/a84dbca2fbf7b47e5f95c87a07034ae8)
for a minimal reproduction of why process death is asynchronous and why
the test needs to retry after aborting.
2025-04-20 12:21:02 -07:00
Brayden Moon
6d6ca454cd feat: allow multi-line input (#438)
## Description
This PR implements multi-line input support for Codex when it asks for
user feedback (Issue #344). Users can now use Shift+Enter to add new
lines in their responses, making it easier to provide formatted code
snippets, lists, or other structured content.

## Changes
- Replace the single-line TextInput component with the
MultilineTextEditor component in terminal-chat-input.tsx
- Add support for Shift+Enter to create new lines
- Update key handling logic to properly handle history navigation in a
multi-line context
- Add reference to the editor to access cursor position information
- Update help text to inform users about the Shift+Enter functionality
- Add tests for the new functionality

## Testing
- Added new test file (terminal-chat-input-multiline.test.tsx) to test
the multi-line input functionality
- All existing tests continue to pass
- Manually tested the feature to ensure it works as expected

## Fixes
Closes #344

## Screenshots
N/A

## Additional Notes
This implementation maintains backward compatibility while adding the
requested multi-line input functionality. The UI remains clean and
intuitive, with a simple hint about using Shift+Enter for new lines.

---------

Co-authored-by: Thibault Sottiaux <tibo@openai.com>
2025-04-20 08:51:38 -07:00
Fouad Matin
b3b195351e feat: /diff command to view git diff (#426)
Adds `/diff` command to view git diff
2025-04-19 16:23:27 -07:00
Michael Bolin
419f085cc4 re-enable Prettier check for codex-cli in CI (#417)
This check was lost in https://github.com/openai/codex/pull/287. Both
the root folder and `codex-cli/` have their own `pnpm format` commands
that check the formatting of different things.

Also ran `pnpm format:fix` to fix the formatting violations that got in
while this was disabled in CI.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/openai/codex/pull/417).
* #420
* #419
* #416
* __->__ #417
2025-04-19 11:22:45 -07:00
Thomas
081786eaa6 feat: add /command autocomplete (#317)
Add interactive slash‑command autocomplete & navigation in chat input

    Description
This PR enhances the chat input component by adding first‑class support
for slash commands (/help, /clear, /compact, etc.)
    with:

* **Live filtering:** As soon as the user types leading `/`, a list of
matching commands is shown below the prompt.
* **Arrow‑key navigation:** Up/Down arrows cycle through suggestions.
* **Enter to autocomplete:** Pressing Enter on a partial command will
fill it (without submitting) so you can add
    arguments or simply press Enter again to execute.
* **Type‑safe registry:** A new `slash‑commands.ts` file declares all
supported commands in one place, along with
    TypeScript types to prevent drift.
* **Validation:** Only registered commands will ever autocomplete or be
suggested; unknown single‑word slash inputs still
    show an “Invalid command” system message.
        * **Automated tests:**
            * Unit tests for the command registry and prefix filtering

            * Existing tests continue passing with no regressions

    Motivation
Slash commands provide a quick, discoverable way to control the agent
(clearing history, compacting context, opening overlays,
etc.). Before, users had to memorize the exact command or rely on the
generic /help list—autocomplete makes them far more
    accessible and reduces typos.

    Changes

* `src/utils/slash‑commands.ts` – defines `SlashCommand` and exports a
flat list of supported commands + descriptions
        * `terminal‑chat‑input.tsx`
            * Import and type the command registry

* Render filtered suggestions under the prompt when input starts with
`/`

* Hook into `useInput` to handle Up/Down and Enter for selection & fill

* Flag to swallow the first Enter (autocomplete) and only submit on the
next
* Updated tests in `tests/slash‑commands.test.ts` to cover registry
contents and filtering logic
        * Removed old JS version and fixed stray `@ts‑expect‑error`

    How to test locally

        1. Type `/` in the prompt—you should see matching commands.
2. Use arrows to move the highlight, press Enter to fill, then Enter
again to execute.
3. Run the full test suite (`npm test`) to verify no regressions.

    Notes

* Future work could include fuzzy matching, paging long lists, or more
visual styling.
* This change is purely additive and does not affect non‑slash inputs or
existing slash handlers.

---------

Co-authored-by: Fouad Matin <169186268+fouad-openai@users.noreply.github.com>
Co-authored-by: Thibault Sottiaux <tibo@openai.com>
2025-04-19 07:25:46 -07:00
John Gardner
965420cfc5 feat: read approvalMode from config file (#298)
This PR implements support for reading the approvalMode setting from the
user's config file (`~/.codex/config.json` or `~/.codex/config.yaml`),
allowing users to set a persistent default approval mode without needing
to specify command-line flags for each session.

Changes:
- Added approvalMode to the AppConfig type in config.ts
- Updated loadConfig() to read the approval mode from the config file
- Modified saveConfig() to persist the approval mode setting
- Updated CLI logic to respect the config-defined approval mode (while
maintaining CLI flag priority)
- Added comprehensive tests for approval mode config functionality
- Updated README to document the new config option in both YAML and JSON
formats
- additions to `.gitignore` for other CLI tools

Motivation:
As a user who regularly works with CLI-tools, I found it odd to have to
alias this with the command flags I wanted when `approvalMode` simply
wasn't being parsed even though it was an optional prop in `config.ts`.
This change allows me (and other users) to set the preference once in
the config file, streamlining daily usage while maintaining the ability
to override via command-line flags when needed.

Testing:
I've added a new test case loads and saves approvalMode correctly that
verifies:
- Reading the approvalMode from the config file works correctly
- Saving the approvalMode to the config file works as expected
- The value persists through load/save operations

All tests related to the implementation are passing.
2025-04-19 07:25:25 -07:00
Robbie Hammond
8e2760e83d Add fallback text for missing images (#397)
# What?
* When a prompt references an image path that doesn’t exist, replace it
with
  ```[missing image: <path>]``` instead of throwing an ENOENT.
* Adds a few unit tests for input-utils as there weren't any beforehand.

# Why?
Right now if you enter an invalid image path (e.g. it doesn't exist),
codex immediately crashes with a ENOENT error like so:
```
Error: ENOENT: no such file or directory, open 'test.png'
   ...
 {
  errno: -2,
  code: 'ENOENT',
  syscall: 'open',
  path: 'test.png'
}
```
This aborts the entire session. A soft fallback lets the rest of the
input continue.

# How?
Wraps the image encoding + inputItem content pushing in a try-catch. 

This is a minimal patch to avoid completely crashing — future work could
surface a warning to the user when this happens, or something to that
effect.

---------

Co-authored-by: Thibault Sottiaux <tibo@openai.com>
2025-04-18 22:55:24 -07:00
autotaker
ca7ab76569 feat: add user-defined safe commands configuration and approval logic #380 (#386)
This pull request adds a feature that allows users to configure
auto-approved commands via a `safeCommands` array in the configuration
file.

## Related Issue
#380 

## Changes
- Added loading and validation of the `safeCommands` array in
`src/utils/config.ts`
- Implemented auto-approval logic for commands matching `safeCommands`
prefixes in `src/approvals.ts`
- Added test cases in `src/tests/approvals.test.ts` to verify
`safeCommands` behavior
- Updated documentation with examples and explanations of the
configuration
2025-04-18 22:35:32 -07:00
Fouad Matin
aa32e22d4b fix: /bug report command, thinking indicator (#381)
- Fix `/bug` report command
- Fix thinking indicator
2025-04-18 18:13:34 -07:00
Benny Yen
d61da89ed3 feat: notify when a newer version is available (#333)
**Summary**  
This change introduces a new startup check that notifies users if a
newer `@openai/codex` version is available. To avoid spamming, it writes
a small state file recording the last check time and will only re‑check
once every 24 hours.

**What’s Changed**  
- **New file** `src/utils/check-updates.ts`  
  - Runs `npm outdated --global @openai/codex`  
  - Reads/writes `codex-state.json` under `CONFIG_DIR`  
  - Limits checks to once per day (`UPDATE_CHECK_FREQUENCY = 24h`)  
- Uses `boxen` for a styled alert and `which` to locate the npm binary
- **Hooked into** `src/cli.tsx` entrypoint:
  ```ts
  import { checkForUpdates } from "./utils/check-updates";
  // …
  // after loading config
  await checkForUpdates().catch();
  ```
- **Dependencies**  
  - Added `boxen@^8.0.1`, `which@^5.0.0`, `@types/which@^3.0.4`  
- **Tests**  
  - Vitest suite under `tests/check-updates.test.ts`  
  - Snapshot in `__snapshots__/check-updates.test.ts.snap`  

**Motivation**  
Addresses issue #244. Users running a stale global install will now see
a friendly reminder—at most once per day—to upgrade and enjoy the latest
features.

**Test Plan**  
- `getNPMCommandPath()` resolves npm correctly  
- `checkOutdated()` parses `npm outdated` JSON  
- State file prevents repeat alerts within 24h  
- Boxen snapshot matches expected output  
- No console output when state indicates a recent check  

**Related Issue**  
try resolves #244


**Preview**
Prompt a pnpm‑style alert when outdated  

![outdated‑alert](https://github.com/user-attachments/assets/294dad45-d858-45d1-bf34-55e672ab883a)

Let me know if you’d tweak any of the messaging, throttle frequency,
placement in the startup flow, or anything else.

---------

Co-authored-by: Thibault Sottiaux <tibo@openai.com>
2025-04-18 17:00:45 -07:00
Amar Sood
82f5abbeea Fix handling of Shift+Enter in e.g. Ghostty (#338)
Fix: Shift + Enter no longer prints “[27;2;13~” in the single‑line
input. Validated as working and necessary in Ghostty on Linux.

## Key points
- src/components/vendor/ink-text-input.tsx
- Added early handler that recognises the two modifyOtherKeys
escape‑sequences
    - [13;<mod>u  (mode 2 / CSI‑u)
    - [27;<mod>;13~ (mode 1 / legacy CSI‑~)
- If Ctrl is held (hasCtrl flag) → call onSubmit() (same as plain
Enter).
- Otherwise → insert a real newline at the caret (same as Option+Enter).
  - Prevents the raw sequence from being inserted into the buffer.

- src/components/chat/multiline-editor.tsx
- Replaced non‑breaking spaces with normal spaces to satisfy eslint
no‑irregular‑whitespace rule (no behaviour change).

All unit tests (114) and ESLint now pass:
npm test ✔️
npm run lint ✔️
2025-04-18 09:19:06 -07:00