diff --git a/codex-rs/app-server-protocol/src/protocol/v2.rs b/codex-rs/app-server-protocol/src/protocol/v2.rs index 13a6545359a..4311baba5fa 100644 --- a/codex-rs/app-server-protocol/src/protocol/v2.rs +++ b/codex-rs/app-server-protocol/src/protocol/v2.rs @@ -330,6 +330,15 @@ pub struct ProfileV2 { pub additional: HashMap, } +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] +#[serde(rename_all = "snake_case")] +#[ts(export_to = "v2/")] +pub struct AnalyticsConfig { + pub enabled: Option, + #[serde(default, flatten)] + pub additional: HashMap, +} + #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)] #[serde(rename_all = "snake_case")] #[ts(export_to = "v2/")] @@ -354,6 +363,7 @@ pub struct Config { pub model_reasoning_effort: Option, pub model_reasoning_summary: Option, pub model_verbosity: Option, + pub analytics: Option, #[serde(default, flatten)] pub additional: HashMap, } diff --git a/codex-rs/core/src/config/mod.rs b/codex-rs/core/src/config/mod.rs index 8eac13fd2ef..035794f4aa9 100644 --- a/codex-rs/core/src/config/mod.rs +++ b/codex-rs/core/src/config/mod.rs @@ -353,6 +353,10 @@ pub struct Config { /// or placeholder replacement will occur for fast keypress bursts. pub disable_paste_burst: bool, + /// When `false`, disables analytics across Codex product surfaces in this machine. + /// Defaults to `true`. + pub analytics: bool, + /// OTEL configuration (exporter type, endpoint, headers, etc.). pub otel: crate::config::types::OtelConfig, } @@ -813,6 +817,10 @@ pub struct ConfigToml { /// or placeholder replacement will occur for fast keypress bursts. pub disable_paste_burst: Option, + /// When `false`, disables analytics across Codex product surfaces in this machine. + /// Defaults to `true`. + pub analytics: Option, + /// OTEL configuration. pub otel: Option, @@ -1390,6 +1398,12 @@ impl Config { notices: cfg.notice.unwrap_or_default(), check_for_update_on_startup, disable_paste_burst: cfg.disable_paste_burst.unwrap_or(false), + analytics: config_profile + .analytics + .as_ref() + .and_then(|a| a.enabled) + .or(cfg.analytics.as_ref().and_then(|a| a.enabled)) + .unwrap_or(true), tui_notifications: cfg .tui .as_ref() @@ -3039,6 +3053,9 @@ approval_policy = "untrusted" # `ConfigOverrides`. profile = "gpt3" +[analytics] +enabled = true + [model_providers.openai-chat-completions] name = "OpenAI using Chat Completions" base_url = "https://api.openai.com/v1" @@ -3064,6 +3081,9 @@ model = "o3" model_provider = "openai" approval_policy = "on-failure" +[profiles.zdr.analytics] +enabled = false + [profiles.gpt5] model = "gpt-5.1" model_provider = "openai" @@ -3204,6 +3224,7 @@ model_verbosity = "high" tui_notifications: Default::default(), animations: true, show_tooltips: true, + analytics: true, tui_scroll_events_per_tick: None, tui_scroll_wheel_lines: None, tui_scroll_trackpad_lines: None, @@ -3287,6 +3308,7 @@ model_verbosity = "high" tui_notifications: Default::default(), animations: true, show_tooltips: true, + analytics: true, tui_scroll_events_per_tick: None, tui_scroll_wheel_lines: None, tui_scroll_trackpad_lines: None, @@ -3385,6 +3407,7 @@ model_verbosity = "high" tui_notifications: Default::default(), animations: true, show_tooltips: true, + analytics: false, tui_scroll_events_per_tick: None, tui_scroll_wheel_lines: None, tui_scroll_trackpad_lines: None, @@ -3469,6 +3492,7 @@ model_verbosity = "high" tui_notifications: Default::default(), animations: true, show_tooltips: true, + analytics: true, tui_scroll_events_per_tick: None, tui_scroll_wheel_lines: None, tui_scroll_trackpad_lines: None, diff --git a/codex-rs/core/src/config/profile.rs b/codex-rs/core/src/config/profile.rs index 9007064905a..e1c45c1f169 100644 --- a/codex-rs/core/src/config/profile.rs +++ b/codex-rs/core/src/config/profile.rs @@ -29,6 +29,7 @@ pub struct ConfigProfile { pub experimental_use_freeform_apply_patch: Option, pub tools_web_search: Option, pub tools_view_image: Option, + pub analytics: Option, /// Optional feature toggles scoped to this profile. #[serde(default)] pub features: Option, diff --git a/codex-rs/core/src/config/types.rs b/codex-rs/core/src/config/types.rs index 3aa72d5ce50..6c421d4608f 100644 --- a/codex-rs/core/src/config/types.rs +++ b/codex-rs/core/src/config/types.rs @@ -273,6 +273,15 @@ pub enum HistoryPersistence { None, } +// ===== Analytics configuration ===== + +/// Analytics settings loaded from config.toml. Fields are optional so we can apply defaults. +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default)] +pub struct AnalyticsConfigToml { + /// When `false`, disables analytics across Codex product surfaces in this profile. + pub enabled: Option, +} + // ===== OTEL configuration ===== #[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]