greentic_dev/
cli.rs

1use std::path::PathBuf;
2
3use clap::{Args, Parser, Subcommand, ValueEnum};
4use greentic_component::cmd::{
5    build::BuildArgs as ComponentBuildArgs, doctor::DoctorArgs as ComponentDoctorArgs,
6    flow::FlowCommand as ComponentFlowCommand, hash::HashArgs as ComponentHashArgs,
7    inspect::InspectArgs as ComponentInspectArgs, new::NewArgs as ComponentNewArgs,
8    store::StoreCommand as ComponentStoreCommand,
9    templates::TemplatesArgs as ComponentTemplatesArgs,
10};
11
12#[derive(Parser, Debug)]
13#[command(name = "greentic-dev")]
14#[command(version)]
15#[command(about = "Greentic developer tooling CLI")]
16pub struct Cli {
17    #[command(subcommand)]
18    pub command: Command,
19}
20
21#[derive(Subcommand, Debug)]
22pub enum Command {
23    /// Flow tooling (validate, lint, bundle inspection)
24    #[command(subcommand)]
25    Flow(FlowCommand),
26    /// Pack tooling (delegates to packc for build/lint/sign/verify/new; uses greentic-pack for inspect/plan/events)
27    #[command(subcommand)]
28    Pack(PackCommand),
29    /// Component tooling (delegates to greentic-component built-ins + distributor add)
30    #[command(subcommand)]
31    Component(ComponentCommand),
32    /// Manage greentic-dev configuration
33    #[command(subcommand)]
34    Config(ConfigCommand),
35    /// MCP tooling
36    #[command(subcommand)]
37    Mcp(McpCommand),
38}
39
40#[derive(Subcommand, Debug)]
41pub enum FlowCommand {
42    /// Validate a flow YAML file and emit the canonical bundle JSON
43    Validate(FlowValidateArgs),
44    /// Add a configured component step to a flow via config-flow
45    AddStep(FlowAddStepArgs),
46}
47
48#[derive(Args, Debug)]
49pub struct FlowValidateArgs {
50    /// Path to the flow definition (YAML)
51    #[arg(short = 'f', long = "file")]
52    pub file: PathBuf,
53    /// Emit compact JSON instead of pretty-printing
54    #[arg(long = "json")]
55    pub json: bool,
56}
57
58#[derive(Args, Debug)]
59pub struct FlowAddStepArgs {
60    /// Flow identifier (maps to flows/<id>.ygtc)
61    pub flow_id: String,
62    /// Component coordinate (store://... or repo://...). If omitted, greentic-dev will prompt.
63    #[arg(long = "coordinate")]
64    pub coordinate: Option<String>,
65    /// Distributor profile to use (overrides GREENTIC_DISTRIBUTOR_PROFILE/env config)
66    #[arg(long = "profile")]
67    pub profile: Option<String>,
68    /// Config flow selection
69    #[arg(long = "mode", value_enum)]
70    pub mode: Option<ConfigFlowModeArg>,
71    /// Automatically append routing from an existing node (if provided)
72    #[arg(long = "after")]
73    pub after: Option<String>,
74}
75
76#[derive(Subcommand, Debug)]
77pub enum PackCommand {
78    /// Delegate to packc build
79    Build(PackcArgs),
80    /// Delegate to packc lint
81    Lint(PackcArgs),
82    /// Delegate to packc new
83    New(PackcArgs),
84    /// Delegate to packc sign
85    Sign(PackcArgs),
86    /// Delegate to packc verify
87    Verify(PackcArgs),
88    /// Inspect a .gtpack (or directory via temporary build)
89    Inspect(PackInspectArgs),
90    /// Generate a deployment plan
91    Plan(PackPlanArgs),
92    /// Events helpers
93    #[command(subcommand)]
94    Events(PackEventsCommand),
95    /// Execute a pack locally with mocks/telemetry support
96    Run(PackRunArgs),
97    /// Initialize a pack workspace from a remote coordinate
98    Init(PackInitArgs),
99}
100
101#[derive(Args, Debug)]
102pub struct PackRunArgs {
103    /// Path to the pack (.gtpack) to execute
104    #[arg(short = 'p', long = "pack")]
105    pub pack: PathBuf,
106    /// Flow entry identifier override
107    #[arg(long = "entry")]
108    pub entry: Option<String>,
109    /// JSON payload to use as run input
110    #[arg(long = "input")]
111    pub input: Option<String>,
112    /// Enforcement policy for pack signatures
113    #[arg(long = "policy", default_value = "devok", value_enum)]
114    pub policy: RunPolicyArg,
115    /// OTLP collector endpoint (optional)
116    #[arg(long = "otlp")]
117    pub otlp: Option<String>,
118    /// Comma-separated list of allowed outbound hosts
119    #[arg(long = "allow")]
120    pub allow: Option<String>,
121    /// Mocks toggle
122    #[arg(long = "mocks", default_value = "on", value_enum)]
123    pub mocks: MockSettingArg,
124    /// Directory to persist run artifacts (transcripts, logs)
125    #[arg(long = "artifacts")]
126    pub artifacts: Option<PathBuf>,
127}
128
129#[derive(Args, Debug)]
130pub struct PackInitArgs {
131    /// Remote pack coordinate (e.g. pack://org/name@1.0.0)
132    pub from: String,
133    /// Distributor profile to use (overrides GREENTIC_DISTRIBUTOR_PROFILE/env config)
134    #[arg(long = "profile")]
135    pub profile: Option<String>,
136}
137
138#[derive(Args, Debug, Clone, Default)]
139#[command(disable_help_flag = true)]
140pub struct PackcArgs {
141    /// Arguments passed directly to the `packc` command
142    #[arg(
143        value_name = "ARGS",
144        trailing_var_arg = true,
145        allow_hyphen_values = true
146    )]
147    pub passthrough: Vec<String>,
148}
149
150#[derive(Args, Debug)]
151pub struct PackInspectArgs {
152    /// Path to the .gtpack file or pack directory
153    #[arg(value_name = "PATH")]
154    pub path: PathBuf,
155    /// Signature policy to enforce
156    #[arg(long, value_enum, default_value = "devok")]
157    pub policy: PackPolicyArg,
158    /// Emit JSON output
159    #[arg(long)]
160    pub json: bool,
161}
162
163#[derive(Subcommand, Debug)]
164pub enum PackEventsCommand {
165    /// List event providers declared in a pack
166    List(PackEventsListArgs),
167}
168
169#[derive(Args, Debug)]
170pub struct PackEventsListArgs {
171    /// Path to a .gtpack archive or pack source directory.
172    #[arg(value_name = "PATH")]
173    pub path: PathBuf,
174    /// Output format: table (default), json, yaml.
175    #[arg(long, value_enum, default_value = "table")]
176    pub format: PackEventsFormatArg,
177    /// When set, print additional diagnostics (for directory builds).
178    #[arg(long)]
179    pub verbose: bool,
180}
181
182#[derive(Args, Debug)]
183pub struct PackPlanArgs {
184    /// Path to a .gtpack archive or pack source directory.
185    #[arg(value_name = "PATH")]
186    pub input: PathBuf,
187    /// Tenant identifier to embed in the plan.
188    #[arg(long, default_value = "tenant-local")]
189    pub tenant: String,
190    /// Environment identifier to embed in the plan.
191    #[arg(long, default_value = "local")]
192    pub environment: String,
193    /// Emit compact JSON output instead of pretty-printing.
194    #[arg(long)]
195    pub json: bool,
196    /// When set, print additional diagnostics (for directory builds).
197    #[arg(long)]
198    pub verbose: bool,
199}
200
201#[derive(Subcommand, Debug, Clone)]
202pub enum ComponentCommand {
203    /// Add a remote component to the current workspace via the distributor
204    Add(ComponentAddArgs),
205    /// Scaffold a new Greentic component project
206    New(ComponentNewArgs),
207    /// List available component templates
208    Templates(ComponentTemplatesArgs),
209    /// Run component doctor checks
210    Doctor(ComponentDoctorArgs),
211    /// Inspect manifests and describe payloads
212    Inspect(ComponentInspectArgs),
213    /// Recompute manifest hashes
214    Hash(ComponentHashArgs),
215    /// Build component wasm + scaffold config flows
216    Build(ComponentBuildArgs),
217    /// Flow utilities (config flow scaffolding)
218    #[command(subcommand)]
219    Flow(ComponentFlowCommand),
220    /// Interact with the component store
221    #[command(subcommand)]
222    Store(ComponentStoreCommand),
223}
224
225#[derive(Args, Debug, Clone)]
226pub struct ComponentAddArgs {
227    /// Remote component coordinate (e.g. component://org/name@^1.0)
228    pub coordinate: String,
229    /// Distributor profile to use (overrides GREENTIC_DISTRIBUTOR_PROFILE/env config)
230    #[arg(long = "profile")]
231    pub profile: Option<String>,
232    /// Resolution intent (dev or runtime)
233    #[arg(long = "intent", default_value = "dev", value_enum)]
234    pub intent: DevIntentArg,
235}
236
237#[derive(Subcommand, Debug)]
238pub enum McpCommand {
239    /// Inspect MCP provider metadata
240    Doctor(McpDoctorArgs),
241}
242
243#[derive(Args, Debug)]
244pub struct McpDoctorArgs {
245    /// MCP provider identifier or config path
246    pub provider: String,
247    /// Emit compact JSON instead of pretty output
248    #[arg(long = "json")]
249    pub json: bool,
250}
251
252#[derive(Subcommand, Debug)]
253pub enum ConfigCommand {
254    /// Set a key in ~/.greentic/config.toml (e.g. defaults.component.org)
255    Set(ConfigSetArgs),
256}
257
258#[derive(Args, Debug)]
259pub struct ConfigSetArgs {
260    /// Config key path (e.g. defaults.component.org)
261    pub key: String,
262    /// Value to assign to the key (stored as a string)
263    pub value: String,
264    /// Override config file path (default: ~/.greentic/config.toml)
265    #[arg(long = "file")]
266    pub file: Option<PathBuf>,
267}
268
269#[derive(Copy, Clone, Debug, ValueEnum)]
270pub enum PackSignArg {
271    Dev,
272    None,
273}
274
275#[derive(Copy, Clone, Debug, ValueEnum)]
276pub enum PackPolicyArg {
277    Devok,
278    Strict,
279}
280
281#[derive(Copy, Clone, Debug, ValueEnum)]
282pub enum RunPolicyArg {
283    Strict,
284    Devok,
285}
286
287#[derive(Copy, Clone, Debug, ValueEnum)]
288pub enum VerifyPolicyArg {
289    Strict,
290    Devok,
291}
292
293#[derive(Copy, Clone, Debug, ValueEnum)]
294pub enum MockSettingArg {
295    On,
296    Off,
297}
298
299#[derive(Copy, Clone, Debug, ValueEnum)]
300pub enum PackEventsFormatArg {
301    Table,
302    Json,
303    Yaml,
304}
305
306#[derive(Copy, Clone, Debug, ValueEnum)]
307pub enum ConfigFlowModeArg {
308    Default,
309    Custom,
310}
311#[derive(Copy, Clone, Debug, ValueEnum)]
312pub enum DevIntentArg {
313    Dev,
314    Runtime,
315}
316
317#[cfg(test)]
318mod tests {}