1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
//! clap argument parsing + subcommand dispatch. Per design §6.3, supports a
//! `--non-interactive` flag for CI, plus `--verbose` / `--debug` diagnostics.
use std::path::PathBuf;
use clap::{Parser, Subcommand};
#[derive(Debug, Parser)]
#[command(
name = "skillpack",
bin_name = "skillpack",
version,
about = "Generate and verify the agent-distribution layer for any OSS project (Claude Code, Cursor, Codex, OpenCode, GitHub Copilot)."
)]
pub struct Cli {
#[command(subcommand)]
pub command: Commands,
/// Print what skillpack detected in the repo (introspection output).
#[arg(long, global = true)]
pub verbose: bool,
/// Print every subprocess call skillpack makes.
#[arg(long, global = true)]
pub debug: bool,
}
#[derive(Debug, Subcommand)]
pub enum Commands {
/// Scaffold the distribution layer (introspect → interview → generate).
Init {
/// Project root to operate on. Defaults to the current directory.
#[arg(long, value_name = "DIR", default_value = ".")]
root: PathBuf,
/// Skip interactive prompts; require a `skillpack.toml` to exist.
/// Intended for CI — never offers to keep unverified output.
#[arg(long)]
non_interactive: bool,
/// Accept the pre-commit verification and write files even when `verify`
/// flags warnings. Critical (`fail`) results still block the write.
/// Without this flag, any non-pass result prompts the user.
#[arg(long)]
accept_warnings: bool,
/// Override the license SPDX id for this run (writes it to skillpack.toml).
#[arg(long, value_name = "SPDX")]
license: Option<String>,
/// Agent ecosystem(s) to generate distribution files for. Repeat to
/// emit multiple: `--target claude --target cursor`. Defaults to
/// `claude` only (backward compatible).
#[arg(long, value_enum, num_args = 1.., value_name = "ECOSYSTEM")]
target: Vec<Target>,
},
/// Check the distribution files against the agent schemas + CLI drift.
Verify {
#[arg(long, value_name = "DIR", default_value = ".")]
root: PathBuf,
/// Output format. `human` (default) prints a readable report; `json`
/// prints a machine-readable object with per-check ids for CI gating.
#[arg(long, value_enum, default_value_t = crate::verify::OutputFormat::Human)]
format: crate::verify::OutputFormat,
},
/// Diagnose why introspection chose `has_cli` / language as it did.
/// Prints the detected profile + a chronological trace of the decision
/// branches that fired (which candidate was tried, why it was rejected,
/// what would make it succeed). Read-only — never writes files.
Doctor {
/// Project root to operate on. Defaults to the current directory.
#[arg(long, value_name = "DIR", default_value = ".")]
root: PathBuf,
},
}
/// Which agent ecosystem to generate distribution files for.
/// Per design §10 (Phase 4: multi-ecosystem delivery).
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, clap::ValueEnum, Default)]
pub enum Target {
/// Claude Code: `.claude-plugin/` + `skills/<name>/SKILL.md`.
#[default]
Claude,
/// Cursor: `.cursor/rules/<name>.mdc` rule file.
Cursor,
Codex,
/// OpenCode: `.opencode/agents/<name>.md` agent definition file.
/// Per opencode.ai/docs/agents — frontmatter (`description` required,
/// `mode`/`temperature`/`permissions` optional); no `.claude-plugin/`.
#[clap(name = "opencode")]
OpenCode,
/// GitHub Copilot: `.github/copilot-instructions.md` custom instructions.
/// Per docs.github.com/copilot — plain markdown, no frontmatter.
Copilot,
}