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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
use clap::{Parser, Subcommand};
#[derive(Parser, Debug)]
#[command(
name = "smart-password-manager-cli",
version,
about = "Command line interface for smart password management",
long_about = "Smart Password Manager CLI is a Unix-style utility for managing\n\
smart passwords: passwords regenerated on demand from a secret\n\
phrase instead of being stored.\n\n\
It stores only public keys, descriptions and lengths — never\n\
secrets or passwords.\n\n\
Author: Alexander Suvorov\n\
License: BSD-3-Clause\n\
Repo: https://github.com/smartlegionlab/smart-password-manager-cli-rs\n\
Website: https://smartlegionlab.github.io"
)]
pub struct Cli {
#[command(subcommand)]
pub command: Command,
}
#[derive(Subcommand, Debug)]
pub enum Command {
/// Add a new entry (description, secret phrase, length)
Add {
/// Entry description (e.g. "GitHub Account")
#[arg(short, long)]
description: Option<String>,
/// Password length (12–100)
#[arg(short, long, default_value_t = 16)]
length: usize,
/// Secret phrase (min 12 chars). If omitted, prompted interactively.
#[arg(long)]
secret: Option<String>,
/// Read secret phrase from stdin
#[arg(long)]
secret_stdin: bool,
},
/// Generate the password for an existing entry
Get {
/// Public key of the entry (full or short form like "abcd…wxyz")
#[arg(short, long)]
key: Option<String>,
/// Description of the entry (alternative to --key)
#[arg(short, long)]
description: Option<String>,
/// Secret phrase (min 12 chars). If omitted, prompted interactively.
#[arg(long)]
secret: Option<String>,
/// Read secret phrase from stdin
#[arg(long)]
secret_stdin: bool,
/// Copy the password to the system clipboard instead of stdout
#[arg(long)]
copy: bool,
/// Render the password as a QR code in the terminal
#[arg(long)]
qr: bool,
/// Output the password as JSON
#[arg(long)]
json: bool,
},
/// List all stored entries
List {
/// Output as JSON
#[arg(long)]
json: bool,
},
/// Delete an entry
Delete {
/// Public key of the entry
#[arg(short, long)]
key: Option<String>,
/// Description of the entry
#[arg(short, long)]
description: Option<String>,
/// Skip confirmation prompt
#[arg(short = 'y', long)]
yes: bool,
},
/// Edit an entry's metadata (description and/or length)
Edit {
/// Public key of the entry
#[arg(short, long)]
key: Option<String>,
/// Current description of the entry
#[arg(short, long)]
description: Option<String>,
/// New description
#[arg(long)]
new_description: Option<String>,
/// New length (12–100)
#[arg(long)]
new_length: Option<usize>,
},
/// Verify that a secret phrase matches a stored entry
Verify {
/// Public key of the entry
#[arg(short, long)]
key: Option<String>,
/// Description of the entry
#[arg(short, long)]
description: Option<String>,
/// Secret phrase (min 12 chars). If omitted, prompted interactively.
#[arg(long)]
secret: Option<String>,
/// Read secret phrase from stdin
#[arg(long)]
secret_stdin: bool,
},
}