1use crate::commands::{
7 ByCommand, ForCommand, FreeCommand, FreezeCommand, InCommand, InfoCommand, KillCommand,
8 ListCommand, OnCommand, OrphansCommand, PortsCommand, StopCommand, StuckCommand, ThawCommand,
9 TreeCommand, UnstickCommand, WaitCommand, WatchCommand, WhyCommand,
10};
11use clap::{Parser, Subcommand};
12use clap_complete::Shell;
13
14const VERSION_INFO: &str = concat!(
15 env!("PROC_VERSION"),
16 "\nhttps://github.com/yazeed/proc-cli",
17 "\nLicense: MIT"
18);
19
20#[derive(Parser)]
22#[command(name = "proc")]
23#[command(author, version = VERSION_INFO, about, long_about = None)]
24#[command(propagate_version = true)]
25#[command(
26 after_help = "Targets: :port, PID, or process name. Give several as separate arguments.
27Run 'proc --help' for examples or visit https://github.com/yazeed/proc-cli"
28)]
29#[command(after_long_help = "EXAMPLES:
30
31 Port/Process Lookup:
32 proc on :3000 What's on port 3000?
33 proc on :3000 :8080 What's on several ports?
34 proc on node What ports are the processes named node using?
35
36 Find by File:
37 proc for ./server Processes running this program (or holding it open)
38 proc for /usr/bin/node Processes running this executable
39 proc for app.log What has this file open? (not searched on Windows)
40
41 Filter by Name:
42 proc by node Processes named 'node' (the whole name)
43 proc by node --cmd Anything with 'node' in its name or command line
44 proc by node --in . Node processes in current directory
45 proc by node --min-cpu 5 Node processes using >5% CPU
46
47 Filter by Directory:
48 proc in . Processes in current directory
49 proc in . --by node Node processes in cwd
50
51 List All:
52 proc list All processes
53 proc list --min-cpu 10 Processes using >10% CPU
54
55 Info/Kill/Stop (multi-target):
56 proc info :3000 :8080 Info for several targets
57 proc kill :3000 node Kill port 3000 and the processes named node
58 proc kill serve --cmd Kill processes with 'serve' in their command line
59 proc kill 1234 5678 :8080 Kill two PIDs and whatever is on 8080
60 proc stop :3000 :8080 Stop several targets gracefully
61
62 Watch (Real-Time):
63 proc watch Watch all processes (alias: proc top)
64 proc watch node Watch the processes named node
65 proc watch :3000 Watch process on port 3000
66 proc watch :3000 :8080 node Watch several targets
67 proc watch -n 1 --sort mem 1s refresh, sorted by memory
68 proc watch --in . --by node Node processes in current directory
69
70 Freeze/Thaw:
71 proc freeze node Pause the processes named node (SIGSTOP)
72 proc freeze :3000 --yes Freeze by port, skip confirm
73 proc thaw node Resume frozen processes (SIGCONT)
74
75 Free Ports:
76 proc free :3000 Kill process, verify port freed
77 proc free :3000 :8080 --yes Free several ports
78
79 Diagnostics:
80 proc why :3000 Why is port 3000 busy? (ancestry)
81 proc orphans Find orphaned processes
82 proc orphans --kill Find and kill orphans
83
84 Wait:
85 proc wait node Wait until node processes exit
86 proc wait 1234 5678 Wait until both exit
87 proc wait :3000 --timeout 60 Wait up to 60s for port to free
88 proc wait node -n 10 -q Check every 10s, quiet mode
89
90 Other:
91 proc ports List all listening TCP ports
92 proc tree --min-cpu 5 Process tree filtered by CPU
93 proc stuck Find hung processes
94 proc unstick --force Recover or terminate stuck processes
95 proc stop nginx --signal USR1 Send a different first signal (force-killed after --timeout if it lives)
96
97Targets: :port, PID, or process name. Give several as separate arguments.
98A name matches the process name, the file name of its executable or the file name
99of its first argument, ignoring case (like pkill -x, but case-insensitive):
100'node' does not match 'Claude Helper'. Add --cmd to match any part of the name
101or the full command line instead (like pkill -f). A path is not a name: use
102--cmd, or 'proc for <file>' for an executable. proc doesn't expand wildcards;
103an unquoted node* is expanded by your shell into file names; use --cmd for
104partial matches.
105Comma-separated targets (:3000,:8080) still work but are deprecated and will be
106removed in a future major release; they print a note on stderr (not with --json).
107--in takes the next word as its directory unless that word starts with '-':
108put it after the targets, or write --in=DIR.
109For more information, visit: https://github.com/yazeed/proc-cli")]
110pub struct Cli {
111 #[command(subcommand)]
113 pub command: Option<Commands>,
114}
115
116#[derive(Subcommand)]
118pub enum Commands {
119 #[command(visible_alias = ":")]
121 On(OnCommand),
122
123 #[command(visible_alias = "f")]
125 For(ForCommand),
126
127 #[command(visible_alias = "b")]
129 By(ByCommand),
130
131 In(InCommand),
133
134 #[command(visible_aliases = ["l", "ps"])]
136 List(ListCommand),
137
138 #[command(visible_aliases = ["i", "inspect"])]
140 Info(InfoCommand),
141
142 #[command(visible_alias = "p")]
144 Ports(PortsCommand),
145
146 #[command(visible_alias = "k")]
148 Kill(KillCommand),
149
150 #[command(visible_alias = "s")]
152 Stop(StopCommand),
153
154 #[command(visible_alias = "t")]
156 Tree(TreeCommand),
157
158 #[command(visible_aliases = ["w", "top"])]
160 Watch(WatchCommand),
161
162 #[command(visible_alias = "x")]
164 Stuck(StuckCommand),
165
166 #[command(visible_alias = "u")]
168 Unstick(UnstickCommand),
169
170 Freeze(FreezeCommand),
172
173 Thaw(ThawCommand),
175
176 #[command(visible_alias = "o")]
178 Orphans(OrphansCommand),
179
180 Why(WhyCommand),
182
183 Free(FreeCommand),
185
186 Wait(WaitCommand),
188
189 #[command(hide = true)]
191 Completions {
192 #[arg(value_enum)]
194 shell: Shell,
195 },
196
197 #[command(hide = true)]
199 Manpage,
200}