diff --git a/codex-rs/Cargo.lock b/codex-rs/Cargo.lock index 035f37e5..1fa5f89a 100644 --- a/codex-rs/Cargo.lock +++ b/codex-rs/Cargo.lock @@ -519,6 +519,15 @@ dependencies = [ "terminal_size", ] +[[package]] +name = "clap_complete" +version = "4.5.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aad5b1b4de04fead402672b48897030eec1f3bfe1550776322f59f6d6e6a5677" +dependencies = [ + "clap", +] + [[package]] name = "clap_derive" version = "4.5.32" @@ -581,6 +590,7 @@ version = "0.0.0" dependencies = [ "anyhow", "clap", + "clap_complete", "codex-common", "codex-core", "codex-exec", diff --git a/codex-rs/README.md b/codex-rs/README.md index 9cd03a7a..b25b5cf2 100644 --- a/codex-rs/README.md +++ b/codex-rs/README.md @@ -47,6 +47,16 @@ Typing `@` triggers a fuzzy-filename search over the workspace root. Use up/down Sometimes it is not convenient to `cd` to the directory you want Codex to use as the "working root" before running Codex. Fortunately, `codex` supports a `--cd` option so you can specify whatever folder you want. You can confirm that Codex is honoring `--cd` by double-checking the **workdir** it reports in the TUI at the start of a new session. +### Shell completions + +Generate shell completion scripts via: + +```shell +codex completion bash +codex completion zsh +codex completion fish +``` + ### Experimenting with the Codex Sandbox To test to see what happens when a command is run under the sandbox provided by Codex, we provide the following subcommands in Codex CLI: diff --git a/codex-rs/cli/Cargo.toml b/codex-rs/cli/Cargo.toml index 78fd08a7..2a75be50 100644 --- a/codex-rs/cli/Cargo.toml +++ b/codex-rs/cli/Cargo.toml @@ -17,6 +17,7 @@ workspace = true [dependencies] anyhow = "1" clap = { version = "4", features = ["derive"] } +clap_complete = "4" codex-core = { path = "../core" } codex-common = { path = "../common", features = ["cli"] } codex-exec = { path = "../exec" } diff --git a/codex-rs/cli/src/main.rs b/codex-rs/cli/src/main.rs index 0e9ba018..51a089d4 100644 --- a/codex-rs/cli/src/main.rs +++ b/codex-rs/cli/src/main.rs @@ -1,4 +1,7 @@ +use clap::CommandFactory; use clap::Parser; +use clap_complete::Shell; +use clap_complete::generate; use codex_cli::LandlockCommand; use codex_cli::SeatbeltCommand; use codex_cli::login::run_login_with_chatgpt; @@ -47,10 +50,20 @@ enum Subcommand { #[clap(visible_alias = "p")] Proto(ProtoCli), + /// Generate shell completion scripts. + Completion(CompletionCommand), + /// Internal debugging commands. Debug(DebugArgs), } +#[derive(Debug, Parser)] +struct CompletionCommand { + /// Shell to generate completions for + #[clap(value_enum, default_value_t = Shell::Bash)] + shell: Shell, +} + #[derive(Debug, Parser)] struct DebugArgs { #[command(subcommand)] @@ -103,6 +116,9 @@ async fn cli_main(codex_linux_sandbox_exe: Option) -> anyhow::Result<() prepend_config_flags(&mut proto_cli.config_overrides, cli.config_overrides); proto::run_main(proto_cli).await?; } + Some(Subcommand::Completion(completion_cli)) => { + print_completion(completion_cli); + } Some(Subcommand::Debug(debug_args)) => match debug_args.cmd { DebugCommand::Seatbelt(mut seatbelt_cli) => { prepend_config_flags(&mut seatbelt_cli.config_overrides, cli.config_overrides); @@ -136,3 +152,9 @@ fn prepend_config_flags( .raw_overrides .splice(0..0, cli_config_overrides.raw_overrides); } + +fn print_completion(cmd: CompletionCommand) { + let mut app = MultitoolCli::command(); + let name = app.get_name().to_string(); + generate(cmd.shell, &mut app, name, &mut std::io::stdout()); +}