Stash allows you to temporarily hide windows at the edges of your screen, keeping your workspace clean while maintaining quick access to important applications. Windows remain partially visible at the edge and automatically reveal when you hover near them or use a keybind.This feature is perfect for:
Monitoring apps (Activity Monitor, system stats)
Communication tools (Messages, Slack) that you check frequently
Reference materials you want nearby but not always visible
When you stash a window, Loop moves it to a screen edge with only a small portion remaining visible. The window automatically reveals when your mouse approaches the edge and hides again when you move away.
Stash functionality is managed by the StashManager singleton class:
Loop/Stashing/StashManager.swift
/// Manages the behavior of windows that can be temporarily hidden (stashed)/// and revealed on screen edges.final class StashManager { static let shared = StashManager() /// How many pixels of the window should be visible when stashed private var stashedWindowVisiblePadding: CGFloat { Defaults[.stashedWindowVisiblePadding] } /// Should the stashed windows be animated when revealed or hidden? private var animate: Bool { Defaults[.animateStashedWindows] }}
StashManager listens for mouse movement events to reveal windows:
private func startListeningToRevealTriggers() { let monitor = PassiveEventMonitor( events: [ .mouseMoved, // Normal mouse movement .leftMouseDragged // Dragging items to stashed windows ], callback: { [weak self] cgEvent in self?.handleMouseMoved(cgEvent: cgEvent) } ) monitor.start()}
The system uses debouncing to avoid excessive processing:
/// The time interval to debounce mouse moved eventsprivate let mouseMovedDebounceInterval: TimeInterval = 0.05/// The throttle interval for revealing/hiding windowsprivate let revealThrottleInterval: TimeInterval = 0.1
func getScreenForEdge(currentScreen: NSScreen, edge: StashEdge) -> NSScreen? { // Two screens are considered in the same "row" or "column" // if they overlap by at least `threshold` points let threshold: CGFloat = 100 return switch edge { case .left: currentScreen.leftmostScreenInSameRow(overlapThreshold: threshold) case .right: currentScreen.rightmostScreenInSameRow(overlapThreshold: threshold) case .bottom: currentScreen.bottommostScreenInSameColumn(overlapThreshold: threshold) }}
This ensures:
Left stash uses the leftmost screen in the same row
Right stash uses the rightmost screen in the same row
Bottom stash uses the bottommost screen in the same column
Treat all screens as a unified virtual space when stashing. Loop automatically finds the appropriate screen edge.
/// Two windows can be stacked along the same edge as long as there is/// enough non-overlapping space to allow the user to easily position /// the cursor over either window.private let minimumVisibleSizeToKeepWindowStacked: CGFloat = 100private func unstashOverlappingWindows(_ windowToStash: StashedWindowInfo) { for (id, stashedWindow) in store.stashed { // If trying to stash in the same place as another window if stashedWindow.action.id == windowToStash.action.id, stashedWindow.screen.isSameScreen(windowToStash.screen) { // Replace the old window unstash(stashedWindow, resetFrame: true, resetFrameAnimated: animate) } }}
When you stash a window where another is already stashed, the original window is automatically unstashed and restored to its previous position.
private func processFrontmostAppChange(with notification: Notification) { // If a stashed window's application becomes active through // non-mouse means (Spotlight, Cmd+Tab, etc.) if appWindow.cgWindowID == window.window.cgWindowID { await revealWindow(window) }}
Activate the stashed application via Cmd+Tab or Spotlight.
Stashed window states persist across app restarts:
func start() { store.restore() // Restore stashed windows from previous session}func onApplicationWillTerminate() { // Move all stashed windows back on-screen before closing restoreAllStashedWindows(animate: false)}
When Loop quits, all stashed windows are automatically restored to prevent “lost” windows.