Feature request: add a local /open slash command for URLs and workspace files in Codex CLI

Open 💬 2 comments Opened Jun 25, 2026 by thising

What variant of Codex are you using?

CLI

What feature would you like to see?

I would like Codex CLI to provide a built-in local /open slash command for explicitly opening URLs and local workspace paths with the system opener.

Suggested MVP behavior:

  • /open . opens the current session working directory.
  • /open <relative-or-absolute-path> opens a local file or directory.
  • /open <http-or-https-url> opens the URL in the system browser.
  • /open <file-url> resolves the local file:// URL and opens the target path.

This would be useful when Codex creates or references local artifacts during a session, such as generated HTML reports, images, screenshots, logs, Markdown files, or output directories. Today the user often has to leave the TUI or ask Codex to run a shell command such as open, xdg-open, or start, which adds friction and can unnecessarily involve the agent/tool execution flow.

The command should be a local user action, not a model turn. It should not submit a message to the model or mutate the conversation context.

Proposed safety and scope boundaries for the initial version:

  • Only run when explicitly invoked by the user through the slash command.
  • Do not execute shell strings; use argv or platform-native opener APIs to avoid shell injection.
  • Allow only local filesystem paths and http:// / https:// URLs by default.
  • Reject unsupported URL schemes with a clear error.
  • Treat remote workspace paths as out of scope for the MVP unless there is already a safe local mapping.
  • Do not try to infer “the current generated file” automatically in the MVP. A future follow-up could add /open recent or an artifact picker if Codex has a reliable artifact model for that.

Additional information

I searched for existing issues and PRs and did not find an existing Codex CLI /open slash command proposal or implementation.

Related but distinct:

  • #28209 asks for opening an image externally from Codex App. This proposal is for a CLI slash command, but the underlying workflow is similar: users want a direct way to open local artifacts created or referenced by Codex.

View original on GitHub ↗

2 Comments

Nicolas0315 · 2 months ago

Implemented a candidate fix on my fork:

https://github.com/openai/codex/compare/main...Nicolas0315:codex:codex/tui-open-command?expand=1

Summary:

  • Adds /open <path-or-url> as a local TUI slash command, not a model turn.
  • Supports existing local relative/absolute paths, http:// / https:// URLs, and local file:// URLs.
  • Rejects unsupported URL schemes, malformed URL-looking inputs, missing paths, and file:// URLs with query/fragment suffixes.
  • Uses argv-based platform openers (explorer.exe, open, xdg-open) and does not execute shell strings.

Verification:

  • Local rtx4090: just fmt, git diff --check, cargo check --manifest-path codex-rs/Cargo.toml -p codex-tui, just test -p codex-tui open_command, just test -p codex-tui certain_commands_are_available_during_task all passed.
  • SSH rtx4090: git diff --check, cargo check --manifest-path codex-rs/Cargo.toml -p codex-tui, and both focused tests passed.
  • SSH cyberagent-mac-m5max: fresh clone at c38b2e9ba69cb57d197c6e5ba78b5e52ae0870f9, patch apply, and git diff --check passed; Rust test/build run was stopped after a long timeout while linking/building codex-tui test artifacts.
  • SSH rtx5060ti: fresh clone, patch apply, and git diff --check passed; cargo check is blocked by the host linker misconfiguration where /usr/bin/link.exe is GNU coreutils link instead of MSVC link.exe.
  • SSH nicolas2025: fresh clone, patch apply, and git diff --check passed; Rust execution is blocked because cargo/rustc are zero-byte stubs in /c/Users/ogosh/work/.cargo/bin.
  • SSH nicolas-macbook-pro: fresh clone, patch apply, and git diff --check passed; Rust execution is blocked because cargo/rustc are not installed.
alarcritty · 2 months ago

I poked around the TUI a bit and I think this would slot in pretty naturally. Slash
commands get dispatched in chatwidget/slash_dispatch.rs, and a bunch of them already
run fully locally without ever hitting the model or touching the conversation, which is
exactly what you're asking for. /diff is basically the template: it grabs the session
cwd, does its thing, and drops the result into the history as a cell. /open could work
the same way, and since the cwd is already sitting on the widget, /open . and relative
paths would resolve without any extra plumbing.

The URL side is almost free. webbrowser is already a dependency and there's an existing
OpenUrlInBrowser event that opens the link and reports back success/failure as a local
message, so http/https (and a file:// you'd want to hand to the browser) don't need
any new opening code.

The one thing that's genuinely missing is opening a local file or directory with its
default app. webbrowser won't do it (it only launches browsers), and the per-OS opener
the desktop deep-link uses isn't reusable here either, since it's hardwired to launch the
desktop app and doesn't even have a Linux path. So that's the real gap: a cross-platform
"open this path with whatever app handles it," Linux included.

For that I'd just pull in a small argv-based opener crate like open, which goes through
open / start / xdg-open with argv instead of a shell string. That handles the
no-shell-injection requirement on its own and covers all three platforms in one call.
URLs stay on the existing webbrowser path. Net result is one new dependency doing only
the part nothing else covers, and the URL handling stays on code that's already battle-
tested.

For an MVP I'd keep it to roughly what you listed: /open <url> to the browser,
/open <file://...> resolved to a path, /open . and relative/absolute paths against the
session cwd, reject any other scheme with a clear error, and explicitly leave out remote
workspaces and any "open the latest generated file" magic for now. Tests would mirror the
existing slash-command ones (path resolution, file-url handling, bad scheme, missing path)
without actually spawning anything in CI, plus regenerating the slash-popup snapshot.

Really the only open question is whether you're fine taking on one more dependency for the
opener, the alternative being hand-rolling the per-OS process spawning yourself, which the
crate already does correctly. Happy to put up a PR if that'd be welcome, otherwise feel
free to take the sketch and run with it.