Skip to content

Latest commit

 

History

131 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

panes

panes is a cross-platform window management app written in Rust.

The first milestone is intentionally narrow:

  • native tray/menu shell,
  • keyboard/menu-triggered window commands,
  • shared layout logic for macOS and Windows,
  • platform adapters that find the active window, detect displays, and apply calculated window rectangles.

Drag-to-snap, richer preferences, and platform-specific polish come after the keyboard/menu path is working.

Workspace

  • crates/panes-core: platform-neutral commands, geometry, layout calculations, and window history.
  • crates/panes-platform: traits for native platform adapters.
  • crates/panes-macos: macOS accessibility, display, tray, and hotkey adapter.
  • crates/panes-windows: Windows display, window, tray, and hotkey adapter.
  • crates/panes-app: app entry point.

Shared geometry uses logical desktop coordinates with the primary display's lower-left corner as the origin, x increasing rightward, and y increasing upward. Displays left of or below the primary can have negative coordinates. Native adapters convert to and from their platform coordinate systems at the panes-platform boundary.

Configuration

panes reads an optional TOML config file at startup:

  • macOS: ~/Library/Application Support/panes/config.toml
  • Windows: %APPDATA%\panes\config.toml
  • Linux: ~/.config/panes/config.toml

A missing file means built-in defaults. See docs/config.example.toml for all supported keys: layout settings (gap, split ratios, almost-maximize size, resize step), per-command hotkey overrides, disabled commands, and launch at login.

Invalid individual values fall back to their defaults with a warning on stderr; an unparseable file falls back to full defaults with an error naming the file and problem.

Default hotkeys

macOS keeps the compact Control+Option namespace. Windows keeps directional commands on arrow keys and assigns commands that previously used letters or digits to function keys. This avoids consuming AltGr character input and does not rely on Windows-key shortcuts reserved by the operating system. Center Half is available from the tray menu but is unbound by default.

Command macOS Windows
Left Half Control+Alt+ArrowLeft Control+Alt+ArrowLeft
Right Half Control+Alt+ArrowRight Control+Alt+ArrowRight
Top Half Control+Alt+ArrowUp Control+Alt+ArrowUp
Bottom Half Control+Alt+ArrowDown Control+Alt+ArrowDown
Top Left Control+Alt+U Control+Shift+F1
Top Right Control+Alt+I Control+Shift+F2
Bottom Left Control+Alt+J Control+Shift+F3
Bottom Right Control+Alt+K Control+Shift+F4
First Third Control+Alt+Digit1 Control+Shift+F5
Center Third Control+Alt+Digit2 Control+Shift+F6
Last Third Control+Alt+Digit3 Control+Shift+F7
First Two Thirds Control+Alt+Digit4 Control+Shift+F8
Center Two Thirds Control+Alt+Digit5 Control+Shift+F9
Last Two Thirds Control+Alt+Digit6 Control+Shift+F10
Maximize Control+Alt+Enter Control+Alt+Enter
Almost Maximize Control+Alt+A Control+Shift+F11
Maximize Height Control+Alt+H Control+Alt+Shift+F1
Center Control+Alt+C Control+Alt+Shift+F2
Restore Control+Alt+Backspace Control+Alt+Backspace
Move Left Control+Alt+Shift+ArrowLeft Control+Alt+Shift+ArrowLeft
Move Right Control+Alt+Shift+ArrowRight Control+Alt+Shift+ArrowRight
Move Up Control+Alt+Shift+ArrowUp Control+Alt+Shift+ArrowUp
Move Down Control+Alt+Shift+ArrowDown Control+Alt+Shift+ArrowDown
Grow Control+Alt+Equal Control+Alt+Shift+F3
Shrink Control+Alt+Minus Control+Alt+Shift+F4

Configuration overrides use these same accelerator names on either platform.

Launch at login

Use the tray's Launch at Login checkbox to update both the platform login registration and [general].launch-at-login in the config file. Panes checks the operating-system state at startup and repairs a missing or stale registration to match the saved preference.

On macOS 13 or later, launch at login uses the bundled app's system service. Build and launch Panes.app; a bare cargo run executable cannot register as a login item. If macOS requires approval, the tray identifies that state and you can allow Panes in System Settings → General → Login Items.

On Windows, launch at login uses the current user's Run registry key. Moving the portable executable leaves the old entry stale; launching Panes from its new location repairs or removes that entry according to the saved preference.

Command line

Run a command once against the currently focused window by its stable command id:

panes exec left-half
panes exec --delay 500 top-right

The optional delay is measured in milliseconds and gives you time to focus the target window after invoking the command from a terminal. List every supported id with:

panes exec --list

An exec invocation is a separate one-shot process. It reads the normal layout configuration, applies one command, and exits nonzero with an error if the command id, permission state, focused window, or native operation is invalid. It does not share window history with the resident tray process, so restore and repeated-command cycling require the resident process until a future inter-process command channel is added.

Window-management failures

Transient desktop states—no focused window, no saved restore rectangle, or an unsupported/vanished window—are ignored in release builds and emitted as structured event=command_failure diagnostics in development builds. Permission, native API, and display-geometry failures are also logged in release builds. Command failures do not show tray notifications because common focus and window-state changes would make them noisy during normal use.

Restore history is intentionally conservative. It is discarded when a native window identifier is observed with different application/window metadata or when the connected display geometry changes. Restore rectangles are fitted to the current work area so stale coordinates cannot place a window offscreen.

Development

The workspace requires Rust 1.85.0. rust-toolchain.toml pins that release and installs rustfmt and Clippy through rustup. Keep its channel aligned with the workspace rust-version when raising the minimum supported compiler.

Clone the repository, then run the complete local check set:

cargo fmt --all -- --check
cargo check --workspace --all-targets
cargo clippy --workspace --all-targets --all-features -- -D warnings
cargo test --workspace --all-targets

On macOS, install the Xcode command-line tools, then start the menu-bar app with cargo run -p panes-app. Building the app bundle additionally requires the standard qlmanage, sips, iconutil, and plutil tools included with macOS.

On 64-bit Windows 10 or 11, install rustup with the MSVC toolchain and Visual Studio Build Tools with the Windows SDK, then run cargo run -p panes-app from PowerShell. The Windows SDK resource compiler embeds the application manifest and version metadata in release builds.

Pull requests and pushes to main run the same formatting, check, lint, and test gates on macOS arm64 and Windows x86_64. Successful jobs also upload versioned platform packages. See docs/releasing.md for the artifact contract and deferred distribution work.

macOS Accessibility permission

Panes needs macOS Accessibility permission to inspect and move application windows. On the first launch, it requests access with the system prompt. While access is missing, the tray shows Grant Accessibility Permission…; choose it to open System Settings → Privacy & Security → Accessibility.

Panes checks for the grant in the background and becomes ready without a restart. The tray item changes to Accessibility Permission Granted when the process is trusted. Window commands also perform a non-prompting trust check, so using a command never repeats the system prompt.

For permission-flow testing, quit Panes and reset Accessibility consent:

# Reset all Accessibility grants (useful for `cargo run` development builds).
tccutil reset Accessibility

# Reset only the bundled app.
tccutil reset Accessibility io.github.martinbha.panes

Accessibility trust is tied to the app's identity, signature, and location. The bundled app uses a stable ad-hoc designated requirement, so rebuilding it at the same location should preserve its grant. Running a bare development binary, moving or replacing the app, or changing its signature may require you to reset or re-grant access.

macOS app bundle

On macOS, create a double-clickable release app with:

scripts/bundle-macos.sh

The command creates dist/Panes.app. It is an ad-hoc signed local build intended for development and manual testing. The stable signing requirement helps preserve Accessibility permission across rebuilds at the same location, but the app is not Developer ID signed or notarized. Move it to /Applications before granting Accessibility permission if you want to keep it there. Panes runs as a menu-bar-only app, so it does not appear in the Dock.

Create the versioned ZIP used by CI with:

scripts/package-macos.sh

See macOS Accessibility permission for the first-launch flow and development reset commands.

For an app intended to leave the development machine, sign and notarize the bundle with an Apple Developer certificate before distributing it.

Windows package

On 64-bit Windows, build a release executable and versioned portable ZIP from PowerShell:

scripts/package-windows.ps1

The package is written to dist and contains panes.exe plus the README. The release executable is a tray application, carries version and DPI-awareness metadata, and does not open a console window. It is currently unsigned and is distributed as a portable ZIP; an installer is intentionally deferred until the release and signing process is established.

About

No description, website, or topics provided.

Resources

Stars

5 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages