Skip to content

Releases: nuggocto/kickoutchi

1.1.2

Choose a tag to compare

@github-actions github-actions released this 07 Jul 11:56
f0f261b

Release Notes

Added

  • Homebrew tap publishing for releases. cargo-dist now generates the formula,
    and the release workflow publishes it to nuggocto/homebrew-tap so macOS and
    Linux users can install with brew install nuggocto/tap/kickoutchi.
  • Scoop bucket packaging for Windows. The repository now carries a seed manifest
    and Excavator workflow under packaging/scoop/, with the live bucket at
    nuggocto/scoop-bucket auto-updating from GitHub Release assets and their
    .sha256 sidecars.

Changed

  • Install documentation now lists Homebrew, Scoop, AUR, Nix, Cargo, installers,
    and direct archives as supported release paths.
  • The release workflow now waits for Homebrew publishing before announcing a
    release, keeps the tap push behind HOMEBREW_TAP_TOKEN, and skips unchanged
    Homebrew commits on safe reruns.

Install kickoutchi 1.1.2

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://github.com/nuggocto/kickoutchi/releases/download/v1.1.2/kickoutchi-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://github.com/nuggocto/kickoutchi/releases/download/v1.1.2/kickoutchi-installer.ps1 | iex"

Install prebuilt binaries via Homebrew

brew install nuggocto/tap/kickoutchi

Download kickoutchi 1.1.2

File Platform Checksum
kickoutchi-aarch64-apple-darwin.tar.xz Apple Silicon macOS checksum
kickoutchi-x86_64-apple-darwin.tar.xz Intel macOS checksum
kickoutchi-x86_64-pc-windows-msvc.zip x64 Windows checksum
kickoutchi-aarch64-unknown-linux-gnu.tar.xz ARM64 Linux checksum
kickoutchi-x86_64-unknown-linux-gnu.tar.xz x64 Linux checksum

1.1.1

Choose a tag to compare

@github-actions github-actions released this 05 Jul 12:24
d03f63c

Release Notes

Fixed

  • Protected-process defaults now cover Linux and macOS Docker owners including
    dockerd, docker-proxy, and com.docker.backend, and Linux protected-name
    matching accounts for /proc/<pid>/comm truncation of long configured names.
  • CLI list and inspect output now handle broken pipes explicitly, so piping to
    short readers exits cleanly inside the documented exit-code contract instead
    of panicking.
  • Tree kill no longer aborts when only the frozen root is reparented by an
    unfrozen parent exiting mid-sweep, while the frozen-set protection gate fails
    closed if process metadata unexpectedly loses a name.
  • The TUI no longer performs selected-process metadata scans on the input path
    before opening kill confirmations; it uses the existing background worker and
    refuses submission until identity metadata has landed.
  • Human-facing sanitization now replaces bidi and zero-width display controls,
    closing terminal display-spoofing gaps in names, paths, and status text.
  • Inspect tree output now renders branchy descendants in parent order instead
    of depth-only order, so indentation matches the actual tree.
  • Docker enrichment bounds its post-timeout output drain, and Windows tree
    fallback exit probes use zero-timeout waits instead of blocking per member.
  • Linux /proc/net address decoding uses native-endian words, fixing
    big-endian Linux without changing little-endian behavior.

Changed

  • CI supply-chain checks now run on a schedule, GitHub Actions are pinned to
    commit SHAs, release workflow permissions are narrowed, and warnings are
    enforced by CI rather than the published Cargo manifest.
  • Contract tests add real-binary coverage for configured protected-process
    refusal and UDP/IPv6 listing, avoid PID substring assertions, and use longer
    helper deadlines for slower CI hosts.

Install kickoutchi 1.1.1

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://github.com/nuggocto/kickoutchi/releases/download/v1.1.1/kickoutchi-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://github.com/nuggocto/kickoutchi/releases/download/v1.1.1/kickoutchi-installer.ps1 | iex"

Download kickoutchi 1.1.1

File Platform Checksum
kickoutchi-aarch64-apple-darwin.tar.xz Apple Silicon macOS checksum
kickoutchi-x86_64-apple-darwin.tar.xz Intel macOS checksum
kickoutchi-x86_64-pc-windows-msvc.zip x64 Windows checksum
kickoutchi-aarch64-unknown-linux-gnu.tar.xz ARM64 Linux checksum
kickoutchi-x86_64-unknown-linux-gnu.tar.xz x64 Linux checksum

1.1.0

Choose a tag to compare

@github-actions github-actions released this 04 Jul 11:12
2aa55f7

Release Notes

Added

  • Windows kickoutchi inspect --pid <PID> / --port <PORT>: the read-only
    family view is available on Windows. It shows ancestors, descendants,
    siblings, ports, command lines, and the matching kick kill --pid <root> --tree
    hint without signalling anything. Windows reports parent links only
    after creation-time sanity checks, omits the POSIX process-group section, and
    states the native WSL2 limitation plainly. The Windows inspect renderer reuses
    one process snapshot for command-line lookups within a report instead of
    rebuilding process metadata per displayed PID.
  • Windows CLI kickoutchi kill --port <PORT> --tree (and --pid, --force):
    terminates the descendant tree through Job Object containment. Normal
    kick kill remains single-PID precise, --group stays Unix-only, and the
    Windows TUI still does not bind or advertise t/T tree keys.
    • The Windows path preflights side-effect-free before assigning the root to a
      Job Object, treats that root assignment as the irreversible commit boundary,
      converges descendants under containment, then uses explicit
      TerminateJobObject for contained members. The root handle is verified
      against the user-confirmed creation marker before the Job Object commit, so
      a recycled PID cannot retarget the kill between confirmation and execution.
    • Windows tree termination is hard termination only. Members that cannot join
      the job after commit fall back to verified individual TerminateProcess
      handles when possible, and partial containment/not-terminated results are
      reported honestly instead of being collapsed into success. Post-commit
      convergence failures now keep their specific reason in the report, including
      protected descendants, unsafe PIDs, cap overflows, incomplete metadata, and
      snapshot failures.
    • Windows parent links with missing creation-time metadata now fail closed when
      they could point into the confirmed tree, so --tree refuses as incomplete
      metadata instead of silently omitting a possible descendant. Post-commit
      reporting also distinguishes already-exited pinned members and protected
      late children already contained by the job from real survivors.

Install kickoutchi 1.1.0

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://github.com/nuggocto/kickoutchi/releases/download/v1.1.0/kickoutchi-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://github.com/nuggocto/kickoutchi/releases/download/v1.1.0/kickoutchi-installer.ps1 | iex"

Download kickoutchi 1.1.0

File Platform Checksum
kickoutchi-aarch64-apple-darwin.tar.xz Apple Silicon macOS checksum
kickoutchi-x86_64-apple-darwin.tar.xz Intel macOS checksum
kickoutchi-x86_64-pc-windows-msvc.zip x64 Windows checksum
kickoutchi-aarch64-unknown-linux-gnu.tar.xz ARM64 Linux checksum
kickoutchi-x86_64-unknown-linux-gnu.tar.xz x64 Linux checksum

1.0.1

Choose a tag to compare

@github-actions github-actions released this 04 Jul 06:36
74a9fa2

Release Notes

Fixed

  • macOS scoped kills now narrow process-table snapshots to the active tree or
    group during execution, so unrelated system EPERM rows do not hide real
    target-scope safety failures while unreadable in-scope members still fail
    closed.
  • The TUI status line now sanitizes every value it renders — the active filter
    text and the filter-error, error, and kill-status fields — so a process name
    or error message carrying control or escape bytes cannot redraw the terminal
    or fake output through the status bar.
  • The "no confirmed socket" port diagnostic now sanitizes the related
    process's name before printing it. This closes the one hint path where a
    process that named itself with terminal escape sequences could reach stderr
    unsanitized; the quoted command line in the same message was already
    escaped.

Install kickoutchi 1.0.1

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://github.com/nuggocto/kickoutchi/releases/download/v1.0.1/kickoutchi-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://github.com/nuggocto/kickoutchi/releases/download/v1.0.1/kickoutchi-installer.ps1 | iex"

Download kickoutchi 1.0.1

File Platform Checksum
kickoutchi-aarch64-apple-darwin.tar.xz Apple Silicon macOS checksum
kickoutchi-x86_64-apple-darwin.tar.xz Intel macOS checksum
kickoutchi-x86_64-pc-windows-msvc.zip x64 Windows checksum
kickoutchi-aarch64-unknown-linux-gnu.tar.xz ARM64 Linux checksum
kickoutchi-x86_64-unknown-linux-gnu.tar.xz x64 Linux checksum

1.0.0

Choose a tag to compare

@github-actions github-actions released this 03 Jul 14:30
3992de2

Release Notes

Added

  • Linux and macOS kickoutchi kill --port <PORT> --tree (and --pid,
    --force) terminates the whole process tree rooted at the target, not just
    the single port-owning process — for cleaning up dev servers, agents, and
    runners that leave worker children behind. It is opt-in: normal kick kill
    is unchanged and still signals exactly one PID.

    • Tree kill does a fresh bounded tree count before any signal is sent, then
      freezes before it kills: it SIGSTOPs the root first so it cannot spawn
      more children, sweeps its descendants to a fixed point, and re-verifies
      every process's identity while it is stopped (where its PID cannot be
      recycled) before signalling. This is what lets it clean up a process that
      is actively spawning children rather than losing the race.
    • It signals leaves-first, root last, sending SIGTERM then SIGCONT for a
      normal kill (or SIGKILL for --force). Any refusal after freezing —
      identity drift, a protected descendant, an unsafe PID, or exceeding the
      256-process cap — thaws every process it stopped and sends no termination.
    • Interactive confirmation requires typing tree (or force for
      --force); a protected root requires typing its PID or name and then the
      tree confirmation word. --yes only skips the prompt for an all-clear tree,
      cannot bypass a protected root, and is refused if the fresh execution-time
      scan would have required warnings to be reviewed — a condition that is
      applied once more to the final frozen member set, because a tree can grow
      between the skip and the end of the freeze.
    • Root protection is decided from both readers, not just the socket row: a
      root whose port row has no readable name but whose process-table entry is
      on the protected list still requires the protected confirmation, and
      execution re-checks the fresh scan's root classification — a root that
      turns out protected only at kill time (for example after an exec into a
      protected name, which keeps its PID and start marker) is refused unless
      the protected confirmation was actually completed. Both the CLI and the
      TUI share this gate.
    • A tree that exceeds the process cap is refused rather than partially
      killed, so a runaway fork bomb is reported and left intact instead of half
      signalled. The --tree flag exists only on Linux and macOS builds;
      Windows has no freeze primitive, so it does not get a weaker tree kill
      under the same name.
    • On Linux every member is pinned with a pidfd before its first SIGSTOP,
      and the same handle is used for thaw and final delivery. macOS has no
      pidfd, so delivery is layered instead: every member is stopped and
      identity-verified first (a stopped process cannot fork, exec, or exit on
      its own), and the verified start marker is re-checked immediately before
      each terminating signal, so a PID that was recycled under an external
      SIGKILL is reported as exited rather than signalled.
    • kill --pid <PID> --tree can start from a live parent PID even when that
      root owns no visible port, so cases where a child owns the port but the
      parent supervises the tree can be cleaned up from the parent. The banner
      for such a root carries the same ownership warning as a port-owning one
      when the process belongs to another user.
  • The TUI now has tree kill too: t requests tree termination of the selected
    row's process and T (Shift) requests a tree force-kill, mirroring the
    x/X convention including its Caps Lock handling. The confirmation modal
    enumerates the tree on a background worker (the table stays responsive and
    shows the count once the scan lands), lists the members with depth
    indentation, shows the same warnings as the CLI banner, and requires typing
    tree (or force); a protected root asks for its PID or name first and the
    word second, exactly like the CLI. Execution never trusts the previewed
    tree: it revalidates the root identity and re-runs the bounded pre-flight
    gates against a fresh scan before the first freeze signal. The header and
    help modal advertise the keys only on Linux/macOS builds, and the normal
    x/X kill flow is unchanged. The modal budgets its member preview from
    the terminal height, so the typed-word instruction, the input echo, and the
    Esc hint stay visible even at the smallest supported size.

  • Linux and macOS kickoutchi inspect --pid <PID> / --port <PORT>: a
    strictly read-only family view for picking the right root before a tree
    kill. It shows the target with its command line, ports, and process group;
    the ancestor chain nearest-first with command lines (so a supervisor like an
    agent or package runner is identifiable); siblings; the bounded descendant
    tree with per-member ports; and the process-group members with the ones
    outside the descendant tree called out — exactly the processes a tree kill
    from that target would leave alive. Protected names are marked, every
    OS-provided string is sanitized, all sections are display-capped with honest
    "and N more" lines, and the report ends with the matching
    kick kill --pid <root> --tree command. It never signals anything: killing
    upward stays a human decision made with the family in view.

    • inspect --port follows the same resolution rules as kill --port
      (refuses ambiguous multi-owner ports, reports unreadable owners as a
      permission problem), while inspect --pid accepts any live PID including
      portless supervisors — and, being read-only, even PID 1.
    • Tree snapshots now also carry the process group ID (from stat on Linux
      and proc_bsdinfo on macOS, read in the same pass as before). Because
      group kill derives its membership from this field, it is read as
      fail-closed as the start marker: a live process whose group cannot be read
      fails the scan, and the kernel's own group 0 maps to "no targetable
      group". The read-only inspect view renders an untargetable group as
      unknown.
    • When the process group has members outside the descendant tree — exactly
      the processes a tree kill would leave alive — the inspect report's footer
      now also offers the matching kick kill --pid <root> --group command.
  • Linux and macOS kickoutchi kill --port <PORT> --group (and --pid,
    --force): terminates the target's whole POSIX process group — every
    process sharing its group ID — instead of its parent-link tree. This is the
    honest tool for the two cases tree scope cannot cover: survivors that
    reparented away from the tree (double-fork daemons, orphaned workers whose
    spawner exited) and runaway spawners whose tree outgrows the 256-process
    tree cap. --group conflicts with --tree at parse time, exists only on
    Linux/macOS builds like --tree, and leaves normal kick kill unchanged.

    • Same freeze-first pipeline and refusal gates as tree kill: the confirmed
      root is SIGSTOPped first, members are swept to a fixed point, every
      frozen member's identity is re-verified while stopped, and any refusal
      thaws everything. Group membership is re-proven after every stop (a
      member whose group changed under the freeze refuses the whole kill), but
      a member whose parent died mid-kill is fine — reparenting does not
      change group membership, which is the point of the scope.
    • Normal group termination queues SIGTERM to every frozen member before any
      SIGCONT, so parent-like group members cannot wake up and spawn survivors
      while other members are still only frozen.
    • It is deliberately never implemented as kill(-pgid, ...): every member
      is enumerated, frozen, verified, and signalled individually through the
      same delivery path as tree kill (per-member pidfds on Linux), so the
      unsafe-PID, protected-process, and identity gates apply to every PID. If
      Kickoutchi itself sits in the target group (a plain sh -c script puts
      everything in one group), the kill refuses before anything is stopped.
    • The group cap is 512 processes — double the tree cap, because group scope
      is the designated tool for over-cap spawner trees — and past it the kill
      refuses rather than executing partially.
    • Interactive confirmation requires typing group (or force for
      --force) after a banner that names the group ID and lists every
      member: a process group can contain unrelated commands launched from the
      same shell, so the full blast radius is always shown. A protected root
      requires its PID or name first; a protected member refuses the whole group.
      --yes is stricter than tree scope: it only skips the prompt for a group
      of at most 8 members with no warnings anywhere, and both the fresh
      execution-time scan and the final frozen member set must still pass that
      same all-clear gate (size cap included), because a group has no structural
      tie to the confirmed target and can grow mid-freeze.
    • Execution revalidates the root against a fresh scan and additionally
      requires it to still sit in the confirmed group — a root that moved
      groups between confirmation and execution would silently retarget the
      sweep, so it refuses instead.

Changed

  • Cargo metadata now declares rust-version = "1.95.0", matching the README,
    mise.toml, and GitHub Actions, so crates.io consumers get the same
    machine-readable MSRV as local and CI builds.
  • Nix release installs are prepared for reproducible builds with a committed
    flake.lock instead of a floating nixos-unstable input.
  • AUR packaging notes now make the release order explicit: keep package
    metadata pinned to the last published assets until the v1.0.0 GitHub
    Release exists, then update checksums and .SRCINFO; actual AUR publication
    still waits for accoun...
Read more

0.1.2

Choose a tag to compare

@github-actions github-actions released this 28 Jun 02:06
c321b54

Release Notes

Added

  • Release installers now include the kickoutchi-update helper from
    cargo-dist, so installer-based Linux, macOS, and Windows users can update to
    newer releases by running kickoutchi-update after installing this version or
    newer.
  • The README now documents how installer users get the updater helper and how
    existing 0.1.0/0.1.1 installs can opt in by rerunning the latest installer
    once.

Install kickoutchi 0.1.2

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://github.com/nuggocto/kickoutchi/releases/download/v0.1.2/kickoutchi-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://github.com/nuggocto/kickoutchi/releases/download/v0.1.2/kickoutchi-installer.ps1 | iex"

Download kickoutchi 0.1.2

File Platform Checksum
kickoutchi-aarch64-apple-darwin.tar.xz Apple Silicon macOS checksum
kickoutchi-x86_64-apple-darwin.tar.xz Intel macOS checksum
kickoutchi-x86_64-pc-windows-msvc.zip x64 Windows checksum
kickoutchi-aarch64-unknown-linux-gnu.tar.xz ARM64 Linux checksum
kickoutchi-x86_64-unknown-linux-gnu.tar.xz x64 Linux checksum

0.1.1

Choose a tag to compare

@github-actions github-actions released this 27 Jun 21:58
252ea60

Release Notes

Added

  • Added a cargo-deny policy for dependency advisories, duplicate/wildcard
    dependency rules, allowed source registries, and dependency licenses.
  • GitHub Actions CI and the local mise run check task now run
    cargo deny check alongside formatting, strict Clippy, and tests.

Changed

  • Cargo source packages now exclude local mise.toml, keeping local tool-trust
    config out of published crate sources.

Fixed

  • The source Arch kickoutchi PKGBUILD now invokes /usr/bin/cargo,
    /usr/bin/rustc, and /usr/bin/rustdoc directly during prepare/build/check,
    so user tool shims cannot break makepkg builds or doctests.

Install kickoutchi 0.1.1

Install prebuilt binaries via shell script

curl --proto '=https' --tlsv1.2 -LsSf https://github.com/nuggocto/kickoutchi/releases/download/v0.1.1/kickoutchi-installer.sh | sh

Install prebuilt binaries via powershell script

powershell -ExecutionPolicy Bypass -c "irm https://github.com/nuggocto/kickoutchi/releases/download/v0.1.1/kickoutchi-installer.ps1 | iex"

Download kickoutchi 0.1.1

File Platform Checksum
kickoutchi-aarch64-apple-darwin.tar.xz Apple Silicon macOS checksum
kickoutchi-x86_64-apple-darwin.tar.xz Intel macOS checksum
kickoutchi-x86_64-pc-windows-msvc.zip x64 Windows checksum
kickoutchi-aarch64-unknown-linux-gnu.tar.xz ARM64 Linux checksum
kickoutchi-x86_64-unknown-linux-gnu.tar.xz x64 Linux checksum

0.1.0

Choose a tag to compare

@github-actions github-actions released this 27 Jun 05:09
600f71b

Release Notes

Changed

  • Windows TUI/CLI termination now separates user intent from the underlying
    delivery mechanism: lowercase x / non---force is a normal termination
    request with y confirmation, while uppercase X / --force keeps the
    stronger typed force confirmation. Windows still delivers both through
    TerminateProcess because Kickoutchi does not have a reliable graceful
    process-handle equivalent; the confirmation copy and project notes now state
    that plainly instead of making lowercase x look like an accidental force key.

  • The Windows protected-process defaults now include core Windows process names
    such as System, svchost.exe, services.exe, lsass.exe, wininit.exe,
    and Docker/Postgres .exe variants. The system/service classifier also treats
    PID 4, known Windows OS process names, and children of services.exe as
    system/service rows for warning and optional hiding.

  • CLI kill now performs a best-effort post-kill port refresh after a successful
    termination and reports whether the confirmed target ports are still visible,
    instead of only telling the user to refresh manually.

  • Linux termination now opens a pidfd before the mandatory pre-signal
    revalidation and sends SIGTERM/SIGKILL through pidfd_send_signal instead
    of raw kill(pid, signal). This keeps the signal tied to the prepared process
    handle after the PID/start-time/port checks pass. It raises the floor for
    termination to Linux 5.3+ (pidfd_open); older kernels fail closed with an
    actionable error that names the requirement, without sending a signal.

  • TUI refresh now uses a single in-flight background worker instead of running
    the full Linux /proc/<pid>/fd owner scan on the render/input loop. The last
    good snapshot remains visible while refresh is running. The first snapshot is
    still collected synchronously so the TUI opens onto real rows instead of a
    blank table, and any in-flight background refresh is abandoned when a
    synchronous snapshot (such as the post-kill refresh) is applied, so a stale
    scan cannot overwrite newer rows.

  • Safe termination now carries an internal Linux process-start identity from
    /proc/<pid>/stat through confirmation and pre-signal revalidation. The raw
    tick value is not rendered or serialized, but it lets Kickoutchi refuse a kill
    if PID reuse is detected before the signal boundary.

  • Post-Phase-6 internal cleanup, no external behavior change: collapsed the
    duplicate KillTarget constructor into a single from_entries, switched the
    confirmation modal's force-mode check from a signal-label string comparison to
    KillMode equality, and narrowed current_user_id to private.

  • Comment accuracy, no behavior change: PortEntry.child_pids is now documented
    as a reserved field that stays empty on real rows (the Linux collector never
    fills it; selected-row children live in ProcessContext, and it remains only
    for the list --json shape and the fake fixture); the already-exited TUI kill
    test no longer describes the removed "refreshed snapshot" status wording; and
    parse_process_start_time_ticks now explains why it right-splits on ") " so
    an unescaped ) inside comm cannot be mistaken for the field terminator.

  • The KillTarget construction invariants are now release assertions instead of
    debug-only ones: the target must contain at least one row, and every row's PID
    must match the target PID. A future caller that builds a kill target from no
    rows, or from rows owned by another PID, now fails fast on the termination path
    instead of carrying a degenerate, port-less, or mis-targeted target forward.

  • Linux collector owner resolution now only records owners for socket inodes
    found in the collected /proc/net/* rows. It keeps every PID that references a
    target socket inode, so forked or inherited listening sockets are represented
    as multiple candidate owners instead of being collapsed to whichever PID was
    scanned first.

  • Linux collector now reads /proc/<pid>/status through a byte-bounded reader,
    matching the existing cap on /proc/<pid>/cmdline, so every /proc read in the
    collector is explicitly limited; PPid sits near the top of status, so the
    cap never truncates the parent PID.

  • TUI/CLI query matching now normalizes text filter needles once per query and
    avoids formatting socket-address strings unless the search text is
    socket-shaped, reducing per-keypress allocations in search mode.

  • Removed the unused direct anyhow dependency from Cargo.toml; typed module
    errors remain the current error boundary.

  • No-match port related-process diagnostics now use stricter rules that keep the
    main table limited to OS-confirmed sockets, preserve CLI exit codes, avoid
    polluting JSON output, and require port-shaped matchers instead of raw
    substring matching.

  • protected_processes in the config file now extends the built-in defaults
    instead of replacing them, with exact-match de-duplication. Adding redis
    no longer silently removes protection from systemd, postgres, and the
    other defaults; this matches the documented "can be extended in config"
    behavior.

  • Internal restructure: shared application code moved from src/main.rs to
    src/lib.rs (public surface: a single kickoutchi::run()), with thin
    binary wrappers in src/bin/kickoutchi.rs and src/bin/kick.rs. Behavior
    is unchanged; the shared code now compiles once for both binaries, unit
    tests no longer run twice, and the duplicate-target Cargo warning is gone.

Fixed

  • Docker details enrichment now runs through a selected-row background worker, so
    opening details on a slow Docker host no longer blocks TUI input. Docker
    enrichment also works for partial-metadata rows with no readable process name
    when Docker reports a matching published host port.

  • Windows termination liveness check now uses WaitForSingleObject(handle, 0)
    instead of comparing GetExitCodeProcess against STILL_ACTIVE, removing
    the ambiguity where exit code 259 was indistinguishable from "still running".

  • Protected-process confirmation now compares user input against the
    sanitized process name, so what the prompt displays is exactly what the
    user must type (PID fallback still works).

  • Windows TUI Caps Lock behavior no longer turns an intended lowercase x into
    force-kill. The force-kill key now requires an explicit Shift-modified X, so
    a Caps Lock uppercase X stays on the normal termination path.

  • Typed force confirmation now accepts force case-insensitively, so FORCE
    does not trap users who entered the confirmation prompt with Caps Lock enabled.

  • Protected-process confirmation now matches process names case-insensitively on
    Windows, matching Windows protected-name policy.

  • Windows termination now waits briefly for a successful TerminateProcess call
    to complete before reporting success, reducing stale post-kill refreshes where
    a port can still appear immediately after the kill request.

  • No-match related-process diagnostics now skip Kickoutchi's current process and
    its ancestors, avoiding false hints for the parent PowerShell/cargo command
    that launched kick list --port <PORT>.

  • CLI kill --yes now prints the target banner — identity, ports, equivalent
    command, and any safety warnings (system/service process, ownership by another
    uid, partial metadata, child processes) — to stderr before signalling, instead
    of showing them only on the interactive confirmation path. --yes opts out of
    the prompt, not the warnings; the protected-process and unsafe-PID gates are
    unchanged, and stdout and exit codes are untouched so scripts are unaffected.

  • TUI kill status lines now report only the signal outcome instead of also
    claiming a refreshed snapshot before the post-kill re-collect has run. The freed
    port still drops from the table via the best-effort refresh, but a failed
    re-collect surfaces as the usual error line rather than a status that overstates
    a refresh that did not happen.

  • TUI header now lists x/X kill so the force-kill key is discoverable from the
    main screen, matching the input handling and the help modal.

  • TUI termination now re-collects the port snapshot when a target exits between
    confirmation and pidfd_open. The prepare-error already-exited path returned
    without re-collecting, leaving the freed port on the table for up to one refresh
    interval. Other prepare failures (permission denied, an old kernel) leave the
    process running, so the table is already current for them.

  • Termination confirmations now warn when a target is classified as a
    system/service process, not only when it is on the protected-process list.

  • Pre-signal revalidation now reports ownership unavailable if any confirmed
    target port becomes visible without a readable PID, including mixed cases where
    another confirmed port still has the original PID.

  • No-match related-process diagnostics no longer treat colon-shaped incidental
    tokens such as duration:3000ms or host:3000abc as socket evidence.

  • kill --port now refuses inherited/shared listening sockets instead of
    signaling one arbitrary owner and reporting success while another process keeps
    the port open. The Linux collector emits one row per PID referencing the same
    socket inode, which lets the existing ambiguous-target guard list every
    candidate and require --pid.

  • kill --port on a visible port whose owning PID is unavailable now exits with
    the documented permission-denied code 4 instead of the no-match code 3,
    including when ownership becomes unavailable during the mandatory pre-signal
    revalidation.

  • kill --pid now matches kill --port and the TUI when a confirmed target port
    stays visible but its owning PID becomes unreadable...

Read more