No description
Find a file
2026-06-15 21:03:33 +02:00
docs feat: Keyboard navigation and custom keybinds. 2026-06-15 21:03:33 +02:00
src feat: Keyboard navigation and custom keybinds. 2026-06-15 21:03:33 +02:00
.gitignore spike: Scaffolding. 2026-06-13 22:31:22 +02:00
AGENTS.md feat: Allow disabling timeout. 2026-06-15 17:09:39 +02:00
Cargo.lock feat: Cache persistence. 2026-06-15 17:11:55 +02:00
Cargo.toml feat: Cache persistence. 2026-06-15 17:11:55 +02:00
CONTEXT.md feat: Keyboard navigation and custom keybinds. 2026-06-15 21:03:33 +02:00
README.md feat: Anchor offsets. 2026-06-14 05:42:02 +02:00
rustfmt.toml lint: Linter and formatter fixes. 2026-06-14 22:19:13 +02:00

swavey

An Alt+Tab-style workspace switcher for Sway. Press a keybind, cycle through workspaces, and land on the selected one after a brief timeout.

Requirements

  • Sway window manager
  • Rust toolchain — install via rustup
  • GTK4 and gtk4-layer-shell system libraries

On Arch Linux:

sudo pacman -S gtk4 gtk4-layer-shell

Installing

cargo install --path .

This builds in release mode and places the binary in ~/.cargo/bin/, which rustup adds to $PATH automatically.

Sway configuration

Add the following to your Sway config (~/.config/sway/config):

# Start the daemon on launch and restart it on config reload
exec_always swavey daemon

# Workspace navigation
bindsym $mod+Tab       exec swavey next
bindsym $mod+Shift+Tab exec swavey prev

Reload Sway ($mod+Shift+c) or start a new session. The daemon starts automatically.

While the panel is visible it holds exclusive keyboard focus. Escape cancels, Tab advances forward, and Shift+Tab advances backward — no additional Sway bindings required.

Configuration

Create ~/.config/swavey/config.toml to customise the panel. All fields are optional:

[panel]
anchor = "center"       # center | top | bottom | left | right
offset = "0px"          # distance from anchor edge: "20px" or "0.1" (10% of output dimension)
timeout_ms = 750        # milliseconds before the selected workspace is committed
animation = "fade"      # fade | none
animation_ms = 150

[fallback]
icon = "󰓇"             # shown for workspaces with no entry below

[workspaces]
"1" = { name = "Web",   icon = "🌐" }
"2" = { name = "Code",  icon = "" }
"3" = { name = "Chat",  icon = "" }
"4" = { name = "Music", icon = "" }

Icons accept a UTF-8 character or Nerd Font glyph (rendered as a label), or an absolute or ~/-relative path to an SVG or image file.

Reload configuration without restarting:

swavey reload

Commands

Command Effect
swavey daemon Start the background daemon
swavey next Show panel / advance selection forward
swavey prev Show panel / advance selection backward
swavey cancel Dismiss panel without switching
swavey reload Reload config (sends SIGHUP to daemon)

Logging

Set RUST_LOG to control log verbosity:

RUST_LOG=debug swavey daemon