Commit Graph

106 Commits

  • 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
    ```
  • fix: auto-open model-selector when model is not found (#448)
    Change the check from checking if the model has been deprecated to check
    if the model_not_found
    
    
    https://github.com/user-attachments/assets/ad0f7daf-5eb4-4e4b-89e5-04240044c64f
  • Remove README.md and bin from package.json#files field (#461)
    This PR removes always included files and folders from the
    [`package.json#files`
    field](https://docs.npmjs.com/cli/v11/configuring-npm/package-json#files):
    
    > Certain files are always included, regardless of settings:
    > - package.json
    > - README
    > - LICENSE / LICENCE
    > - The file in the "main" field
    > - The file(s) in the "bin" field
    
    Validated by running `pnpm i && cd codex-cli && pnpm build && pnpm
    release:readme && pnpm pack` and confirming both the `README.md` file
    and `bin` directory are still included in the tarball:
    
    <img width="227" alt="image"
    src="https://github.com/user-attachments/assets/ecd90a07-73c7-4940-8c83-cb1d51dfcf96"
    />
  • feat: tab completions for file paths (#279)
    Made a PR as was requested in the #113
  • 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
  • fix: allow proper exit from new Switch approval mode dialog (#453)
    As described in
    https://github.com/openai/codex/issues/392#issuecomment-2817090022
    introduced by #400
    
    The testing I'd done worked correctly because I was using the (s)
    shortcut, but selecting the same option using arrow‑key → Enter on
    “Switch approval mode” was preventing the user from subsequently exiting
    the Switch approval mode dialog, requiring a ^C to quit codex entirely.
    With this fix, both entry methods work correctly in my testing.
    
    Per codex:
    
    Issue
    
    - When you navigated down (↓) to “Switch approval mode (s)” in the Shell
    Command review dialog and pressed Enter, the ApprovalModeOverlay would
    open—but because the underlying `TerminalChatCommandReview` component
    stayed mounted (albeit disabled), its own Ink input handlers immediately
    re‑captured the same key events and re‑opened the overlay as soon as you
    hit Esc or Enter again. In practice this made it impossible to exit the
    submenu.
    
    Root cause
    
    - We only disabled the SelectInput via `isDisabled`, but never fully
    unmounted the review UI when an overlay was shown, so its `useInput` and
    `<Select>` hooks were still active and “stealing” keys.
    
    Fix
    
    - In `terminal-chat.tsx` we now only render `<TerminalChatInput>` (and
    by extension `TerminalChatCommandReview`) when `overlayMode === "none"`.
    That unmounts all of its key handlers whenever any overlay (history,
    model, approval, help, diff) is open, so no input leaks through.
    
    Files changed
    
    - **src/components/chat/terminal-chat.tsx**: Wrapped the entire
    `<TerminalChatInput>` block in `overlayMode === "none" && agent`
    
    With that in place, arrow‑key → Enter on “Switch approval mode”
    correctly opens the overlay, and then you can use Enter/Esc inside the
    overlay without getting stuck or immediately re‑opening it.
  • 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
  • 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>
  • 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.
  • fix: remove unnecessary isLoggingEnabled() checks (#420)
    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
  • Make it so CONFIG_DIR is not in the list of writable roots by default (#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
  • 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>
  • use spawn instead of exec to avoid injection vulnerability (#416)
    https://github.com/openai/codex/pull/160 introduced a call to `exec()`
    that takes a format string as an argument, but it is not clear that the
    expansions within the format string are escaped safely. As written, it
    is possible a carefully crafted command (e.g., if `cwd` were `"; && rm
    -rf` or something...) could run arbitrary code.
    
    Moving to `spawn()` makes this a bit better, as now at least `spawn()`
    itself won't run an arbitrary process, though I suppose `osascript`
    itself still could if the value passed to `-e` were abused. I'm not
    clear on the escaping rules for AppleScript to ensure that `safePreview`
    and `cwd` are injected safely.
    
    ---
    [//]: # (BEGIN SAPLING FOOTER)
    Stack created with [Sapling](https://sapling-scm.com). Best reviewed
    with [ReviewStack](https://reviewstack.dev/openai/codex/pull/416).
    * #423
    * #420
    * #419
    * __->__ #416
  • feat: /diff command to view git diff (#426)
    Adds `/diff` command to view git diff
  • 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
  • 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>
  • 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.
  • gracefully handle SSE parse errors and suppress raw parser code (#367)
    Closes #187
    Closes #358
    
    ---------
    
    Co-authored-by: Thibault Sottiaux <tibo@openai.com>
  • feat: allow switching approval modes when prompted to approve an edit/command (#400)
    Implements https://github.com/openai/codex/issues/392
    
    When the user is in suggest or auto-edit mode and gets an approval
    request, they now have an option in the `Shell Command` dialog to:
    `Switch approval mode (v)`
    
    That option brings up the standard `Switch approval mode` dialog,
    allowing the user to switch into the desired mode, then drops them back
    to the `Shell Command` dialog's `Allow command?` prompt, allowing them
    to approve the current command and let the agent continue doing the rest
    of what it was doing without interruption.
    ```
    ╭────────────────────────────────────────────────────────
    │Shell Command
    │                          
    │$ apply_patch << 'PATCH'    
    │*** Begin Patch                      
    │*** Update File: foo.txt          
    │@@ -1 +1 @@                         
    │-foo                                          
    │+bar                                         
    │*** End Patch                         
    │PATCH                                    
    │                                                
    │                                                
    │Allow command?                   
    │                                                
    │    Yes (y)                                
    │    Explain this command (x) 
    │    Edit or give feedback (e)  
    │    Switch approval mode (v)
    │    No, and keep going (n)    
    │    No, and stop for now (esc)
    ╰────────────────────────────────────────────────────────╭────────────────────────────────────────────────────────
    │ Switch approval mode      
    │ Current mode: suggest  
    │                                          
    │                                          
    │                                          
    │ ❯ suggest                        
    │   auto-edit                       
    │   full-auto                        
    │ type to search · enter to confirm · esc to cancel 
    ╰────────────────────────────────────────────────────────
    ```
  • fix: configure husky and lint-staged for pnpm monorepo (#384)
    # Improve Developer Experience with Husky and lint-staged for pnpm
    Monorepo
    
    ## Summary
    This PR enhances the developer experience by configuring Husky and
    lint-staged to work properly with our pnpm monorepo structure. It
    centralizes Git hooks at the root level and ensures consistent code
    quality across the project.
    
    ## Changes
    - Centralized Husky and lint-staged configuration at the monorepo root
    - Added pre-commit hook that runs lint-staged to enforce code quality
    - Configured lint-staged to:
      - Format JSON, MD, and YAML files with Prettier
      - Lint and typecheck TypeScript files before commits
    - Fixed release script in codex-cli package.json (changed "pmpm" to "npm
    publish")
    - Removed duplicate Husky and lint-staged configurations from codex-cli
    package.json
    
    ## Benefits
    - **Consistent Code Quality**: Ensures all committed code meets project
    standards
    - **Automated Formatting**: Automatically formats code during commits
    - **Early Error Detection**: Catches type errors and lint issues before
    they're committed
    - **Centralized Configuration**: Easier to maintain and update in one
    place
    - **Improved Collaboration**: Ensures consistent code style across the
    team
    
    ## Future Improvements
    We could further enhance this setup by
    **Commit Message Validation**: Add commitlint to enforce conventional
    commit messages
    
    ---------
    
    Co-authored-by: Thibault Sottiaux <tibo@openai.com>
  • 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>
  • fix: enable shell option for child process execution (#391)
    ## 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.
  • 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
  • feat: add flex mode option for cost savings (#372)
    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>
  • fix: /bug report command, thinking indicator (#381)
    - Fix `/bug` report command
    - Fix thinking indicator
  • 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>
  • Fix #371 Allow multiple containers on same machine (#373)
    - Docker container name based on work  directory
    - Centralize container removal logic
    - Improve quoting for command arguments
    - Ensure workdir is always set and normalized
    
    Resolves: #371 
    
    Signed-off-by: BadPirate <badpirate@gmail.com>
    
    Signed-off-by: BadPirate <badpirate@gmail.com>
  • chore: migrate to pnpm for improved monorepo management (#287)
    # 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.
  • feat: add /bug report command (#312)
    Add `/bug` command for chat session
  • fix: Improper spawn of sh on Windows Powershell (#318)
    # Fix CLI launcher on Windows by replacing `sh`-based entrypoint with
    cross-platform Node script
    
    ## What's changed
    
    * This PR attempts to replace the sh-based entry point with a node
    script that works on all platforms including Windows Powershell and CMD
    
    ## Why 
    
    * Previously, when installing Codex globally via `npm i -g
    @openai/codex`, Windows resulted in a broken CLI issue due to the `ps1`
    launcher trying to execute `sh.exe`.
    
    * If users don't have Unix-style shell, running the command will fail as
    seen below since `sh.exe` can't be found
    
    * Output:
     ``` 
    & : The term 'sh.exe' is not recognized as the name of a cmdlet,
    function, script file, or operable program. Check the
    spelling of the name, or if a path was included, verify that the path is
    correct and try again.
    At C:\Users\{user}\AppData\Roaming\npm\codex.ps1:24 char:7
    +     & "sh$exe"  "$basedir/node_modules/@openai/codex/bin/codex" $args
    +       ~~~~~~~~
    + CategoryInfo : ObjectNotFound: (sh.exe:String) [],
    CommandNotFoundException
        + FullyQualifiedErrorId : CommandNotFoundException
    ```
    
    
    
    ## How
    * By using a Node based entry point that resolves the path to the compiled ESM bundle and dynamically loads it using native ESM
    
    * Removed dependency on platform-specific launchers allowing a single entrypoint to work everywhere Node.js runs.
    
    
    ## Result
    
    Codex CLI now supports cross-platform and launches correctly via:
    * macOS / Linux
    * Windows PowerShell
    * GitBash
    * CMD
    * WSL
    
    Directly addresses #316 
    
    ![image](https://github.com/user-attachments/assets/85faaca4-24bc-47c9-8160-4e30df6da4c3)
    
    
    ![image](https://github.com/user-attachments/assets/a13f7adc-52c1-4c0e-af02-e35a35dc45d4)
  • 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 ✔️
  • fix: update context left display logic in TerminalChatInput component (#307)
    Added persistent context length with colour coding.
  • bump(version): 0.1.2504172351 (#310)
    Release `@openai/codex@0.1.2504172351`
  • add: changelog (#308)
    - Release `@openai/codex@0.1.2504172304`
    - Add changelog
  • fix: canonicalize the writeable paths used in seatbelt policy (#275)
    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
  • fix: raw-exec-process-group.test improve reliability and error handling (#280)
    description:
    
    Makes the test verifying process group termination more
    robust against timing variations. It increases a delay slightly 
    and correctly handles the scenario where the test process might 
    be aborted before it can output the grandchild PID
    
    current:
    
    ![image](https://github.com/user-attachments/assets/6dd7a9b4-b578-433d-a3db-c0c8c71950d9)
    
    fixed:
    
    ![image](https://github.com/user-attachments/assets/c9a1ffdf-3001-4563-b486-fbefb1830a8b)
  • fix: handle invalid commands (#304)
    ### What is added?
    
    I extend the if-else blocks with an additional condition where the
    commands validity is checked. This only applies for entered inputs that
    start with '/' and are a single word. This isn't necessarily restrictive
    from the previous behavior of the program. When an invalid command is
    detected, an error message is printed with a direction to retrieve
    command list.
    
    ### Why is it added?
    
    There are three main reasons for this change 
    
    **1. Model Hallucination**: When invalid commands are passed as prompts
    to models, models hallucinate behavior. Since there was a fall through
    in invalid commands, the models took these as prompts and hallucinated
    that they completed the prompted task. An example of this behavior is
    below. In the case of this example, the model though they had access to
    `/clearhistory` tool where in reality that isn't the case.
    A before and after effect of this tool is below:
    
    ![img](https://github.com/user-attachments/assets/3166f151-d5d0-46d6-9ba7-c7e64ff35e4a)
    
    ![img2](https://github.com/user-attachments/assets/69934306-af68-423d-a5f0-9d922be01d27)
    
    
    **2. Saves Users Credits and Time**: Since false commands and invalid
    commands aren't processed by the model, the user doesn't spend money on
    stuff that could have been mitigated much easily. The time argument is
    especially applicable for reasoning models.
    
    **3. Saves GPU Time**: GPU time is valuable, and it is not necessary to
    spend it on unnecessary/invalid requests.
    
    ### Code Explanation
    
    If no command is matched, we check if the inputValue start with `/`
    which indicated the input is a command (I will address the case where it
    is isn't below). If the inputValue start with `/` we enter the else if
    statement. I used a nested if statement for readability and further
    extendability in the future.
    
    There are alternative ways to check besides regex, but regex is a short
    code and looks clean.
    
    **Check Conditions**: The reason why I only check single word(command)
    case is that to allow prompts where the user might decide to start with
    `/` and aren't commands. The nested if statements also come in handy
    where in the future other contributors might want to extend this
    checking.
    
    The code passes type, lint and test checks.
  • feat: add /compact (#289)
    Added the ability to compact. Not sure if I should switch the model over
    to gpt-4.1 for longer context or if keeping the current model is fine.
    Also I'm not sure if setting the compacted to system is best practice,
    would love feedback 😄
    
    Mentioned in this issue: https://github.com/openai/codex/issues/230
  • bump(version): 0.1.2504161551 (#254)
    Bump version
    
    ---------
    
    Signed-off-by: Fouad Matin <fouad@openai.com>
    Co-authored-by: Jon Church <me@jonchurch.com>
  • fix: standardize filename to kebab-case 🐍➡️🥙 (#302)
    Probably not the most exciting PR you’ll get today, but I noticed that
    every file in the repo follows kebab-case… except one brave little
    underscore in `cli_singlepass.tsx`.
    
    So I made the world a little more consistent. Just a filename rename —
    no logic changes, no semicolons harmed
    
    Didn’t touch any code, I promise. Just bringing order to the filesystem
    — one hyphen at a time.