Skip to main content

zenith_cli/commands/plugin/
agent.rs

1//! The set of AI coding agents the Zenith skill can be installed into, plus how
2//! each one consumes a skill.
3
4/// An AI coding agent Zenith can install its skill for.
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
6pub enum Agent {
7    ClaudeCode,
8    Codex,
9    OpenCode,
10    Cursor,
11    Windsurf,
12    Aider,
13    Zed,
14    Gemini,
15    Copilot,
16    Continue,
17    Kiro,
18    Antigravity,
19}
20
21/// How an agent loads a skill — this decides what we write to disk.
22#[derive(Debug, Clone, Copy, PartialEq, Eq)]
23pub enum SkillFormat {
24    /// Folder skill: a `SKILL.md` plus the full `references/`, `templates/`,
25    /// `themes/` tree (progressive disclosure works). Optional slash-commands.
26    Folder,
27    /// A single self-contained rule/markdown file. References cannot be loaded
28    /// on demand, so the file points the agent at the self-documenting CLI.
29    Rule,
30}
31
32/// Installation scope.
33#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
34pub enum Scope {
35    /// Per-project: write under the project directory (e.g. `.claude/`).
36    Project,
37    /// Per-user: write under `$HOME` (e.g. `~/.claude/`).
38    User,
39}
40
41/// Every agent, in a stable order (used by `--all` and auto-detect).
42pub const ALL_AGENTS: &[Agent] = &[
43    Agent::ClaudeCode,
44    Agent::Codex,
45    Agent::OpenCode,
46    Agent::Cursor,
47    Agent::Windsurf,
48    Agent::Aider,
49    Agent::Zed,
50    Agent::Gemini,
51    Agent::Copilot,
52    Agent::Continue,
53    Agent::Kiro,
54    Agent::Antigravity,
55];
56
57impl Agent {
58    /// Parse a CLI agent name. Accepts a few common aliases.
59    pub fn parse(s: &str) -> Option<Agent> {
60        match s {
61            "claude" | "claude-code" | "claudecode" => Some(Agent::ClaudeCode),
62            "codex" => Some(Agent::Codex),
63            "opencode" | "open-code" => Some(Agent::OpenCode),
64            "cursor" => Some(Agent::Cursor),
65            "windsurf" => Some(Agent::Windsurf),
66            "aider" => Some(Agent::Aider),
67            "zed" => Some(Agent::Zed),
68            "gemini" | "gemini-cli" => Some(Agent::Gemini),
69            "copilot" | "github-copilot" => Some(Agent::Copilot),
70            "continue" | "continue-dev" => Some(Agent::Continue),
71            "kiro" => Some(Agent::Kiro),
72            "antigravity" => Some(Agent::Antigravity),
73            _ => None,
74        }
75    }
76
77    /// Human-readable name for messages.
78    pub fn display(self) -> &'static str {
79        match self {
80            Agent::ClaudeCode => "Claude Code",
81            Agent::Codex => "Codex",
82            Agent::OpenCode => "OpenCode",
83            Agent::Cursor => "Cursor",
84            Agent::Windsurf => "Windsurf",
85            Agent::Aider => "Aider",
86            Agent::Zed => "Zed",
87            Agent::Gemini => "Gemini",
88            Agent::Copilot => "Copilot",
89            Agent::Continue => "Continue",
90            Agent::Kiro => "Kiro",
91            Agent::Antigravity => "Antigravity",
92        }
93    }
94
95    /// How this agent consumes a skill.
96    pub fn format(self) -> SkillFormat {
97        match self {
98            Agent::ClaudeCode | Agent::Codex | Agent::OpenCode => SkillFormat::Folder,
99            Agent::Cursor
100            | Agent::Windsurf
101            | Agent::Aider
102            | Agent::Zed
103            | Agent::Gemini
104            | Agent::Copilot
105            | Agent::Continue
106            | Agent::Kiro
107            | Agent::Antigravity => SkillFormat::Rule,
108        }
109    }
110}