Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Mantle

Introduction

Mantle runs a desktop shell written in Lua on Wayland. Your shell.lua returns surfaces such as bars, windows and popups. Each surface holds nodes for layout and drawing. Signals keep their properties up to date as capabilities report changes.

The video is a Mantle shell: demo/director types each save and records the result. just demo records it again; The demo covers changing it.

Your first shell

Install Mantle, then create a config directory:

mantle init

Open ~/.config/mantle/shell.lua and replace its contents with this bar:

return panel {
    id = "bar",
    layer = "top",
    anchor = { top = true, left = true, right = true },
    width = "fill",
    height = 32,
    exclusive_zone = true,
    background = "#1e1e2e",
    child = row {
        width = "fill",
        height = "fill",
        padding = { left = 12, right = 12 },
        children = {
            text { content = "Mantle", font_weight = 700, foreground = "#89b4fa", align_v = "center" },
            rect { width = "fill" },
            text {
                content = mantle.clock:map(function(clock)
                    return os.date("%H:%M", clock.time)
                end, "--:--"),
                font_weight = 700,
                foreground = "#cdd6f4",
                align_v = "center",
            },
        },
    },
}

PartWhat it does
panelPlaces a 32 px bar at the top of each output and reserves that space from windows
row and the "fill" rectPut the label on the left and push the clock to the right
mantle.clock:map(...)Updates the clock when the clock capability pushes time. Until the first push the signal holds the second argument, and the callback does not run

Check the config before starting a shell, then run it:

mantle check
mantle -d
mantle log -f

check evaluates and lays out the config without Wayland. It catches Lua and layout errors, but cannot test every value, callback or compositor response (what check covers). -d starts the shell detached; log -f follows its output. Change "Mantle" in shell.lua and save it. The bar reloads in place. If a save fails, the previous bar stays visible and the error goes to the log (reload behavior).

mantle init also writes .luarc.json so lua-language-server can complete the API and flag type mistakes (editor setup).

Where to go next

To buildStart with
A clock that changes on clickClock bar, then signals
An app launcher opened by a keyApp launcher, then CLI keybinds
A bar with workspace buttonsWorkspaces
A popup, window or lock screenSurfaces
Your own widget layoutNodes and paint
Help with a shell that shows nothingFAQ

Every cookbook recipe is a complete shell.lua you can run on its own. The glossary defines terms used throughout the book.

Source: init, starter, check, watcher, reload.