Documentation menu
Safety
Target identity, confirmations, protected processes, and the checks applied before Kickoutchi sends a signal.
A port can change owners between inspection and termination. Kickoutchi resolves and checks the target again before signaling it. This page documents those checks and their limits.
Confirmations
Nothing is terminated without a confirmation step, and the prompt scales with the risk:
- Normal kill • type
y. - Force kill • type the word
force(unless you setconfirm_force_kill = false). - Tree kill • type
treefor normal scoped termination, orforcefor force tree kill. - Group kill • type
groupfor normal scoped termination, orforcefor force group kill. - Protected process • type the PID or the process name.
Before any prompt, Kickoutchi prints the target’s identity, the affected ports, the equivalent shell command, and any warnings.
Hard guardrails
- PID 0, PID 1, Kickoutchi’s own PID, and Windows PID 4 are blocked outright • they can’t be targeted at all.
kill --portrefuses ambiguous ports. If two PIDs own the same port, Kickoutchi lists the candidates and makes you choose with--pidinstead of guessing.- A port with no readable owner is not killable • it exits
4(permission denied) rather than acting on incomplete information. - Incomplete Linux ownership scans also block
kill --port. Even when one owner is visible, Kickoutchi signals nothing if restricted process visibility could hide a co-owner of that port. - Scoped kills are bounded. Over-cap or non-converging trees/groups refuse instead of partially killing a moving target.
Protected processes
Some processes are load-bearing: init, your database, Docker, core OS services. These are
marked protected and require typing the PID or name to confirm • force or --yes can’t shortcut
it. The built-in list includes Docker owners such as dockerd, docker-proxy, and
com.docker.backend, and it is extensible via config.
On Linux, process names truncated by the kernel midway through a Unicode character use the same bounded decoding for listing, protection matching, and final validation. A truncated character alone no longer blocks termination; ownership and process identity checks still apply.
Human-facing output also sanitizes OS-provided names, paths, and status text before rendering them, including control bytes, ANSI escapes, bidi controls, and zero-width display controls.
The target can’t wander off
This is the important one. After you confirm, Kickoutchi re-validates the target right before it signals:
- It re-collects ports and checks the confirmed target still matches.
- If the port’s owner changed, it aborts • no termination is sent.
- If the owner became unreadable, it aborts as ownership-unavailable (exit
4). - If the target became protected in the meantime, it aborts (exit
6).
For normal process scope, only the confirmed PID is ever signalled. For tree/group scope, only the explicitly confirmed scope is signalled, after a fresh scan and verification.
Scoped-kill safety on Linux/macOS
Tree and group kill are ogre-sized controls: broader than one PID, so they use a stricter pipeline:
- They are opt-in:
--tree,--group, or TUIt/Tfor tree scope. - They count before signalling; cap refusals happen with zero side effects.
- They freeze the root first, then sweep members to a fixed point.
- They verify every stopped member’s identity where PID reuse is impossible, and pin that post-stop identity for rollback, so a recycled PID is resumed rather than signalled.
- They thaw everything on any refusal, permission problem, identity drift, protected descendant, or
partial metadata, and a cleanup error names only processes whose
SIGCONTwas refused. - Group termination queues every
SIGTERMbefore anySIGCONT, so parent-like members cannot wake up early and spawn survivors.
Read the full flow in Scoped kills.
Scoped-kill safety on Windows
Windows tree kill uses Job Object containment rather than a freeze-first signal pipeline:
- It preflights the confirmed root and observed tree before any Job Object assignment.
- It refuses before commit for unsafe PIDs, protected descendants, incomplete metadata, identity drift, or an over-cap tree.
- It proves Job Object freeze/thaw support on an empty disposable job before touching the target.
- It treats assigning the root to the Job Object as the irreversible commit boundary.
- It freezes the committed job for a final validation sweep, closing the descendant-spawn window,
and reapplies
--yeswarning authorization during that sweep. - It withholds all termination when a live member cannot join the job, rather than terminating that process individually and reopening the containment gap.
- It terminates contained members with hard termination and reports delivered, already-exited, unconfirmed, and not-terminated members separately.
- It fails closed when missing creation-time metadata could hide a descendant inside the confirmed tree.
Platform specifics
In a nested Linux PID namespace, a process outside the namespace may still hold the same socket. Kickoutchi marks that ownership evidence as partial and refuses termination when the required ownership checks cannot be completed, even if one owner is visible.
| Platform | How termination stays honest |
|---|---|
| Linux | Uses pidfd on kernel 5.3+ for delivery. Tree/group kill opens pidfds before SIGSTOP, then reuses them for thaw/final signals. |
| macOS | No pidfd, so tree/group kill uses stop-verify: once a process is stopped, its verified PID cannot be recycled before the signal lands. |
| Windows | Uses process handles for precise single-PID termination and Job Objects for CLI tree kill. inspect is available; --group and TUI t/T are not. |
After the kick
After a successful termination, Kickoutchi performs a best-effort re-collection and reports whether the confirmed ports disappeared.
See the exit codes for how each of these outcomes is reported to scripts.