Add top-level exec-server subcommand (#17162)

## Summary
- add a top-level `codex exec-server` subcommand, marked experimental in
CLI help
- launch an adjacent or PATH-provided `codex-exec-server`, with a
source-tree `cargo run -p codex-exec-server --` fallback
- cover the new subcommand parser path

## Validation
- `just fmt`
- `git diff --check`
- not run: Rust test suite

Co-authored-by: Codex <noreply@openai.com>

---------

Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
starr-openai
2026-04-08 15:38:07 -07:00
committed by GitHub
parent 794a0240f9
commit 49677ec71f
2 changed files with 29 additions and 0 deletions

View File

@@ -30,6 +30,7 @@ codex-utils-cli = { workspace = true }
codex-config = { workspace = true }
codex-core = { workspace = true }
codex-exec = { workspace = true }
codex-exec-server = { workspace = true }
codex-execpolicy = { workspace = true }
codex-features = { workspace = true }
codex-login = { workspace = true }

View File

@@ -150,6 +150,9 @@ enum Subcommand {
#[clap(hide = true, name = "stdio-to-uds")]
StdioToUds(StdioToUdsCommand),
/// [EXPERIMENTAL] Run the standalone exec-server binary.
ExecServer(ExecServerCommand),
/// Inspect feature flags.
Features(FeaturesCli),
}
@@ -376,6 +379,17 @@ struct AppServerCommand {
auth: codex_app_server::AppServerWebsocketAuthArgs,
}
#[derive(Debug, Parser)]
struct ExecServerCommand {
/// Transport endpoint URL. Supported values: `ws://IP:PORT` (default).
#[arg(
long = "listen",
value_name = "URL",
default_value = "ws://127.0.0.1:0"
)]
listen: String,
}
#[derive(Debug, clap::Subcommand)]
#[allow(clippy::enum_variant_names)]
enum AppServerSubcommand {
@@ -994,6 +1008,14 @@ async fn cli_main(arg0_paths: Arg0DispatchPaths) -> anyhow::Result<()> {
tokio::task::spawn_blocking(move || codex_stdio_to_uds::run(socket_path.as_path()))
.await??;
}
Some(Subcommand::ExecServer(cmd)) => {
reject_remote_mode_for_subcommand(
root_remote.as_deref(),
root_remote_auth_token_env.as_deref(),
"exec-server",
)?;
run_exec_server_command(cmd).await?;
}
Some(Subcommand::Features(FeaturesCli { sub })) => match sub {
FeaturesSubcommand::List => {
reject_remote_mode_for_subcommand(
@@ -1064,6 +1086,12 @@ async fn cli_main(arg0_paths: Arg0DispatchPaths) -> anyhow::Result<()> {
Ok(())
}
async fn run_exec_server_command(cmd: ExecServerCommand) -> anyhow::Result<()> {
codex_exec_server::run_main_with_listen_url(&cmd.listen)
.await
.map_err(anyhow::Error::from_boxed)
}
async fn enable_feature_in_config(interactive: &TuiCli, feature: &str) -> anyhow::Result<()> {
FeatureToggles::validate_feature(feature)?;
let codex_home = find_codex_home()?;