[go: up one dir, main page]

cred/
cli.rs

1//! CLI argument and command definitions for cred.
2//! Parsed once in `main` and dispatched to command handlers.
3
4use crate::targets::Target;
5use crate::vault::SecretFormat;
6use clap::{Args, Parser, Subcommand};
7
8#[derive(Debug, Clone, Copy)]
9/// Global switches derived from CLI flags/env that affect output and prompts.
10pub struct CliFlags {
11    pub json: bool,
12    pub non_interactive: bool,
13    pub dry_run: bool,
14    pub yes: bool,
15    pub no_color: bool,
16}
17
18#[derive(Parser)]
19#[command(name = "cred")]
20#[command(about = "Local-first credential manager", long_about = None)]
21pub struct Cli {
22    /// Output JSON (machine-readable); no prose/tables
23    #[arg(long, global = true)]
24    pub json: bool,
25    /// Run without prompts; fail if input required
26    #[arg(long, global = true)]
27    pub non_interactive: bool,
28    /// Do not mutate anything; show planned changes
29    #[arg(long, global = true)]
30    pub dry_run: bool,
31    /// Confirm destructive actions (required for deletes)
32    #[arg(long, short = 'y', global = true)]
33    pub yes: bool,
34
35    #[command(subcommand)]
36    pub command: Commands,
37}
38
39#[derive(Subcommand)]
40pub enum Commands {
41    /// Initialize a new cred project in the current directory
42    Init,
43
44    /// Run health checks (use --json for machine output)
45    Doctor,
46
47    /// Manage global target authentication
48    Target {
49        #[command(subcommand)]
50        action: TargetAction,
51    },
52
53    /// Manage local secrets
54    Secret {
55        #[command(subcommand)]
56        action: SecretAction,
57    },
58
59    /// Import secrets from a .env file into the local vault
60    Import(ImportArgs),
61
62    /// Export vault secrets to a .env file
63    Export(ExportArgs),
64
65    /// Upload (Push) secrets to a remote hosting target (e.g. GitHub)
66    Push(PushArgs),
67
68    /// Atomic Delete: Removes secrets from the Remote Target AND Local Vault.
69    Prune(PruneArgs),
70
71    /// Inspect and modify cred global configuration (non-secret)
72    Config {
73        #[command(subcommand)]
74        action: ConfigAction,
75    },
76
77    /// Project-level utilities
78    Project {
79        #[command(subcommand)]
80        action: ProjectAction,
81    },
82}
83
84#[derive(Args, Debug)]
85pub struct PushArgs {
86    /// The target to push to
87    pub target: Target,
88
89    /// Specific keys to push. If empty, pushes all secrets.
90    #[arg(num_args = 0..)]
91    pub keys: Vec<String>,
92
93    /// Explicit repository (required if not in git for GitHub)
94    #[arg(long)]
95    pub repo: Option<String>,
96}
97
98#[derive(Args, Debug)]
99pub struct PruneArgs {
100    /// The target to prune from
101    pub target: Target,
102
103    /// Specific keys to remove
104    #[arg(num_args = 0..)]
105    pub keys: Vec<String>,
106
107    /// Explicit repository (required if not in git for GitHub)
108    #[arg(long)]
109    pub repo: Option<String>,
110
111    /// Prune all known keys (requires --yes unless dry-run)
112    #[arg(long)]
113    pub all: bool,
114}
115
116#[derive(Subcommand, Debug)]
117pub enum ConfigAction {
118    /// Get a config value by key path (e.g. preferences.default_target)
119    Get { key: String },
120    /// Set a config value by key path
121    Set { key: String, value: String },
122    /// Unset a config value by key path
123    Unset { key: String },
124    /// List the full config
125    List,
126}
127
128#[derive(Subcommand, Debug)]
129pub enum ProjectAction {
130    /// Show project status (git/vault/targets), JSON recommended
131    Status,
132}
133
134#[derive(Subcommand, Debug)]
135pub enum TargetAction {
136    Set(SetTargetArgs),
137    List,
138    /// Revoke a target's authentication token (Logout)
139    Revoke {
140        name: Target,
141    },
142}
143
144#[derive(Args, Debug)]
145pub struct SetTargetArgs {
146    pub name: Target,
147
148    /// Auth token (will prompt if omitted)
149    #[arg(long)]
150    pub token: Option<String>,
151}
152
153#[derive(Subcommand, Debug)]
154pub enum SecretAction {
155    /// Set a secret value (with optional metadata)
156    Set {
157        key: String,
158        value: String,
159        /// Optional description for the secret
160        #[arg(long, short = 'd')]
161        description: Option<String>,
162        /// Format hint: raw, multiline, base64, json (auto-detected if omitted)
163        #[arg(long, short = 'f')]
164        format: Option<SecretFormat>,
165    },
166    /// Get a secret value
167    Get { key: String },
168    /// List all secrets
169    List {},
170    /// Set or update a secret's description
171    Describe {
172        key: String,
173        /// The description text (omit to clear)
174        description: Option<String>,
175    },
176    /// Remove from Local Vault ONLY (Use 'prune' for remote removal)
177    Remove { key: String },
178    /// Revoke a generated secret at the source AND locally
179    Revoke {
180        key: String,
181        #[arg(long)]
182        target: Target,
183    },
184}
185
186#[derive(Args, Debug)]
187pub struct ImportArgs {
188    /// Path to a .env file to import
189    pub path: String,
190    /// Overwrite existing keys instead of skipping
191    #[arg(long)]
192    pub overwrite: bool,
193}
194
195#[derive(Args, Debug)]
196pub struct ExportArgs {
197    /// Path to write the exported .env file
198    pub path: String,
199    /// Overwrite the output file if it exists
200    #[arg(long)]
201    pub force: bool,
202}