Skip to main content

greentic_dev/
cli.rs

1use std::{ffi::OsString, path::PathBuf};
2
3use crate::secrets_cli::SecretsCommand;
4use clap::{Args, Parser, Subcommand};
5
6#[derive(Parser, Debug)]
7#[command(name = "greentic-dev")]
8#[command(version)]
9#[command(about = "Greentic developer tooling CLI")]
10pub struct Cli {
11    #[command(subcommand)]
12    pub command: Command,
13}
14
15#[derive(Subcommand, Debug)]
16pub enum Command {
17    /// Flow passthrough (greentic-flow)
18    Flow(PassthroughArgs),
19    /// Pack passthrough (greentic-pack; pack run uses greentic-runner-cli)
20    Pack(PassthroughArgs),
21    /// Component passthrough (greentic-component)
22    Component(PassthroughArgs),
23    /// Manage greentic-dev configuration
24    #[command(subcommand)]
25    Config(ConfigCommand),
26    /// MCP tooling
27    #[command(subcommand)]
28    Mcp(McpCommand),
29    /// GUI passthrough (greentic-gui)
30    Gui(PassthroughArgs),
31    /// Secrets convenience wrappers
32    #[command(subcommand)]
33    Secrets(SecretsCommand),
34    /// Install/update delegated Greentic tool binaries
35    #[command(subcommand)]
36    Tools(ToolsCommand),
37    /// Install delegated assets
38    Install(InstallArgs),
39    /// Decode a CBOR file to text
40    Cbor(CborArgs),
41    /// Deterministic orchestration for dev workbench workflows
42    Wizard(Box<WizardCommand>),
43}
44
45#[derive(Args, Debug, Clone)]
46#[command(disable_help_flag = true)]
47pub struct PassthroughArgs {
48    /// Arguments passed directly to the underlying command
49    #[arg(
50        value_name = "ARGS",
51        trailing_var_arg = true,
52        allow_hyphen_values = true
53    )]
54    pub args: Vec<OsString>,
55}
56
57#[derive(Subcommand, Debug)]
58pub enum McpCommand {
59    /// Inspect MCP provider metadata
60    Doctor(McpDoctorArgs),
61}
62
63#[derive(Args, Debug)]
64pub struct McpDoctorArgs {
65    /// MCP provider identifier or config path
66    pub provider: String,
67    /// Emit compact JSON instead of pretty output
68    #[arg(long = "json")]
69    pub json: bool,
70}
71
72#[derive(Subcommand, Debug)]
73pub enum ConfigCommand {
74    /// Set a key in greentic-dev config (e.g. defaults.component.org)
75    Set(ConfigSetArgs),
76}
77
78#[derive(Subcommand, Debug)]
79pub enum ToolsCommand {
80    /// Install delegated tools (component/flow/pack/gui/runner/secrets)
81    Install(ToolsInstallArgs),
82}
83
84#[derive(Subcommand, Debug)]
85pub enum InstallSubcommand {
86    /// Install delegated tools (component/flow/pack/gui/runner/secrets)
87    Tools(ToolsInstallArgs),
88}
89
90#[derive(Args, Debug)]
91pub struct InstallArgs {
92    #[command(subcommand)]
93    pub command: Option<InstallSubcommand>,
94    /// Tenant identifier for commercial installs
95    #[arg(long = "tenant")]
96    pub tenant: Option<String>,
97    /// Auth token or env:VAR indirection for commercial installs
98    #[arg(long = "token")]
99    pub token: Option<String>,
100    /// Override the directory used for installed binaries
101    #[arg(long = "bin-dir")]
102    pub bin_dir: Option<PathBuf>,
103    /// Override the directory used for installed docs
104    #[arg(long = "docs-dir")]
105    pub docs_dir: Option<PathBuf>,
106    /// Locale (BCP47) used for translated install manifests/docs
107    #[arg(long = "locale")]
108    pub locale: Option<String>,
109}
110
111#[derive(Args, Debug)]
112pub struct ToolsInstallArgs {
113    /// Reinstall tools to pull latest available versions
114    #[arg(long = "latest")]
115    pub latest: bool,
116}
117
118#[derive(Args, Debug)]
119pub struct ConfigSetArgs {
120    /// Config key path (e.g. defaults.component.org)
121    pub key: String,
122    /// Value to assign to the key (stored as a string)
123    pub value: String,
124    /// Override config file path (default: $XDG_CONFIG_HOME/greentic-dev/config.toml)
125    #[arg(long = "file")]
126    pub file: Option<PathBuf>,
127}
128
129#[derive(Args, Debug)]
130pub struct CborArgs {
131    /// Path to the CBOR file to decode
132    #[arg(value_name = "PATH")]
133    pub path: PathBuf,
134}
135
136#[derive(Args, Debug, Clone)]
137pub struct WizardCommand {
138    #[command(subcommand)]
139    pub command: Option<WizardSubcommand>,
140    #[command(flatten)]
141    pub launch: WizardLaunchArgs,
142}
143
144#[derive(Subcommand, Debug, Clone)]
145pub enum WizardSubcommand {
146    /// Validate a launcher AnswerDocument non-interactively
147    Validate(WizardValidateArgs),
148    /// Apply a launcher AnswerDocument non-interactively
149    Apply(WizardApplyArgs),
150}
151
152#[derive(Args, Debug, Clone)]
153pub struct WizardLaunchArgs {
154    /// Frontend mode (text/json/adaptive-card)
155    #[arg(long = "frontend", default_value = "json")]
156    pub frontend: String,
157    /// Locale (BCP47), passed to providers and recorded in plan metadata
158    #[arg(long = "locale")]
159    pub locale: Option<String>,
160    /// Emit a portable AnswerDocument envelope JSON file
161    #[arg(long = "emit-answers")]
162    pub emit_answers: Option<PathBuf>,
163    /// Pin schema version for emitted/validated AnswerDocument
164    #[arg(long = "schema-version")]
165    pub schema_version: Option<String>,
166    /// Migrate AnswerDocument to the selected schema version when needed
167    #[arg(long = "migrate")]
168    pub migrate: bool,
169    /// Override output directory (default: `.greentic/wizard/<run-id>/`)
170    #[arg(long = "out")]
171    pub out: Option<PathBuf>,
172    /// Preview only (default mode is apply when --dry-run is not set)
173    #[arg(long = "dry-run")]
174    pub dry_run: bool,
175    /// Skip interactive confirmation prompt
176    #[arg(long = "yes")]
177    pub yes: bool,
178    /// Allow execution in non-interactive contexts
179    #[arg(long = "non-interactive")]
180    pub non_interactive: bool,
181    /// Allow commands outside the default run-command allowlist
182    #[arg(long = "unsafe-commands")]
183    pub unsafe_commands: bool,
184    /// Allow destructive operations (delete/overwrite/move) when requested by a plan step
185    #[arg(long = "allow-destructive")]
186    pub allow_destructive: bool,
187}
188
189#[derive(Args, Debug, Clone)]
190pub struct WizardValidateArgs {
191    /// Answers file (AnswerDocument envelope)
192    #[arg(long = "answers")]
193    pub answers: PathBuf,
194    /// Frontend mode (text/json/adaptive-card)
195    #[arg(long = "frontend", default_value = "json")]
196    pub frontend: String,
197    /// Locale (BCP47), passed to providers and recorded in plan metadata
198    #[arg(long = "locale")]
199    pub locale: Option<String>,
200    /// Emit a portable AnswerDocument envelope JSON file
201    #[arg(long = "emit-answers")]
202    pub emit_answers: Option<PathBuf>,
203    /// Pin schema version for emitted/validated AnswerDocument
204    #[arg(long = "schema-version")]
205    pub schema_version: Option<String>,
206    /// Migrate AnswerDocument to the selected schema version when needed
207    #[arg(long = "migrate")]
208    pub migrate: bool,
209    /// Override output directory (default: `.greentic/wizard/<run-id>/`)
210    #[arg(long = "out")]
211    pub out: Option<PathBuf>,
212}
213
214#[derive(Args, Debug, Clone)]
215pub struct WizardApplyArgs {
216    /// Answers file (AnswerDocument envelope)
217    #[arg(long = "answers")]
218    pub answers: PathBuf,
219    /// Frontend mode (text/json/adaptive-card)
220    #[arg(long = "frontend", default_value = "json")]
221    pub frontend: String,
222    /// Locale (BCP47), passed to providers and recorded in plan metadata
223    #[arg(long = "locale")]
224    pub locale: Option<String>,
225    /// Emit a portable AnswerDocument envelope JSON file
226    #[arg(long = "emit-answers")]
227    pub emit_answers: Option<PathBuf>,
228    /// Pin schema version for emitted/validated AnswerDocument
229    #[arg(long = "schema-version")]
230    pub schema_version: Option<String>,
231    /// Migrate AnswerDocument to the selected schema version when needed
232    #[arg(long = "migrate")]
233    pub migrate: bool,
234    /// Override output directory (default: `.greentic/wizard/<run-id>/`)
235    #[arg(long = "out")]
236    pub out: Option<PathBuf>,
237    /// Skip interactive confirmation prompt
238    #[arg(long = "yes")]
239    pub yes: bool,
240    /// Allow execution in non-interactive contexts
241    #[arg(long = "non-interactive")]
242    pub non_interactive: bool,
243    /// Allow commands outside the default run-command allowlist
244    #[arg(long = "unsafe-commands")]
245    pub unsafe_commands: bool,
246    /// Allow destructive operations (delete/overwrite/move) when requested by a plan step
247    #[arg(long = "allow-destructive")]
248    pub allow_destructive: bool,
249}