muster_cli/cli.rs
1//! CLI type definitions for muster.
2//!
3//! This module defines the clap command structure used by the muster binary.
4//! It is exposed as a library target so that tools like `clap-markdown` can
5//! generate documentation from the type definitions.
6
7use std::path::PathBuf;
8
9use clap::{Parser, Subcommand};
10
11/// Terminal session group management built on tmux.
12///
13/// Muster organizes terminal sessions into named, color-coded groups with saved
14/// profiles, runtime theming, and push-based state synchronization via tmux
15/// control mode.
16#[derive(Parser)]
17#[command(name = "muster", version, about = "Terminal session group management")]
18pub struct Cli {
19 /// Path to the config directory
20 #[arg(long, env = "MUSTER_CONFIG_DIR")]
21 pub config_dir: Option<PathBuf>,
22
23 /// Output in JSON format
24 #[arg(long, global = true)]
25 pub json: bool,
26
27 #[command(subcommand)]
28 pub command: Command,
29}
30
31/// Top-level commands.
32#[derive(Subcommand)]
33pub enum Command {
34 /// List profiles and running sessions
35 List,
36
37 /// Create or attach to a profile's session
38 #[command(alias = "launch")]
39 Up {
40 /// Profile name or ID
41 profile: String,
42 /// Switch to this tab index on attach
43 #[arg(long)]
44 tab: Option<u32>,
45 /// Create session but don't attach
46 #[arg(long)]
47 detach: bool,
48 },
49
50 /// Attach to a running session
51 #[command(hide = true)]
52 Attach {
53 /// Profile name, ID, or session name
54 session: String,
55 /// Tab index to switch to
56 #[arg(long)]
57 tab: Option<u32>,
58 },
59
60 /// Destroy a session
61 #[command(alias = "kill")]
62 Down {
63 /// Profile name, ID, or session name
64 session: String,
65 },
66
67 /// Create an ad-hoc session
68 New {
69 /// Display name
70 name: String,
71 /// Tab definition (`name:cwd[:command]`), repeatable
72 #[arg(long)]
73 tab: Vec<String>,
74 /// Color (hex)
75 #[arg(long, default_value = "#808080")]
76 color: String,
77 /// Create session but don't attach
78 #[arg(long)]
79 detach: bool,
80 },
81
82 /// Manage session colors
83 #[command(alias = "colour")]
84 Color {
85 /// Profile name, ID, or session name
86 session: Option<String>,
87 /// New color (hex or named)
88 color: Option<String>,
89 /// List available named colors
90 #[arg(long)]
91 list: bool,
92 },
93
94 /// Show processes running inside sessions
95 Ps {
96 /// Profile name or ID (shows all sessions if omitted)
97 profile: Option<String>,
98 },
99
100 /// Show listening ports inside sessions
101 Ports {
102 /// Profile name or ID (shows all sessions if omitted)
103 profile: Option<String>,
104 },
105
106 /// Show resource usage (CPU, memory, GPU) for session processes
107 Top {
108 /// Profile name or ID (shows all sessions if omitted)
109 profile: Option<String>,
110 },
111
112 /// Show all sessions with details
113 Status,
114
115 /// Peek at recent terminal output
116 Peek {
117 /// Profile name, ID, or session name
118 session: String,
119 /// Tab names to show (all if omitted)
120 #[arg(value_name = "TABS")]
121 tabs: Vec<String>,
122 /// Lines of output per tab
123 #[arg(short = 'n', long, default_value = "50")]
124 lines: u32,
125 },
126
127 /// Pin the current tab to the session's profile
128 Pin,
129
130 /// Unpin the current tab from the session's profile
131 Unpin,
132
133 /// Sync a window rename to the profile (called by tmux hook)
134 #[command(hide = true)]
135 SyncRename {
136 /// Session name
137 session: String,
138 /// Window index
139 window: u32,
140 /// New window name
141 name: String,
142 },
143
144 /// Handle pane death notification (called by tmux hook)
145 #[command(name = "_pane-died", hide = true)]
146 PaneDied {
147 session_name: String,
148 window_name: String,
149 pane_id: String,
150 exit_code: i32,
151 },
152
153 /// Handle bell notification (called by tmux hook)
154 #[command(name = "_bell", hide = true)]
155 Bell {
156 session_name: String,
157 window_name: String,
158 },
159
160 /// Profile management
161 Profile {
162 #[command(subcommand)]
163 action: ProfileAction,
164 },
165
166 /// Notification management
167 Notifications {
168 #[command(subcommand)]
169 action: NotificationAction,
170 },
171
172 /// Release a muster-managed session back to plain tmux
173 Release {
174 /// Profile name, ID, or session name
175 session: String,
176 /// New name for the released session (defaults to session name without muster_ prefix)
177 #[arg(long)]
178 name: Option<String>,
179 },
180
181 /// Adopt an existing tmux session under muster management
182 Adopt {
183 /// Existing tmux session name
184 session: String,
185 /// Display name (defaults to session name)
186 #[arg(long)]
187 name: Option<String>,
188 /// Color (hex or named)
189 #[arg(long, default_value = "#808080")]
190 color: String,
191 /// Also save as a persistent profile
192 #[arg(long)]
193 save: bool,
194 /// Adopt without attaching
195 #[arg(long)]
196 detach: bool,
197 },
198
199 /// Output shell integration code for automatic profile suggestions on cd
200 #[command(name = "shell-init")]
201 ShellInit {
202 /// Shell type: fish, bash, or zsh
203 shell: String,
204 },
205
206 /// Suggest profiles matching a directory (used by shell integration)
207 #[command(name = "shell-suggest", hide = true)]
208 ShellSuggest {
209 /// Directory path to match against profile CWDs
210 dir: String,
211 },
212
213 /// Show or update settings
214 Settings {
215 /// Set terminal emulator (e.g. ghostty, alacritty, kitty, wezterm, terminal, iterm2)
216 #[arg(long)]
217 terminal: Option<String>,
218 /// Set default shell
219 #[arg(long)]
220 shell: Option<String>,
221 /// Set tmux binary path
222 #[arg(long)]
223 tmux_path: Option<String>,
224 },
225}
226
227/// Profile subcommands.
228#[derive(Subcommand)]
229pub enum ProfileAction {
230 /// List all profiles
231 List,
232
233 /// Delete a profile
234 Delete {
235 /// Profile name or ID
236 id: String,
237 },
238
239 /// Save a new profile (or snapshot a running session with --from-session)
240 Save {
241 /// Profile name
242 name: String,
243 /// Tab definition (`name:cwd[:command]`), repeatable
244 #[arg(long)]
245 tab: Vec<String>,
246 /// Color (hex or named)
247 #[arg(long, default_value = "#808080")]
248 color: String,
249 /// Snapshot tabs from a running tmux session
250 #[arg(long, value_name = "SESSION")]
251 from_session: Option<String>,
252 },
253
254 /// Add a tab to an existing profile
255 AddTab {
256 /// Profile name or ID
257 profile: String,
258 /// Tab name
259 #[arg(long)]
260 name: String,
261 /// Working directory
262 #[arg(long)]
263 cwd: String,
264 /// Startup command
265 #[arg(long)]
266 command: Option<String>,
267 },
268
269 /// Show a profile's full definition
270 Show {
271 /// Profile name or ID
272 id: String,
273 },
274
275 /// Edit a profile in $EDITOR
276 Edit {
277 /// Profile name or ID
278 id: String,
279 },
280
281 /// Update profile fields inline
282 Update {
283 /// Profile name or ID
284 id: String,
285 /// New display name
286 #[arg(long)]
287 name: Option<String>,
288 /// New color (hex or named)
289 #[arg(long)]
290 color: Option<String>,
291 },
292
293 /// Remove a tab from a profile
294 RemoveTab {
295 /// Profile name or ID
296 profile: String,
297 /// Tab name or 0-based index
298 tab: String,
299 },
300}
301
302/// Notification subcommands.
303#[derive(Subcommand)]
304pub enum NotificationAction {
305 /// Install macOS notification app bundle
306 Setup,
307 /// Remove macOS notification app bundle
308 Remove,
309 /// Send a test notification to verify the notification system works
310 Test,
311}