use std::path::Path;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Agent {
Codex,
Claude,
}
impl Agent {
pub const ALL: [Agent; 2] = [Agent::Codex, Agent::Claude];
pub fn command(self) -> &'static str {
match self {
Agent::Codex => "codex",
Agent::Claude => "claude",
}
}
pub fn name(self) -> &'static str {
match self {
Agent::Codex => "Codex",
Agent::Claude => "Claude Code",
}
}
pub fn short(self) -> &'static str {
match self {
Agent::Codex => "Codex",
Agent::Claude => "Claude",
}
}
pub fn install_hint(self) -> &'static str {
match self {
Agent::Codex => "npm i -g @openai/codex",
Agent::Claude => "npm i -g @anthropic-ai/claude-code",
}
}
pub fn from_program(program: &str) -> Option<Agent> {
let name = Path::new(program).file_name()?.to_str()?;
Agent::ALL.into_iter().find(|a| a.command() == name)
}
pub fn is_interactive(self, args: &[String]) -> bool {
match self {
Agent::Codex => crate::codex::cli::is_interactive(args),
Agent::Claude => crate::claude::cli::is_interactive(args),
}
}
pub fn environment(self, cwd: &str) -> String {
let (who, what) = match self {
Agent::Codex => (
"Codex CLI, OpenAI's coding agent for the terminal",
"command output, or the Codex CLI interface itself",
),
Agent::Claude => (
"Claude Code, Anthropic's coding agent for the terminal",
"tool calls and their output, or the Claude Code interface itself",
),
};
format!(
"<environment>\nThe user is working in {who}, in the directory {cwd}. Text on their \
screen is the assistant's answers, the user's messages, {what} (tips, status lines, \
prompts).\n</environment>\n\n"
)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn agent_from_program() {
assert_eq!(Agent::from_program("codex"), Some(Agent::Codex));
assert_eq!(Agent::from_program("/usr/bin/claude"), Some(Agent::Claude));
assert_eq!(Agent::from_program("htop"), None);
}
}