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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
use clap::{Parser, Subcommand};
use std::path::PathBuf;
/// warren — install any CLI tool unlimited times, fully isolated
#[derive(Parser, Debug)]
#[command(
name = "warren",
version,
about = "Install any CLI tool unlimited times. Every instance is its own world.",
long_about = "warren is a rootless CLI runtime that lets you install and run unlimited\nisolated instances of any CLI application — each with its own identity,\nconfiguration, and data.",
after_help = "Examples:\n warren dig \"curl -fsSL https://example.com/install | bash\" --as myapp\n warren dig flatpak:com.discordapp.Discord --as discord-work\n warren dig app:discord --as discord-home\n warren ls\n warren run myapp -- --help\n warren inspect myapp\n warren session save\n warren session restore"
)]
pub struct Cli {
#[command(subcommand)]
pub command: Command,
}
#[derive(Subcommand, Debug)]
pub enum Command {
/// Install a new instance from a source
Dig {
/// Install source: URL piped to shell, local script, package name,
/// or app source (flatpak:<id>, snap:<name>, apt:<pkg>, app:<name>,
/// desktop:<id>, or a bare Flathub id like com.discordapp.Discord)
source: String,
/// Alias for this instance
#[arg(long = "as", value_name = "ALIAS")]
alias: String,
/// Skip confirmation prompts
#[arg(long, short)]
yes: bool,
/// Treat as a graphical app (`.desktop` entry + detached run)
#[arg(long, conflicts_with = "no_gui")]
gui: bool,
/// Treat as a CLI app even if it looks graphical
#[arg(long, conflicts_with = "gui")]
no_gui: bool,
},
/// Run an installed instance
Run {
/// Instance alias to run
alias: String,
/// Arguments to pass to the application
#[arg(last = true)]
args: Vec<String>,
},
/// List all instances
Ls,
/// Inspect an instance
Inspect {
/// Instance alias to inspect
alias: String,
},
/// Remove an instance
Rm {
/// Instance alias to remove
alias: String,
/// Skip confirmation prompt
#[arg(long, short)]
yes: bool,
},
/// Update an instance by re-running its installer
Update {
/// Instance alias to update
alias: String,
/// Skip confirmation prompts
#[arg(long, short)]
yes: bool,
},
/// Clone an instance into a new one
Clone {
/// Source instance alias
source: String,
/// Destination alias for the clone
dest: String,
},
/// Export an instance to a portable archive
Export {
/// Instance alias to export
alias: String,
/// Output path for the archive
#[arg(long, short)]
out: Option<PathBuf>,
},
/// Import an instance from an archive
Import {
/// Path to the archive file
path: PathBuf,
/// Alias for the imported instance
#[arg(long = "as", value_name = "ALIAS")]
alias: Option<String>,
},
/// Show warren environment information
Env,
/// Save and restore your desktop workspace session
Session {
#[command(subcommand)]
action: SessionAction,
},
/// Manage shell integration
Shell {
#[command(subcommand)]
action: ShellAction,
},
}
#[derive(Subcommand, Debug)]
pub enum ShellAction {
/// Install shell integration (PATH setup)
Install,
/// Show current shell detection info
Info,
}
#[derive(Subcommand, Debug)]
pub enum SessionAction {
/// Save the current desktop session (apps, terminals, workdirs)
Save {
/// Snapshot name (default: session-YYYYMMDD-HHMMSS)
#[arg(long)]
name: Option<String>,
/// How many snapshots to keep; older ones are deleted
#[arg(long)]
keep: Option<usize>,
},
/// Restore a saved session with one command (default: latest)
Restore {
/// Snapshot name to restore (default: latest saved session)
#[arg(long)]
name: Option<String>,
/// Print the relaunch plan without starting anything
#[arg(long)]
dry_run: bool,
},
/// List saved sessions
Ls,
/// Delete a saved session
Rm {
/// Session name to delete
name: String,
/// Skip confirmation prompt
#[arg(long, short)]
yes: bool,
},
/// Delete old snapshots, keeping only the newest ones
Prune {
/// How many newest snapshots to keep
#[arg(long)]
keep: Option<usize>,
},
}