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
//! CLI surface — clap derive structs.
use clap::{Parser, Subcommand};
#[derive(Debug, Parser)]
#[command(
name = "claude-oops",
version,
about = "Automatic safety net for Claude Code — snapshot before risky ops, restore in seconds.",
long_about = None,
)]
pub struct Cli {
#[command(subcommand)]
pub command: Cmd,
}
#[derive(Debug, Subcommand)]
pub enum Cmd {
/// Take an explicit snapshot. Always runs (no idempotency check).
Snap {
/// Optional human-readable message.
#[arg(short = 'm', long)]
message: Option<String>,
/// Override the trigger label (used by hook scripts).
#[arg(long, default_value = "manual")]
trigger: String,
/// Suppress informational output.
#[arg(long)]
quiet: bool,
},
/// List snapshots for this repo.
List {
/// Emit JSON instead of a table.
#[arg(long)]
json: bool,
/// Limit number of rows shown.
#[arg(long)]
limit: Option<usize>,
},
/// Show diff between working tree and a snapshot.
Diff {
/// Snapshot id (or unambiguous prefix).
id: String,
},
/// Show the file-level summary of a snapshot (which files changed).
Show {
/// Snapshot id (or unambiguous prefix).
id: String,
},
/// Restore the working tree to a snapshot.
///
/// Without paths, restores the whole tree. Pass paths after `--` to
/// restore only those files (everything else in the working tree is
/// left alone). Example: `claude-oops to abc123f -- src/auth.rs`.
To {
/// Snapshot id (or unambiguous prefix).
id: String,
/// Skip confirmation prompt.
#[arg(short = 'f', long, alias = "yes")]
force: bool,
/// Paths to restore (after `--`); empty = restore everything.
#[arg(last = true)]
paths: Vec<String>,
},
/// Delete a snapshot.
Drop {
/// Snapshot id.
id: String,
},
/// Apply retention policy: keep last 30 OR last 7 days.
Clean,
/// Install hooks into ~/.claude/settings.json.
Install,
/// Remove hooks we previously installed.
Uninstall,
/// Print project status (count, latest, disk usage).
Status,
/// Internal: hook entry point invoked by Claude Code on PreToolUse.
/// Reads JSON from stdin per the Claude Code hook protocol.
#[command(name = "_hook-pre-tool-use", hide = true)]
HookPreToolUse,
}