zenith_cli/commands/plugin/
render.rs1use super::agent::Agent;
8use super::assets::{skill_description, skill_md_body};
9
10const RULE_NOTE: &str = "> **Single-file install.** The `references/` packs, `templates/`, and \
13`themes/` ship with the full folder skill (Claude Code, Codex, OpenCode) and live in the \
14[repo](https://github.com/zenitheditor/zenith). In this agent, drive the self-documenting \
15`zenith` CLI directly — run `zenith --help` and `zenith <command> --help` for exact flags, \
16and read the repo's `examples/*.zen` for syntax.";
17
18pub fn render_rule(agent: Agent) -> String {
20 let body = skill_md_body();
21 let desc = skill_description().unwrap_or_default();
22 match agent {
23 Agent::Cursor => format!(
25 "---\nalwaysApply: false\ndescription: {desc}\n---\n\n{RULE_NOTE}\n\n{body}",
26 desc = yaml_scalar(&desc),
27 ),
28 Agent::Windsurf => format!("{RULE_NOTE}\n\n{body}"),
30 Agent::Aider
32 | Agent::Zed
33 | Agent::Gemini
34 | Agent::Copilot
35 | Agent::Continue
36 | Agent::Kiro
37 | Agent::Antigravity => format!("# Zenith\n\n{RULE_NOTE}\n\n{body}"),
38 Agent::ClaudeCode | Agent::Codex | Agent::OpenCode => body.to_owned(),
40 }
41}
42
43fn yaml_scalar(s: &str) -> String {
46 let needs = s.contains(':')
47 || s.contains('#')
48 || s.contains('"')
49 || s.contains('\'')
50 || s.starts_with(char::is_whitespace)
51 || s.ends_with(char::is_whitespace);
52 if needs {
53 format!("\"{}\"", s.replace('\\', "\\\\").replace('"', "\\\""))
54 } else {
55 s.to_owned()
56 }
57}