1#[derive(Debug)]
2pub struct AgentConfig {
3 pub name: &'static str,
4 pub skill_dir: &'static str,
5 pub skill_filename: &'static str,
6 pub manual_note: Option<&'static str>,
9}
10
11pub const AGENTS: &[AgentConfig] = &[
12 AgentConfig {
13 name: "claude",
14 skill_dir: ".claude/skills/ane",
15 skill_filename: "SKILL.md",
16 manual_note: None,
17 },
18 AgentConfig {
19 name: "codex",
20 skill_dir: ".agents/skills/ane",
21 skill_filename: "SKILL.md",
22 manual_note: None,
23 },
24 AgentConfig {
25 name: "gemini",
26 skill_dir: ".gemini/skills/ane",
27 skill_filename: "SKILL.md",
28 manual_note: None,
29 },
30 AgentConfig {
31 name: "opencode",
32 skill_dir: ".opencode/skills/ane",
33 skill_filename: "SKILL.md",
34 manual_note: None,
35 },
36 AgentConfig {
37 name: "cline",
38 skill_dir: ".cline/skills/ane",
39 skill_filename: "SKILL.md",
40 manual_note: None,
41 },
42 AgentConfig {
43 name: "maki",
44 skill_dir: ".agents/skills/ane",
45 skill_filename: "SKILL.md",
46 manual_note: Some(
47 "Maki's per-project skill auto-loading is not publicly documented. This file \
48 follows the Agent Skills open standard at .agents/skills/. If Maki does not \
49 pick it up automatically, reference it from your AGENTS.md.",
50 ),
51 },
52 AgentConfig {
53 name: "crush",
54 skill_dir: ".crush/skills/ane",
55 skill_filename: "SKILL.md",
56 manual_note: None,
57 },
58];
59
60pub fn find_agent(name: &str) -> Option<&'static AgentConfig> {
61 AGENTS.iter().find(|a| a.name.eq_ignore_ascii_case(name))
62}
63
64pub fn agent_names() -> Vec<&'static str> {
65 AGENTS.iter().map(|a| a.name).collect()
66}
67
68#[cfg(test)]
69mod tests {
70 use super::*;
71
72 #[test]
73 fn find_agent_returns_config_for_all_supported_names() {
74 for name in [
75 "claude", "codex", "gemini", "opencode", "cline", "maki", "crush",
76 ] {
77 assert!(
78 find_agent(name).is_some(),
79 "find_agent({name:?}) returned None"
80 );
81 }
82 }
83
84 #[test]
85 fn find_agent_is_case_insensitive() {
86 assert!(find_agent("Claude").is_some());
87 assert!(find_agent("CLAUDE").is_some());
88 }
89
90 #[test]
91 fn find_agent_returns_none_for_unknown_agent() {
92 assert!(find_agent("vim").is_none());
93 }
94
95 #[test]
96 fn find_agent_returns_none_for_old_charm_name() {
97 assert!(find_agent("charm").is_none());
99 }
100}