Skip to main content

sbox/
cli.rs

1use std::path::PathBuf;
2
3use clap::{Args, Parser, Subcommand, ValueEnum};
4
5#[derive(Debug, Clone, Parser)]
6#[command(
7    name = "sbox",
8    version,
9    about = "Policy-driven sandboxed command runner"
10)]
11pub struct Cli {
12    #[arg(long, global = true)]
13    pub config: Option<PathBuf>,
14
15    #[arg(long, global = true)]
16    pub workspace: Option<PathBuf>,
17
18    #[arg(long, global = true, value_enum)]
19    pub backend: Option<CliBackendKind>,
20
21    #[arg(long, global = true)]
22    pub image: Option<String>,
23
24    #[arg(long, global = true)]
25    pub profile: Option<String>,
26
27    #[arg(long, global = true, value_enum)]
28    pub mode: Option<CliExecutionMode>,
29
30    #[arg(short = 'v', long, global = true, action = clap::ArgAction::Count)]
31    pub verbose: u8,
32
33    #[arg(long, global = true)]
34    pub quiet: bool,
35
36    #[arg(long, global = true)]
37    pub strict_security: bool,
38
39    #[command(subcommand)]
40    pub command: Commands,
41}
42
43#[derive(Debug, Clone, Subcommand)]
44pub enum Commands {
45    Init(InitCommand),
46    Run(RunCommand),
47    Exec(ExecCommand),
48    Shell(ShellCommand),
49    Plan(PlanCommand),
50    Doctor(DoctorCommand),
51    Clean(CleanCommand),
52    Shim(ShimCommand),
53}
54
55#[derive(Debug, Clone, Args)]
56pub struct InitCommand {
57    #[arg(long)]
58    pub force: bool,
59
60    #[arg(long)]
61    pub preset: Option<String>,
62
63    #[arg(long)]
64    pub output: Option<PathBuf>,
65
66    /// Launch an interactive wizard to generate sbox.yaml
67    #[arg(long, short = 'i')]
68    pub interactive: bool,
69}
70
71#[derive(Debug, Clone, Args)]
72#[command(trailing_var_arg = true)]
73pub struct RunCommand {
74    #[arg(required = true, num_args = 1.., allow_hyphen_values = true)]
75    pub command: Vec<String>,
76}
77
78#[derive(Debug, Clone, Args)]
79#[command(trailing_var_arg = true)]
80pub struct ExecCommand {
81    pub profile: String,
82
83    #[arg(required = true, num_args = 1.., allow_hyphen_values = true)]
84    pub command: Vec<String>,
85}
86
87#[derive(Debug, Clone, Args, Default)]
88pub struct ShellCommand {
89    #[arg(long)]
90    pub shell: Option<String>,
91}
92
93#[derive(Debug, Clone, Args)]
94#[command(trailing_var_arg = true)]
95pub struct PlanCommand {
96    #[arg(long)]
97    pub show_command: bool,
98
99    /// Omit to show the policy for the profile selected by --profile without a specific command.
100    #[arg(num_args = 0.., allow_hyphen_values = true)]
101    pub command: Vec<String>,
102}
103
104#[derive(Debug, Clone, Args, Default)]
105pub struct DoctorCommand {
106    #[arg(long)]
107    pub strict: bool,
108}
109
110#[derive(Debug, Clone, Args, Default)]
111pub struct CleanCommand {
112    #[arg(long)]
113    pub sessions: bool,
114
115    #[arg(long)]
116    pub images: bool,
117
118    #[arg(long)]
119    pub caches: bool,
120
121    #[arg(long)]
122    pub all: bool,
123
124    #[arg(long = "global")]
125    pub global_scope: bool,
126}
127
128#[derive(Debug, Clone, Copy, ValueEnum)]
129pub enum CliBackendKind {
130    Podman,
131    Docker,
132}
133
134#[derive(Debug, Clone, Copy, ValueEnum)]
135pub enum CliExecutionMode {
136    Host,
137    Sandbox,
138}
139
140#[derive(Debug, Clone, Args)]
141pub struct ShimCommand {
142    /// Directory to write shim scripts into (default: ~/.local/bin)
143    #[arg(long)]
144    pub dir: Option<PathBuf>,
145
146    /// Overwrite existing shim files
147    #[arg(long)]
148    pub force: bool,
149
150    /// Print what would be created without writing anything
151    #[arg(long)]
152    pub dry_run: bool,
153}