Skip to content

Releases: topce/fq

fq 0.4.0 — macOS, Linux and Windows

Choose a tag to compare

@topce topce released this 16 Sep 19:50

The same command line everywhere, with a per-platform implementation behind it:

macOS Linux Windows
Enumeration lsappinfo (the apps the Force Quit dialog shows), osascript fallback /proc scan of the graphical session, wmctrl -lpx alternative tasklist (windowed processes), PowerShell alternative
Kill SIGKILL to the process group SIGKILL to the process group, or to the process tree taskkill /T /F
Sleep (-s) pmset sleepnow systemctl suspend SetSuspendState

Install

  • macOS and Linuxbrew — brew install topce/fq/fq (builds from this tag)
  • macOS, Linux — opam install fq, or build from source: dune build
  • Arch Linux — fq in the AUR
  • Windows — build from source with a native OCaml ≥ 5.1 and opam 2.2+
    (dune build, then _build\default\bin\main.exe)

No prebuilt archives are attached to this release: Homebrew, opam and the AUR
build from this tag's source. See docs/RELEASING.md for how the optional
archives and the Scoop/WinGet manifests are produced and published.

Verification

macOS (arm64) has the full suite green — unit tests, the -s/--sleep end-to-end
checks, the platform checks against a fixture /proc tree — plus the real
lsappinfo backend. The Linux and Windows code paths are covered by
fixture-driven end-to-end tests (a synthetic /proc tree whose pids are live
processes for the Linux kill path; stub taskkill for the Windows one) and by
the unit tests, but this release has not been run on real Linux or Windows
hardware by the maintainer yet. Please report anything that misbehaves.

What changed

[0.4.0] - 2026-09-16

Added

  • Linux support. Applications are enumerated from /proc: a process is an
    application when it runs in a graphical session (DISPLAY/WAYLAND_DISPLAY),
    does not belong to a terminal (it is neither a shell nor the job a terminal
    is running in the foreground — an application started with app & or
    detached from its terminal counts) and is not session infrastructure (window
    manager, compositors, panels, session/sound daemons, portals, input methods).
    Helper
    processes of a multi-process application run the application's own binary and
    are folded into it, and applications are named after their .desktop entry
    when there is one. Victims are killed as a process group, or — for a process
    that does not lead its own group — as a whole process tree read from /proc.
    -b wmctrl lists the windows on screen instead (X11).
  • Windows support. Applications are enumerated with tasklist /V (windowed
    processes; the image name without .exe), with PowerShell Get-Process as
    the alternative backend. Victims are terminated with taskkill /PID <pid> /T /F, helpers included. The process tree is read once with PowerShell for
    the "this terminal is never killed" logic.
  • Platform-specific sleep commands: systemctl suspend (with pm-suspend and
    zzz as fallbacks) on Linux and SetSuspendState('Suspend') (with
    rundll32 as a fallback) on Windows. On Windows the detached helper that
    guarantees the sleep when the terminal itself is force-quit is a hidden,
    detached PowerShell script.
  • Platform-specific protected system applications: the session shell, window
    managers and session daemons on Linux; Explorer, the desktop window manager
    and the core session processes on Windows.
  • -b/--backend accepts the backends of the running platform only, and an
    unsupported platform is refused with a clear message instead of failing
    somewhere deeper.
  • The help text, prompts and messages are platform-aware ("put the Mac to
    sleep", "put the computer to sleep", "put the PC to sleep").
  • Packaging for every channel: packaging/ renders the Homebrew, Scoop,
    WinGet, AUR and nfpm manifests from a SHA256SUMS file, and
    docs/RELEASING.md is the release runbook (tagging, the package managers,
    building the optional archives by hand, canary stage, verification,
    rollback, monitoring).
  • Test hooks for driving the non-native code paths anywhere: FQ_PLATFORM,
    FQ_ENUM_OUTPUT, FQ_PROC_ROOT and FQ_DESKTOP_DIRS (documented in the
    README), plus test/test_platforms.sh, which exercises the Linux backend
    and its real kill path against a synthetic /proc tree.

Changed

  • A failed force-quit now always exits 1. Previously the exit status was only
    turned into 1 by -s/--sleep; without it, a force-quit that failed (a
    permission error, say) reported the failure but exited 0, contradicting the
    documented exit status.
  • FQ_APPS_FILE is read directly instead of with cat, so the test hooks work
    on Windows too.

fq 0.3.1

Choose a tag to compare

@topce topce released this 13 Sep 14:22

fq 0.3.1

Bug-fix release. fq -y -o -s no longer kills fq's own process group — the
"self process" — so it reliably keeps the terminal running and still puts the
Mac to sleep.

Fixed

  • --others no longer kills fq's own process group. If an application in the
    list led fq's process group (so it was not an ancestor), fq treated it as a
    victim and sent SIGKILL to the whole group, taking itself down with it; the
    requested -s/--sleep then never happened. The process-group leader is now
    treated as self by --others, and force_quit_pid never signals fq's own
    process group or pid, so the sleep (and anything else still to do) always
    runs.
  • With no other application to quit, fq -o -y -s still puts the Mac to sleep.

Tests

  • test/test_sleep.sh covers the self-process case: fq is placed in a process
    group led by a non-ancestor application and -o -y -s must leave that
    application running and still put the Mac to sleep.
  • test/test_fq.ml checks that a force-quit refuses fq's own pid.

Install

brew install topce/fq/fq

Note: an unrelated message broker is also published as fq in homebrew-core,
so use the fully qualified brew install topce/fq/fq.

Full changelog: https://github.com/topce/fq/blob/main/CHANGELOG.md

v0.3.0

Choose a tag to compare

@topce topce released this 13 Sep 13:56

Fixed

  • -s/--sleep is no longer skipped when there is nothing to force-quit. Every
    mode that found zero victims exited before reaching the sleep code, so
    fq -o -y -s — the natural "quit everything else, then sleep" command —
    silently did nothing at all when every other application was protected or
    the application running the terminal was the only one left. The sleep is now
    a step of its own that every mode reaches; with nothing to quit and without
    -y, fq asks about the sleep alone ("Put the Mac to sleep? [y/N]") instead
    of asking to force-quit zero applications.
  • The sleep is no longer asked for twice: the combined "force quit … and put
    the Mac to sleep?" confirmation now covers the sleep, so a single y both
    quits and sleeps. This was still broken when naming an application on the
    command line (fq -s Safari), which asked a second time after the first y
    and then treated the second, unanswered prompt as a decline — so the Mac was
    never put to sleep.

Added

  • FQ_SLEEP_CMD overrides the program used to put the Mac to sleep, and
    FQ_APPS_FILE (pid name lines) overrides application enumeration. Both
    exist so the test suite can exercise the real code paths without touching
    running applications or actually sleeping the machine.

Tests

  • test/test_sleep.sh covers the sleep behaviour end to end, driven through
    the built executable with a synthetic application list and a stub sleep
    command: nothing-to-quit still sleeps (including a machine with no
    applications at all), one confirmation never asks twice (for --others,
    --pid, and a named application alike), a declined confirmation never
    sleeps, and a refused protected application exits 1 without sleeping.