Skip to main content

agent_rules_tool/
cli.rs

1//! CLI definitions for the `agent-rules-tool` binary.
2//!
3//! Library users typically call [`lint_string`](crate::lint_string) and
4//! [`migrate_string`](crate::migrate_string) instead.
5#![allow(missing_docs)]
6
7use crate::Severity;
8use crate::format::{RuleFormat, RuleFormatArg};
9use clap::{Parser, Subcommand};
10use std::path::PathBuf;
11
12#[derive(Parser)]
13#[command(
14    name = "agent-rules-tool",
15    about = "Lint and migrate agent rules per agent-rules-spec"
16)]
17pub struct Cli {
18    #[command(subcommand)]
19    pub command: Commands,
20}
21
22#[derive(Subcommand)]
23pub enum Commands {
24    /// Lint agent rule files against the agent-rules-spec schema
25    Lint {
26        /// Directory to lint (default: .agents/rules)
27        #[arg(short = 'd', long, conflicts_with = "input_file")]
28        directory: Option<PathBuf>,
29
30        /// Single file to lint
31        #[arg(short = 'i', long, conflicts_with = "directory")]
32        input_file: Option<PathBuf>,
33
34        /// Failure threshold: exit 1 if any violation at/above this level (default: error)
35        #[arg(long, default_value = "error")]
36        severity: SeverityArg,
37
38        /// Write YAML lint report to this path
39        #[arg(long)]
40        report: Option<PathBuf>,
41    },
42
43    /// Migrate agent rule files between tool-native and canonical formats
44    Migrate {
45        /// Source format (or auto to detect from frontmatter / directory)
46        #[arg(value_enum)]
47        from: RuleFormatArg,
48
49        /// Source directory (default: scan all known tool dirs)
50        #[arg(short = 'd', long, conflicts_with = "input_file")]
51        directory: Option<PathBuf>,
52
53        /// Single file to migrate
54        #[arg(short = 'i', long, conflicts_with = "directory")]
55        input_file: Option<PathBuf>,
56
57        /// Target format (default: agents)
58        #[arg(long, default_value = "agents")]
59        to: RuleFormatArg,
60
61        /// Output directory (dir mode) or file (file mode)
62        #[arg(short = 'o', long)]
63        output: Option<PathBuf>,
64
65        /// Overwrite existing output files
66        #[arg(long)]
67        force: bool,
68    },
69}
70
71#[derive(Debug, Clone, Copy, clap::ValueEnum)]
72pub enum SeverityArg {
73    Warn,
74    Error,
75}
76
77impl From<SeverityArg> for Severity {
78    fn from(arg: SeverityArg) -> Self {
79        match arg {
80            SeverityArg::Warn => Severity::Warn,
81            SeverityArg::Error => Severity::Error,
82        }
83    }
84}
85
86impl Commands {
87    pub fn lint_severity(&self) -> Option<Severity> {
88        match self {
89            Commands::Lint { severity, .. } => Some((*severity).into()),
90            _ => None,
91        }
92    }
93
94    pub fn migrate_to(&self) -> Option<RuleFormat> {
95        match self {
96            Commands::Migrate { to, .. } => Some(RuleFormat::from(*to)),
97            _ => None,
98        }
99    }
100}