diff --git a/crates/quicproquo-client/src/main.rs b/crates/quicproquo-client/src/main.rs index 8bc50f3..3c5b886 100644 --- a/crates/quicproquo-client/src/main.rs +++ b/crates/quicproquo-client/src/main.rs @@ -53,8 +53,25 @@ struct Args { #[arg(long, global = true, env = "QPQ_STATE_PASSWORD")] state_password: Option, + // ── Default-repl args (used when no subcommand is given) ───────── + /// State file path (identity + MLS state). Used when running the default REPL. + #[arg(long, default_value = "qpq-state.bin", env = "QPQ_STATE")] + state: PathBuf, + + /// Server address (host:port). Used when running the default REPL. + #[arg(long, default_value = "127.0.0.1:7000", env = "QPQ_SERVER")] + server: String, + + /// OPAQUE username for automatic registration/login. + #[arg(long, env = "QPQ_USERNAME")] + username: Option, + + /// OPAQUE password (prompted securely if --username is set but --password is not). + #[arg(long, env = "QPQ_PASSWORD")] + password: Option, + #[command(subcommand)] - command: Command, + command: Option, } #[derive(Debug, Subcommand)] @@ -324,7 +341,7 @@ async fn main() -> anyhow::Result<()> { // For the REPL, defer init_auth so it can resolve its own token via OPAQUE. // For all other subcommands, initialize auth immediately. - let is_repl = matches!(args.command, Command::Repl { .. }); + let is_repl = matches!(args.command, None | Some(Command::Repl { .. })); if !is_repl { let auth_ctx = ClientAuth::from_parts(args.access_token.clone(), args.device_id.clone()); init_auth(auth_ctx); @@ -332,7 +349,15 @@ async fn main() -> anyhow::Result<()> { let state_pw = args.state_password.as_deref(); - match args.command { + // Default to REPL when no subcommand is given. + let command = args.command.unwrap_or_else(|| Command::Repl { + state: args.state, + server: args.server, + username: args.username, + password: args.password, + }); + + match command { Command::RegisterUser { server, username,