Skip to content

Repository files navigation

pleamar

Badge License Badge Language Badge Commit Badge Issues Badge X Badge Ko-fi


pleamar is a language and a Rust runtime for your desktop shell: bars, launchers, notification centres, docks, lock screens and widgets, written as scenes where every property is a spring and the animation never waits for the logic.




Install

Guide

Reference

pleamar-wm

Marea



Shell, window manager, companion: three pieces

pleamar is a shell toolkit, like Quickshell. You write your bar, widgets and launchers with it, and they run on the compositor you already use — Hyprland, Sway, niri, KDE… No need to change anything else.

The other two are separate, and optional:

  • pleamar-wm is a Wayland compositor built on top of pleamar, where the window manager itself is a pleamar scene. Only if you want a whole desktop of it; you don't need it to use pleamar.
  • Marea is my own shell, written in pleamar: a good example of how far a scene can go.

So if you are on Hyprland and just want a new bar, pleamar is all you need.

Where it runs

Hyprland, Sway, niri, river, Wayfire, Labwc… ✅ Its home: bars, panels and shells anchor to the screen (layer-shell)
KDE Plasma (Wayland) ✅ Bars and shells work; what is Hyprland's own —its workspaces— does not
GNOME (Wayland) ⚠️ Only scenes in a normal window: GNOME has no layer-shell, so a bar cannot anchor. pleamar-wm can be picked as a session next to it
pleamar-wm ✅ A whole desktop of its own
X11 sessions ❌ pleamar is for Wayland

Features

  • Animation that never depends on logic: the scene declares what moves and with which spring; a render thread walks it at the screen's pace. With the logic stalled for 600 ms, 38 frames still come out at 17 ms each.
  • A language of its own, checked on load: a misspelled name is an error with file, line, arrow and «did you mean…?», never an undefined at runtime.
  • Every property is a spring — interrupt it halfway and it turns without a jolt.
  • Shapes that melt into each other: shadow, rim, light, gradients, glass, blur, glow, particles and your own WGSL shaders, all signed distance underneath. An svg comes in as paths, by layers, and melts with what carries it.
  • Luau logic in a sandbox, on its own thread, behind permissions you approve — a plugin runs with what you allow it, never with everything you can do.
  • System services with no code: clock, audio, battery, network, media, notifications, tray, windows and their thumbnails, brightness, files — named in the scene and filled.
  • Lock screens on ext-session-lock, where the compositor guarantees nothing else is seen while it lasts.
  • Live reload: save the file and it reloads without losing what was in motion; save it broken and the last good scene stays, with a band saying where.
  • Its own compositor: pleamar-wm runs other programs' windows inside a scene, so the window manager is one more file you can rewrite.
  • Your AI agent knows it: the installer teaches Claude Code, Codex and OpenCode to build and verify pleamar scenes for you.
  • And it can use your desktop: in pleamar-wm an agent gets a pointer and a keyboard of its own — it clicks and types in your browser while your mouse and keyboard stay yours, and you see it work. It speaks Cua Driver's protocol.
  • Light: 81 MB and a first frame in 175 ms, against 336 MB and 1876 ms for the same bar in Quickshell.

Gallery


Preview Desktop

pleamar-wm with Marea: free windows, glass drop buttons, one scene each.



Preview Effects

examples/effects.plm: a WGSL aurora with glowing particles, a ripple that follows the pointer, a heat haze.



Install

One line installs pleamar, the pleamar-wm window manager and Marea in your home (nothing outside it), and keeps them up to date:

curl -fsSL https://raw.githubusercontent.com/k4ditano/pleamar/main/install.sh | sh
pleamar-update new changes, built and put in place (it says what is new)
pleamar-update --session also pleamar-wm in the login screen (asks for sudo)
pleamar-update --agent AI agents may use your windows in pleamar-wm, with a cursor of their own
pleamar-update --uninstall the programs go; your ~/.config/pleamar stays

It tells you what your distribution is missing to build it (pacman, apt, dnf, zypper) and offers to install it, builds in ~/.local/share/pleamar/src, puts pleamar, pleamar-wm, pleamar-session, marea and pleamar-update in ~/.local/bin, and makes your ~/.config/pleamar the first time.

Everything of yours lives in ~/.config/pleamar/ — the folder for your dotfiles: your shells (shells/), what starts with the desktop (autostart; on Hyprland or any other compositor, exec-once = pleamar --autostart), and for pleamar-wm its session.conf, keys.conf and your own wm/session.plm.

Nix and NixOS

nix run github:k4ditano/pleamar -- --scene bar.plm

As a flake input (pleamar.url = "github:k4ditano/pleamar"): the package (pleamar.packages.${system}.default, or pkgs.pleamar through pleamar.overlays.default) and a home-manager module:

imports = [ inputs.pleamar.homeManagerModules.default ];
programs.pleamar = {
  enable = true;
  autostart = true;   # runs ~/.config/pleamar/autostart with your graphical session
};

The whole desktop (pleamar-wm with Marea, in your login screen) is pleamar-wm's NixOS module. With Nix on another distribution, graphical Nix programs need nixGL to reach your GPU driver.

With your AI agent

The installer writes pleamar's skill for every agent it finds — Claude Code, Codex, OpenCode — and it refreshes itself on every update. Ask one «make me a bar with the time, the volume and my workspaces» and it knows the language, where the file goes, how to start it with your desktop, and how to check it (it compiles it, opens it without a screen and looks at the picture) before saying it is done. pleamar --install-skill does it by hand; pleamar --docs prints the documentation of the version you have.

And it can use the desktop. A second skill, pleamar-desktop, teaches it pleamar-wm's agent hands (pleamar-update --agent, or agent on in session.conf): ask «go to reddit and find my last post» and it looks at the window, clicks and types with a mint cursor of its own, on a seat apart from yours — your mouse and keyboard stay free, the monitor it works on glows while it does, and it stops to ask before publishing, sending or buying anything.

A whole scene

language 0.1
scene Clock {
    surface { size: 240, 96; anchor: top; margin: 12 }
    permissions { services: "clock" }

    //  The time comes from the system: not a single line of logic here.
    service clock as now { time: text = "--:--"; date: text }

    prop hot = 0 ~quick

    body {
        color: #151616
        rim: 6%
        shadow: 0, 6, 18, 35%
        box { from: 0, 0; size: 240, 96; corner: 20 }
    }
    text now.time { at: 120, 44; anchor: center; size: 34; color: #f5f7f5 }
    text now.date { at: 120, 72; anchor: center; size: 12; color: #9ed6bd; opacity: 45% + hot * 55% }

    zone box whole { from: 0, 0; size: 240, 96; corner: 20 }
    on enter whole { hot: 1 }
    on leave whole { hot: 0 }
}

pleamar --scene clock.plm. Save the file and it reloads without losing whatever was in motion; save it broken and the last good scene stays on screen, with a band on top saying what does not compile and where. Rebuild pleamar itself and the running one starts again with the same arguments.

Getting started from the source

cargo build --release
./target/release/pleamar --scene examples/bar.plm       # a bar: workspaces, window, time and volume
./target/release/pleamar --scene examples/long-list.plm # five thousand rows in sixteen copies
./target/release/pleamar --scene examples/paths.plm     # paths, curves and gradients
./target/release/pleamar --scene examples/window.plm     # a normal window, with its frame
./target/release/pleamar --scene examples/icons.plm      # the system tray; right-click opens an icon's menu
./target/release/pleamar --scene examples/settings.plm     # saves what you pick in its own folder
./target/release/pleamar --check examples/bar.plm    # reads it, says whether it is fine, exits
./run-tests.sh                                               # the language tests, and the examples in its reference

Options used daily: --screen A,B (which monitors), --say (talk to it from outside, or from a compositor shortcut), --mouse "360,90@500 click@3200" (a pretend mouse, to rehearse without touching the real one), --stall MS (stall the logic on purpose and watch the screen carry on).

If something stutters on your machine, pleamar --report measures every scene running for 30 seconds while you use the desktop, and writes down what it saw —frame times, where the late frames went, the card, the CPU's clock and temperature, what else took the CPU— in ~/pleamar-report-….md, with no personal data. Send it to us in an issue.

The quick comparison

The same bar, written twice: in Quickshell (proyecto-marea, 370 QML files) and in pleamar (marea-plm, one .plm and one .luau). Both running at once, both freshly started, same 60 Hz monitor, on an RTX 2060.

Quickshell pleamar
real memory (PSS) 336 MB 81 MB
time to first frame 1876 ms 175 ms
frames per second while animating ~24 60
CPU per painted frame 0.257 % 0.083 %
CPU with nothing moving never drops 0.3 %
opening a panel 6.2 % → 12.3 %, and 9.5 % after closing it 4.4 % → 4.9 %, and back to 4.5 %

On raw CPU, with both animating, the difference is 20 %: 4.96 % against 6.17 %. That is what it is, and it should be said before the pretty numbers. What changes the picture is that pleamar is painting two and a half times more frames while spending less, and that when nothing moves it sleeps.

The numbers, how they were taken and what to watch out for: marea-plm/MEDIDAS.md.

The language in five minutes

A .plm file is a scene: what is seen, and how it reacts.

surface { size: full, 44; anchor: top } the window it asks for. Several per scene, and kind: window for a normal one
fact open = false · text title = "…" what the logic may report. Typed too: fact mode: low | normal | critical
prop x = 360 ~calm something that moves. Every property is a spring
service audio { volume: number; muted: bool } a system service, by name, with no logic
model rows max 14 { label: text } · for r in rows { … } a list the logic fills
box, ellipse, arc, line, path, text, image, input what gets drawn
figure hat = file "hat.svg" an svg as geometry: its layers are paths, so they melt, tint and turn
body { color/gradient/rim/light/shadow } several shapes melted into one silhouette
row / column layout, with gap, padding, alignment, view: to scroll and wrap: for a grid
component Row(r: record) { … } something to copy, with typed parameters and named slots
on press hit { open = true } · every 2s { … } rules, run by the renderer
follow, blink, wave, spin, look movement that carries itself
layer, gesture, posture who wins a slot, and timelines
permissions { run: "date"; services: "audio" } undeclared, the logic cannot

The full reference, with its grammar and its checked examples, is in docs/11-language-reference.md. To start from zero, docs/guide.md; to copy and paste, docs/recipes.md.

The logic

If there is a bar.luau next to bar.plm, that is its logic: Luau in a sandbox, on its own thread, which the renderer never waits for. It can only cross the boundary the scene declares — fact.open = true, text.title = …, model.rows = {…}, emit, and listening with on(…) — plus timers, sys for services and run for system commands, all behind permissions. Reference in docs/10-luau-logic.md.

A library with its own .luau next to it is a plugin: its boundary lives under its name (Clock.now), it runs on its own thread, and its permissions are approved by whoever uses it, with pleamar --approve. Unapproved, it runs touching nothing.

In the editor

pleamar --lsp is a language server over stdio, with this same compiler behind it: mistakes as you type, which words fit here, what the word under the cursor means, go to where a name was declared, where it is used, and renaming it. pleamar --highlight vim|vscode writes the syntax file straight from the vocabulary, so it cannot fall behind. Both, already generated, in editor/.

How it is built

Three threads that never wait for each other: platform (windows and input), logic (Luau) and render (owner of the springs and the clock). Plus one per plugin, one per service, and a workshop thread for text and images.

language/ From text to scene: tokens tokenises, tree groups without knowing what anything means, compiler gives it meaning and checks the names, vocabulary is the list of what exists
scene.rs The contract: properties, expressions, drawing instructions, rules, layers, gestures, zones, surfaces
render.rs The interpreter. Still, it does not paint a single frame
gpu.rs · shape.wgsl One quad per element; each pixel only runs the shapes of the element covering it
shapes.rs The geometry, written once, used three times: the GPU, the mouse and the bounding boxes
logic_luau.rs A scene's logic: Luau in a sandbox, with the boundary and nothing else
text.rs Real text (cosmic-text) and images (SVG, PNG, JPEG) in an atlas at the monitor's scale
platform/ The only part that knows about the system: Wayland, the services, files, the clock
lsp.rs The language server and the highlighters, both drawn from the vocabulary

What is missing

Measured against two real Quickshell configs (648 QML files between them), in docs/07-whats-missing.md: a live view of a whole screen inside the scene (windows come as thumbnails), input methods for Japanese or Chinese, and list copies that are born and die on their own.

Known limitations, each one with its plan to fix it, in docs/08-limitations.md. They are written down as they show up, not at the end.

Documentation

docs/guide.md From zero to a bar, step by step
docs/recipes.md Patterns that already work, ready to copy
docs/11-language-reference.md The reference: grammar, types, every element and every property
docs/10-luau-logic.md What the logic can do, and what it cannot
docs/07-whats-missing.md Parity with Quickshell, told by real usage
docs/08-limitations.md Everything that fails or is missing, with its plan
docs/02-how-it-works.md Inside: the threads, the renderer, the why
skill/ The skill the installer gives your AI agents

The working notes (01, 03–06, 09) are the design logbook: how this got here.

Special Thanks


wgpu - For every pixel

Luau - For logic that can be sandboxed

cosmic-text - For real text

resvg - For reading svg

Smithay - For the compositor's protocol side

Quickshell - For showing what a desktop written in a language can be

Hyprland - For showing how good a desktop can feel

License

pleamar is under the BSD 3-Clause License, like Hyprland: use it, change it, ship it, sell it — keep the copyright notice. Every dependency is permissive (MIT, Apache-2.0, BSD-3-Clause, Zlib); THIRD-PARTY.md lists them, and their notices travel with any binary you hand out.

Contributions are welcome, made with AI or without it: see the AI policy.

Made by @k4ditano — follow along on X for what comes next. If it makes your desktop nicer, you can buy me a coffee on Ko-fi ☕

About

A desktop shell language and runtime where animation does not depend on logic. Rust, wgpu, layer-shell, SDF — an alternative to Quickshell.

Topics

Resources

Stars

97 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages