Skip to content

Summoning Tuicc

Lshika edited this page Aug 6, 2026 · 1 revision

Summoning tuicc

The full per-WM reference for running tuicc as a single, long-lived process that your WM toggles into and out of view, instead of relaunching it each time. Getting Started has the short, beginner-friendly version (sway only, via Quick install); this page is the complete reference for all four WMs, including the by-hand setup and the reasoning behind each line.

Launch tuicc once (by hand, or from your WM's startup config), then bind a key that shows/hides its window; dismissing (Enter on most actions, or Escape at the top level) hides it instantly with a warm process and warm caches, ready for the next summon. The only way to actually end the process is Ctrl+C.

install.sh sets most of this up for you — clones, creates a venv, seeds config.toml with self_app_id already set, drops a filled-in toggle script into ~/.local/bin/, and prints the exact block below for your WM so you can paste it in yourself (it never edits your WM config for you). Everything below also works by hand if you'd rather skip the installer.

Pick the one path below that matches your WM — each launches tuicc's window carrying a recognizable identity (tuicc_scratch) so the WM config can target it specifically, and so setting [wm] self_app_id = "tuicc_scratch" in tuicc's own config.toml lets it mark (and later dismiss) its own window unambiguously, no focus-timing assumptions needed (see Writing a WM Provider if you're curious why that matters).

sway (and scroll) — scratchpad, single-keybind toggle

contrib/sway/tuicc_toggle.py picks the right action based on tuicc's current state — launches it if it isn't running, dismisses it if it's focused, brings it to focus otherwise (un-hiding it from the scratchpad, or just switching to it) — one keybind instead of juggling separate launch/show/hide binds. Edit APP_ID/TUICC_MAIN at the top to match your setup, chmod +x it, then:

# ~/.config/sway/config
for_window [app_id="tuicc_scratch"] floating enable
for_window [app_id="tuicc_scratch"] move position 0 0
for_window [app_id="tuicc_scratch"] resize set 100 ppt 100 ppt
for_window [app_id="tuicc_scratch"] fullscreen enable
bindsym $mod+Tab exec ~/scripts_sway/tuicc_toggle.py

One for_window line per action, deliberately not one line with actions comma-chained — verified live (swayfx 0.5.3/sway 1.11.0): chaining floating enable, fullscreen enable (etc.) into a single rule reports every action as successful, but the window ends up neither floating-sized nor fullscreen once it actually maps. Splitting into separate rules, same criteria repeated, reliably produces the correct end state; costs nothing extra if your WM doesn't have this quirk, so it's the recommended form regardless.

Don't add a static for_window ... move scratchpad rule alongside this — the script does the scratchpad move/show itself, and a static rule would hide tuicc the instant it maps, before the script's first launch ever gets to show it. The full, fullscreen tuicc experience (shown above, and what install.sh sets up by default — no i3/sway config expertise needed to get there) also needs [wm] fullscreen_only = true set in tuicc's own config.toml (see Config Reference): the toggle script reads that value at runtime and re-asserts fullscreen enable on every show/focus, since sway drops a container back to plain floating the instant any new window is mapped anywhere in the session, even briefly on tuicc's own workspace before it's moved elsewhere. The move position 0 0/resize set 100 ppt 100 ppt lines matter for that same gap: they pin tuicc's underlying floating geometry to the full output up front, so the brief drop out of fullscreen loses only the border/always-on-top treatment, not its size — without them, tuicc pops down to whatever size sway defaults a new floating window to (usually a small centered box) and back, a much more jarring flicker (found live testing this exact transition on i3). Plain floating is a deliberate tweak, not the default — use plain floating enable (drop the move position/resize set/fullscreen enable lines) and set fullscreen_only = false in config.toml if you'd rather have tuicc float at its own natural size.

If you'd rather not use the toggle script, a plain three-line summon still works, just with separate implicit show/hide instead of one smart toggle:

# ~/.config/sway/config
exec kitty --app-id tuicc_scratch -e python /path/to/tuicc/main.py
for_window [app_id="tuicc_scratch"] move scratchpad
bindsym $mod+Tab [app_id="tuicc_scratch"] scratchpad show

i3 — scratchpad, single-keybind toggle

Same idea, via contrib/i3/tuicc_toggle.py — i3's criteria use class, not app_id (i3 is X11-only, and kitty's --app-id flag sets the X11 WM_CLASS class from the same invocation):

# ~/.config/i3/config
for_window [class="tuicc_scratch"] floating enable
for_window [class="tuicc_scratch"] move position 0 0
for_window [class="tuicc_scratch"] resize set 100 ppt 100 ppt
for_window [class="tuicc_scratch"] fullscreen enable
bindsym $mod+Tab exec --no-startup-id ~/scripts_i3/tuicc_toggle.py

Same deal as sway above — set [wm] fullscreen_only = true in config.toml (the packaged default, and what install.sh sets up) to match, or false plus dropping , move position 0 0, resize set 100 ppt 100 ppt, fullscreen enable down to plain floating enable (both in the rule and in config.toml) if you'd rather have tuicc float instead.

Or, without the toggle script:

# ~/.config/i3/config
exec --no-startup-id kitty --app-id tuicc_scratch -e python /path/to/tuicc/main.py
for_window [class="tuicc_scratch"] move scratchpad
bindsym $mod+Tab [class="tuicc_scratch"] scratchpad show

Hyprland — special workspace

# ~/.config/hypr/hyprland.conf
exec-once = kitty --app-id tuicc_scratch -e python /path/to/tuicc/main.py
windowrulev2 = workspace special:tuicc silent, class:^(tuicc_scratch)$
bind = $mainMod, Tab, togglespecialworkspace, tuicc

niri — dedicated workspace

niri has no scratchpad-equivalent, so there's no built-in toggle — set [wm] return_to_origin = true in tuicc's own config so Escape returns you to whatever workspace you summoned from:

// ~/.config/niri/config.kdl
workspace "tuicc"
spawn-at-startup "python" "/path/to/tuicc/main.py"

binds {
    Mod+Tab { focus-workspace "tuicc"; }
}

The catch with Hyprland and niri

All four WMs above still need a working provider = "sway" / provider = "i3" under [wm] in tuicc's own config, matching whichever IPC your compositor speaks — Hyprland and niri need their own WM provider (not built yet) to report live state at all. The toggle keybinds above document the summon shape ahead of that provider landing, so the WM-side setup is ready the moment it does.

$mod+Tab above is just this page's example default (and what install.sh proposes if you accept its default) — it can collide with a window-switcher bind on some setups, so treat it as a starting point to rebind, not a fixed convention.

Clone this wiki locally