supercode-cli 0.5.113

Volter Harness — a lightweight, fully-customizable AI coding agent CLI in Rust. Any model via OpenRouter; natively continues Claude Code and Codex sessions.
//! The harnesses' vendor-bound telemetry (company RFC 0023 decision 17, "Telemetry"): for each detected harness, each
//! stream it sends somewhere — on or off, where it goes, and the setting that turns it off — read from the harness's
//! own settings and this process's environment. Read-only: a harness's configuration is never edited here. An
//! OpenTelemetry export pointed anywhere but the team's own receiver is called out; a launch with a vendor stream on
//! warns once per change of what is on.

use std::collections::BTreeMap;
use std::path::{Path, PathBuf};

#[derive(Debug, Clone, serde::Serialize)]
pub struct Stream {
    pub harness: &'static str,
    pub stream: &'static str,
    pub on: bool,
    pub destination: String,
    /// The setting that turns it off, as the person would write it.
    pub off_with: &'static str,
    /// An export pointed at something other than the team's receiver.
    pub foreign: bool,
}

fn home() -> PathBuf {
    std::env::var_os("HOME")
        .map(PathBuf::from)
        .unwrap_or_default()
}

fn read_json(path: &Path) -> Option<serde_json::Value> {
    serde_json::from_str(&std::fs::read_to_string(path).ok()?).ok()
}

/// A setting as the harness reads it: this process's environment first, then the settings file's `env` table.
fn setting(name: &str, file_env: &BTreeMap<String, String>) -> Option<String> {
    std::env::var(name)
        .ok()
        .or_else(|| file_env.get(name).cloned())
}

fn truthy(value: Option<String>) -> bool {
    matches!(
        value.as_deref().map(str::trim),
        Some("1") | Some("true") | Some("TRUE") | Some("yes")
    )
}

/// Whether an OTLP endpoint is the team's own receiver: this machine, or the Teams server a context names.
fn ours(endpoint: &str) -> bool {
    let host = endpoint
        .split("://")
        .nth(1)
        .unwrap_or(endpoint)
        .split(['/', ':'])
        .next()
        .unwrap_or("");
    if matches!(host, "localhost" | "127.0.0.1" | "::1" | "[::1]") {
        return true;
    }
    std::env::var("SUPERCODE_TEAMS_ORIGIN")
        .ok()
        .map(|origin| origin.contains(host) && !host.is_empty())
        .unwrap_or(false)
}

fn claude(out: &mut Vec<Stream>) {
    let settings = home().join(".claude").join("settings.json");
    if !settings.exists() && !home().join(".claude").exists() {
        return;
    }
    let env: BTreeMap<String, String> = read_json(&settings)
        .and_then(|v| v.get("env").cloned())
        .and_then(|v| v.as_object().cloned())
        .map(|m| {
            m.into_iter()
                .map(|(k, v)| {
                    let text = v
                        .as_str()
                        .map(str::to_string)
                        .unwrap_or_else(|| v.to_string());
                    (k, text)
                })
                .collect()
        })
        .unwrap_or_default();
    let quiet = truthy(setting("CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC", &env));
    out.push(Stream {
        harness: "claude-code",
        stream: "operational metrics",
        on: !(quiet || truthy(setting("DISABLE_TELEMETRY", &env))),
        destination: "Anthropic and its third-party metrics logging".into(),
        off_with: "DISABLE_TELEMETRY=1 in ~/.claude/settings.json \"env\"",
        foreign: false,
    });
    out.push(Stream {
        harness: "claude-code",
        stream: "error reports",
        on: !(quiet || truthy(setting("DISABLE_ERROR_REPORTING", &env))),
        destination: "a third-party error tracker".into(),
        off_with: "DISABLE_ERROR_REPORTING=1 in ~/.claude/settings.json \"env\"",
        foreign: false,
    });
    let export = truthy(setting("CLAUDE_CODE_ENABLE_TELEMETRY", &env));
    let endpoint = setting("OTEL_EXPORTER_OTLP_LOGS_ENDPOINT", &env)
        .or_else(|| setting("OTEL_EXPORTER_OTLP_ENDPOINT", &env))
        .unwrap_or_default();
    out.push(Stream {
        harness: "claude-code",
        stream: "OpenTelemetry export",
        on: export,
        foreign: export && !endpoint.is_empty() && !ours(&endpoint),
        destination: if endpoint.is_empty() {
            "none configured".into()
        } else {
            endpoint
        },
        off_with: "remove CLAUDE_CODE_ENABLE_TELEMETRY from ~/.claude/settings.json \"env\"",
    });
}

fn codex(out: &mut Vec<Stream>) {
    let dir = std::env::var_os("CODEX_HOME")
        .map(PathBuf::from)
        .unwrap_or_else(|| home().join(".codex"));
    if !dir.exists() {
        return;
    }
    let config: toml::Value = std::fs::read_to_string(dir.join("config.toml"))
        .ok()
        .and_then(|text| text.parse().ok())
        .unwrap_or(toml::Value::Table(Default::default()));
    let analytics = config
        .get("analytics")
        .and_then(|t| t.get("enabled"))
        .and_then(toml::Value::as_bool)
        .unwrap_or(true);
    out.push(Stream {
        harness: "codex",
        stream: "usage and health data",
        on: analytics,
        destination: "OpenAI".into(),
        off_with: "[analytics] enabled = false in ~/.codex/config.toml",
        foreign: false,
    });
    let otel = config.get("otel");
    let exporter = otel.and_then(|t| t.get("exporter"));
    let endpoint = exporter
        .and_then(|e| e.get("otlp-http").or_else(|| e.get("otlp-grpc")))
        .and_then(|e| e.get("endpoint"))
        .and_then(toml::Value::as_str)
        .unwrap_or("")
        .to_string();
    let on = match exporter {
        Some(toml::Value::String(kind)) => kind != "none",
        Some(toml::Value::Table(_)) => true,
        _ => false,
    };
    out.push(Stream {
        harness: "codex",
        stream: "OpenTelemetry export",
        on,
        foreign: on && !endpoint.is_empty() && !ours(&endpoint),
        destination: if endpoint.is_empty() {
            "none configured".into()
        } else {
            endpoint
        },
        off_with: "[otel] exporter = \"none\" in ~/.codex/config.toml",
    });
}

fn gemini(out: &mut Vec<Stream>) {
    let settings = home().join(".gemini").join("settings.json");
    if !home().join(".gemini").exists() {
        return;
    }
    let value = read_json(&settings).unwrap_or(serde_json::Value::Null);
    let usage = value
        .pointer("/privacy/usageStatisticsEnabled")
        .or_else(|| value.get("usageStatisticsEnabled"))
        .and_then(serde_json::Value::as_bool)
        .unwrap_or(true);
    out.push(Stream {
        harness: "gemini",
        stream: "usage statistics",
        on: usage,
        destination: "Google".into(),
        off_with: "\"privacy\": { \"usageStatisticsEnabled\": false } in ~/.gemini/settings.json",
        foreign: false,
    });
    let telemetry = value.get("telemetry");
    let on = telemetry
        .and_then(|t| t.get("enabled"))
        .and_then(serde_json::Value::as_bool)
        .unwrap_or(false);
    let endpoint = telemetry
        .and_then(|t| t.get("otlpEndpoint"))
        .and_then(serde_json::Value::as_str)
        .unwrap_or("")
        .to_string();
    out.push(Stream {
        harness: "gemini",
        stream: "OpenTelemetry export",
        on,
        foreign: on && !endpoint.is_empty() && !ours(&endpoint),
        destination: if endpoint.is_empty() {
            "none configured".into()
        } else {
            endpoint
        },
        off_with: "\"telemetry\": { \"enabled\": false } in ~/.gemini/settings.json",
    });
}

/// Every detected harness's streams.
pub fn streams() -> Vec<Stream> {
    let mut out = Vec::new();
    claude(&mut out);
    codex(&mut out);
    gemini(&mut out);
    out
}

/// Before launching a harness: one warning when what it sends to its vendor changed since the last warning (a
/// fingerprint of its streams kept under the config home), never again for the same state.
pub fn warn_once_on_launch(harness: &str, config_home: &Path) {
    let mine: Vec<Stream> = streams()
        .into_iter()
        .filter(|s| s.harness == harness)
        .collect();
    let on: Vec<&Stream> = mine
        .iter()
        .filter(|s| s.on && (s.foreign || !s.stream.contains("OpenTelemetry")))
        .collect();
    let fingerprint = on
        .iter()
        .map(|s| format!("{}={}", s.stream, s.destination))
        .collect::<Vec<_>>()
        .join(";");
    let file = config_home.join("telemetry-warned").join(harness);
    if std::fs::read_to_string(&file).ok().as_deref() == Some(fingerprint.as_str()) {
        return;
    }
    if !on.is_empty() {
        for s in &on {
            eprintln!(
                "note: {harness} sends {} to {}; turn it off with {}",
                s.stream, s.destination, s.off_with
            );
        }
    }
    let _ = std::fs::create_dir_all(file.parent().unwrap_or(config_home));
    let _ = std::fs::write(&file, fingerprint);
}