use std::path::PathBuf;
use clap::{Args, Parser, Subcommand, ValueEnum, ValueHint};
const ROOT_AFTER_HELP: &str = "\
EXAMPLES:
codex-cli agent prompt 'Summarize this diff'
codex-cli auth status --format json
codex-cli prompt-segment status
codex-cli completion zsh
ENVIRONMENT:
CODEX_CLI_MODEL, CODEX_CLI_REASONING, CODEX_ALLOW_DANGEROUS_ENABLED
CODEX_SECRET_DIR, CODEX_AUTH_FILE, CODEX_SECRET_CACHE_DIR
CODEX_AUTO_REFRESH_ENABLED, CODEX_AUTO_REFRESH_MIN_DAYS
CODEX_AUTH_REMOTE_SSH, CODEX_AUTH_REMOTE_NAME, CODEX_AUTH_REMOTE_REFRESH
CODEX_CHATGPT_BASE_URL, CODEX_OAUTH_CLIENT_ID
CODEX_RATE_LIMITS_DEFAULT_ALL_ENABLED, CODEX_RATE_LIMITS_WATCH_MAX_ROUNDS, CODEX_RATE_LIMITS_WATCH_INTERVAL_SECONDS
CODEX_RATE_LIMITS_CURL_CONNECT_TIMEOUT_SECONDS, CODEX_RATE_LIMITS_CURL_MAX_TIME_SECONDS, CODEX_RATE_LIMITS_CACHE_TTL
CODEX_PROMPT_SEGMENT_ENABLED, CODEX_PROMPT_SEGMENT_TTL, CODEX_PROMPT_SEGMENT_STALE_SUFFIX, CODEX_PROMPT_SEGMENT_NAME_SOURCE
CODEX_PROMPT_SEGMENT_REFRESH_MIN_SECONDS, CODEX_PROMPT_SEGMENT_LOCK_STALE_SECONDS
CODEX_PROMPT_SEGMENT_CURL_CONNECT_TIMEOUT_SECONDS, CODEX_PROMPT_SEGMENT_CURL_MAX_TIME_SECONDS, CODEX_PROMPT_SEGMENT_EXE
CODEX_PROMPT_SEGMENT_SHOW_5H_ENABLED, CODEX_PROMPT_SEGMENT_SHOW_FALLBACK_NAME_ENABLED, CODEX_PROMPT_SEGMENT_SHOW_FULL_EMAIL_ENABLED
CODEX_PROMPT_SEGMENT_COLOR_ENABLED, CODEX_PROMPT_SEGMENT_ZSH_ESCAPE_ENABLED
ZSH_CACHE_DIR, ZSH_DEBUG, NO_COLOR, STARSHIP_SESSION_KEY, STARSHIP_SHELL
EXIT CODES:
0 success
1 runtime error
64 command-line usage error
65 invalid input data";
#[derive(Parser)]
#[command(
name = "codex-cli",
version,
long_version = nils_build_info::long_version(env!("CARGO_PKG_VERSION")),
about = "Codex CLI for nils-cli workspace",
long_about = "Run Codex-oriented agent helpers, authentication helpers, diagnostics, configuration, and prompt-segment utilities.",
after_help = ROOT_AFTER_HELP
)]
pub struct Cli {
#[command(subcommand)]
pub command: Option<Command>,
}
#[derive(Subcommand)]
pub enum Command {
Agent(AgentArgs),
Auth(AuthArgs),
Diag(DiagArgs),
Config(ConfigArgs),
PromptSegment(PromptSegmentArgs),
Completion(CompletionArgs),
}
#[derive(Args)]
pub struct AgentArgs {
#[command(subcommand)]
pub command: Option<AgentCommand>,
}
#[derive(Subcommand)]
pub enum AgentCommand {
Prompt {
#[arg(long = "ephemeral")]
ephemeral: bool,
#[arg(value_name = "prompt", num_args = 0..)]
prompt: Vec<String>,
},
Advice {
#[arg(long = "ephemeral")]
ephemeral: bool,
#[arg(value_name = "question", num_args = 0..)]
question: Vec<String>,
},
Knowledge {
#[arg(long = "ephemeral")]
ephemeral: bool,
#[arg(value_name = "concept", num_args = 0..)]
concept: Vec<String>,
},
Commit {
#[arg(short = 'p', long = "push")]
push: bool,
#[arg(short = 'a', long = "auto-stage")]
auto_stage: bool,
#[arg(long = "ephemeral")]
ephemeral: bool,
#[arg(value_name = "extra", num_args = 0..)]
extra: Vec<String>,
},
Resume {
#[arg(value_name = "session_id")]
session_id: String,
#[arg(long = "cd", value_name = "dir", value_hint = ValueHint::DirPath)]
cd: Option<PathBuf>,
},
}
#[derive(Args)]
pub struct AuthArgs {
#[command(subcommand)]
pub command: Option<AuthCommand>,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, ValueEnum)]
pub enum OutputFormat {
#[value(name = "text")]
Text,
#[value(name = "json")]
Json,
}
#[derive(Args, Clone, Debug, Default)]
pub struct OutputModeArgs {
#[arg(long = "format", value_enum, value_name = "format")]
pub format: Option<OutputFormat>,
#[arg(long = "json", hide = true, conflicts_with = "format")]
pub json: bool,
}
impl OutputModeArgs {
pub fn is_json(&self) -> bool {
self.json || matches!(self.format, Some(OutputFormat::Json))
}
}
#[derive(Subcommand)]
pub enum AuthCommand {
Login {
#[command(flatten)]
output: OutputModeArgs,
#[arg(long = "api-key")]
api_key: bool,
#[arg(long = "device-code")]
device_code: bool,
},
Use {
#[command(flatten)]
output: OutputModeArgs,
#[arg(id = "target", value_name = "target", num_args = 0..)]
args: Vec<String>,
},
Save {
#[command(flatten)]
output: OutputModeArgs,
#[arg(short = 'y', long = "yes")]
yes: bool,
#[arg(id = "secret", value_name = "secret", num_args = 0..)]
args: Vec<String>,
},
Remove {
#[command(flatten)]
output: OutputModeArgs,
#[arg(short = 'y', long = "yes")]
yes: bool,
#[arg(id = "secret", value_name = "secret", num_args = 0..)]
args: Vec<String>,
},
Refresh {
#[command(flatten)]
output: OutputModeArgs,
#[arg(id = "secret", value_name = "secret", num_args = 0..)]
args: Vec<String>,
},
AutoRefresh {
#[command(flatten)]
output: OutputModeArgs,
},
Status {
#[command(flatten)]
output: OutputModeArgs,
},
Current {
#[command(flatten)]
output: OutputModeArgs,
},
Sync {
#[command(flatten)]
output: OutputModeArgs,
},
Remote(AuthRemoteArgs),
}
#[derive(Args)]
pub struct AuthRemoteArgs {
#[command(subcommand)]
pub command: Option<AuthRemoteCommand>,
}
#[derive(Subcommand)]
pub enum AuthRemoteCommand {
Pull {
#[command(flatten)]
output: OutputModeArgs,
#[arg(long = "ssh", value_name = "host")]
ssh: Option<String>,
#[arg(long = "name", value_name = "name")]
name: Option<String>,
#[arg(long = "access-only")]
access_only: bool,
#[arg(long = "write-active")]
write_active: bool,
#[arg(long = "refresh")]
refresh: bool,
},
#[command(hide = true)]
Export {
#[arg(long = "name", value_name = "name")]
name: String,
#[arg(long = "access-only")]
access_only: bool,
#[arg(long = "refresh")]
refresh: bool,
},
}
#[derive(Args)]
pub struct DiagArgs {
#[command(subcommand)]
pub command: Option<DiagCommand>,
}
#[derive(Subcommand)]
pub enum DiagCommand {
RateLimits(RateLimitsArgs),
}
#[derive(Args)]
pub struct RateLimitsArgs {
#[arg(short = 'c', long = "clear-cache")]
pub clear_cache: bool,
#[arg(short = 'd', long = "debug")]
pub debug: bool,
#[arg(long = "cached")]
pub cached: bool,
#[arg(long = "no-refresh-auth")]
pub no_refresh_auth: bool,
#[arg(long = "format", value_enum, value_name = "format")]
pub format: Option<OutputFormat>,
#[arg(long = "json", hide = true, conflicts_with = "format")]
pub json: bool,
#[arg(long = "one-line")]
pub one_line: bool,
#[arg(long = "all")]
pub all: bool,
#[arg(long = "async")]
pub async_mode: bool,
#[arg(long = "watch", requires = "async_mode")]
pub watch: bool,
#[arg(long = "jobs")]
pub jobs: Option<String>,
pub secret: Option<String>,
}
#[derive(Args)]
pub struct ConfigArgs {
#[command(subcommand)]
pub command: Option<ConfigCommand>,
}
#[derive(Subcommand)]
pub enum ConfigCommand {
Show,
Set { key: String, value: String },
}
#[derive(Args)]
pub struct PromptSegmentArgs {
#[command(subcommand)]
pub command: Option<PromptSegmentCommand>,
#[arg(long = "no-5h")]
pub no_5h: bool,
#[arg(long = "ttl")]
pub ttl: Option<String>,
#[arg(long = "time-format")]
pub time_format: Option<String>,
#[arg(long = "show-timezone")]
pub show_timezone: bool,
#[arg(long = "refresh")]
pub refresh: bool,
#[arg(long = "is-enabled", hide = true)]
pub is_enabled: bool,
}
#[derive(Subcommand)]
pub enum PromptSegmentCommand {
Check,
Status {
#[command(flatten)]
output: OutputModeArgs,
},
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, ValueEnum)]
pub enum CompletionShell {
Bash,
Zsh,
}
#[derive(Args)]
pub struct CompletionArgs {
#[arg(value_enum, value_name = "shell")]
pub shell: CompletionShell,
}