use anyhow::Result;
const DEFAULT_PORT: u16 = 8787;
pub fn print_env(agent: &str, port: Option<u16>) -> Result<()> {
let port = port.unwrap_or(DEFAULT_PORT);
match agent {
"opencode" => {
println!("# SHIFT proxy — OpenCode");
println!("# Recommended: use the @shift-preflight/opencode-plugin instead.");
println!("# If configuring manually, add to ~/.config/opencode/opencode.json:");
println!("# \"provider\": {{ \"anthropic\": {{ \"options\": {{ \"baseURL\": \"http://localhost:{}/v1\" }} }} }}", port);
println!("#");
println!("# NOTE: OpenCode's Anthropic client appends only /messages to the");
println!("# baseURL, so /v1 MUST be included. Other agents (Claude Code, Codex)");
println!("# use SDKs that append /v1/messages, so they do NOT include /v1.");
}
"claude" | "claude-code" => {
println!("# SHIFT proxy — Claude Code");
println!("# Add to your shell profile (~/.zshrc, ~/.bashrc):");
println!("export ANTHROPIC_BASE_URL=\"http://localhost:{}\"", port);
println!();
println!("# Or add to ~/.claude/settings.json:");
println!(
"# {{ \"env\": {{ \"ANTHROPIC_BASE_URL\": \"http://localhost:{}\" }} }}",
port
);
}
"codex" => {
println!("# SHIFT proxy — Codex CLI");
println!("# Codex CLI uses ~/.codex/config.toml (NOT environment variables).");
println!("# Add the following line to ~/.codex/config.toml:");
println!();
println!("openai_base_url = \"http://localhost:{}\"", port);
println!();
println!("# Or pass as a one-off flag:");
println!("# codex -c 'openai_base_url=\"http://localhost:{}\"'", port);
}
"cursor" => {
println!("# SHIFT proxy — Cursor");
println!("# Cursor requires manual configuration through its settings UI.");
println!("# 1. Open Cursor Settings > Models");
println!("# 2. Enter your own OpenAI API key");
println!("# 3. Set \"Override OpenAI Base URL\" to:");
println!("# http://localhost:{}/v1", port);
println!(
"# Note: This only works with your own API key, not Cursor's built-in models."
);
}
_ => anyhow::bail!(
"unknown agent '{}'. Supported: opencode, claude-code, codex, cursor",
agent
),
}
Ok(())
}
pub fn print_env_all(port: Option<u16>) -> Result<()> {
let port = port.unwrap_or(DEFAULT_PORT);
println!("# SHIFT proxy — configuration for all supported agents");
println!("# Only Claude Code uses shell env vars. Other agents need");
println!("# config files or UI settings. Run `shift-ai setup` for");
println!("# automatic configuration of all detected agents.");
println!();
println!("# Claude Code (env var — add to shell profile)");
println!("export ANTHROPIC_BASE_URL=\"http://localhost:{}\"", port);
println!();
println!("# Codex CLI — add to ~/.codex/config.toml:");
println!("# openai_base_url = \"http://localhost:{}\"", port);
println!();
println!("# OpenCode — use @shift-preflight/opencode-plugin (recommended)");
println!("# Cursor — set in Settings > Models > Override OpenAI Base URL");
Ok(())
}
pub fn print_agent_list(port: Option<u16>) -> Result<()> {
let port = port.unwrap_or(DEFAULT_PORT);
let base = format!("http://localhost:{}", port);
let base_v1 = format!("http://localhost:{}/v1", port);
let codex_val = format!("openai_base_url = \"{}\"", base);
println!("Agent Method Configuration");
let sep = "─".repeat(75);
println!("{sep}");
println!(
"{:<16}{:<26}{base}",
"Claude Code", "ANTHROPIC_BASE_URL env"
);
println!(
"{:<16}{:<26}{codex_val}",
"Codex CLI", "~/.codex/config.toml"
);
println!(
"{:<16}{:<26}{base}/v1",
"OpenCode", "opencode-plugin (auto)"
);
println!("{:<16}{:<26}{base_v1}", "Cursor", "Settings UI (manual)");
println!();
println!("Claude Code: eval \"$(shift-ai env claude-code)\"");
println!("Codex CLI: shift-ai env codex (prints TOML snippet)");
println!("All agents: shift-ai setup (interactive, recommended)");
Ok(())
}