Released Sep 2026
Record sheet · No. 147
Phantomat
A Hyprland plugin that puts every window on one endless canvas, then flies the camera to whichever one you type.

What it is
Tiling window managers divide the desktop into workspaces, and an overview only shows them for a moment. With a desk full of windows open, the day goes into remembering which workspace holds what, and a second monitor adds a second set of places to remember.
Phantomat makes the overview the desktop. Every window keeps a position on one plane; a monitor is a camera looking at part of it; zooming out pulls the camera back through a curved lens, and typing part of a title flies the camera to the matching window. Workspaces become places on the canvas, and a window can sit across the seam between two screens.
It is a plugin, not a compositor. It loads into Hyprland, takes over the workspace renderer through function hooks, and keeps the window model Hyprland already has. The builder forked hyprland-scroll-overview, kept its history, and added the canvas layer in a single day with Claude Opus 5.5; the commits say so in their trailers, and the launch post says so in the builder's own words.
The result is a serious piece of systems code with a narrow support surface: no releases, installation from source, open issues, and a README that says it has been used daily on one setup. Hyprland updates can break it until it is rebuilt.
Who built it
A design engineer in Portsmouth, UK. His X bio reads Fractional design engineer for startups. Clients backed by YC, $20M+ raised. 2 slots for November. His GitHub account dates from 2014 and carries 24 public repositories; most of them are visual work, including monolith-terrain, a Three.js topographic map with 105 stars, machine-sight, a Three.js perception lens, and omarchy-cosmos-screensaver, a GLSL screensaver. He made 9 of the 14 commits that sit on top of the upstream plugin, and all 9 credit Claude Opus 5.5 as a co-author.
How it is put together
The parts · 8Phantomat treats the desktop as a scene with a camera, and treats Hyprland as the renderer it borrows. Every managed window gets a box in one world coordinate space; each monitor owns a camera offset and a zoom into that space; the render path draws the part each camera sees. The plugin does not reimplement the compositor. It hooks the functions that draw workspaces, schedule frames, route surface damage and place popups, and substitutes a canvas scene for the workspace scene. That choice keeps Hyprland's window model, input routing and protocol support, and it puts the project's maintenance burden on the internal function signatures it hooks. The canvas layer is split into modules with narrow jobs: Navigator for search and selection, Hud for the overlay, BarrelShader for the lens, Memory for persistence, Config for the Lua surface, and Window for the X11 and popup translations. The largest file, scrollOverview.cpp, remains the place where the canvas state and the render loop meet.
- main.cpp
- Plugin entry and lifecycle. Declares 14
CFunctionHookpointers, installs and removes them, exposesPLUGIN_API_VERSION, and fails with a notification when another overview plugin already holds the hooks. - scrollOverview.cpp / scrollOverview.hpp
- The canvas itself:
CScrollOverview, one per monitor, with camera offset, zoom, window boxes, linked-screen camera sharing, fullscreen, fill and pin state, the render loop and the input forwarding. 9,305 lines in the.cpp. - Navigator.cpp
- Type-to-find: folds text, scores tokens against title, class and category, orders results, draws app icons, and implements the arrow-key geometry and the Alt-Tab switcher.
- Hud.cpp / Tuning.cpp
- The overlay and the live tuner: palette, minimap, key sheet, corner readouts, and the settings list that writes each adjustment to the tuning Lua file.
- BarrelShader.cpp / shaders/barrel.frag
- The final-pass lens: barrel distortion, edge blur, vignette and chromatic fringe, with the HUD and minimap composited after the warp.
- Memory.cpp
- Layout persistence: a TSV file under
XDG_STATE_HOME, at most 96 window entries, a camera per monitor, and sanity checks on every value loaded. - Config.cpp / examples/spatialoverview.lua
- The Lua surface: 96 config values and six Lua functions under
plugin.spatialoverview, plus the example file the installer copies. - tests/ and scripts/
- 17 nested Python tests with C helpers, and the install, uninstall and safe-unload scripts.
Choices, and the alternative
Fork
hyprland-scroll-overviewinstead of writing a compositor over a new compositor or a standalone overviewThe upstream supplies the Hyprland plugin plumbing, the workspace renderer and the fixes already in its history. the fork keeps that history and credits it. The cost is a 9,305-line
scrollOverview.cppand 386 upstream commits the new project has to carry.Hook 14 compositor functions over the public plugin API alone
A custom workspace renderer and a custom input route are not in the public API; the hooks are what let the canvas replace the workspace scene. The cost is version fragility: issue #20 reports the build failing on Hyprland 0.57.
Treat the monitors as one linked desk by default over one independent canvas per monitor
Linked cameras keep a window's position continuous across the seam and make the two screens one space;
canvas.linked_screens = falsekeeps the separate-camera mode for people who want it. The cost is a more complex focus and fullscreen model.Keep the
spatialoverviewnames after renaming the product over renaming everythingThe plugin id, settings file, dispatchers and
hyprctlcommand keep working for existing configs; only what people read changes. The cost is two names in the product, and a README paragraph explaining why.Store layout in a plain TSV and settings in Lua over a database or a settings UI
The memory file is inspectable, tolerant of damaged lines and small enough to read; the Lua files match Omarchy's config and let the live tuner write changes as they are made. The cost is a second tuning file and an order of application the user has to know.
Read fromREADME.md, docs/window-rules.md, main.cpp, scrollOverview.cpp, scrollOverview.hpp, Navigator.cpp, Memory.cpp, Config.cpp, BarrelShader.cpp, shaders/barrel.frag, Hud.cpp, Tuning.cpp, Window.cpp, tests/ and scripts/install.sh in kaolti/phantomat at main, read 2026-11-02; the nine commit messages and file lists from the GitHub API; hyprpm.toml, CMakeLists.txt and examples/spatialoverview.lua.
Build log
7 stages- 01
The desktop a tiling window manager hides
Hyprland tiles windows into workspaces. A workspace is a screenful; switching to another one is a keypress, and the windows on the old one stop being visible. An overview, the zoomed-out grid most compositors offer, is a temporary look: hold a key, see the shapes, pick one, and the grid closes. The desktop is still a stack of screens, not a space. That is the gap Phantomat aims at. Its README calls it a zoomable, infinite-canvas window manager: every window lives on one endless plane instead of in workspaces. The monitor is a camera onto that plane, not the plane itself. Zooming out is not a mode that ends when you pick a window; the canvas persists, and the 100% view is the same canvas seen close up. The builder put the motive in the launch post:
I wanted infinite canvas for my desktop. So I built it with Omarchy and Opus.The target user is someone with many windows and more than one monitor, the kind of person who already uses an overview often enough to want it to stay open. Phantomat is not a compositor. It is a Hyprland plugin, and it needs a Hyprland new enough to expose the Lua configuration it reads. That narrows the audience to Linux users on Hyprland, mostly the Omarchy distribution the builder uses, and it is why the README's install section begins with Hyprland 0.56 or newer. - 02
A design engineer, a fork, and one day of Opus
The builder is Zsolt Kacso,
kaoltion GitHub and X. His public repositories are mostly visual:monolith-terrain, a Three.js topographic map with 105 stars;machine-sight, a Three.js perception lens;omarchy-cosmos-screensaver, a GLSL screensaver. Phantomat is the outlier: a C++ system plugin. It is a fork.yayuuu/hyprland-scroll-overviewis a Hyprland plugin that scrolls workspaces like Niri; it was created on 2026-04-18, has 515 stars and 47 forks, and was still being pushed on 2026-11-01. Phantomat's README credits yayuuu, Daniel Skorupa, Vaxry and the Hypr Development team, and the upstream history is kept in the repository. The GitHub API counts 400 commits onmain; 386 of them are upstream, and 14 were made after the fork point. The 14 are where the canvas work is. Nine are by Kacso, all dated 2026-09-24, from08:05:18to22:38:31UTC: 14 hours 33 minutes. All nine carryCo-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>. Together they add 18,209 lines and remove 3,195. The first commit alone changes 62 files, adds 14,087 and removes 2,950, and rewritesscrollOverview.cppby +6,538/−2,160 while addingNavigator.cpp,Hud.cpp,BarrelShader.cpp,Memory.cpp,Tuning.cpp,Icons.cpp,Popups.cpp, the lens shader, the install scripts and a nested-test harness. Eighteen minutes after the last commit, at22:56:09Z, he posted the launch:I wanted infinite canvas for my desktop. So I built it with Omarchy and Opus. I'm calling it Phantomat.The post carries a 47-second 3840×2160 demo video and, at the reading on 2026-11-02, 1,181 likes, 75 retweets and 69 replies. The other five commits after the fork are other people's. Paul Harfas made three, Pablo made one and Eo made one. Pablo's commit, which draws the HUD and minimap upright on rotated monitors, carries a Cursor co-author trailer. The trailers name the model, not the host: nothing in the repository says whether the agent was Claude Code, another harness, or a mixture. What the repository does show is that nine commits are the builder's entire contribution and that Claude Opus 5.5 is credited on every one of them. - 03
The canvas is a renderer and an input router
main.cppis the entry point. It declares 14CFunctionHookpointers and hooks the compositor functions the canvas has to replace:renderWorkspace, two damage paths,scheduleFrame,sendFrameEventsToWorkspace, surface frame, twodrawTexpaths, popup reposition, drag-target begin, and three X11 configure and message paths.PLUGIN_API_VERSIONreturnsHYPRLAND_API_VERSION, so a build is tied to the headers it was compiled against.CScrollOverviewis the canvas object, one per monitor. It holds a camera offset and a zoom, maps a window's world box to a screen box (canvasWorldToScreen) and back (canvasScreenToWorld), and decides which windows a canvas draws. Withcanvas.linked_screenson, the monitors show adjacent parts of one plane and their cameras move together; with it off, each monitor has its own camera. The header exposes the operations the canvas needs:landOnWindow,summonWindow,fitAllWindows,panCamera,zoomCameraBy,nudgeWindow,canvasRedo,followCanvasWindow,checkpointCanvas,saveSharedCanvasLayout. The hooks are the design. Hyprland's public plugin API does not offer a custom workspace renderer or a custom input route, so the plugin replaces the functions that draw workspaces and handle surface frames, then draws its own scene. The same interception is what makes X11 windows usable on a canvas: an X11 client knows only the position the X server holds, which on the canvas is often not where the window is drawn.Window.cppre-sends the drawn position and translates the positions the app asks for back. Popups are drawn fixed to the screen instead of on the canvas, because a menu that opens at a transformed position is a menu the pointer cannot hit. This is why the plugin is powerful and fragile in the same place. A canvas that owns the render path can put every window on one plane; it also owns the contract with the compositor's internals, and that contract changes between Hyprland versions. - 04
Navigator, lens, HUD, and the files that remember
The visible layer is four programs.
Navigator.cppis 689 lines: it folds text to a comparable form, scores each token against the title, class and category of every window, sorts the results, and draws the palette with app icons. The arrow keys follow Android's rules: a candidate has to reach further in that direction with both edges and lie within 45° of the side; a window in line with the current one comes first.Alt+Tabuses the same selection model for recent windows.BarrelShader.cppandshaders/barrel.fragare the lens. The fragment shader is 208 lines and does the barrel distortion, edge blur, vignette and red/blue fringe in one final pass. The minimap and the search palette are composited after the lens, so the text stays flat while the desktop bends.Hud.cppis 1,070 lines of palette, minimap, key sheet and corner readouts;Tuning.cppis 440 lines of live tuner that writes each change tospatialoverview-tuning.luaas it is made.Memory.cppis the smallest piece and the one that makes the canvas feel persistent. It writes a tab-separated file at$XDG_STATE_HOME/spatial-overview/canvas-memory.tsv(or~/.local/state/...), keeps at most 96 window entries, stores a camera per monitor, and rejects non-finite or absurd geometry before it reaches the scene. A damaged line costs that one window its memory, not the file.Config.cppis the surface: 96addConfigValueV2calls and six Lua functions, all underplugin.spatialoverview, fromcanvas.linked_screensandcanvas.persistenttonavigator.accentanddistortion.chromatic.hyprctl spatialoverviewprints the canvases' state as JSON. The live tuner writes a second Lua file that is applied after the main one, so a tuned value wins until its line is deleted. - 05
What it asks of the machine
The build is C++23 with CMake, and there are Makefile, Meson and Nix flake paths beside it. The target links
hyprland,hyprgraphics,pangocairo,pixman-1,libdrm,libinput,libudev,wayland-server,xkbcommonand Lua 5.4. The installer checks forg++15 or newer,make,pkg-config,python3, and those development packages; on Arch or Omarchy the package line isbase-devel git hyprland hyprgraphics pango lua.scripts/install.shis 114 lines and does more than copy a file. It refuses to run without~/.config/hypr/hyprland.lua, compares the installed Hyprland headers with the running compositor, buildsspatialoverview.so, installs it under~/.local/share/spatial-overview/, copiesexamples/spatialoverview.luaif the user has none, backs uphyprland.lua, appends a marked block that loads the plugin and the settings, and callshyprctl plugin load.scripts/uninstall.shremoves the block and restores the layout. There are no GitHub releases and no tags. Installation is from a checkout, and the README says to run the installer again after a Hyprland update because the plugin is built against the headers.hyprpm.tomlexists for Hyprland's plugin manager, withmake allas the build command, but the supported path in the README is the shell installer. The machine requirements are modest by model standards and steep by desktop standards: no GPU model is named beyond the tested NVIDIA setup, but the plugin needs a working Hyprland 0.56 or newer with its Lua config, a C++23 compiler new enough to be GCC 15, and development headers that match the running compositor. The cost is setup time and the maintenance that comes with a source build. - 06
Seventeen test files, fifteen open issues, one setup
The test suite runs a nested Hyprland inside a window and drives it with Python. There are 17 files in
tests/, 15 of them*-nested.py, plustests/nested.lua, an X11 test app, a virtual-pointer protocol description and a probe that measures frames per second. The names map to the rules:navigator,fullscreen,fullscreen-cases,keys,linked,fill,places,arrows,drag,popup,tuner,framerate,multimonitor,x11,install. The window-rules document states the invariant each one checks: no other window moves, the window stays floating and drawn, both screens stay in the same view, and zooming out and back changes nothing. The tests are the part of the repository that most clearly came from the same day as the features. The commit message for the frame fix says a window showed 15 fps before and 60 after;tests/framerate-nested.pyis the measurement, andtests/tools/fps-probe.pyis the window that animates on every frame it is given. The X11 commit addstests/x11-nested.py,tests/tools/x11-menu.candtests/tools/wl-click.py. The support surface is narrower than the test list suggests. On 2026-11-02 the repository has 15 open issues and pull requests, no releases and no tags. Issue #20, opened 2026-10-30, says the build fails on Hyprland 0.57.0 becausedesktop/Workspace.hppno longer exists. Issue #21 reports a visible window throttled to 15–60 fps at 240 Hz. Issue #18 reports drag-and-drop broken in canvas mode. The README is direct about the reason:This hooks deep into Hyprland internals, so a Hyprland update can break it until it is updated too. It has been used daily on one setup (Omarchy, Hyprland 0.56.2, NVIDIA, two monitors); other setups are less tested.There is no CI directory in the tree. The nested tests are run by hand, and the last push is 2026-10-08, three weeks before the second wave of attention. - 07
246 stars, a launch video, and a second wave
The GitHub reading on 2026-11-02 is 246 stars, 20 forks, 1 watcher, 15 open issues and pull requests, 0 releases and 0 tags, under BSD-3-Clause. The repository was created on
2026-09-24T08:07:06Z, two minutes after the first commit's timestamp, and its last push is2026-10-08T09:45:55Z. The upstream it forked,yayuuu/hyprland-scroll-overview, has 515 stars and 47 forks. The first wave is the launch post. On 2026-09-24 at22:56:09Z, Kacso posted the 47-second demo video with the sentence about wanting an infinite canvas and building it with Omarchy and Opus. At the reading it has 1,181 likes, 75 retweets and 69 replies. The replies are short and technical: one person says he tried an infinite-canvas concept years earlier and likes the choices here; another says it would suit a Vision Pro; another just says it is good. The second wave is a creator pick. On 2026-10-31 at21:00:09Z,@OmarchyUpdates, a community-run account with 1,878 followers and the bioIndependent Omarchy updates: releases, PR watch and fixes you can copy, posted a short recommendation. That post has 121 likes, 11 retweets, 6 replies and 67 bookmarks, and X's trending pageOmarchy Linux Expands to Phones, TVs and Easy Installsembeds it alongside hop and OmarchyTV. The second wave came three weeks after the code stopped moving; it is attention on the idea, not on a new release. Against the upstream, the numbers are a derivative's numbers: 246 stars against 515, 14 own commits against 386 upstream ones. Against the launch post, the stars are smaller than the likes. The video did the work, and the repository's own last push predates the second wave.
What they would tell you
- Nine commits, all with Claude Opus 5.5 in the trailer, add 18,209 lines and remove 3,195 in 14 hours 33 minutes. That is the AI-written delta. The other 386 commits are the upstream plugin, and the 246 stars sit on both. The model gets credit for the canvas layer, not for the Hyprland plugin plumbing underneath it.
- The launch post has 1,181 likes and a 47-second 4K video; the repository has 246 stars. The video is the thing that travelled. The second wave, 121 likes on a community account five weeks after launch, arrived when the last push was already three weeks old.
- The 9,305-line
scrollOverview.cppis the price of the fork. The initial commit changed 6,538 lines in it and added ten new modules around it; the new code is modular, and the file it plugs into is not. Anyone reviewing the canvas has to read a 9,305-line translation unit. - Fourteen internal function hooks are the mechanism and the risk. Issue #20 says the build fails on Hyprland 0.57 because a header moved; the README says an update can break the plugin until it is rebuilt. A plugin that owns the render path is a bet on a moving internal API.
- The support surface is one setup. The README says Omarchy, Hyprland 0.56.2, NVIDIA and two monitors; issue #21 reports 15–60 fps at 240 Hz, issue #18 reports drag-and-drop broken, and there are 15 open issues and no releases. The tests are real, and they do not cover the configurations the issues come from.
- The trailers are co-author credits, not line-level provenance. They establish that the model was at the table for every commit; they do not say which lines it wrote, and the commit messages, which read like behavioural specs, are the better record of what was intended.
- The rename is a compatibility decision. The product is Phantomat; the plugin id, settings file and dispatcher are still
spatialoverview, and the README explains that existing configs keep working. The name from Lem is the user-facing half; the old name is the part that has to stay stable.
Adjacent records
All records →No. 116
Wake
A native desktop app that reads the private session directories of every coding agent on the machine, read-only, and gives them one window: browse by agent or project, full-text search that treats Chinese text and code substrings alike, one-click resume in the original project directory, a bundled MCP server and a command line so the agents themselves can read the history back, and remote hosts mirrored over SSH.
No. 054
Notch So Good
A pixel-art crab called Chawd lives in the MacBook notch and watches your coding agent: a timer while it works, a colour-coded notification when it needs you, and Allow / Deny buttons when it asks permission.
No. 144
typesafe-computer-use
It drives a Mac toward a goal typed in plain English: OCR and the accessibility tree read the screen, a TypeSafe classifier picks the next action, and a writing model runs only for free text. A decision costs about $0.0002, a fiftieth of a cent, against $0.032 for a frontier model reading the same screenshot.


