use crate::commands::{
ByCommand, ForCommand, FreeCommand, FreezeCommand, InCommand, InfoCommand, KillCommand,
ListCommand, OnCommand, OrphansCommand, PortsCommand, StopCommand, StuckCommand, ThawCommand,
TreeCommand, UnstickCommand, WaitCommand, WatchCommand, WhyCommand,
};
use clap::{Parser, Subcommand};
use clap_complete::Shell;
const VERSION_INFO: &str = concat!(
env!("PROC_VERSION"),
"\nhttps://github.com/yazeed/proc-cli",
"\nLicense: MIT"
);
#[derive(Parser)]
#[command(name = "proc")]
#[command(author, version = VERSION_INFO, about, long_about = None)]
#[command(propagate_version = true)]
#[command(
after_help = "Targets: :port, PID, or process name. Give several as separate arguments.
Run 'proc --help' for examples or visit https://github.com/yazeed/proc-cli"
)]
#[command(after_long_help = "EXAMPLES:
Port/Process Lookup:
proc on :3000 What's on port 3000?
proc on :3000 :8080 What's on several ports?
proc on node What ports are the processes named node using?
Find by File:
proc for ./server Processes running this program (or holding it open)
proc for /usr/bin/node Processes running this executable
proc for app.log What has this file open? (not searched on Windows)
Filter by Name:
proc by node Processes named 'node' (the whole name)
proc by node --cmd Anything with 'node' in its name or command line
proc by node --in . Node processes in current directory
proc by node --min-cpu 5 Node processes using >5% CPU
Filter by Directory:
proc in . Processes in current directory
proc in . --by node Node processes in cwd
List All:
proc list All processes
proc list --min-cpu 10 Processes using >10% CPU
Info/Kill/Stop (multi-target):
proc info :3000 :8080 Info for several targets
proc kill :3000 node Kill port 3000 and the processes named node
proc kill serve --cmd Kill processes with 'serve' in their command line
proc kill 1234 5678 :8080 Kill two PIDs and whatever is on 8080
proc stop :3000 :8080 Stop several targets gracefully
Watch (Real-Time):
proc watch Watch all processes (alias: proc top)
proc watch node Watch the processes named node
proc watch :3000 Watch process on port 3000
proc watch :3000 :8080 node Watch several targets
proc watch -n 1 --sort mem 1s refresh, sorted by memory
proc watch --in . --by node Node processes in current directory
Freeze/Thaw:
proc freeze node Pause the processes named node (SIGSTOP)
proc freeze :3000 --yes Freeze by port, skip confirm
proc thaw node Resume frozen processes (SIGCONT)
Free Ports:
proc free :3000 Kill process, verify port freed
proc free :3000 :8080 --yes Free several ports
Diagnostics:
proc why :3000 Why is port 3000 busy? (ancestry)
proc orphans Find orphaned processes
proc orphans --kill Find and kill orphans
Wait:
proc wait node Wait until node processes exit
proc wait 1234 5678 Wait until both exit
proc wait :3000 --timeout 60 Wait up to 60s for port to free
proc wait node -n 10 -q Check every 10s, quiet mode
Other:
proc ports List all listening TCP ports
proc tree --min-cpu 5 Process tree filtered by CPU
proc stuck Find hung processes
proc unstick --force Recover or terminate stuck processes
proc stop nginx --signal USR1 Send a different first signal (force-killed after --timeout if it lives)
Targets: :port, PID, or process name. Give several as separate arguments.
A name matches the process name, the file name of its executable or the file name
of its first argument, ignoring case (like pkill -x, but case-insensitive):
'node' does not match 'Claude Helper'. Add --cmd to match any part of the name
or the full command line instead (like pkill -f). A path is not a name: use
--cmd, or 'proc for <file>' for an executable. proc doesn't expand wildcards;
an unquoted node* is expanded by your shell into file names; use --cmd for
partial matches.
Comma-separated targets (:3000,:8080) still work but are deprecated and will be
removed in a future major release; they print a note on stderr (not with --json).
--in takes the next word as its directory unless that word starts with '-':
put it after the targets, or write --in=DIR.
For more information, visit: https://github.com/yazeed/proc-cli")]
pub struct Cli {
#[command(subcommand)]
pub command: Option<Commands>,
}
#[derive(Subcommand)]
pub enum Commands {
#[command(visible_alias = ":")]
On(OnCommand),
#[command(visible_alias = "f")]
For(ForCommand),
#[command(visible_alias = "b")]
By(ByCommand),
In(InCommand),
#[command(visible_aliases = ["l", "ps"])]
List(ListCommand),
#[command(visible_aliases = ["i", "inspect"])]
Info(InfoCommand),
#[command(visible_alias = "p")]
Ports(PortsCommand),
#[command(visible_alias = "k")]
Kill(KillCommand),
#[command(visible_alias = "s")]
Stop(StopCommand),
#[command(visible_alias = "t")]
Tree(TreeCommand),
#[command(visible_aliases = ["w", "top"])]
Watch(WatchCommand),
#[command(visible_alias = "x")]
Stuck(StuckCommand),
#[command(visible_alias = "u")]
Unstick(UnstickCommand),
Freeze(FreezeCommand),
Thaw(ThawCommand),
#[command(visible_alias = "o")]
Orphans(OrphansCommand),
Why(WhyCommand),
Free(FreeCommand),
Wait(WaitCommand),
#[command(hide = true)]
Completions {
#[arg(value_enum)]
shell: Shell,
},
#[command(hide = true)]
Manpage,
}