Files
cdxs/src/cli.rs
T
chuan c13ebdc4dc
Release / Prepare release (push) Successful in 6s
Release / Build release assets (push) Successful in 7m6s
Release 0.1.6
2026-06-01 19:56:23 +08:00

391 lines
8.6 KiB
Rust

use std::path::PathBuf;
use clap::{Args, Parser, Subcommand};
#[derive(Parser)]
#[command(name = "cdxs", version, about = "Codex Switch CLI")]
pub struct Cli {
#[command(subcommand)]
pub command: Option<Commands>,
}
#[derive(Subcommand)]
pub enum Commands {
/// Login to Codex through OpenAI OAuth.
Login(LoginArgs),
/// Import an existing Codex auth file.
Import(ImportArgs),
/// List saved accounts.
List {
#[arg(long)]
json: bool,
#[arg(short, long)]
force: bool,
},
/// List saved accounts without refreshing quota.
Show {
#[arg(long)]
json: bool,
},
/// Pull account state from the sync server.
Pull {
#[arg(short, long)]
force: bool,
},
/// Push account state to the sync server.
Push {
#[arg(short, long)]
force: bool,
},
/// Remove a saved account.
Remove {
#[arg(
value_name = "ACCOUNT_ID_OR_EMAIL",
help = "Account id, exact email, or email prefix"
)]
account: String,
},
/// Switch Codex auth.json to a saved account.
Switch {
#[arg(
value_name = "ACCOUNT_ID_OR_EMAIL",
help = "Account id, exact email, or email prefix"
)]
account: Option<String>,
#[arg(short, long, conflicts_with = "account")]
auto: bool,
#[arg(long)]
codex_home: Option<PathBuf>,
#[arg(long)]
apply_fingerprint: bool,
#[arg(long)]
model: Option<String>,
#[arg(long, alias = "reasoning-effort")]
effort: Option<String>,
#[arg(long)]
name: Option<String>,
},
/// Prepare auth, set CODEX_HOME, and execute a command.
Run(RunArgs),
/// Run a minimal Codex exec to refresh Codex-side quota state.
Ping(PingArgs),
/// Refresh and display Codex quota.
Quota {
#[arg(value_name = "ACCOUNT_ID_OR_EMAIL")]
accounts: Vec<String>,
#[arg(long)]
json: bool,
},
/// Account management commands.
Account {
#[command(subcommand)]
command: AccountCommands,
},
/// Managed CODEX_HOME commands.
Home {
#[command(subcommand)]
command: HomeCommands,
},
/// Run or manage the cdxs sync server.
Server {
#[command(subcommand)]
command: ServerCommands,
},
/// Sync local cdxs.toml with a server.
Sync {
#[command(subcommand)]
command: SyncCommands,
},
/// Inspect and manage Codex sessions.
Session {
#[command(subcommand)]
command: SessionCommands,
},
}
#[derive(Args)]
pub struct LoginArgs {
/// Start OpenAI OAuth login for Codex.
#[command(subcommand)]
pub command: Option<LoginCommands>,
/// Add an API key account directly, for example: cdxs login --api sk-...
#[arg(long, value_name = "KEY")]
pub api: Option<String>,
#[arg(long)]
pub base_url: Option<String>,
#[arg(long)]
pub alias: Option<String>,
#[arg(long)]
pub model: Option<String>,
#[arg(long)]
pub name: Option<String>,
#[arg(long)]
pub manual: bool,
#[arg(long, default_value_t = 1455)]
pub port: u16,
#[arg(long)]
pub switch: bool,
}
#[derive(Args)]
pub struct ImportArgs {
/// Import OAuth/API-key auth from auth.json.
#[command(subcommand)]
pub command: Option<ImportCommands>,
#[arg(long)]
pub file: Option<PathBuf>,
#[arg(long)]
pub codex_home: Option<PathBuf>,
#[arg(long)]
pub switch: bool,
}
#[derive(Subcommand)]
pub enum LoginCommands {
/// Start OpenAI OAuth login for Codex.
Oauth {
#[arg(long)]
manual: bool,
#[arg(long, default_value_t = 1455)]
port: u16,
#[arg(long)]
switch: bool,
},
/// Add an OpenAI API key account.
Api {
#[arg(long)]
key: String,
#[arg(long)]
base_url: Option<String>,
#[arg(long)]
alias: Option<String>,
#[arg(long)]
model: Option<String>,
#[arg(long)]
name: Option<String>,
#[arg(long)]
switch: bool,
},
}
#[derive(Subcommand)]
pub enum ImportCommands {
/// Import OAuth/API-key auth from auth.json.
Auth {
#[arg(long)]
file: Option<PathBuf>,
#[arg(long)]
codex_home: Option<PathBuf>,
#[arg(long)]
switch: bool,
},
}
#[derive(Subcommand)]
pub enum AccountCommands {
List {
#[arg(long)]
json: bool,
#[arg(short, long)]
force: bool,
},
Current {
#[arg(long)]
json: bool,
},
Show {
account: String,
#[arg(long)]
json: bool,
},
Remove {
account: String,
},
AddApiKey {
#[arg(long)]
key: String,
#[arg(long)]
base_url: Option<String>,
#[arg(long)]
alias: Option<String>,
#[arg(long)]
model: Option<String>,
#[arg(long)]
name: Option<String>,
#[arg(long)]
switch: bool,
},
}
#[derive(Subcommand)]
pub enum HomeCommands {
List {
#[arg(long)]
json: bool,
},
Create {
name: String,
#[arg(long)]
path: PathBuf,
#[arg(long)]
account: Option<String>,
},
Bind {
name: String,
account: String,
},
Path {
name: String,
},
Remove {
name: String,
},
}
#[derive(Subcommand)]
pub enum ServerCommands {
Run {
#[arg(long, default_value = "127.0.0.1:8765")]
bind: String,
#[arg(long)]
data_dir: Option<PathBuf>,
},
User {
#[command(subcommand)]
command: ServerUserCommands,
},
}
#[derive(Subcommand)]
pub enum ServerUserCommands {
Add {
username: String,
#[arg(long)]
password: String,
#[arg(long)]
data_dir: Option<PathBuf>,
},
}
#[derive(Subcommand)]
pub enum SyncCommands {
Login {
#[arg(long)]
server: String,
#[arg(long)]
user: String,
#[arg(long)]
password: String,
},
Pull {
#[arg(short, long)]
force: bool,
},
Push {
#[arg(short, long)]
force: bool,
},
Remote {
#[arg(long)]
json: bool,
},
Status,
}
#[derive(Subcommand)]
pub enum SessionCommands {
/// List Codex sessions from state_5.sqlite.
List {
#[arg(long)]
all_homes: bool,
#[arg(long)]
json: bool,
},
/// Show token and file statistics for one session.
Stats {
session_id: String,
#[arg(long)]
all_homes: bool,
#[arg(long)]
json: bool,
},
/// Move sessions into the cdxs trash and hide them from Codex.
Trash {
session_ids: Vec<String>,
#[arg(long)]
all_homes: bool,
},
/// List sessions stored in cdxs trash.
TrashList {
#[arg(long)]
all_homes: bool,
#[arg(long)]
json: bool,
},
/// Restore sessions from cdxs trash.
Restore {
session_ids: Vec<String>,
#[arg(long)]
all_homes: bool,
},
/// Check or repair Codex session visibility.
Visibility {
#[command(subcommand)]
command: SessionVisibilityCommands,
},
/// Copy missing session threads across managed CODEX_HOME directories.
SyncThreads {
#[arg(long)]
all_homes: bool,
#[arg(long)]
dry_run: bool,
#[arg(long)]
json: bool,
},
}
#[derive(Subcommand)]
pub enum SessionVisibilityCommands {
Check {
#[arg(long)]
all_homes: bool,
#[arg(long)]
json: bool,
},
Repair {
#[arg(long)]
all_homes: bool,
#[arg(long)]
json: bool,
},
}
#[derive(Args)]
pub struct RunArgs {
#[arg(long, conflicts_with = "home")]
pub account: Option<String>,
#[arg(long, conflicts_with = "account")]
pub home: Option<String>,
#[arg(long)]
pub codex_home: Option<PathBuf>,
/// Command after `--`, for example: cdxs run --account me -- codex
#[arg(required = true, trailing_var_arg = true, allow_hyphen_values = true)]
pub command: Vec<String>,
}
#[derive(Args)]
pub struct PingArgs {
#[arg(long, value_name = "ACCOUNT_ID_OR_EMAIL")]
pub account: Vec<String>,
#[arg(long, default_value_t = 5)]
pub concurrency: usize,
#[arg(long)]
pub codex_home: Option<PathBuf>,
#[arg(long, default_value = "gpt-5.4")]
pub model: String,
#[arg(long, default_value = "none")]
pub reasoning_effort: String,
#[arg(long, default_value = "hello")]
pub prompt: String,
}