Files
codex/codex-rs/tui/src/cli.rs
T
Eric Traut 787823cf95 Add --no-daemon to bypass the shared background server (#46088)
## What changed

- Run with `--no-daemon` without starting or probing the shared server, even when it is already running. Preserve the flag through `resume` and `fork`, and honor it for session archive commands.
- Reject combinations with `--remote`, `codex agents`, and `codex queue`, which require a server connection. Point users to `codex --no-daemon` when the agents overview cannot start its shared server.
- Centralize daemon eligibility checks and exclude launches using `--profile` or `CODEX_EXEC_SERVER_URL` from implicit daemon reuse.

## Testing

Add coverage for flag propagation, incompatible command combinations, and daemon eligibility. Add a PTY test verifying that `--no-daemon` starts the TUI without creating daemon state or connecting to an existing control socket.

GitOrigin-RevId: acc6a7cb339df6433bb8273c796194cdceda37c1
2026-09-17 02:46:49 +00:00

154 lines
4.6 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
use clap::Args;
use clap::FromArgMatches;
use clap::Parser;
use codex_utils_absolute_path::AbsolutePathBuf;
use codex_utils_cli::ApprovalModeCliArg;
use codex_utils_cli::CliConfigOverrides;
use codex_utils_cli::SharedCliOptions;
#[derive(Parser, Clone, Debug)]
#[command(version)]
pub struct Cli {
/// Internal: launching CLI that handles daemon updates after the TUI exits.
#[clap(skip)]
pub daemon_cli_executable: Option<AbsolutePathBuf>,
/// Optional user prompt to start the session.
#[arg(value_name = "PROMPT", value_hint = clap::ValueHint::Other)]
pub prompt: Option<String>,
/// Error out when config.toml contains fields that are not recognized by this version of Codex.
#[arg(long = "strict-config", default_value_t = false)]
pub strict_config: bool,
// Internal controls set by the top-level `codex resume` subcommand.
// These are not exposed as user flags on the base `codex` command.
#[clap(skip)]
pub resume_picker: bool,
#[clap(skip)]
pub resume_last: bool,
/// Internal: resume a specific recorded session by id (UUID). Set by the
/// top-level `codex resume <SESSION_ID>` wrapper; not exposed as a public flag.
#[clap(skip)]
pub resume_session_id: Option<String>,
/// Internal: show all sessions (disables cwd filtering and shows CWD column).
#[clap(skip)]
pub resume_show_all: bool,
/// Internal: include non-interactive sessions in resume listings.
#[clap(skip)]
pub resume_include_non_interactive: bool,
/// Internal: open the daemon-wide agents overview instead of starting a thread.
#[clap(skip)]
pub agents_overview: bool,
// Internal controls set by the top-level `codex fork` subcommand.
// These are not exposed as user flags on the base `codex` command.
#[clap(skip)]
pub fork_picker: bool,
#[clap(skip)]
pub fork_last: bool,
/// Internal: fork a specific recorded session by id (UUID). Set by the
/// top-level `codex fork <SESSION_ID>` wrapper; not exposed as a public flag.
#[clap(skip)]
pub fork_session_id: Option<String>,
/// Internal: show all sessions (disables cwd filtering and shows CWD column).
#[clap(skip)]
pub fork_show_all: bool,
#[clap(flatten)]
pub shared: TuiSharedCliOptions,
/// Configure when the model requires human approval before executing a command.
#[arg(long = "ask-for-approval", short = 'a')]
pub approval_policy: Option<ApprovalModeCliArg>,
/// Enable live web search. When enabled, the native Responses `web_search` tool is available to the model (no per‑call approval).
#[arg(long = "search", default_value_t = false)]
pub web_search: bool,
/// Disable alternate screen mode
///
/// Runs the TUI in inline mode, preserving terminal scrollback history.
#[arg(long = "no-alt-screen", default_value_t = false)]
pub no_alt_screen: bool,
/// Run without the shared background server, even if it is already running.
#[arg(long)]
pub no_daemon: bool,
#[clap(skip)]
pub config_overrides: CliConfigOverrides,
}
impl std::ops::Deref for Cli {
type Target = SharedCliOptions;
fn deref(&self) -> &Self::Target {
&self.shared.0
}
}
impl std::ops::DerefMut for Cli {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.shared.0
}
}
#[derive(Clone, Debug, Default)]
pub struct TuiSharedCliOptions(SharedCliOptions);
impl TuiSharedCliOptions {
pub fn into_inner(self) -> SharedCliOptions {
self.0
}
}
impl std::ops::Deref for TuiSharedCliOptions {
type Target = SharedCliOptions;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl std::ops::DerefMut for TuiSharedCliOptions {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl Args for TuiSharedCliOptions {
fn augment_args(cmd: clap::Command) -> clap::Command {
mark_tui_args(SharedCliOptions::augment_args(cmd))
}
fn augment_args_for_update(cmd: clap::Command) -> clap::Command {
mark_tui_args(SharedCliOptions::augment_args_for_update(cmd))
}
}
impl FromArgMatches for TuiSharedCliOptions {
fn from_arg_matches(matches: &clap::ArgMatches) -> Result<Self, clap::Error> {
SharedCliOptions::from_arg_matches(matches).map(Self)
}
fn update_from_arg_matches(&mut self, matches: &clap::ArgMatches) -> Result<(), clap::Error> {
self.0.update_from_arg_matches(matches)
}
}
fn mark_tui_args(cmd: clap::Command) -> clap::Command {
cmd.mut_arg("dangerously_bypass_approvals_and_sandbox", |arg| {
arg.conflicts_with("approval_policy")
})
.mut_arg("auto_review", |arg| arg.conflicts_with("approval_policy"))
}