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    Bootstrap(BootstrapCommand),
54    Audit(AuditCommand),
55}
56
57#[derive(Debug, Clone, Args)]
58pub struct InitCommand {
59    #[arg(long)]
60    pub force: bool,
61
62    #[arg(long)]
63    pub preset: Option<String>,
64
65    #[arg(long)]
66    pub output: Option<PathBuf>,
67
68    /// Launch an interactive wizard to generate sbox.yaml
69    #[arg(long, short = 'i')]
70    pub interactive: bool,
71}
72
73#[derive(Debug, Clone, Args)]
74#[command(trailing_var_arg = true)]
75pub struct RunCommand {
76    #[arg(required = true, num_args = 1.., allow_hyphen_values = true)]
77    pub command: Vec<String>,
78}
79
80#[derive(Debug, Clone, Args)]
81#[command(trailing_var_arg = true)]
82pub struct ExecCommand {
83    pub profile: String,
84
85    #[arg(required = true, num_args = 1.., allow_hyphen_values = true)]
86    pub command: Vec<String>,
87}
88
89#[derive(Debug, Clone, Args, Default)]
90pub struct ShellCommand {
91    #[arg(long)]
92    pub shell: Option<String>,
93}
94
95#[derive(Debug, Clone, Args)]
96#[command(trailing_var_arg = true)]
97pub struct PlanCommand {
98    #[arg(long)]
99    pub show_command: bool,
100
101    /// Omit to show the policy for the profile selected by --profile without a specific command.
102    #[arg(num_args = 0.., allow_hyphen_values = true)]
103    pub command: Vec<String>,
104}
105
106#[derive(Debug, Clone, Args, Default)]
107pub struct DoctorCommand {
108    #[arg(long)]
109    pub strict: bool,
110}
111
112#[derive(Debug, Clone, Args, Default)]
113pub struct CleanCommand {
114    #[arg(long)]
115    pub sessions: bool,
116
117    #[arg(long)]
118    pub images: bool,
119
120    #[arg(long)]
121    pub caches: bool,
122
123    #[arg(long)]
124    pub all: bool,
125
126    #[arg(long = "global")]
127    pub global_scope: bool,
128}
129
130#[derive(Debug, Clone, Copy, ValueEnum)]
131pub enum CliBackendKind {
132    Podman,
133    Docker,
134}
135
136#[derive(Debug, Clone, Copy, ValueEnum)]
137pub enum CliExecutionMode {
138    Host,
139    Sandbox,
140}
141
142/// Scan the project's lockfile for known-malicious or vulnerable package versions.
143/// Delegates to the ecosystem's native audit tool (npm audit, cargo audit, etc.)
144/// and runs on the host (not in a sandbox) so it can reach advisory databases.
145#[derive(Debug, Clone, Args, Default)]
146pub struct AuditCommand {
147    /// Extra arguments forwarded to the underlying audit tool.
148    #[arg(num_args = 0.., allow_hyphen_values = true)]
149    pub extra_args: Vec<String>,
150}
151
152/// Generate the package lockfile inside the sandbox without running install scripts.
153/// Requires `package_manager:` to be configured in sbox.yaml.
154/// After bootstrap, run `sbox run -- <rebuild-command>` to execute scripts with network off.
155#[derive(Debug, Clone, Args, Default)]
156pub struct BootstrapCommand {}
157
158#[derive(Debug, Clone, Args)]
159pub struct ShimCommand {
160    /// Directory to write shim scripts into (default: ~/.local/bin)
161    #[arg(long)]
162    pub dir: Option<PathBuf>,
163
164    /// Overwrite existing shim files
165    #[arg(long)]
166    pub force: bool,
167
168    /// Print what would be created without writing anything
169    #[arg(long)]
170    pub dry_run: bool,
171}