Commit Graph

88 Commits

  • Apply argument comment lint across codex-rs (#14652)
    ## Why
    
    Once the repo-local lint exists, `codex-rs` needs to follow the
    checked-in convention and CI needs to keep it from drifting. This commit
    applies the fallback `/*param*/` style consistently across existing
    positional literal call sites without changing those APIs.
    
    The longer-term preference is still to avoid APIs that require comments
    by choosing clearer parameter types and call shapes. This PR is
    intentionally the mechanical follow-through for the places where the
    existing signatures stay in place.
    
    After rebasing onto newer `main`, the rollout also had to cover newly
    introduced `tui_app_server` call sites. That made it clear the first cut
    of the CI job was too expensive for the common path: it was spending
    almost as much time installing `cargo-dylint` and re-testing the lint
    crate as a representative test job spends running product tests. The CI
    update keeps the full workspace enforcement but trims that extra
    overhead from ordinary `codex-rs` PRs.
    
    ## What changed
    
    - keep a dedicated `argument_comment_lint` job in `rust-ci`
    - mechanically annotate remaining opaque positional literals across
    `codex-rs` with exact `/*param*/` comments, including the rebased
    `tui_app_server` call sites that now fall under the lint
    - keep the checked-in style aligned with the lint policy by using
    `/*param*/` and leaving string and char literals uncommented
    - cache `cargo-dylint`, `dylint-link`, and the relevant Cargo
    registry/git metadata in the lint job
    - split changed-path detection so the lint crate's own `cargo test` step
    runs only when `tools/argument-comment-lint/*` or `rust-ci.yml` changes
    - continue to run the repo wrapper over the `codex-rs` workspace, so
    product-code enforcement is unchanged
    
    Most of the code changes in this commit are intentionally mechanical
    comment rewrites or insertions driven by the lint itself.
    
    ## Verification
    
    - `./tools/argument-comment-lint/run.sh --workspace`
    - `cargo test -p codex-tui-app-server -p codex-tui`
    - parsed `.github/workflows/rust-ci.yml` locally with PyYAML
    
    ---
    
    * -> #14652
    * #14651
  • feat: improve skills cache key to take into account config layering (#14806)
    Fix https://github.com/openai/codex/issues/14161
    
    This fixes sub-agent [[skills.config]] overrides being ignored when
    parent and child share the same cwd. The root cause was that turn skill
    loading rebuilt from cwd-only state and reused a cwd-scoped cache, so
    role-local skill enable/disable overrides did not reliably affect the
    spawned agent's effective skill set.
    
    This change switches turn construction to use the effective per-turn
    config and adds a config-aware skills cache keyed by skill roots plus
    final disabled paths.
  • move plugin/skill instructions into dev msg and reorder (#14609)
    Move the general `Apps`, `Skills` and `Plugins` instructions blocks out
    of `user_instructions` and into the developer message, with new `Apps ->
    Skills -> Plugins` order for better clarity.
    
    Also wrap those sections in stable XML-style instruction tags (like
    other sections) and update prompt-layout tests/snapshots. This makes the
    tests less brittle in snapshot output (we can parse the sections), and
    it consolidates the capability instructions in one place.
    
    #### Tests
    Updated snapshots, added tests.
    
    `<AGENTS_MD>` disappearing in snapshots is expected: before this change,
    the wrapped user-instructions message was kept alive by `Skills`
    content. Now that `Skills` and `Plugins` are in the developer message,
    that wrapper only appears when there is real
    project-doc/user-instructions content.
    
    ---------
    
    Co-authored-by: Charley Cunningham <ccunningham@openai.com>
  • feat: support skill-scoped managed network domain overrides in skill config (#14522)
    ## Summary
    
    This lets skill loading split `permissions.network` into two distinct
    pieces:
    
    - `permissions.network.enabled` still feeds the skill
    `PermissionProfile` and remains the coarse gate for whether the skill
    can use network access at all.
    - `permissions.network.allowed_domains` and
    `permissions.network.denied_domains` are lifted into a new
    `SkillManagedNetworkOverride` so managed-network sessions can start
    per-skill scoped proxies with the right domain overrides.
    
    The change also updates `SkillMetadata` construction sites and adds
    loader tests covering YAML parsing plus normalization of the network
    gate vs. domain override fields.
    
    ## Follow-up
    A PR that uses the network_override to spin up a skill-specific proxy if
    network_override is not none.
  • fix: move inline codex-rs/core unit tests into sibling files (#14444)
    ## Why
    PR #13783 moved the `codex.rs` unit tests into `codex_tests.rs`. This
    applies the same extraction pattern across the rest of `codex-rs/core`
    so the production modules stay focused on runtime code instead of large
    inline test blocks.
    
    Keeping the tests in sibling files also makes follow-up edits easier to
    review because product changes no longer have to share a file with
    hundreds or thousands of lines of test scaffolding.
    
    ## What changed
    - replaced each inline `mod tests { ... }` in `codex-rs/core/src/**`
    with a path-based module declaration
    - moved each extracted unit test module into a sibling `*_tests.rs`
    file, using `mod_tests.rs` for `mod.rs` modules
    - preserved the existing `cfg(...)` guards and module-local structure so
    the refactor remains structural rather than behavioral
    
    ## Testing
    - `cargo test -p codex-core --lib` (`1653 passed; 0 failed; 5 ignored`)
    - `just fix -p codex-core`
    - `cargo fmt --check`
    - `cargo shear`
  • feat: Add additional macOS Sandbox Permissions for Launch Services, Contacts, Reminders (#14155)
    Add additional macOS Sandbox Permissions levers for the following:
    
    - Launch Services
    - Contacts
    - Reminders
  • feat: support disabling bundled system skills (#13792)
    Support disable bundled system skills with a config:
    
    [skills.bundled]
    enabled = false
  • chore: use @plugin instead of $plugin for plaintext mentions (#13921)
    change plaintext plugin-mentions from `$plugin` to `@plugin`, ensure TUI
    can correctly decode these from history.
    
    tested locally, added/updated tests.
  • chore(otel): rename OtelManager to SessionTelemetry (#13808)
    ## Summary
    This is a purely mechanical refactor of `OtelManager` ->
    `SessionTelemetry` to better convey what the struct is doing. No
    behavior change.
    
    ## Why
    
    `OtelManager` ended up sounding much broader than what this type
    actually does. It doesn't manage OTEL globally; it's the session-scoped
    telemetry surface for emitting log/trace events and recording metrics
    with consistent session metadata (`app_version`, `model`, `slug`,
    `originator`, etc.).
    
    `SessionTelemetry` is a more accurate name, and updating the call sites
    makes that boundary a lot easier to follow.
    
    ## Validation
    
    - `just fmt`
    - `cargo test -p codex-otel`
    - `cargo test -p codex-core`
  • feat: structured plugin parsing (#13711)
    #### What
    
    Add structured `@plugin` parsing and TUI support for plugin mentions.
    
    - Core: switch from plain-text `@display_name` parsing to structured
    `plugin://...` mentions via `UserInput::Mention` and
    `[$...](plugin://...)` links in text, same pattern as apps/skills.
    - TUI: add plugin mention popup, autocomplete, and chips when typing
    `$`. Load plugin capability summaries and feed them into the composer;
    plugin mentions appear alongside skills and apps.
    - Generalize mention parsing to a sigil parameter, still defaults to `$`
    
    <img width="797" height="119" alt="image"
    src="https://github.com/user-attachments/assets/f0fe2658-d908-4927-9139-73f850805ceb"
    />
    
    Builds on #13510. Currently clients have to build their own `id` via
    `plugin@marketplace` and filter plugins to show by `enabled`, but we
    will add `id` and `available` as fields returned from `plugin/list`
    soon.
    
    ####Tests
    
    Added tests, verified locally.
  • core/protocol: add structured macOS additional permissions and merge them into sandbox execution (#13499)
    ## Summary
    - Introduce strongly-typed macOS additional permissions across
    protocol/core/app-server boundaries.
    - Merge additional permissions into effective sandbox execution,
    including macOS seatbelt profile extensions.
    - Expand docs, schema/tool definitions, UI rendering, and tests for
    `network`, `file_system`, and `macos` additional permissions.
  • feat: merge skill permission profiles into the turn sandbox for zsh-fork execs (#13496)
    ## Summary
    
    This changes the Unix shell escalation path for skill-matched
    executables to apply a skill's `PermissionProfile` as additive
    permissions on top of the existing turn/request sandbox policy.
    
    Previously, skill-matched executables compiled the skill permission
    profile into a standalone sandbox policy and executed against that
    replacement policy. Now they go through the same
    `additional_permissions` merge path used elsewhere in shell sandbox
    preparation.
    
    ## What Changed
    
    - Changed `skill_escalation_execution()` to return
    `EscalationPermissions::PermissionProfile(...)` for non-empty skill
    permission profiles.
    - Kept empty or missing skill permission profiles on the `TurnDefault`
    path.
    - Added tests covering the new additive skill-permission behavior.
    - Added inline comments in `prepare_escalated_exec()` clarifying the
    difference between additive permission merging and fully specified
    replacement sandbox policies.
    - Removed the now-unused skill permission compiler module after
    switching this path away from standalone compiled skill sandbox
    policies.
    
    ## Testing
    
    - Ran `just fmt` in `codex-rs`
    - Ran `cargo test -p codex-core`
    
    `cargo test -p codex-core` still hits an unrelated existing failure:
    `shell_snapshot::tests::snapshot_shell_does_not_inherit_stdin`
    
    ## Follow-up
    
    This change intentionally does not merge skill-specific macOS seatbelt
    profile extensions through the `additional_permissions` path yet.
    Filesystem and network permissions now follow the additive merge path,
    but seatbelt extension permissions still need separate handling in a
    follow-up PR.
  • chore: Nest skill and protocol network permissions under network.enabled (#13427)
    ## Summary
    
    Changes the permission profile shape from a bare network boolean to a
    nested object.
    
    Before:
    
    ```yaml
    permissions:
      network: true
    ```
    
    After:
    
    ```yaml
    permissions:
      network:
        enabled: true
    ```
    
    This also updates the shared Rust and app-server protocol types so
    `PermissionProfile.network` is no longer `Option<bool>`, but
    `Option<NetworkPermissions>` with `enabled: Option<bool>`.
    
    ## What Changed
    
    - Updated `PermissionProfile` in `codex-rs/protocol/src/models.rs`:
    - `pub network: Option<bool>` -> `pub network:
    Option<NetworkPermissions>`
    - Added `NetworkPermissions` with:
      - `pub enabled: Option<bool>`
    - Changed emptiness semantics so `network` is only considered empty when
    `enabled` is `None`
    - Updated skill metadata parsing to accept `permissions.network.enabled`
    - Updated core permission consumers to read
    `network.enabled.unwrap_or(false)` where a concrete boolean is needed
    - Updated app-server v2 protocol types and regenerated schema/TypeScript
    outputs
    - Updated docs to mention `additionalPermissions.network.enabled`
  • Feat: Preserve network access on read-only sandbox policies (#13409)
    ## Summary
    
    `PermissionProfile.network` could not be preserved when additional or
    compiled permissions resolved to
    `SandboxPolicy::ReadOnly`, because `ReadOnly` had no network_access
    field. This change makes read-only + network
    enabled representable directly and threads that through the protocol,
    app-server v2 mirror, and permission-
      merging logic.
    
    ## What changed
    
    - Added `network_access: bool` to `SandboxPolicy::ReadOnly` in the core
    protocol and app-server v2 protocol.
    - Kept backward compatibility by defaulting the new field to false, so
    legacy read-only payloads still
        deserialize unchanged.
    - Updated `has_full_network_access()` and sandbox summaries to respect
    read-only network access.
      - Preserved PermissionProfile.network when:
          - compiling skill permission profiles into sandbox policies
          - normalizing additional permissions
          - merging additional permissions into existing sandbox policies
    - Updated the approval overlay to show network in the rendered
    permission rule when requested.
      - Regenerated app-server schema fixtures for the new v2 wire shape.
  • chore: remove SkillMetadata.permissions and derive skill sandboxing from permission_profile (#13061)
    ## Summary
    
    This change removes the compiled permissions field from skill metadata
    and keeps permission_profile as the single source of truth.
    
    Skill loading no longer compiles skill permissions eagerly. Instead, the
    zsh-fork skill escalation path compiles `skill.permission_profile` when
    it needs to determine the sandbox to apply for a skill script.
    
      ## Behavior change
    
      For skills that declare:
    ```
      permissions: {}
    ```
    we now treat that the same as having no skill permissions override,
    instead of creating and using a default readonly sandbox. This change
    makes the behavior more intuitive:
    
      - only non-empty skill permission profiles affect sandboxing
    - omitting permissions and writing permissions: {} now mean the same
    thing
    - skill metadata keeps a single permissions representation instead of
    storing derived state too
    
    Overall, this makes skill sandbox behavior easier to understand and more
    predictable.
  • feat: load from plugins (#12864)
    Support loading plugins.
    
    Plugins can now be enabled via [plugins.<name>] in config.toml. They are
    loaded as first-class entities through PluginsManager, and their default
    skills/ and .mcp.json contributions are integrated into the existing
    skills and MCP flows.
  • fix: use AbsolutePathBuf for permission profile file roots (#12970)
    ## Why
    `PermissionProfile` should describe filesystem roots as absolute paths
    at the type level. Using `PathBuf` in `FileSystemPermissions` made the
    shared type too permissive and blurred together three different
    deserialization cases:
    
    - skill metadata in `agents/openai.yaml`, where relative paths should
    resolve against the skill directory
    - app-server API payloads, where callers should have to send absolute
    paths
    - local tool-call payloads for commands like `shell_command` and
    `exec_command`, where `additional_permissions.file_system` may
    legitimately be relative to the command `workdir`
    
    This change tightens the shared model without regressing the existing
    local command flow.
    
    ## What Changed
    - changed `protocol::models::FileSystemPermissions` and the app-server
    `AdditionalFileSystemPermissions` mirror to use `AbsolutePathBuf`
    - wrapped skill metadata deserialization in `AbsolutePathBufGuard`, so
    relative permission roots in `agents/openai.yaml` resolve against the
    containing skill directory
    - kept app-server/API deserialization strict, so relative
    `additionalPermissions.fileSystem.*` paths are rejected at the boundary
    - restored cwd/workdir-relative deserialization for local tool-call
    payloads by parsing `shell`, `shell_command`, and `exec_command`
    arguments under an `AbsolutePathBufGuard` rooted at the resolved command
    working directory
    - simplified runtime additional-permission normalization so it only
    canonicalizes and deduplicates absolute roots instead of trying to
    recover relative ones later
    - updated the app-server schema fixtures, `app-server/README.md`, and
    the affected transport/TUI tests to match the final behavior
  • feat: include sandbox config with escalation request (#12839)
    ## Why
    
    Before this change, an escalation approval could say that a command
    should be rerun, but it could not carry the sandbox configuration that
    should still apply when the escalated command is actually spawned.
    
    That left an unsafe gap in the `zsh-fork` skill path: skill scripts
    under `scripts/` that did not declare permissions could be escalated
    without a sandbox, and scripts that did declare permissions could lose
    their bounded sandbox on rerun or cached session approval.
    
    This PR extends the escalation protocol so approvals can optionally
    carry sandbox configuration all the way through execution. That lets the
    shell runtime preserve the intended sandbox instead of silently widening
    access.
    
    We likely want a single permissions type for this codepath eventually,
    probably centered on `Permissions`. For now, the protocol needs to
    represent both the existing `PermissionProfile` form and the fuller
    `Permissions` form, so this introduces a temporary disjoint union,
    `EscalationPermissions`, to carry either one.
    
    Further, this means that today, a skill either:
    
    - does not declare any permissions, in which case it is run using the
    default sandbox for the turn
    - specifies permissions, in which case the skill is run using that exact
    sandbox, which might be more restrictive than the default sandbox for
    the turn
    
    We will likely change the skill's permissions to be additive to the
    existing permissions for the turn.
    
    ## What Changed
    
    - Added `EscalationPermissions` to `codex-protocol` so escalation
    requests can carry either a `PermissionProfile` or a full `Permissions`
    payload.
    - Added an explicit `EscalationExecution` mode to the shell escalation
    protocol so reruns distinguish between `Unsandboxed`, `TurnDefault`, and
    `Permissions(...)` instead of overloading `None`.
    - Updated `zsh-fork` shell reruns to resolve `TurnDefault` at execution
    time, which keeps ordinary `UseDefault` commands on the turn sandbox and
    preserves turn-level macOS seatbelt profile extensions.
    - Updated the `zsh-fork` skill path so a skill with no declared
    permissions inherits the conversation's effective sandbox instead of
    escalating unsandboxed.
    - Updated the `zsh-fork` skill path so a skill with declared permissions
    reruns with exactly those permissions, including when a cached session
    approval is reused.
    
    ## Testing
    
    - Added unit coverage in
    `core/src/tools/runtimes/shell/unix_escalation.rs` for the explicit
    `UseDefault` / `RequireEscalated` / `WithAdditionalPermissions`
    execution mapping.
    - Added unit coverage in
    `core/src/tools/runtimes/shell/unix_escalation.rs` for macOS seatbelt
    extension preservation in both the `TurnDefault` and
    explicit-permissions rerun paths.
    - Added integration coverage in `core/tests/suite/skill_approval.rs` for
    permissionless skills inheriting the turn sandbox and explicit skill
    permissions remaining bounded across cached approval reuse.
  • Skip system skills for extra roots (#12744)
    When extra roots is set do not load system skills.
  • Revert "Ensure shell command skills trigger approval (#12697)" (#12721)
    This reverts commit daf0f03ac8.
    
    # External (non-OpenAI) Pull Request Requirements
    
    Before opening this Pull Request, please read the dedicated
    "Contributing" markdown file or your PR may be closed:
    https://github.com/openai/codex/blob/main/docs/contributing.md
    
    If your PR conforms to our contribution guidelines, replace this text
    with a detailed and high quality description of your changes.
    
    Include a link to a bug report or enhancement request.
  • Surface skill permission profiles in zsh-fork exec approvals (#12753)
    ## Summary
    
    - Preserve each skill’s raw permissions block as a permission_profile on
    SkillMetadata during skill loading.
    - Keep compiling that same metadata into the existing runtime
    Permissions object, so current enforcement
        behavior stays intact.
    - When zsh-fork intercepts execution of a script that belongs to a
    skill, include the skill’s
        permission_profile in the exec approval request.
    - This lets approval UIs show the extra filesystem access the skill
    declared when prompting for approval.
  • chore: migrate additional permissions to PermissionProfile (#12731)
    This PR replaces the old `additional_permissions.fs_read/fs_write` shape
    with a shared `PermissionProfile`
    model and wires it through the command approval, sandboxing, protocol,
    and TUI layers. The schema is adopted from the
    `SkillManifestPermissions`, which is also refactored to use this unified
    struct. This helps us easily expose permission profiles in app
    server/core as a follow-up.
  • fix: clarify the value of SkillMetadata.path (#12729)
    Rename `SkillMetadata.path` to `SkillMetadata.path_to_skills_md` for
    clarity.
    
    Would ideally change the type to `AbsolutePathBuf`, but that can be done
    later.
  • Ensure shell command skills trigger approval (#12697)
    Summary
    - detect skill-invoking shell commands based on the original command
    string, request approvals when needed, and cache positive decisions per
    session
    - keep implicit skill invocation emitted after approval and keep skill
    approval decline messaging centralized to the shell handler
    - expand and adjust skill approval tests to cover shell-based skill
    scripts while matching the new detection expectations
    
    Testing
    - Not run (not requested)
  • Simplify skill tracking (#12652)
    Remove a few layers of structs and store SkillMetadata.
    
    ---------
    
    Co-authored-by: alexsong-oai <alexsong@openai.com>
  • Support implicit skill invocation analytics events (#12049)
    - use `skills_for_cwd` lookup to scope allowed skills and build
    invocation context for downstream processing
    - add detection in `stream_events_utils` to classify tool calls as
    implicit skill invocations per the proposal (script runners, extensions,
    `scripts` dirs, and SKILL.md reads)
    - deduplicate invocations per turn and emit analytics/OTEL events on the
    same background queue as explicit invokes
  • refactor(core): move embedded system skills into codex-skills crate (#12435)
    ## Why
    
    `codex-core` was carrying the embedded system-skill sample assets (and a
    `build.rs` that walks those files to register rerun triggers). Those
    assets change infrequently, but any change under `codex-core` still ties
    them to `codex-core`'s build/cache lifecycle.
    
    This change moves the embedded system-skills packaging into a dedicated
    `codex-skills` crate so it can be cached independently. That reduces
    unnecessary invalidation/rebuild pressure on `codex-core` when the
    skills bundle is the only thing that changes.
    
    ## What Changed
    
    - Added a new `codex-rs/skills` crate (`codex-skills`) with:
      - `Cargo.toml`
      - `BUILD.bazel`
      - `build.rs` to track skill asset file changes for Cargo rebuilds
    - `src/lib.rs` containing the embedded system-skills install/cache logic
    previously in `codex-core`
    - Moved the embedded sample skill assets from
    `codex-rs/core/src/skills/assets/samples` to
    `codex-rs/skills/src/assets/samples`.
    - Updated `codex-rs/core/Cargo.toml` to depend on `codex-skills` and
    removed `codex-core`'s direct `include_dir` dependency.
    - Removed `codex-core`'s `build.rs`.
    - Replaced `codex-rs/core/src/skills/system.rs` implementation with a
    thin re-export wrapper to keep existing `codex-core` call sites
    unchanged.
    - Updated workspace manifests/lockfile (`codex-rs/Cargo.toml`,
    `codex-rs/Cargo.lock`) for the new crate.
  • chore: move config diagnostics out of codex-core (#12427)
    ## Why
    
    Compiling `codex-rs/core` is a bottleneck for local iteration, so this
    change continues the ongoing extraction of config-related functionality
    out of `codex-core` and into `codex-config`.
    
    The goal is not just to move code, but to reduce `codex-core` ownership
    and indirection so more code depends on `codex-config` directly.
    
    ## What Changed
    
    - Moved config diagnostics logic from
    `core/src/config_loader/diagnostics.rs` into
    `config/src/diagnostics.rs`.
    - Updated `codex-core` to use `codex-config` diagnostics types/functions
    directly where possible.
    - Removed the `core/src/config_loader/diagnostics.rs` shim module
    entirely; the remaining `ConfigToml`-specific calls are in
    `core/src/config_loader/mod.rs`.
    - Moved `CONFIG_TOML_FILE` into `codex-config` and updated existing
    references to use `codex_config::CONFIG_TOML_FILE` directly.
    - Added a direct `codex-config` dependency to `codex-cli` for its
    `CONFIG_TOML_FILE` use.
  • skill-creator: lazy-load PyYAML in frontmatter parsing (#12080)
    init-skill should work even without PyYAML
  • Add remote skill scope/product_surface/enabled params and cleanup (#11801)
    skills/remote/list: params=hazelnutScope, productSurface, enabled;
    returns=data: { id, name, description }[]
    skills/remote/export: params=hazelnutId; returns={ id, path }
  • feat(skills): add permission profiles from openai.yaml metadata (#11658)
    ## Summary
    
    This PR adds support for skill-level permissions in .codex/openai.yaml
    and wires that through the skill loading pipeline.
    
      ## What’s included
    
    1. Added a new permissions section for skills (network, filesystem, and
    macOS-related access).
    2. Implemented permission parsing/normalization and translation into
    runtime permission profiles.
    3. Threaded the new permission profile through SkillMetadata and loader
    flow.
    
      ## Follow-up
    
    A follow-up PR will connect these permission profiles to actual sandbox
    enforcement and add user approval prompts for executing binaries/scripts
    from skill directories.
    
    
     ## Example 
    `openai.yaml` snippet:
    ```
      permissions:
        network: true
        fs_read:
          - "./data"
          - "./data"
        fs_write:
          - "./output"
        macos_preferences: "readwrite"
        macos_automation:
          - "com.apple.Notes"
        macos_accessibility: true
        macos_calendar: true
    ```
    
    compiled skill permission profile metadata (macOS): 
    ```
    SkillPermissionProfile {
          sandbox_policy: SandboxPolicy::WorkspaceWrite {
              writable_roots: vec![
                  AbsolutePathBuf::try_from("/ABS/PATH/TO/SKILL/output").unwrap(),
              ],
              read_only_access: ReadOnlyAccess::Restricted {
                  include_platform_defaults: true,
                  readable_roots: vec![
                      AbsolutePathBuf::try_from("/ABS/PATH/TO/SKILL/data").unwrap(),
                  ],
              },
              network_access: true,
              exclude_tmpdir_env_var: false,
              exclude_slash_tmp: false,
          },
          // Truncated for readability; actual generated profile is longer.
          macos_seatbelt_permission_file: r#"
      (allow user-preference-write)
      (allow appleevent-send
          (appleevent-destination "com.apple.Notes"))
      (allow mach-lookup (global-name "com.apple.axserver"))
      (allow mach-lookup (global-name "com.apple.CalendarAgent"))
      ...
      "#.to_string(),
    ```
  • Extract tool building (#11337)
    Make it clear what input go into building tools and allow for easy reuse
    for pre-warm request
  • feat: add SkillPolicy to skill metadata and support allow_implicit_invocation (#11244)
    Tested by setting the policy in agents/openai.yaml to true, false, and
    leaving it unset (default).
    ```
    policy:
      allow_implicit_invocation: false
    ```
    <img width="847" height="289" alt="Screenshot 2026-02-09 at 3 42 41 PM"
    src="https://github.com/user-attachments/assets/d3476264-3355-47cf-894a-4ffba53e3481"
    />
  • skill-creator: Remove invalid reference. (#10960)
    Remove references to two files that do not exist.
  • Load requirements on windows (#10770)
    We support requirements on Unix, loading from
    `/etc/codex/requirements.toml`. On MacOS, we also support MDM.
    
    Now, on Windows, we'll load requirements from
    `%ProgramData%\OpenAI\Codex\requirements.toml`
  • TUI/Core: preserve duplicate skill/app mention selection across submit + resume (#10855)
    ## What changed
    
    - In `codex-rs/core/src/skills/injection.rs`, we now honor explicit
    `UserInput::Skill { name, path }` first, then fall back to text mentions
    only when safe.
    - In `codex-rs/tui/src/bottom_pane/chat_composer.rs`, mention selection
    is now token-bound (selected mention is tied to the specific inserted
    `$token`), and we snapshot bindings at submit time so selection is not
    lost.
    - In `codex-rs/tui/src/chatwidget.rs` and
    `codex-rs/tui/src/bottom_pane/mod.rs`, submit/queue paths now consume
    the submit-time mention snapshot (instead of rereading cleared composer
    state).
    - In `codex-rs/tui/src/mention_codec.rs` and
    `codex-rs/tui/src/bottom_pane/chat_composer_history.rs`, history now
    round-trips mention targets so resume restores the same selected
    duplicate.
    - In `codex-rs/tui/src/bottom_pane/skill_popup.rs` and
    `codex-rs/tui/src/bottom_pane/chat_composer.rs`, duplicate labels are
    normalized to `[Repo]` / `[App]`, app rows no longer show `Connected -`,
    and description space is a bit wider.
    
    <img width="550" height="163" alt="Screenshot 2026-02-05 at 9 56 56 PM"
    src="https://github.com/user-attachments/assets/346a7eb2-a342-4a49-aec8-68dfec0c7d89"
    />
    <img width="550" height="163" alt="Screenshot 2026-02-05 at 9 57 09 PM"
    src="https://github.com/user-attachments/assets/5e04d9af-cccf-4932-98b3-c37183e445ed"
    />
    
    
    ## Before vs now
    
    - Before: selecting a duplicate could still submit the default/repo
    match, and resume could lose which duplicate was originally selected.
    - Now: the exact selected target (skill path or app id) is preserved
    through submit, queue/restore, and resume.
    
    ## Manual test
    
    1. Build and run this branch locally:
       - `cd /Users/daniels/code/codex/codex-rs`
       - `cargo build -p codex-cli --bin codex`
       - `./target/debug/codex`
    2. Open mention picker with `$` and pick a duplicate entry (not the
    first one).
    3. Confirm duplicate UI:
       - repo duplicate rows show `[Repo]`
       - app duplicate rows show `[App]`
       - app description does **not** start with `Connected -`
    4. Submit the prompt, then press Up to restore draft and submit again.  
       Expected: it keeps the same selected duplicate target.
    5. Use `/resume` to reopen the session and send again.  
    Expected: restored mention still resolves to the same duplicate target.
  • Added support for live updates to skills (#10478)
    Add a centralized FileWatcher in codex-core (using notify) that watches
    skill roots from the config layer stack (recursive)
    
    Send `SkillsChanged` events when relevant file system changes are
    detected
    
    On `SkillsChanged`:
    * Invalidate the skills cache immediately in ThreadManager
    * Emit EventMsg::SkillsUpdateAvailable to active sessions
    ~~* Broadcast a new app-server notification:
    SkillsListUpdatedNotification~~
    
    This change does not inject new items into the event stream. That means
    the agent will not know about new skills, so it won't be able to
    implicitly invoke new skills. It also won't know about changes to
    existing skills, so if it has already read the contents of a modified
    skill, it will not honor the new behavior.
    
    This change also does not detect modifications to AGENTS.md.
    
    I plan to address these limitations in a follow-on PR modeled after
    #9985. Injection of new skills and AGENTS was deemed to risky, hence the
    need to split the feature into two stages. The changes in this PR were
    designed to easily accommodate the second stage once we have some other
    foundational changes in place.
    
    Testing: In addition to automated tests, I did manual testing to confirm
    that newly-created skills, deleted skills, and renamed skills are
    reflected in the TUI skill picker menu. Also confirmed that
    modifications to behaviors for explicitly-invoked skills are honored.
    
    ---------
    
    Co-authored-by: Xin Lin <xl@openai.com>
  • feat: add APIs to list and download public remote skills (#10448)
    Add API to list / download from remote public skills
  • feat: Read personal skills from .agents/skills (#10437)
    - Issue: https://github.com/agentskills/agentskills/issues/15
    - Follow-up to https://github.com/openai/codex/pull/10317 (for team/repo
    skills)
    - This change now also loads personal/user skills from
    `$HOME/.agents/skills` (or `~/.agents/skills`) in addition to loading
    from `.agents/skills` inside of git repos.
    - The location of `.system` skills remains unchanged.
    - Keeping backwards compatibility with `~/.codex/skills` for now until
    we fully deprecate.
    
    With skills in both personal folders:
    <img width="831" height="421" alt="image"
    src="https://github.com/user-attachments/assets/ad8ac918-bfe6-4a2d-8a8e-d608c9d3d701"
    />
    
    We load from both places:
    <img width="607" height="236" alt="image"
    src="https://github.com/user-attachments/assets/480f4db0-ae64-4dc1-bdf5-c5de98c16f5c"
    />
  • fix: System skills marker includes nested folders recursively (#10350)
    Updated system skills bundled with Codex were not correctly replacing
    the user's skills in their .system folder.
    
    - Fix `.codex-system-skills.marker` not updating by hashing embedded
    system skills recursively (nested dirs + file contents), so updates
    trigger a reinstall.
    - Added a build Cargo hook to rerun if there are changes in
    `src/skills/assets/samples/*`, ensuring embedded skill updates rebuild
    correctly under caching.
    - Add a small unit test to ensure nested entries are included in the
    fingerprint.
  • Make skills prompt explicit about relative-path lookup (#10282)
    Fix cases where the model tries to locate skill scripts from the cwd and
    fails.
  • feat: Support loading skills from .agents/skills (#10317)
    This PR adds support for loading
    [skills](https://developers.openai.com/codex/skills) from
    `.agents/skills/`.
    - Issue: https://github.com/agentskills/agentskills/issues/15
    - Motivation: When skills live on the filesystem, sharing them across
    agents is awkward and often ends up requiring symlinks/duplication. A
    single location under `.agents/` makes it easier to share skills.
    - Loading from `.codex/skills/` will remain but will be deprecated soon.
    The change only applies to the [REPO
    scope](https://developers.openai.com/codex/skills#where-to-save-skills).
    - Documentation will be updated before this change is live.
    
    Testing with skills in two locations of this repo:
    <img width="960" height="152" alt="image"
    src="https://github.com/user-attachments/assets/28975ff9-7363-46dd-ad40-f4c7bfdb8234"
    />
    
    When starting Codex with CWD in `$repo_root` (should only pick up at
    root):
    <img width="513" height="143" alt="image"
    src="https://github.com/user-attachments/assets/389e1ea7-020c-481e-bda0-ce58562db59f"
    />
    
    When starting Codex with CWD in `$repo_root/codex-rs` (should pick up at
    cwd and crawl up to root):
    <img width="552" height="177" alt="image"
    src="https://github.com/user-attachments/assets/a5beb8de-11b4-45ed-8660-80707c77006a"
    />