hexz_cli/args.rs
1//! Command-line argument definitions for the Hexz CLI.
2//!
3//! This module defines all Clap argument structures using a nested "Noun-Verb"
4//! command hierarchy (e.g., `hexz data pack`, `hexz vm boot`).
5//!
6//! **Design principle:** Arguments are defined separately from handlers to keep
7//! CLI structure clear and testable. The actual command implementations live in
8//! the `cmd` module.
9
10use clap::{Parser, Subcommand};
11use std::path::PathBuf;
12
13/// Hexz - High-performance snapshot and streaming engine
14#[derive(Parser)]
15#[command(name = "hexz", version, about, long_about = None)]
16pub struct Cli {
17 #[command(subcommand)]
18 pub command: Commands,
19}
20
21/// Top-level command categories
22#[derive(Subcommand)]
23pub enum Commands {
24 /// Data operations (pack, inspect, diff)
25 #[command(subcommand)]
26 Data(DataCommands),
27
28 /// Virtual machine operations (boot, install, snap, commit)
29 #[command(subcommand)]
30 Vm(VmCommands),
31
32 /// System utilities (doctor, bench, serve, keygen)
33 #[command(subcommand)]
34 Sys(SysCommands),
35}
36
37#[derive(Subcommand)]
38pub enum DataCommands {
39 /// Pack data into a Hexz archive
40 Pack {
41 /// Path to disk image to pack
42 #[arg(long)]
43 disk: Option<PathBuf>,
44
45 /// Path to memory dump to pack
46 #[arg(long)]
47 memory: Option<PathBuf>,
48
49 /// Output archive path (.hxz)
50 #[arg(short, long)]
51 output: PathBuf,
52
53 /// Compression algorithm (lz4, zstd, none)
54 #[arg(long, default_value = "lz4")]
55 compression: String,
56
57 /// Enable encryption
58 #[arg(long)]
59 encrypt: bool,
60
61 /// Train compression dictionary
62 #[arg(long)]
63 train_dict: bool,
64
65 /// Block size in bytes (must be > 0)
66 #[arg(long, default_value_t = 65536, value_parser = clap::value_parser!(u32).range(1..))]
67 block_size: u32,
68
69 /// Enable content-defined chunking (CDC)
70 #[arg(long)]
71 cdc: bool,
72
73 /// Minimum chunk size for CDC
74 #[arg(long, default_value_t = 16384, value_parser = clap::value_parser!(u32).range(1..))]
75 min_chunk: u32,
76
77 /// Average chunk size for CDC
78 #[arg(long, default_value_t = 65536, value_parser = clap::value_parser!(u32).range(1..))]
79 avg_chunk: u32,
80
81 /// Maximum chunk size for CDC
82 #[arg(long, default_value_t = 131072, value_parser = clap::value_parser!(u32).range(1..))]
83 max_chunk: u32,
84
85 /// Suppress all output and progress bars
86 #[arg(long, short)]
87 silent: bool,
88 },
89
90 /// Inspect archive metadata
91 Info {
92 /// Path to archive
93 snap: PathBuf,
94
95 /// Output as JSON
96 #[arg(long)]
97 json: bool,
98 },
99
100 /// Show differences in overlay
101 #[cfg(feature = "diagnostics")]
102 Diff {
103 /// Path to overlay
104 overlay: PathBuf,
105
106 /// Show block-level differences
107 #[arg(long)]
108 blocks: bool,
109
110 /// Show file-level differences
111 #[arg(long)]
112 files: bool,
113 },
114
115 /// Build archive from source directory
116 Build {
117 /// Source directory
118 #[arg(long)]
119 source: PathBuf,
120
121 /// Optional memory dump
122 #[arg(long)]
123 memory: Option<PathBuf>,
124
125 /// Output archive path
126 #[arg(short, long)]
127 output: PathBuf,
128
129 /// Build profile
130 #[arg(long)]
131 profile: Option<String>,
132
133 /// Enable encryption
134 #[arg(long)]
135 encrypt: bool,
136
137 /// Enable CDC
138 #[arg(long)]
139 cdc: bool,
140 },
141
142 /// Analyze archive structure
143 #[cfg(feature = "diagnostics")]
144 Analyze {
145 /// Archive to analyze
146 input: PathBuf,
147 },
148
149 /// Convert external formats to Hexz snapshot
150 Convert {
151 /// Source format (tar, hdf5, webdataset)
152 format: String,
153
154 /// Input file path
155 input: PathBuf,
156
157 /// Output snapshot path (.hxz)
158 output: PathBuf,
159
160 /// Compression algorithm (lz4, zstd)
161 #[arg(long, default_value = "lz4")]
162 compression: String,
163
164 /// Block size in bytes
165 #[arg(long, default_value_t = 65536)]
166 block_size: u32,
167
168 /// Build profile (ml, eda, embedded, generic, archival)
169 #[arg(long)]
170 profile: Option<String>,
171
172 /// Suppress output
173 #[arg(long, short)]
174 silent: bool,
175 },
176}
177
178#[derive(Subcommand)]
179pub enum VmCommands {
180 /// Boot a virtual machine from snapshot
181 #[cfg(feature = "fuse")]
182 Boot {
183 /// Snapshot to boot from
184 snap: String,
185
186 /// RAM size (e.g., "4G")
187 #[arg(long)]
188 ram: Option<String>,
189
190 /// Disable KVM acceleration
191 #[arg(long)]
192 no_kvm: bool,
193
194 /// Network mode (user, bridge, none)
195 #[arg(long, default_value = "user")]
196 network: String,
197
198 /// Hypervisor backend (qemu, firecracker)
199 #[arg(long, default_value = "qemu")]
200 backend: String,
201
202 /// Persistent overlay path
203 #[arg(long)]
204 persist: Option<PathBuf>,
205
206 /// QMP socket path for control
207 #[arg(long)]
208 qmp_socket: Option<PathBuf>,
209
210 /// Disable graphics (headless mode)
211 #[arg(long)]
212 no_graphics: bool,
213
214 /// Enable VNC server
215 #[arg(long)]
216 vnc: bool,
217 },
218
219 /// Install OS from ISO to snapshot
220 #[cfg(feature = "fuse")]
221 Install {
222 /// Path to ISO image
223 #[arg(long)]
224 iso: PathBuf,
225
226 /// Virtual disk size (e.g., "10G")
227 #[arg(long, default_value = "10G")]
228 disk_size: String,
229
230 /// RAM size (e.g., "4G")
231 #[arg(long, default_value = "4G")]
232 ram: String,
233
234 /// Output snapshot path
235 #[arg(short, long)]
236 output: PathBuf,
237
238 /// Disable graphics
239 #[arg(long)]
240 no_graphics: bool,
241
242 /// Enable VNC
243 #[arg(long)]
244 vnc: bool,
245
246 /// Enable CDC
247 #[arg(long)]
248 cdc: bool,
249 },
250
251 /// Create snapshot via QMP
252 #[cfg(unix)]
253 Snap {
254 /// QMP socket path
255 #[arg(long)]
256 socket: PathBuf,
257
258 /// Base snapshot
259 #[arg(long)]
260 base: PathBuf,
261
262 /// Overlay path
263 #[arg(long)]
264 overlay: PathBuf,
265
266 /// Output snapshot
267 #[arg(short, long)]
268 output: PathBuf,
269 },
270
271 /// Commit overlay changes to new snapshot
272 Commit {
273 /// Base snapshot
274 base: PathBuf,
275
276 /// Overlay with changes
277 overlay: PathBuf,
278
279 /// Output snapshot
280 output: PathBuf,
281
282 /// Compression algorithm
283 #[arg(long, default_value = "lz4")]
284 compression: String,
285
286 /// Block size (must be > 0)
287 #[arg(long, default_value_t = 65536, value_parser = clap::value_parser!(u32).range(1..))]
288 block_size: u32,
289
290 /// Keep overlay file after commit
291 #[arg(long)]
292 keep_overlay: bool,
293
294 /// Flatten all layers into single archive
295 #[arg(long)]
296 flatten: bool,
297
298 /// Commit message
299 #[arg(long)]
300 message: Option<String>,
301
302 /// Create thin snapshot (reference base)
303 #[arg(long)]
304 thin: bool,
305 },
306
307 /// Mount snapshot as filesystem
308 #[cfg(feature = "fuse")]
309 Mount {
310 /// Snapshot to mount
311 snap: String,
312
313 /// Mount point directory
314 mountpoint: PathBuf,
315
316 /// Overlay for writes
317 #[arg(long)]
318 overlay: Option<PathBuf>,
319
320 /// Run as daemon
321 #[arg(short, long)]
322 daemon: bool,
323
324 /// Enable read-write mode
325 #[arg(long)]
326 rw: bool,
327
328 /// Cache size (e.g., "1G")
329 #[arg(long)]
330 cache_size: Option<String>,
331
332 /// User ID for files
333 #[arg(long, default_value_t = 1000)]
334 uid: u32,
335
336 /// Group ID for files
337 #[arg(long, default_value_t = 1000)]
338 gid: u32,
339
340 /// Export as NBD device
341 #[arg(long)]
342 nbd: bool,
343 },
344
345 /// Unmount filesystem
346 #[cfg(feature = "fuse")]
347 Unmount {
348 /// Mount point to unmount
349 mountpoint: PathBuf,
350 },
351}
352
353#[derive(Subcommand)]
354pub enum SysCommands {
355 /// Run system diagnostics
356 #[cfg(feature = "diagnostics")]
357 Doctor,
358
359 /// Benchmark archive performance
360 #[cfg(feature = "diagnostics")]
361 Bench {
362 /// Archive to benchmark
363 image: PathBuf,
364
365 /// Block size for testing
366 #[arg(long)]
367 block_size: Option<u32>,
368
369 /// Duration in seconds
370 #[arg(long)]
371 duration: Option<u64>,
372
373 /// Number of threads
374 #[arg(long)]
375 threads: Option<usize>,
376 },
377
378 /// Serve archive over network
379 #[cfg(feature = "server")]
380 Serve {
381 /// Snapshot to serve
382 snap: String,
383
384 /// Server port
385 #[arg(long, default_value_t = 8080)]
386 port: u16,
387
388 /// Run as daemon
389 #[arg(short, long)]
390 daemon: bool,
391
392 /// Enable NBD protocol
393 #[arg(long)]
394 nbd: bool,
395
396 /// Enable S3-compatible API
397 #[arg(long)]
398 s3: bool,
399 },
400
401 /// Generate signing keys
402 #[cfg(feature = "signing")]
403 Keygen {
404 /// Output directory for keys
405 #[arg(short, long)]
406 output_dir: Option<PathBuf>,
407 },
408
409 /// Sign archive
410 #[cfg(feature = "signing")]
411 Sign {
412 /// Private key path
413 #[arg(long)]
414 key: PathBuf,
415
416 /// Archive to sign
417 image: PathBuf,
418 },
419
420 /// Verify archive signature
421 #[cfg(feature = "signing")]
422 Verify {
423 /// Public key path
424 #[arg(long)]
425 key: PathBuf,
426
427 /// Archive to verify
428 image: PathBuf,
429 },
430}