Skip to content

Latest commit

 

History

4 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Finestra

Finestra is a small macOS window-management daemon with a menu bar cheat sheet. It is two single-file Swift programs, no dependencies, no Xcode project.

  • Registers 57 global hotkeys itself through Carbon, so there is no input tap and nothing that can slow down or block other shortcuts
  • Moves, resizes, centres, snaps and maximises the front window, sends it to the next monitor, and remembers the previous frame for undo
  • Arranges the front two, three or four windows into cycling layouts, distributes a row or column of windows around the pointer, rotates and swaps a stack
  • Opens a highlighted file path from any app, or reveals it in Finder
  • Creates a new Markdown or plain text file in the front Finder window with the name ready to type
  • Accepts the same commands over a FIFO, so any tool that can write a line of text can drive it
  • Shows every shortcut in a menu bar panel (the second app, Finestra Shortcuts)

Finestra does not manage clipboard history or replace the macOS app switcher.

Requirements

  • macOS 15 or later. That is all for the one-line install below
  • Building from source additionally needs the Xcode Command Line Tools (xcode-select --install), for swiftc and codesign, and a code-signing identity; see "Build from source"

Install

Nothing needs installing first: no Xcode, no Command Line Tools, no Git. Paste this into Terminal:

curl -fsSL https://raw.githubusercontent.com/braveva/finestra/main/Scripts/install.sh | sh

It downloads the latest release from this repository, installs both apps into ~/Library/Application Support/Finestra/, writes and loads the two launch agents, and then macOS asks to let Finestra control the computer using accessibility features. Click Open System Settings and switch Finestra on. Every shortcut works from that moment, and both apps start again at every login.

The first time a feature talks to Finder, Terminal or iTerm2 (new file, reveal in Finder, opening a path highlighted in a terminal) macOS asks for Automation access. Allow it.

Run the same line again to upgrade. FINESTRA_VERSION=v1.0.0 in front of it pins a release. The installer is Scripts/install.sh in this repository; read it before running it if you like, it uses only tools that ship with macOS.

Build from source

xcode-select --install                    # once, if swiftc is missing
git clone https://github.com/braveva/finestra.git
cd finestra
export FINESTRA_CODESIGN_IDENTITY=-       # ad-hoc; see "Signing" below for a stable identity
./Scripts/verify                          # type-check and run the self-tests
./Scripts/stage-install                   # builds both apps, copies them to Application Support
mkdir -p ~/Library/LaunchAgents
cp .build/LaunchAgents/com.eva.finestra.plist .build/LaunchAgents/com.eva.finestra.shortcuts.plist ~/Library/LaunchAgents/
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.eva.finestra.plist
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.eva.finestra.shortcuts.plist

Scripts/stage-install runs Scripts/build, copies Finestra.app and FinestraShortcuts.app to ~/Library/Application Support/Finestra/, and renders the two launch agent plists into .build/LaunchAgents/ with your home directory filled in. It deliberately does not load them; the launchctl lines above do. Both agents start at login and are kept alive.

Then grant permissions:

  1. Accessibility. Open the pane with open "x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility", click the plus button, press Shift+Command+G in the file dialog and paste ~/Library/Application Support/Finestra/Finestra.app. Every window operation and every hotkey needs this. Restart the daemon afterwards: launchctl kickstart -k gui/$(id -u)/com.eva.finestra
  2. Automation prompts appear the first time a feature talks to Finder, Terminal or iTerm2 (new file, reveal in Finder, opening a path highlighted in a terminal). Allow them.

The menu bar shows a window icon from Finestra Shortcuts once both agents are running.

Signing

Scripts/build refuses to run without a signing identity. FINESTRA_CODESIGN_IDENTITY=- signs ad-hoc, which is fine for a one-off install but means macOS forgets the Accessibility grant after every rebuild. For repeated builds use an Apple Development certificate: find its SHA-1 with security find-identity -v -p codesigning and either export it in FINESTRA_CODESIGN_IDENTITY or put it on one line in a file called .finestra-signing-identity at the repository root (ignored by Git).

Uninstall

launchctl bootout gui/$(id -u)/com.eva.finestra
launchctl bootout gui/$(id -u)/com.eva.finestra.shortcuts
rm ~/Library/LaunchAgents/com.eva.finestra.plist ~/Library/LaunchAgents/com.eva.finestra.shortcuts.plist
rm -r ~/Library/Application\ Support/Finestra

Shortcuts

The default modifier is Control+Option. Click the menu bar icon of Finestra Shortcuts for the full list; the same table is the rows array at the top of Sources/FinestraMenu/main.swift. A few examples:

Keys Action
^⌥ Arrow Slide the window to that edge, size kept
^⌥⌘ Arrow, ^⌥⇧⌘ Arrow Nudge 20 px or 100 px
^⌥⇧ Arrow Narrower, wider, taller, shorter
^⌥ U I J K Four quarters
^⌥ D E G, ^⌥⇧ D E G Left, middle, right third; top, middle, bottom third
^⌥ Return, ^⌥ W, ^⌥ H, ^⌥ C Maximise, full width, full height, centre
^⌥ 2 3 4, ^⌥⇧ 2 3 4 Arrange the front 2, 3 or 4 windows; tap again for the next layout, shift for the previous
^⌥⌘ 2 to 5, ^⌥⇧⌘ 2 to 5 Row across or column down through the pointer
^⌥ [ ], ^⌥ R Swap up or down in the stack; rotate all
^⌥ N, ^⌥ Z Send to the next monitor; undo
^⌥ F, ^⌥⇧ F Open the highlighted path; reveal its folder
^⌥ T, ^⌥⇧ T New Markdown or plain text file in the front Finder window

To change a binding, edit hotkeyTable in Sources/FinestraDaemon/main.swift and the matching row in the menu app, then run ./Scripts/verify (it checks the table has no duplicate bindings) and rebuild.

Driving it from other tools

The daemon reads one command per line from a FIFO, by default /tmp/finestra.fifo:

echo 'edge left' > /tmp/finestra.fifo
echo 'layout 0,0,0.5,1' > /tmp/finestra.fifo      # x,y,w,h as fractions of the screen
echo 'arrange 3 next' > /tmp/finestra.fifo
echo 'distribute width 4' > /tmp/finestra.fifo

Commands: move dx dy, grow dw dh, edge left|right|top|bottom, center, fullwidth, fullheight, band i n, col i n, layout x,y,w,h [x,y,w,h ...], arrange n next|prev, distribute width|height n, stack, rotate, swap up|down, next, undo, openpath open|reveal, newfile md|txt, windows, screens, resolve. The handler in Sources/FinestraDaemon/main.swift is the reference for arguments.

Runtime files

Path Purpose Override
~/Library/Application Support/Finestra/finestra.log Log, one line per command FINESTRA_LOG
~/Library/Application Support/Finestra/screens.json Stable display identities across reconnects FINESTRA_DB
/tmp/finestra.fifo Command FIFO FINESTRA_FIFO

Layout of this repository

Sources/FinestraDaemon/main.swift   the daemon: hotkeys, FIFO, window logic, self-tests
Sources/FinestraMenu/main.swift     the menu bar cheat sheet
Resources/                          Info.plists and launch agent templates
Scripts/build                       compile and sign both apps into .build/
Scripts/verify                      type-check, self-tests, plist lint
Scripts/stage-install               copy to Application Support, render launch agents

License

MIT, see LICENSE.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages