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}}"}
```
This PR tidies up primitives under storage/.
**Noop changes:**
* Promote logger implementation to top-level utility outside of agent/
* Use logger within storage primitives
* Cleanup doc strings and comments
**Functional changes:**
* Increase command history size to 10_000
* Remove unnecessary debounce implementation and ensure a session ID is
created only once per agent loop
---------
Signed-off-by: Thibault Sottiaux <tibo@openai.com>
## 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
It appears that use of `isLoggingEnabled()` was erroneously copypasta'd
in many places. This PR updates its docstring to clarify that should
only be used to avoid constructing a potentially expensive docstring.
With this change, the only function that merits/uses this check is
`execCommand()`.
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/openai/codex/pull/420).
* #423
* __->__ #420
* #419
To play it safe, let's keep `CONFIG_DIR` out of the default list of
writable roots.
This also fixes an issue where `execWithSeatbelt()` was modifying
`writableRoots` instead of creating a new array.
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/openai/codex/pull/419).
* #423
* #420
* __->__ #419
## Changes
- Added a `requiresShell` function to detect when a command contains
shell operators
- In the `exec` function, enabled the `shell: true` option if shell
operators are present
## Why This Is Necessary
See the discussion in this issue comment:
https://github.com/openai/codex/issues/320#issuecomment-2816528014
## Code Explanation
The `requiresShell` function parses the command arguments and checks for
any shell‑specific operators. If it finds shell operators, it adds the
`shell: true` option when running the command so that it’s executed
through a shell interpreter.
Adding in an option to turn on flex processing mode to reduce costs when
running the agent.
Bumped the openai typescript version to add the new feature.
---------
Co-authored-by: Thibault Sottiaux <tibo@openai.com>
# Migrate to pnpm for improved monorepo management
## Summary
This PR migrates the Codex repository from npm to pnpm, providing faster
dependency installation, better disk space usage, and improved monorepo
management.
## Changes
- Added `pnpm-workspace.yaml` to define workspace packages
- Added `.npmrc` with optimal pnpm configuration
- Updated root package.json with workspace scripts
- Moved resolutions and overrides to the root package.json
- Updated scripts to use pnpm instead of npm
- Added documentation for the migration
- Updated GitHub Actions workflow for pnpm
## Benefits
- **Faster installations**: pnpm is significantly faster than npm
- **Disk space savings**: pnpm's content-addressable store avoids
duplication
- **Strict dependency management**: prevents phantom dependencies
- **Simplified monorepo management**: better workspace coordination
- **Preparation for Turborepo**: as discussed, this is the first step
before adding Turborepo
## Testing
- Verified that `pnpm install` works correctly
- Verified that `pnpm run build` completes successfully
- Ensured all existing functionality is preserved
## Documentation
Added a detailed migration guide in `PNPM_MIGRATION.md` explaining:
- Why we're migrating to pnpm
- How to use pnpm with this repository
- Common commands and workspace-specific commands
- Monorepo structure and configuration
## Next Steps
As discussed, once this change is stable, we can consider adding
Turborepo as a follow-up enhancement.
closes#207
I'd be lying if I said I was familiar with these particulars more than a
couple hours ago, but after investigating and testing locally, this does
fix the go issue, I prefer it over #272 which is a lot of code and a one
off fix
----
cc @bolinfest do you mind taking a look here?
1. Seatbelt compares the paths it gets from the kernal to its policies
1. Go is attempting to write to the os.tmpdir, which we have
allowlisted.
1. The kernel rewrites /var/… to /private/var/… before the sandbox
check.
1. The policy still said /var/…, so writes were denied.
Fix: canonicalise every writable root we feed into the policy
(realpathSync(...)).
We do not have to touch runtime file paths—the kernel already
canonicalises those.
### before
see that the command exited 1, and that the command was reported to be
prohibited, despite using the allowlisted tmpdir
https://github.com/user-attachments/assets/23911101-0ec0-4a59-a0a1-423be04063f0
### after
command exits 0
https://github.com/user-attachments/assets/6ab2bcd6-68bd-4f89-82bb-2c8612e39ac3
This PR replaces all hard‑coded patch markers in apply‑patch.ts with the
corresponding constants (now) exported from parse‑apply‑patch.ts.
Changes
• Import PATCH_PREFIX, PATCH_SUFFIX, ADD_FILE_PREFIX,
DELETE_FILE_PREFIX, UPDATE_FILE_PREFIX, MOVE_FILE_TO_PREFIX,
END_OF_FILE_PREFIX, and HUNK_ADD_LINE_PREFIX from parse‑apply‑patch.ts.
• Remove duplicate string literals for patch markers in apply‑patch.ts.
• Changed is_done() to trim the input to account for the slight
difference between the variables.
Why
• DRY & Consistency: Ensures a single source of truth for patch
prefixes.
• Maintainability: Simplifies future updates to prefix values by
centralizing them.
• Readability: Makes the code more declarative and self‑documenting.
All tests are passing, lint and format was ran.
This adds support for a new flag, `-w,--writable-root`, that can be
specified multiple times to _amend_ the list of folders that should be
configured as "writable roots" by the sandbox used in `full-auto` mode.
Values that are passed as relative paths will be resolved to absolute
paths.
Incidentally, this required updating a number of the `agent*.test.ts`
files: it feels like some of the setup logic across those tests could be
consolidated.
In my testing, it seems that this might be slightly out of distribution
for the model, as I had to explicitly tell it to run `apply_patch` and
that it had the permissions to write those files (initially, it just
showed me a diff and told me to apply it myself). Nevertheless, I think
this is a good starting point.
# Shell Command Explanation Option
## Description
This PR adds an option to explain shell commands when the user is
prompted to approve them (Fixes#110). When reviewing a shell command,
users can now select "Explain this command" to get a detailed
explanation of what the command does before deciding whether to approve
or reject it.
## Changes
- Added a new "EXPLAIN" option to the `ReviewDecision` enum
- Updated the command review UI to include an "Explain this command (x)"
option
- Implemented the logic to send the command to the LLM for explanation
using the same model as the agent
- Added a display for the explanation in the command review UI
- Updated all relevant components to pass the explanation through the
component tree
## Benefits
- Improves user understanding of shell commands before approving them
- Reduces the risk of approving potentially harmful commands
- Enhances the educational aspect of the tool, helping users learn about
shell commands
- Maintains the same workflow with minimal UI changes
## Testing
- Manually tested the explanation feature with various shell commands
- Verified that the explanation is displayed correctly in the UI
- Confirmed that the user can still approve or reject the command after
viewing the explanation
## Screenshots

## Additional Notes
The explanation is generated using the same model as the agent, ensuring
consistency in the quality and style of explanations.
---------
Signed-off-by: crazywolf132 <crazywolf132@gmail.com>
I think the retry issue is just that the regex is wrong, checkout the
reported error messages folks are seeing:
> message: 'Rate limit reached for o4-mini in organization
org-{redacted} on tokens per min (TPM): Limit 200000, Used 152566,
Requested 60651. Please try again in 3.965s. Visit
https://platform.openai.com/account/rate-limits to learn more.',
The error message uses `try again` not `retry again`
peep this regexpal: https://www.regexpal.com/?fam=155648
## Fix Windows compatibility issues (#248)
This PR addresses the Windows compatibility issues reported in #248:
1. **Fix sandbox initialization failure on Windows**
- Modified `getSandbox()` to return `SandboxType.NONE` on Windows
instead of throwing an error
- Added a warning log message to inform the user that sandbox is not
available on Windows
2. **Fix Unix commands not working on Windows**
- Created a new module
[platform-commands.ts](cci:7://file:///c:/Users/HP%20840%20G6/workflow/codex/codex-cli/src/utils/agent/platform-commands.ts:0:0-0:0)
that automatically adapts Unix commands to their Windows equivalents
- Implemented a mapping table for common commands and their options
- Integrated this functionality into the command execution process
### Testing
Tested on Windows 10 with the following commands:
- `ls -R .` (now automatically translates to `dir /s .`)
- Other Unix commands like `grep`, `cat`, etc.
The CLI no longer crashes when running these commands on Windows.
I have read the CLA Document and I hereby sign the CLA
---------
Signed-off-by: Alpha Diop <alphakhoss@gmail.com>
**What is added?**
Additional error handling functionality is added before the errors are
thrown to be handled by upstream handlers. The changes improves the user
experience and make the error handling smoother (and more informative).
**Why is it added?**
Before this addition, when a user tried to use a model they needed
previous setup for, the program crashed. This is not necessary here, and
informative message is sufficient and enhances user experience. This
adheres to the specifications stated in the code file as well by not
masking potential logical error detection. Following is before and
after:


Moreover, AFAIK no logic was present to handle this or a similar issue
in upstream handlers.
**How is it scoped? Why won't this mask other errors?**
The new brach triggers *only* for `invalid_request_error` events whose
`code` is model related (`model_not_found`)
This also doesn't prevent the detection (for the case of masking logical
errors) of wrong model names, as they would have been caught earlier on.
The code passes test, lint and type checks. I believe relevant
documentation is added, but I would be more than happy to do further
fixes in the code if necessary.
## Description
This PR fixes the issue where the CLI can't continue after interrupting
the assistant with ESC ESC (Fixes#114). The problem was caused by
duplicate code in the `cancel()` method and improper state reset after
cancellation.
## Changes
- Fixed duplicate code in the `cancel()` method of the `AgentLoop` class
- Added proper reset of the `currentStream` property in the `cancel()`
method
- Created a new `AbortController` after aborting the current one to
ensure future tool calls work
- Added a system message to indicate the interruption to the user
- Added a comprehensive test to verify the fix
## Benefits
- Users can now continue using the CLI after interrupting the assistant
- Improved user experience by providing feedback when interruption
occurs
- Better state management in the agent loop
## Testing
- Added a dedicated test that verifies the agent can process new input
after cancellation
- Manually tested the fix by interrupting the assistant and confirming
that new input is processed correctly
---------
Signed-off-by: crazywolf132 <crazywolf132@gmail.com>
# Description
This PR fixes a typo where the prompt prefix for the agent loop was
missing the word "as"
# Changes
* Added missing word "as" within the agent loop prompt prefix
# Benefits
* The prompt is now grammatically correct and clearer
# Testing
* Manually tested the fix
...and try to parse the suggested time from the error message while we
don't yet have this in a structured way
---------
Signed-off-by: Thibault Sottiaux <tibo@openai.com>
Previously, `parseToolCall()` was using `computeAutoApproval()`, which
was a somewhat parallel implementation of `canAutoApprove()` in order to
get `SafeCommandReason` metadata for presenting information to the user.
The only function that was using `SafeCommandReason` was
`useMessageGrouping()`, but it turns out that function was unused, so
this PR removes `computeAutoApproval()` and all code related to it.
More importantly, I believe this fixes
https://github.com/openai/codex/issues/87 because
`computeAutoApproval()` was calling `parse()` from `shell-quote` without
wrapping it in a try-catch. This PR updates `canAutoApprove()` to use a
tighter try-catch block that is specific to `parse()` and returns an
appropriate `SafetyAssessment` in the event of an error, based on the
`ApprovalPolicy`.
Signed-off-by: Michael Bolin <mbolin@openai.com>