Documentation menu
CLI walkthrough
CLIHeadless commands for tables, JSON, filters, process inspection, and scoped termination.
Use a named subcommand to stay in the CLI. Commands never open the TUI. They print to stdout or stderr and return a stable code.
There are five subcommands on every platform: list, inspect, kill, watch, and why. Only
kill ever signals anything. Windows supports read-only inspect and CLI --tree; --group
stays Linux/macOS-only. Use whichever binary you like • kick is shorter.
Listing ports
The table is plain, whitespace-separated text with no box-drawing • so it stays friendly to
grep and awk. Withheld metadata shows as -. The LABEL column appears once you’ve configured
endpoint labels.
Below the table, notes on stderr explain what the table can’t. A - in the PID column gets a
reason: the socket belongs to another user whose processes you can’t read (named by account on
Linux, for example root (uid 0)), its owner wasn’t attributed, or no readable process holds it at
all, which is normal for kernel-held sockets. On Linux, processes whose executable was deleted or
replaced after they started are listed with the original path, a common sign of a stale build or a
leftover from a package upgrade. Stdout stays a clean table.
Human-readable endpoints retain IPv6 interface scope, for example [fe80::1%3]:5353, throughout
the list table, TUI, inspect, watch, Why, search, diagnostics, and kill confirmations.
%unavailable means the native collector could not report an interface index, which is expected
for IPv6 observations on Linux and macOS; it is not part of the literal address or an error. Legacy
list --json remains unchanged; versioned structured output carries scope separately.
Narrowing the list
kick list --port 3000
kick list --process node
kick list --filter scope:public
kick list --filter 'label:web family:ipv4'
kick list --sort pid--port PORT• only the rows bound to one exact port.--process TEXT• rows whose process name contains the text.--filter TEXT• TUI-style search text or structured filters (see filters).--sort MODE•port,pid,protocol,process,parent, orscope.
JSON for scripts
list --json prints a stable, documented shape • the field names and enum casing are a contract,
so it’s safe to parse.
[
{
"protocol": "tcp",
"local_addr": "127.0.0.1",
"local_port": 3000,
"state": "listen",
"pid": 18422,
"process_name": "node",
"executable_path": "/usr/bin/node",
"command_line": "node server.js",
"parent_pid": 18001,
"parent_process_name": "cursor-agent",
"child_pids": [],
"protected": false,
"platform": "linux",
"permission": "full",
"label": "web dev"
}
]
Missing metadata is null, never an empty string. An empty result is always [].
For the complete in-scope observation • every native TCP state, owner identity, completeness, and
evidence gap • use --snapshot-json instead:
kick list --snapshot-jsonSnapshot mode deliberately ignores --port, --process, --filter, --sort, and
hide_system_processes, and omits full command lines. See
Structured output.
Killing by port or PID
kill takes ports or PIDs • one target, or several at once • and asks before it does anything.
A delivered signal is not an exit, and a closed listener isn’t one either. After delivery, kill
waits up to two seconds and reports both facts on their own lines. A server that closes its
listener but keeps running gets a warning that it’s still running, with the exact command that
sends SIGKILL. While the process still owns its port that’s kick kill --pid PID --force. Once
the port is closed, a plain --pid kill no longer applies, so the hint is
kick kill --pid PID --tree --force, which also stops the process’s children. The exit code still
means the signal was accepted.
On Linux, an unprivileged kill --port usually can’t prove the visible owner is the port’s only
holder, because other users’ processes can’t be read and one of them could share the socket. It’s
refused before any prompt, and the error names the owner and the kick kill --pid PID command that
works.
kick kill --port 3000
kick kill --pid 18422
kick kill --port 3000 --yes
kick kill --pid 18422 --force--force• stronger force confirmation; Unix useskill -9, while Windows delivery is hard termination either way.--yes• skip the normal prompt for a target you already trust.
Several targets at once
Repeat --pid or --port, or separate values with commas, to clean up to 128 processes in one
command. Every target is resolved first; if any of them can’t be resolved, is protected, or can’t be
proven to own its port, Kickoutchi lists the refusals and sends nothing. Otherwise you get one
banner, one prompt, and one summary line. Only failures, survivors, and ports that stayed visible
get their own lines.
Each target keeps every single-process check. The exit code is the most serious outcome across
targets. --tree and --group still take one target.
On Linux and macOS, Ctrl-C during a kill waits for frozen-process cleanup. If delivery has not started, Kickoutchi aborts and resumes only processes it stopped; processes that were already stopped stay stopped. Once delivery starts, the bounded delivery and cleanup sequence finishes before the interrupt takes effect. This applies to single-process, tree, and group kills, and also handles SIGTERM and SIGHUP sent to the CLI.
Inspecting a process family
inspect is the read-only way to choose the right root before a scoped kill. It shows ancestors,
descendants, siblings, command lines, ports, and suggested tree commands. Linux/macOS also show
process-group members and --group hints.
kick inspect --port 3000
kick inspect --pid 18422Tree and group scope
Normal kill still targets one PID. --tree adds descendant cleanup on Linux, macOS, and Windows;
--group is the Linux/macOS-only POSIX process-group scope:
kick kill --port 3000 --tree
kick kill --pid 18422 --tree
kick kill --pid 18422 --group--tree• terminate the target and its descendants. Typetreeto confirm, orforcewith--force.--group• terminate every visible member of the target’s POSIX process group. Typegroupto confirm, orforcewith--force.--treeand--groupconflict; pick one scope.- Windows rejects
--groupand does not expose TUIt/Ttree keys. Windows CLI--treeuses Job Object containment and hard termination.
See Scoped kills for the Unix freeze-first and Windows Job Object safety details.
Watching and explaining
Two read-only commands answer questions list can’t:
kick why 3000
kick why 3000 --all-protocols --all-addresses --json
kick watch --tcp --port 3000
kick watch --filter state:listen --duration 30s --jsonwhy PORT• takes one snapshot, then attempts the exact bind and closes it immediately. It tells occupied, permission denied, address unavailable, and unsupported apart, with the evidence behind each verdict.watch• polls full-state snapshots and streamsbaseline,bind,release,replacement, andcollection_gapevents, as terminal output or NDJSON.
Neither one signals a process or runs Docker. Full walkthrough: Watch & Why.
How the CLI behaves
- An empty unfiltered list is success (exit
0) • a quiet machine isn’t an error. - An empty filtered result is no-match (exit
3) • sokick list --port 3000 && echo busyworks as an occupancy probe. kill --portrefuses ambiguous ports • if two PIDs own one port, it lists the candidates and asks you to pick with--pidinstead of guessing.- A port with no readable owner exits
4(permission denied) rather than pretending it can act, and says why, for example that the socket belongs to another user.
When a --port lookup finds no socket but a process mentions that port on its command line,
Kickoutchi prints a “possible related process” hint to stderr so JSON on stdout stays clean.
Next
Want the terse index of every flag, filter, and exit code? See the command reference. Parsing the output? See Structured output.