diff --git a/README.md b/README.md index f0dc9f5..e00b5a7 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,16 @@ Codex home 的解析顺序: 会话修复、隐藏、恢复和同步可能修改 Codex 会话状态;写入前会备份相关状态文件。 +## 常用快捷命令 + +- `cdxs list`:列出账号,并自动刷新过期配额缓存。 +- `cdxs show`:列出账号,但不请求配额接口。 +- `cdxs switch`:不带参数时自动选择可用配额最优的账号。 +- `cdxs switch <账号>`:切换到指定账号。 +- `cdxs remove <账号>`:删除账号,等价于 `cdxs account remove <账号>`。 +- `cdxs pull`:从同步服务拉取账号状态,等价于 `cdxs sync pull`。 +- `cdxs push`:推送账号状态到同步服务,等价于 `cdxs sync push`。 + ## 同步服务 内置同步服务只保存每个用户的账号状态,并提供登录、拉取、推送接口。它同步的是可迁移的 `cdxs` 账号状态,不同步整个 Codex home。 diff --git a/src/account.rs b/src/account.rs index 620358c..a3adaa5 100644 --- a/src/account.rs +++ b/src/account.rs @@ -79,6 +79,16 @@ pub async fn list_accounts(json: bool, force: bool) -> Result<()> { if quota_report.changed { store.save(&home)?; } + print_accounts(&store, json) +} + +pub fn show_accounts(json: bool) -> Result<()> { + let home = paths::codex_home(None)?; + let store = Store::load(&home)?; + print_accounts(&store, json) +} + +fn print_accounts(store: &Store, json: bool) -> Result<()> { if json { println!("{}", serde_json::to_string_pretty(&store.accounts)?); return Ok(()); diff --git a/src/cli.rs b/src/cli.rs index eadb6e0..5122769 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -22,6 +22,29 @@ pub enum Commands { #[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( diff --git a/src/main.rs b/src/main.rs index 9553fd1..8810868 100644 --- a/src/main.rs +++ b/src/main.rs @@ -51,13 +51,17 @@ async fn main() -> Result<()> { None => account::import_auth(args.file, args.codex_home, args.switch), }, Commands::List { json, force } => account::list_accounts(json, force).await, + Commands::Show { json } => account::show_accounts(json), + Commands::Pull { force } => sync_client::pull(force).await, + Commands::Push { force } => sync_client::push(force).await, + Commands::Remove { account } => account::remove_account(&account), Commands::Switch { account, auto, codex_home, apply_fingerprint, } => { - if auto { + if auto || account.is_none() { account::switch_auto(codex_home, apply_fingerprint).await } else { account::switch_account(