Skip to main content

ane/data/
agents.rs

1#[derive(Debug)]
2pub struct AgentConfig {
3    pub name: &'static str,
4    pub skill_dir: &'static str,
5    pub skill_filename: &'static str,
6    /// Printed after writing if the agent requires manual integration steps
7    /// (e.g. no auto-load convention, or an extra reference must be added).
8    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        // 'charm' is the company; the agent is named 'crush'.
98        assert!(find_agent("charm").is_none());
99    }
100}