mnemo/cli.rs
1use clap::{Parser, Subcommand, ValueEnum};
2use clap_complete::Shell;
3use std::path::PathBuf;
4
5use crate::export::ExportFormat;
6
7#[derive(Parser, Debug)]
8#[command(
9 name = "mnemo",
10 version,
11 about = "Navigation et recherche dans l'historique Bash",
12 long_about = None,
13)]
14pub struct Cli {
15 #[command(subcommand)]
16 pub command: Command,
17}
18
19#[derive(Subcommand, Debug)]
20pub enum Command {
21 /// Initialise la configuration et la base de données.
22 Init {
23 /// Lance l'assistant d'onboarding interactif (intégration Bash, import,
24 /// diagnostic). Toutes les actions proposées sont non destructives.
25 #[arg(long)]
26 wizard: bool,
27 /// En mode `--wizard` non interactif, accepte les choix sûrs par défaut
28 /// sans rien supprimer ni purger.
29 #[arg(long)]
30 yes: bool,
31 },
32
33 /// Génère un script de complétion shell sur stdout (bash, zsh, fish).
34 ///
35 /// mnemo n'écrit jamais dans vos fichiers shell : redirigez la sortie vers
36 /// l'emplacement adéquat (voir `docs/UX_ONBOARDING.md`).
37 Completions {
38 /// Shell cible.
39 #[arg(value_enum)]
40 shell: CompletionShell,
41 },
42
43 /// Importe l'historique Bash (~/.bash_history par défaut) dans la base.
44 Import {
45 /// Fichier d'historique à importer.
46 #[arg(long)]
47 file: Option<PathBuf>,
48 },
49
50 /// Ajoute une commande dans la base.
51 Add {
52 /// Commande à enregistrer.
53 #[arg(long)]
54 cmd: String,
55 /// Répertoire de travail (défaut : répertoire courant).
56 #[arg(long)]
57 cwd: Option<String>,
58 /// Code de sortie de la commande.
59 #[arg(long = "exit-code", default_value_t = 0)]
60 exit_code: i64,
61 },
62
63 /// Ouvre l'interface TUI interactive de recherche.
64 Search {
65 /// Requête initiale (positionnelle, optionnelle).
66 query: Option<String>,
67 /// Requête explicite (équivalent à l'argument positionnel).
68 #[arg(long = "query", value_name = "TEXTE", conflicts_with = "query")]
69 query_opt: Option<String>,
70 /// Mode non interactif : imprime les résultats sur stdout sans TUI.
71 #[arg(long)]
72 print: bool,
73 /// Nombre maximal de résultats affichés en mode --print.
74 #[arg(long, default_value_t = 20)]
75 limit: usize,
76 /// Filtre sur un projet Git (nom du dossier racine ou chemin git_root).
77 #[arg(long, value_name = "NOM")]
78 project: Option<String>,
79 /// Filtre sur une branche Git.
80 #[arg(long, value_name = "BRANCHE")]
81 branch: Option<String>,
82 /// Filtre sur un code de sortie exact (ex : 0, 1, 127).
83 #[arg(long = "exit-code", value_name = "CODE")]
84 exit_code: Option<i64>,
85 /// N'affiche que les commandes en échec (exit_code ≠ 0).
86 #[arg(long, conflicts_with = "exit_code")]
87 failed: bool,
88 /// Limite l'âge des résultats (durée `24h`/`7d`/`2w`/`3m`/`1y` ou date `AAAA-MM-JJ`).
89 #[arg(long, value_name = "DURÉE|DATE")]
90 since: Option<String>,
91 /// N'affiche que les commandes antérieures à une date (`AAAA-MM-JJ`).
92 /// Alias : `--until`.
93 #[arg(long, visible_alias = "until", value_name = "DATE")]
94 before: Option<String>,
95 /// Filtre sur un répertoire de travail exact.
96 #[arg(long, value_name = "CHEMIN")]
97 cwd: Option<String>,
98 /// Filtre sur un shell exact (ex : bash, zsh).
99 #[arg(long, value_name = "SHELL")]
100 shell: Option<String>,
101 /// Produit une sortie JSON stable (implique le mode non interactif).
102 #[arg(long)]
103 json: bool,
104 /// N'affiche que les identifiants, un par ligne (implique le mode non
105 /// interactif). Pratique pour chaîner avec `mnemo show`/`mnemo print`.
106 #[arg(long = "id-only", conflicts_with = "json")]
107 id_only: bool,
108 },
109
110 /// Ouvre la TUI avancée (interface interactive principale).
111 Tui {
112 /// Requête initiale (positionnelle, optionnelle).
113 query: Option<String>,
114 /// Filtre initial sur un projet Git (nom du dossier racine).
115 #[arg(long, value_name = "NOM")]
116 project: Option<String>,
117 /// Filtre initial sur une branche Git.
118 #[arg(long, value_name = "BRANCHE")]
119 branch: Option<String>,
120 /// Filtre initial sur un répertoire de travail.
121 #[arg(long, value_name = "CHEMIN")]
122 cwd: Option<String>,
123 /// N'affiche que les commandes en échec (exit_code ≠ 0).
124 #[arg(long)]
125 failed: bool,
126 },
127
128 /// Affiche le snippet d'intégration Bash à ajouter dans ~/.bashrc.
129 Bashrc,
130
131 /// Gère l'intégration shell installée dans ~/.bashrc.
132 Shell {
133 #[command(subcommand)]
134 action: ShellCommand,
135 },
136
137 /// Applique les migrations de schéma SQLite en attente.
138 Migrate,
139
140 /// Affiche des statistiques d'usage (texte simple).
141 Stats {
142 /// Filtre sur un projet Git (nom du dossier racine, chemin git_root, ou `current`).
143 #[arg(long, value_name = "NOM")]
144 project: Option<String>,
145 /// Filtre sur une branche Git.
146 #[arg(long, value_name = "BRANCHE")]
147 branch: Option<String>,
148 /// Limite la fenêtre d'analyse (durée `24h`/`7d`/`2w`/`3m`/`1y` ou date `AAAA-MM-JJ`).
149 #[arg(long, value_name = "DURÉE|DATE")]
150 since: Option<String>,
151 /// Produit une sortie JSON exploitable.
152 #[arg(long)]
153 json: bool,
154 },
155
156 /// Diagnostique l'installation locale de mnemo.
157 Doctor {
158 /// Répare les éléments manquants (config, base, bloc .bashrc).
159 #[arg(long)]
160 fix: bool,
161 /// Produit une sortie JSON exploitable.
162 #[arg(long)]
163 json: bool,
164 },
165
166 /// Gère la configuration locale de mnemo.
167 Config {
168 #[command(subcommand)]
169 action: ConfigCommand,
170 },
171
172 /// Crée une sauvegarde locale complète (archive .tar.gz).
173 Backup {
174 /// Dossier de destination (défaut : ~/.local/share/mnemo/backups/).
175 #[arg(long, value_name = "DOSSIER")]
176 output: Option<PathBuf>,
177 /// Produit une sortie JSON exploitable.
178 #[arg(long)]
179 json: bool,
180 },
181
182 /// Restaure une sauvegarde (.tar.gz) après vérification.
183 Restore {
184 /// Chemin de l'archive de sauvegarde.
185 archive: PathBuf,
186 /// Montre ce qui serait fait sans rien modifier.
187 #[arg(long = "dry-run")]
188 dry_run: bool,
189 /// Confirme la restauration sans question interactive.
190 #[arg(long)]
191 yes: bool,
192 },
193
194 /// Exporte les commandes en JSON ou CSV.
195 Export {
196 /// Format de sortie.
197 #[arg(long, value_enum)]
198 format: ExportFormat,
199 /// Filtre sur un projet Git (nom du dossier racine ou chemin git_root).
200 #[arg(long, value_name = "NOM")]
201 project: Option<String>,
202 /// Filtre sur une branche Git.
203 #[arg(long, value_name = "BRANCHE")]
204 branch: Option<String>,
205 /// Fichier de sortie (défaut : stdout).
206 #[arg(long, value_name = "FICHIER")]
207 output: Option<PathBuf>,
208 /// Compresse la sortie en gzip (`.json.gz` / `.csv.gz`).
209 #[arg(long)]
210 gzip: bool,
211 },
212
213 /// Affiche les dernières commandes avec leurs IDs.
214 List {
215 /// Nombre de commandes affichées (défaut : 20).
216 #[arg(long)]
217 limit: Option<usize>,
218 /// Filtre sur un projet Git (nom du dossier racine ou chemin git_root).
219 #[arg(long, value_name = "NOM")]
220 project: Option<String>,
221 /// Filtre sur une branche Git.
222 #[arg(long, value_name = "BRANCHE")]
223 branch: Option<String>,
224 /// Produit une sortie JSON exploitable.
225 #[arg(long)]
226 json: bool,
227 },
228
229 /// Affiche le détail complet d'une commande par son ID, sans l'exécuter.
230 ///
231 /// mnemo n'exécute jamais une commande de l'historique : `show` se contente
232 /// de lire la base. Si la commande a déjà été redactée, sa forme redactée
233 /// stockée est affichée telle quelle.
234 Show {
235 /// Identifiant de la commande (voir `mnemo list` ou `mnemo search`).
236 id: i64,
237 },
238
239 /// Imprime uniquement la commande brute sur stdout, sans décor ni exécution.
240 ///
241 /// Aucun label, aucune couleur : la sortie peut être copiée ou redirigée.
242 /// mnemo n'exécute jamais la commande ; l'utilisateur reste responsable de
243 /// ce qu'il fait de la sortie.
244 Print {
245 /// Identifiant de la commande (voir `mnemo list` ou `mnemo search`).
246 id: i64,
247 },
248
249 /// Supprime une commande par son ID (après confirmation).
250 Delete {
251 /// Identifiant de la commande à supprimer.
252 id: i64,
253 /// Montre la commande ciblée sans la supprimer.
254 #[arg(long = "dry-run")]
255 dry_run: bool,
256 /// Confirme la suppression sans question interactive.
257 #[arg(long)]
258 yes: bool,
259 },
260
261 /// Nettoie les commandes plus anciennes qu'une durée donnée.
262 Prune {
263 /// Durée d'ancienneté (ex : 30d, 12w, 6m, 1y).
264 #[arg(long = "older-than", value_name = "DURÉE")]
265 older_than: String,
266 /// Filtre sur un projet Git (nom du dossier racine ou chemin git_root).
267 #[arg(long, value_name = "NOM")]
268 project: Option<String>,
269 /// Filtre sur une branche Git.
270 #[arg(long, value_name = "BRANCHE")]
271 branch: Option<String>,
272 /// Montre ce qui serait supprimé sans rien modifier.
273 #[arg(long = "dry-run")]
274 dry_run: bool,
275 /// Confirme le nettoyage sans question interactive.
276 #[arg(long)]
277 yes: bool,
278 },
279
280 /// Affiche des informations détaillées de version et de build.
281 Version,
282
283 /// Vérifie si une nouvelle version est disponible (sans rien installer).
284 ///
285 /// En terminal interactif, si une mise à jour existe, propose de lancer
286 /// `mnemo upgrade` immédiatement (réponse par défaut : non). En mode non
287 /// interactif (CI, script, cron, pipe), reste une simple vérification.
288 /// `--upgrade` enchaîne directement l'installation quand une mise à jour est
289 /// disponible ; combiné à `--yes`, il permet un upgrade automatisé.
290 /// `--require-signature` rend la vérification Sigstore (cosign) obligatoire
291 /// lors de l'upgrade enchaîné.
292 Update {
293 /// Sortie au format JSON (vérification seule, sans proposition).
294 #[arg(long)]
295 json: bool,
296 /// Si une mise à jour est disponible, lance directement `mnemo upgrade`.
297 #[arg(long)]
298 upgrade: bool,
299 /// Avec `--upgrade`, installe sans confirmation interactive.
300 #[arg(long)]
301 yes: bool,
302 /// Avec `--upgrade`, exige une signature Sigstore valide (cosign).
303 #[arg(long = "require-signature")]
304 require_signature: bool,
305 },
306
307 /// Télécharge et installe la dernière version stable (remplace le binaire).
308 Upgrade {
309 /// Montre ce qui serait fait sans rien télécharger ni remplacer.
310 #[arg(long = "dry-run")]
311 dry_run: bool,
312 /// Confirme l'installation sans question interactive.
313 #[arg(long)]
314 yes: bool,
315 /// Force une version précise (ex : v0.5.0) au lieu de la dernière.
316 #[arg(long, value_name = "VERSION")]
317 version: Option<String>,
318 /// Force un triplet cible (ex : aarch64-unknown-linux-musl).
319 #[arg(long, value_name = "CIBLE")]
320 target: Option<String>,
321 /// Exige une signature Sigstore valide (cosign requis) avant d'installer.
322 #[arg(long = "require-signature")]
323 require_signature: bool,
324 },
325
326 /// Désinstalle mnemo : binaire + intégration shell. Conserve les données.
327 Uninstall {
328 /// Montre ce qui serait supprimé sans rien modifier.
329 #[arg(long = "dry-run")]
330 dry_run: bool,
331 /// Confirme la désinstallation sans question interactive.
332 #[arg(long)]
333 yes: bool,
334 /// Supprime AUSSI la configuration, la base et les sauvegardes.
335 #[arg(long)]
336 purge: bool,
337 },
338
339 /// Inspecte le projet courant et les projets connus de l'historique.
340 Project {
341 #[command(subcommand)]
342 action: ProjectCommand,
343 },
344
345 /// Maintenance de l'historique (nettoyage automatique configurable).
346 Maintenance {
347 #[command(subcommand)]
348 action: MaintenanceCommand,
349 },
350
351 /// Navigue, consulte et exporte des sessions de travail.
352 ///
353 /// Une session regroupe les commandes partageant un même `session_id`,
354 /// capturé par l'intégration shell (`MNEMO_SESSION_ID`). Les commandes
355 /// importées ou enregistrées sans cet identifiant ne sont pas rattachées à
356 /// une session.
357 Session {
358 #[command(subcommand)]
359 action: SessionCommand,
360 },
361
362 /// Analyse et redacte les secrets présents dans l'historique déjà stocké.
363 ///
364 /// `scan` repère les commandes potentiellement sensibles et les affiche
365 /// toujours sous forme redactée. `redact` les nettoie en place (dry-run par
366 /// défaut, sauvegarde obligatoire avant toute écriture). Aucun secret n'est
367 /// jamais affiché en clair.
368 Secrets {
369 #[command(subcommand)]
370 action: SecretsCommand,
371 },
372
373 /// Génère un runbook Markdown réutilisable à partir d'une session ou d'un
374 /// projet Git.
375 ///
376 /// Chaque commande est présentée dans une section Markdown numérotée avec
377 /// son répertoire de travail, triée par ordre chronologique (le plus ancien
378 /// en premier). Les commandes vides sont exclues. Le résultat peut être
379 /// écrit sur stdout (défaut) ou dans un fichier (`--output`).
380 ///
381 /// Exactement un des drapeaux `--last`, `--session` ou `--project` est
382 /// requis. Si aucun n'est fourni, une erreur claire est affichée.
383 Runbook {
384 /// Cible la dernière session (incompatible avec `--session` et
385 /// `--project`).
386 #[arg(long, conflicts_with_all = ["session", "project"])]
387 last: bool,
388 /// Identifiant de session explicite (incompatible avec `--last` et
389 /// `--project`).
390 #[arg(long, value_name = "ID", conflicts_with_all = ["last", "project"])]
391 session: Option<String>,
392 /// Nom court ou chemin `git_root` d'un projet (incompatible avec
393 /// `--last` et `--session`).
394 #[arg(long, value_name = "NOM|CHEMIN", conflicts_with_all = ["last", "session"])]
395 project: Option<String>,
396 /// Fichier de sortie (défaut : stdout).
397 #[arg(long, value_name = "FICHIER")]
398 output: Option<PathBuf>,
399 /// Autorise l'écrasement du fichier de sortie si déjà existant.
400 #[arg(long)]
401 force: bool,
402 /// Nombre maximal de commandes incluses dans le runbook.
403 #[arg(long, value_name = "N")]
404 limit: Option<u32>,
405 /// Titre personnalisé du runbook (défaut : identifiant de session ou
406 /// nom de projet).
407 #[arg(long, value_name = "TITRE")]
408 title: Option<String>,
409 },
410}
411
412/// Regroupe les options de `mnemo search` pour éviter une fonction à trop
413/// d'arguments (filtres combinables passés en un bloc).
414#[derive(Debug, Default)]
415pub struct SearchArgs {
416 pub query: Option<String>,
417 pub print: bool,
418 pub limit: usize,
419 pub project: Option<String>,
420 pub branch: Option<String>,
421 pub exit_code: Option<i64>,
422 pub failed: bool,
423 pub since: Option<String>,
424 pub before: Option<String>,
425 pub cwd: Option<String>,
426 pub shell: Option<String>,
427 pub json: bool,
428 pub id_only: bool,
429}
430
431/// Shells supportés par `mnemo completions`. Limité volontairement à bash, zsh
432/// et fish (un shell inconnu produit une erreur claire de clap). L'enregistrement
433/// automatique du hook reste, lui, Bash-first.
434#[derive(Clone, Copy, Debug, ValueEnum)]
435pub enum CompletionShell {
436 Bash,
437 Zsh,
438 Fish,
439}
440
441impl CompletionShell {
442 /// Convertit vers le générateur `clap_complete` correspondant.
443 pub fn generator(self) -> Shell {
444 match self {
445 CompletionShell::Bash => Shell::Bash,
446 CompletionShell::Zsh => Shell::Zsh,
447 CompletionShell::Fish => Shell::Fish,
448 }
449 }
450}
451
452#[derive(Subcommand, Debug)]
453pub enum ConfigCommand {
454 /// Affiche la configuration effective (valeurs par défaut incluses).
455 Show,
456 /// Affiche le chemin du fichier de configuration.
457 Path,
458 /// Ouvre la configuration dans l'éditeur ($EDITOR, sinon nano/vi).
459 Edit,
460 /// Vérifie la validité du fichier de configuration.
461 Validate,
462 /// Gère la liste des commandes ignorées dans `mnemo stats`.
463 StatsIgnore {
464 #[command(subcommand)]
465 action: StatsIgnoreCommand,
466 },
467}
468
469#[derive(Subcommand, Debug)]
470pub enum ProjectCommand {
471 /// Affiche le projet détecté pour le répertoire courant.
472 Current,
473 /// Liste les projets connus de l'historique.
474 List {
475 /// Nombre maximal de projets affichés.
476 #[arg(long, value_name = "N")]
477 limit: Option<usize>,
478 /// Sortie JSON.
479 #[arg(long)]
480 json: bool,
481 },
482 /// Affiche le détail d'un projet : activité, branches, derniers échecs.
483 Show {
484 /// Racine ou nom court du projet (incompatible avec `--current`).
485 #[arg(value_name = "PROJET", conflicts_with = "current")]
486 project: Option<String>,
487 /// Cible le projet du répertoire courant.
488 #[arg(long)]
489 current: bool,
490 /// Nombre maximal de commandes récentes affichées.
491 #[arg(long, value_name = "N")]
492 limit: Option<usize>,
493 /// Sortie JSON.
494 #[arg(long)]
495 json: bool,
496 },
497 /// Génère un rapport d'activité réutilisable (Markdown par défaut, ou JSON).
498 Report {
499 /// Racine ou nom court du projet (incompatible avec `--current`).
500 #[arg(value_name = "PROJET", conflicts_with = "current")]
501 project: Option<String>,
502 /// Cible le projet du répertoire courant.
503 #[arg(long)]
504 current: bool,
505 /// Borne inférieure (`24h`, `7d`, `2w`, `3m`, `1y` ou `AAAA-MM-JJ`).
506 #[arg(long, value_name = "DURÉE|DATE")]
507 since: Option<String>,
508 /// Borne supérieure (`AAAA-MM-JJ` exclue, ou durée).
509 #[arg(long, value_name = "DURÉE|DATE")]
510 until: Option<String>,
511 /// Format de sortie (`markdown` par défaut).
512 #[arg(long, value_enum, default_value = "markdown")]
513 format: SessionFormat,
514 /// Fichier de sortie (défaut : stdout).
515 #[arg(long, value_name = "FICHIER")]
516 output: Option<PathBuf>,
517 /// Autorise l'écrasement d'un fichier de sortie existant.
518 #[arg(long)]
519 force: bool,
520 /// Nombre maximal de commandes détaillées dans le rapport.
521 #[arg(long, value_name = "N")]
522 limit: Option<usize>,
523 },
524}
525
526#[derive(Subcommand, Debug)]
527pub enum MaintenanceCommand {
528 /// Affiche l'état de la maintenance et ce qui serait nettoyé.
529 Status,
530 /// Exécute le nettoyage configuré.
531 Run {
532 /// Montre ce qui serait supprimé sans rien modifier.
533 #[arg(long = "dry-run")]
534 dry_run: bool,
535 /// Confirme le nettoyage sans question interactive.
536 #[arg(long)]
537 yes: bool,
538 },
539}
540
541#[derive(Subcommand, Debug)]
542pub enum StatsIgnoreCommand {
543 /// Ajoute une commande à la liste ignorée du Top commandes.
544 Add {
545 /// Nom de commande (ex: `create_dir`).
546 name: String,
547 },
548 /// Retire une commande de la liste ignorée.
549 Remove {
550 /// Nom de commande (ex: `create_dir`).
551 name: String,
552 },
553 /// Affiche les commandes actuellement ignorées.
554 List,
555}
556
557#[derive(Subcommand, Debug)]
558pub enum ShellCommand {
559 /// Met à niveau l'intégration Bash installée dans ~/.bashrc.
560 ///
561 /// Remplace un bloc obsolète par la version courante (capture de
562 /// `MNEMO_SESSION_ID` pour `mnemo session`), après sauvegarde et sans
563 /// toucher au reste du fichier. Sans bloc installé, propose `mnemo init`.
564 Upgrade,
565}
566
567/// Format d'export d'une session (`mnemo session export`).
568#[derive(Clone, Copy, Debug, PartialEq, Eq, ValueEnum)]
569pub enum SessionFormat {
570 Markdown,
571 Json,
572}
573
574#[derive(Subcommand, Debug)]
575pub enum SessionCommand {
576 /// Liste les sessions connues, de la plus récente à la plus ancienne.
577 List {
578 /// Nombre maximal de sessions affichées.
579 #[arg(long, value_name = "N")]
580 limit: Option<usize>,
581 },
582 /// Affiche les commandes d'une session, dans l'ordre chronologique.
583 Show {
584 /// Identifiant de session (voir `mnemo session list`).
585 session_id: String,
586 /// Nombre maximal de commandes affichées.
587 #[arg(long, value_name = "N")]
588 limit: Option<usize>,
589 },
590 /// Exporte une session en Markdown (défaut) ou JSON.
591 Export {
592 /// Identifiant de session à exporter (incompatible avec `--last`).
593 #[arg(value_name = "SESSION_ID", conflicts_with = "last")]
594 session_id: Option<String>,
595 /// Cible la session la plus récente au lieu d'un identifiant explicite.
596 #[arg(long)]
597 last: bool,
598 /// Format de sortie (`markdown` par défaut).
599 #[arg(long, value_enum, default_value = "markdown")]
600 format: SessionFormat,
601 /// Fichier de sortie (défaut : stdout).
602 #[arg(long, value_name = "FICHIER")]
603 output: Option<PathBuf>,
604 /// Autorise l'écrasement d'un fichier de sortie existant.
605 #[arg(long)]
606 force: bool,
607 },
608}
609
610#[derive(Subcommand, Debug)]
611pub enum SecretsCommand {
612 /// Repère les commandes potentiellement sensibles (lecture seule).
613 ///
614 /// Les commandes sont toujours affichées sous forme redactée ; aucun secret
615 /// n'apparaît en clair. N'effectue aucune modification.
616 Scan {
617 /// Nombre maximal de résultats affichés.
618 #[arg(long, value_name = "N")]
619 limit: Option<usize>,
620 /// Sortie JSON (sans valeurs sensibles).
621 #[arg(long)]
622 json: bool,
623 },
624 /// Redacte en place les commandes sensibles déjà stockées.
625 ///
626 /// Dry-run par défaut : sans `--apply`, rien n'est modifié. Avec `--apply`,
627 /// une sauvegarde est créée avant toute écriture et seule la colonne
628 /// `command` est mise à jour.
629 Redact {
630 /// Montre ce qui serait redacté sans rien modifier (comportement par
631 /// défaut, accepté explicitement).
632 #[arg(long = "dry-run")]
633 dry_run: bool,
634 /// Applique réellement la redaction (sinon dry-run).
635 #[arg(long)]
636 apply: bool,
637 /// Confirme la redaction sans question interactive.
638 #[arg(long)]
639 yes: bool,
640 /// Force une sauvegarde avant redaction (toujours effectuée avec
641 /// `--apply`, ce drapeau le rend explicite).
642 #[arg(long)]
643 backup: bool,
644 },
645}