Skip to content

Repository files navigation

swift_kick

On recent versions of macOS, closing the last window of an app leaves it running. Pages, Numbers, Preview, Notes and many others keep sitting in the Dock with no windows open, and you have to quit them by hand.

swift_kick quits them for you, the same way Cmd+Q would.

It only ever touches apps you explicitly add. Anything not on your list is never watched and never quit.

Using it

Open swift_kick and you get one window, Monitored Apps — that list is the configuration.

  • Add lists the apps currently running. Pick one or more; they start being watched immediately.
  • × on a row stops watching that app. It does not quit it.
  • Apps you have added but that are not running show (not running).

Close the window and swift_kick keeps working in the background, with no Dock icon and no menu bar item. Open it again from Spotlight or Finder whenever you want to change the list.

Two checkboxes in the footer:

  • Run in background — on by default. Turn it off if you would rather swift_kick quit when you close the window, so "is it running?" is answered by "is the window open?".
  • Run at login — starts watching at login, silently. No window, no Dock icon.

Installing

./build.sh
open build/swift_kick.app

Needs macOS 15 or later and a Swift 6 toolchain. Move the built app wherever you like, /Applications included.

build.sh signs with the first codesigning identity it finds, preferring Developer ID over Apple Development. Override with SIGN_IDENTITY="..." ./build.sh. With no identity it falls back to ad-hoc signing, which works but has an annoying consequence — see below.

Accessibility permission

swift_kick counts windows through the Accessibility API, so macOS requires your permission. It asks on first launch.

Grant it under System Settings → Privacy & Security → Accessibility.

Until then swift_kick shows a banner and does not quit anything, though you can still edit the list. It starts working the moment you grant access — no relaunch needed.

It does not request Screen Recording, and does not need it.

If the banner stays after you grant access, the cause is almost always a stale entry. macOS ties the permission to the app's code signature, so an ad-hoc-signed build looks like a brand new app every time it is rebuilt. Remove every swift_kick entry from the Accessibility list and re-add the current build. Signing with a real identity avoids this entirely.

What it will not do

By design:

  • It never force-quits. If an app refuses to quit — an unsaved-changes sheet, for example — swift_kick leaves it alone.
  • It never quits Finder, the Dock, or other system apps, and they cannot be added.
  • It will not quit an app you have hidden with Cmd+H, or one whose only window is minimized, or one whose last visible window is on another desktop.
  • It only quits an app that it has actually seen open a window. An app sitting idle with no document open is left alone.

When anything is ambiguous — an Accessibility error, a timeout, a window list it cannot read — it does nothing. Leaving an app running is a much better failure than quitting one you were still using.

How it works

swift_kick attaches an Accessibility observer to each app on your list and waits for windows to close. When an app appears to have none left, it waits a moment, then checks twice: once through Accessibility, once against the window server's own list of visible windows across every desktop. Only if both agree the app has no windows does it ask the app to quit, using the same graceful terminate as Cmd+Q.

The second check exists because Accessibility alone is not reliable enough. Some apps keep a permanently blank, invisible window that never disappears, and windows on other desktops are not always visible to Accessibility. Getting either case wrong means quitting an app with a document still open, so both are checked against the window server directly.

Source layout

Path Purpose
AppDelegate.swift Lifecycle, single instance, Dock icon behavior
MonitoredAppsWindow.swift The Monitored Apps window
AddAppDialog.swift The Add App dialog
AllowlistStore.swift Which apps are watched, and persistence
Watcher.swift Observers and the quit sequence
WindowCounter.swift Deciding whether a window is real
ProtectedApps.swift Apps that must never be touched
AccessibilityCoordinator.swift Permission handling, login item

WindowCounter.swift carries comments explaining which window-detection approaches were tried and why they fail; worth reading before changing it.

License

MIT

About

Quits macOS apps that keep running after you close their last window.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages