diff --git a/codex-rs/Cargo.toml b/codex-rs/Cargo.toml index 20a0f160..8ac0361f 100644 --- a/codex-rs/Cargo.toml +++ b/codex-rs/Cargo.toml @@ -22,6 +22,12 @@ version = "0.0.0" # edition. edition = "2024" +[workspace.lints] +rust = { } + +[workspace.lints.clippy] +unwrap_used = "deny" + [profile.release] lto = "fat" # Because we bundle some of these executables with the TypeScript CLI, we diff --git a/codex-rs/apply-patch/Cargo.toml b/codex-rs/apply-patch/Cargo.toml index ff780b35..66935b20 100644 --- a/codex-rs/apply-patch/Cargo.toml +++ b/codex-rs/apply-patch/Cargo.toml @@ -7,6 +7,9 @@ edition = "2024" name = "codex_apply_patch" path = "src/lib.rs" +[lints] +workspace = true + [dependencies] anyhow = "1" regex = "1.11.1" diff --git a/codex-rs/apply-patch/src/lib.rs b/codex-rs/apply-patch/src/lib.rs index 40a8791e..fb8414ec 100644 --- a/codex-rs/apply-patch/src/lib.rs +++ b/codex-rs/apply-patch/src/lib.rs @@ -223,7 +223,9 @@ fn extract_heredoc_body_from_apply_patch_command(src: &str) -> anyhow::Result ExitStatus { #[cfg(windows)] fn synthetic_exit_status(code: i32) -> ExitStatus { use std::os::windows::process::ExitStatusExt; + #[expect(clippy::unwrap_used)] std::process::ExitStatus::from_raw(code.try_into().unwrap()) } diff --git a/codex-rs/core/src/rollout.rs b/codex-rs/core/src/rollout.rs index 07d2cd91..0038dfa6 100644 --- a/codex-rs/core/src/rollout.rs +++ b/codex-rs/core/src/rollout.rs @@ -166,7 +166,9 @@ fn create_log_file() -> std::io::Result { // Custom format for YYYY-MM-DD. let format: &[FormatItem] = format_description!("[year]-[month]-[day]"); - let date_str = timestamp.format(format).unwrap(); + let date_str = timestamp + .format(format) + .map_err(|e| IoError::new(ErrorKind::Other, format!("failed to format timestamp: {e}")))?; let filename = format!("rollout-{date_str}-{session_id}.jsonl"); diff --git a/codex-rs/exec/Cargo.toml b/codex-rs/exec/Cargo.toml index 8348ee34..13ceb9ec 100644 --- a/codex-rs/exec/Cargo.toml +++ b/codex-rs/exec/Cargo.toml @@ -11,6 +11,9 @@ path = "src/main.rs" name = "codex_exec" path = "src/lib.rs" +[lints] +workspace = true + [dependencies] anyhow = "1" chrono = "0.4.40" diff --git a/codex-rs/exec/src/lib.rs b/codex-rs/exec/src/lib.rs index cb11ca62..d8e4b9f5 100644 --- a/codex-rs/exec/src/lib.rs +++ b/codex-rs/exec/src/lib.rs @@ -78,10 +78,12 @@ pub async fn run_main(cli: Cli) -> anyhow::Result<()> { // TODO(mbolin): Take a more thoughtful approach to logging. let default_level = "error"; let _ = tracing_subscriber::fmt() + // Fallback to the `default_level` log filter if the environment + // variable is not set _or_ contains an invalid value .with_env_filter( EnvFilter::try_from_default_env() .or_else(|_| EnvFilter::try_new(default_level)) - .unwrap(), + .unwrap_or_else(|_| EnvFilter::new(default_level)), ) .with_ansi(stderr_with_ansi) .with_writer(std::io::stderr) diff --git a/codex-rs/execpolicy/Cargo.toml b/codex-rs/execpolicy/Cargo.toml index cad60290..9d9188c5 100644 --- a/codex-rs/execpolicy/Cargo.toml +++ b/codex-rs/execpolicy/Cargo.toml @@ -11,6 +11,9 @@ path = "src/main.rs" name = "codex_execpolicy" path = "src/lib.rs" +[lints] +workspace = true + [dependencies] anyhow = "1" starlark = "0.13.0" diff --git a/codex-rs/execpolicy/src/arg_resolver.rs b/codex-rs/execpolicy/src/arg_resolver.rs index d1138a8f..060009f8 100644 --- a/codex-rs/execpolicy/src/arg_resolver.rs +++ b/codex-rs/execpolicy/src/arg_resolver.rs @@ -45,7 +45,12 @@ pub fn resolve_observed_args_with_patterns( let prefix = get_range_checked(&args, 0..num_prefix_args)?; let mut prefix_arg_index = 0; for pattern in prefix_patterns { - let n = pattern.cardinality().is_exact().unwrap(); + let n = pattern + .cardinality() + .is_exact() + .ok_or(Error::InternalInvariantViolation { + message: "expected exact cardinality".to_string(), + })?; for positional_arg in &prefix[prefix_arg_index..prefix_arg_index + n] { let matched_arg = MatchedArg::new( positional_arg.index, @@ -111,7 +116,12 @@ pub fn resolve_observed_args_with_patterns( let suffix = get_range_checked(&args, initial_suffix_args_index..args.len())?; let mut suffix_arg_index = 0; for pattern in suffix_patterns { - let n = pattern.cardinality().is_exact().unwrap(); + let n = pattern + .cardinality() + .is_exact() + .ok_or(Error::InternalInvariantViolation { + message: "expected exact cardinality".to_string(), + })?; for positional_arg in &suffix[suffix_arg_index..suffix_arg_index + n] { let matched_arg = MatchedArg::new( positional_arg.index, diff --git a/codex-rs/execpolicy/src/policy_parser.rs b/codex-rs/execpolicy/src/policy_parser.rs index 594010f5..92ed0bdc 100644 --- a/codex-rs/execpolicy/src/policy_parser.rs +++ b/codex-rs/execpolicy/src/policy_parser.rs @@ -168,6 +168,8 @@ fn policy_builtins(builder: &mut GlobalsBuilder) { .map(|v| v.items.to_vec()) .collect(), ); + + #[expect(clippy::unwrap_used)] let policy_builder = eval .extra .as_ref() @@ -182,6 +184,7 @@ fn policy_builtins(builder: &mut GlobalsBuilder) { strings: UnpackList, eval: &mut Evaluator, ) -> anyhow::Result { + #[expect(clippy::unwrap_used)] let policy_builder = eval .extra .as_ref() @@ -197,6 +200,7 @@ fn policy_builtins(builder: &mut GlobalsBuilder) { reason: String, eval: &mut Evaluator, ) -> anyhow::Result { + #[expect(clippy::unwrap_used)] let policy_builder = eval .extra .as_ref() diff --git a/codex-rs/mcp-client/Cargo.toml b/codex-rs/mcp-client/Cargo.toml index 81f4b85e..c662bffd 100644 --- a/codex-rs/mcp-client/Cargo.toml +++ b/codex-rs/mcp-client/Cargo.toml @@ -3,6 +3,9 @@ name = "codex-mcp-client" version = { workspace = true } edition = "2024" +[lints] +workspace = true + [dependencies] anyhow = "1" mcp-types = { path = "../mcp-types" } diff --git a/codex-rs/mcp-server/Cargo.toml b/codex-rs/mcp-server/Cargo.toml index a0a3b556..aa5721e4 100644 --- a/codex-rs/mcp-server/Cargo.toml +++ b/codex-rs/mcp-server/Cargo.toml @@ -3,6 +3,9 @@ name = "codex-mcp-server" version = { workspace = true } edition = "2024" +[lints] +workspace = true + [dependencies] codex-core = { path = "../core" } mcp-types = { path = "../mcp-types" } diff --git a/codex-rs/mcp-server/src/message_processor.rs b/codex-rs/mcp-server/src/message_processor.rs index d7b4adec..299523f9 100644 --- a/codex-rs/mcp-server/src/message_processor.rs +++ b/codex-rs/mcp-server/src/message_processor.rs @@ -227,6 +227,8 @@ impl MessageProcessor { where T: ModelContextProtocolRequest, { + // result has `Serialized` instance so should never fail + #[expect(clippy::unwrap_used)] let response = JSONRPCMessage::Response(JSONRPCResponse { jsonrpc: JSONRPC_VERSION.into(), id, diff --git a/codex-rs/mcp-types/Cargo.toml b/codex-rs/mcp-types/Cargo.toml index 3c7c8349..81ac2d97 100644 --- a/codex-rs/mcp-types/Cargo.toml +++ b/codex-rs/mcp-types/Cargo.toml @@ -3,6 +3,9 @@ name = "mcp-types" version = { workspace = true } edition = "2024" +[lints] +workspace = true + [dependencies] serde = { version = "1", features = ["derive"] } serde_json = "1" diff --git a/codex-rs/mcp-types/src/lib.rs b/codex-rs/mcp-types/src/lib.rs index 7fb22a7d..afd6f4ad 100644 --- a/codex-rs/mcp-types/src/lib.rs +++ b/codex-rs/mcp-types/src/lib.rs @@ -102,6 +102,8 @@ pub enum CallToolResultContent { impl From for serde_json::Value { fn from(value: CallToolResult) -> Self { + // Leave this as it should never fail + #[expect(clippy::unwrap_used)] serde_json::to_value(value).unwrap() } } @@ -240,6 +242,8 @@ pub struct CompleteResultCompletion { impl From for serde_json::Value { fn from(value: CompleteResult) -> Self { + // Leave this as it should never fail + #[expect(clippy::unwrap_used)] serde_json::to_value(value).unwrap() } } @@ -312,6 +316,8 @@ pub enum CreateMessageResultContent { impl From for serde_json::Value { fn from(value: CreateMessageResult) -> Self { + // Leave this as it should never fail + #[expect(clippy::unwrap_used)] serde_json::to_value(value).unwrap() } } @@ -366,6 +372,8 @@ pub struct GetPromptResult { impl From for serde_json::Value { fn from(value: GetPromptResult) -> Self { + // Leave this as it should never fail + #[expect(clippy::unwrap_used)] serde_json::to_value(value).unwrap() } } @@ -420,6 +428,8 @@ pub struct InitializeResult { impl From for serde_json::Value { fn from(value: InitializeResult) -> Self { + // Leave this as it should never fail + #[expect(clippy::unwrap_used)] serde_json::to_value(value).unwrap() } } @@ -538,6 +548,8 @@ pub struct ListPromptsResult { impl From for serde_json::Value { fn from(value: ListPromptsResult) -> Self { + // Leave this as it should never fail + #[expect(clippy::unwrap_used)] serde_json::to_value(value).unwrap() } } @@ -572,6 +584,8 @@ pub struct ListResourceTemplatesResult { impl From for serde_json::Value { fn from(value: ListResourceTemplatesResult) -> Self { + // Leave this as it should never fail + #[expect(clippy::unwrap_used)] serde_json::to_value(value).unwrap() } } @@ -605,6 +619,8 @@ pub struct ListResourcesResult { impl From for serde_json::Value { fn from(value: ListResourcesResult) -> Self { + // Leave this as it should never fail + #[expect(clippy::unwrap_used)] serde_json::to_value(value).unwrap() } } @@ -628,6 +644,8 @@ pub struct ListRootsResult { impl From for serde_json::Value { fn from(value: ListRootsResult) -> Self { + // Leave this as it should never fail + #[expect(clippy::unwrap_used)] serde_json::to_value(value).unwrap() } } @@ -661,6 +679,8 @@ pub struct ListToolsResult { impl From for serde_json::Value { fn from(value: ListToolsResult) -> Self { + // Leave this as it should never fail + #[expect(clippy::unwrap_used)] serde_json::to_value(value).unwrap() } } @@ -782,6 +802,8 @@ pub struct PaginatedResult { impl From for serde_json::Value { fn from(value: PaginatedResult) -> Self { + // Leave this as it should never fail + #[expect(clippy::unwrap_used)] serde_json::to_value(value).unwrap() } } @@ -904,6 +926,8 @@ pub enum ReadResourceResultContents { impl From for serde_json::Value { fn from(value: ReadResourceResult) -> Self { + // Leave this as it should never fail + #[expect(clippy::unwrap_used)] serde_json::to_value(value).unwrap() } } diff --git a/codex-rs/tui/Cargo.toml b/codex-rs/tui/Cargo.toml index ca7649aa..718bee05 100644 --- a/codex-rs/tui/Cargo.toml +++ b/codex-rs/tui/Cargo.toml @@ -11,6 +11,9 @@ path = "src/main.rs" name = "codex_tui" path = "src/lib.rs" +[lints] +workspace = true + [dependencies] anyhow = "1" clap = { version = "4", features = ["derive"] } diff --git a/codex-rs/tui/src/app.rs b/codex-rs/tui/src/app.rs index edb413c9..e85e0b85 100644 --- a/codex-rs/tui/src/app.rs +++ b/codex-rs/tui/src/app.rs @@ -107,7 +107,7 @@ impl App<'_> { pub(crate) fn run(&mut self, terminal: &mut tui::Tui) -> Result<()> { // Insert an event to trigger the first render. let app_event_tx = self.app_event_tx.clone(); - app_event_tx.send(AppEvent::Redraw).unwrap(); + app_event_tx.send(AppEvent::Redraw)?; while let Ok(event) = self.app_event_rx.recv() { match event { @@ -128,7 +128,7 @@ impl App<'_> { modifiers: crossterm::event::KeyModifiers::CONTROL, .. } => { - self.app_event_tx.send(AppEvent::ExitRequest).unwrap(); + self.app_event_tx.send(AppEvent::ExitRequest)?; } _ => { self.dispatch_key_event(key_event); diff --git a/codex-rs/tui/src/lib.rs b/codex-rs/tui/src/lib.rs index a7de9aae..42da0f48 100644 --- a/codex-rs/tui/src/lib.rs +++ b/codex-rs/tui/src/lib.rs @@ -2,7 +2,6 @@ // The standalone `codex-tui` binary prints a short help message before the // alternate‑screen mode starts; that file opts‑out locally via `allow`. #![deny(clippy::print_stdout, clippy::print_stderr)] - use app::App; use codex_core::config::Config; use codex_core::config::ConfigOverrides;