max / alloy
- Co-Authored-By
- Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 file changed,
+32 insertions,
-10 deletions
| @@ -36,9 +36,15 @@ | |||
| 36 | 36 | ||
| 37 | 37 | ## Launcher | |
| 38 | 38 | ||
| 39 | - | **None by default (terminal-driven).** anyrun (the prior GTK launcher) was dropped in the pivot. On a terminal-first system, launching is the shell: open apps from rio or from yazi. `Mod+D` is left unbound in the scaffold for a TUI launcher when one is chosen (a fuzzy picker run inside a terminal, e.g. via `rio -e`). | |
| 39 | + | **`alloy-menu`: fzf over desktop entries, run in rio.** Bound `Mod+D`. A shell script in `usr/bin/`, about forty lines, that reads `.desktop` files from the system, user and Flatpak paths, pipes names through fzf, and hands the chosen `Exec` line to `swaymsg exec` so the app outlives the terminal that launched it. | |
| 40 | 40 | ||
| 41 | - | Rejected as graphical launchers: anyrun (GTK, dropped), fuzzel/tofi (C, and a graphical launcher is off-thesis now). Candidate TUI pickers to evaluate: a small nu/fzf app picker, or a dedicated `alloy` console verb. | |
| 41 | + | The split with `Mod+Return` is the design. Typing a command is what a shell is for, and a shell is one keystroke away, so the launcher does not list every binary on `PATH`: doing that buries Firefox under coreutils. It lists the graphical apps that have a name, an icon and a binary nobody remembers. Two keys, two jobs. | |
| 42 | + | ||
| 43 | + | This replaces "none by default". That line read as terminal-first discipline and worked as one until `Mod+Return` broke, at which point a session with no launcher had no way to open a terminal and no way to edit the file that would have fixed it. A launcher is the second door. | |
| 44 | + | ||
| 45 | + | fzf carries both TUI menus: this one and `alloy-clipmenu` (`Mod+Shift+V`), the read half of [clipboard history](#clipboard-history). One package, and the picker stays a tool rather than a dependency Alloy authors around. | |
| 46 | + | ||
| 47 | + | Rejected as graphical launchers: anyrun (GTK, dropped in the pivot), fuzzel/tofi (C, and a graphical launcher is off-thesis). A dedicated `alloy` console verb was the other TUI candidate and is still open as a v1 move; it buys theming and a shared shell with the rest of the console, and it costs a Rust surface where a script already does the job. | |
| 42 | 48 | ||
| 43 | 49 | ## Notification daemon | |
| 44 | 50 | ||
| @@ -260,15 +266,18 @@ | |||
| 260 | 266 | ||
| 261 | 267 | ### Clipboard history: **cliphist** | |
| 262 | 268 | ||
| 263 | - | Go, wlroots-friendly, tiny. Text and image histories stored in a local DB, queryable via `cliphist list` and pasteable via `cliphist decode`. Interactive selection via `cliphist list` piped to a TUI picker (fzf/nu), or a future `alloy` console verb. | |
| 269 | + | Go, wlroots-friendly, tiny. Text and image histories stored in a local DB, queryable via `cliphist list` and pasteable via `cliphist decode`. | |
| 264 | 270 | ||
| 265 | - | **Sway integration:** two watchers `exec`'d from the sway config: | |
| 271 | + | **Sway integration:** two watchers `exec`'d from the sway config, and a picker bound to `Mod+Shift+V`: | |
| 266 | 272 | ||
| 267 | 273 | ``` | |
| 268 | 274 | exec wl-paste --type text --watch cliphist store | |
| 269 | 275 | exec wl-paste --type image --watch cliphist store | |
| 276 | + | bindsym $mod+Shift+v exec $term --app-id=alloy-menu -e /usr/bin/alloy-clipmenu | |
| 270 | 277 | ``` | |
| 271 | 278 | ||
| 279 | + | The picker is `usr/bin/alloy-clipmenu`: `cliphist list` into fzf into `cliphist decode` into `wl-copy`, which is the pipeline this section already described. It went unwritten longer than it should have, so the watchers filled a history from the first login that nothing could read back. `cliphist decode` rather than the fzf line itself is what makes images and multi-line text survive the round trip. | |
| 280 | + | ||
| 272 | 281 | No config file; cliphist's storage lives at `~/.local/share/cliphist/db` and needs no tuning. | |
| 273 | 282 | ||
| 274 | 283 | Rejected: clipse (Go, a full TUI where a `cliphist list` pipe suffices), copyq (Qt, retained-mode GUI overkill). | |
| @@ -341,15 +350,20 @@ | |||
| 341 | 350 | ||
| 342 | 351 | **Departure Mono, Alloy's brand mark, is not in the fontconfig chain.** It stays reserved for authored surfaces (the console and `alloy_tui`, headers, brand elements) and is invoked by name where wanted. Nobody reads code or long text in Departure. | |
| 343 | 352 | ||
| 344 | - | ### Monospace: **IosevkaTerm Nerd Font** | |
| 353 | + | ### Monospace: **IosevkaTerm Nerd Font Mono** | |
| 345 | 354 | ||
| 346 | 355 | The Term variant of Iosevka drops ligatures, which is safe for TUIs (yazi, bottom, helix status columns) that count characters. The Nerd Font bundle carries the glyphs starship, yazi, and bottom need for prompt icons and file-type indicators. Iosevka's narrow proportions give more columns per line than JetBrains Mono or Fira Code, real screen-real-estate value in a tiling stack. | |
| 347 | 356 | ||
| 357 | + | **The `Mono` family, in cell grids only.** The Nerd Fonts release ships three families from one typeface: `IosevkaTerm Nerd Font`, `… Nerd Font Mono`, and `… Nerd Font Propo`. They differ in how wide the icon glyphs are allowed to be. Icons live in the Private Use Area, which a terminal measures as one cell, while the plain family draws them at about two, so the glyph paints over whatever follows it. The `Mono` family constrains them to the single cell the terminal allocated. | |
| 358 | + | ||
| 359 | + | In practice the overflow is usually hidden, because yazi and starship both pad icons with a trailing space. The `Mono` family is still what the terminal and the fontconfig `monospace` alias use, because "usually hidden" depends on every TUI author choosing to pad, and the failure is silent when one does not. The cost is real and worth stating: single-cell icons are smaller and fainter than the plain family's, most noticeably at small point sizes. | |
| 360 | + | ||
| 361 | + | Pango consumers are not a cell grid and keep the plain family, where the fuller icons are free. | |
| 362 | + | ||
| 348 | 363 | Applied at: | |
| 349 | - | - `etc/skel/.config/mpv/mpv.conf`: `osd-font='IosevkaTerm Nerd Font'`. | |
| 350 | - | - `etc/skel/.config/imv/config`: `overlay_font = IosevkaTerm Nerd Font:11`. | |
| 351 | - | - Rio config (when it lands): `fonts.regular.family = "IosevkaTerm Nerd Font"`. | |
| 352 | - | - fontconfig `monospace` alias: everything else that asks for mono. | |
| 364 | + | - Rio, all five `fonts.*.family` entries: `IosevkaTerm Nerd Font Mono`. | |
| 365 | + | - fontconfig `monospace` alias: `IosevkaTerm Nerd Font Mono`, for everything else that asks for mono. | |
| 366 | + | - `etc/skel/.config/mpv/mpv.conf`, `etc/skel/.config/imv/config`, the sway bar and title font, mako, swaylock, satty: the plain `IosevkaTerm Nerd Font`, all pango. | |
| 353 | 367 | ||
| 354 | 368 | Rejected: JetBrains Mono (wider characters cost columns per line), Fira Code (older, ligatures on by default), Cascadia Code (Microsoft-shaped, fine but less Alloy-neutral), Berkeley Mono (paid, can't ship). | |
| 355 | 369 | ||
| @@ -369,9 +383,17 @@ | |||
| 369 | 383 | ||
| 370 | 384 | Alloy declines to prescribe. Nothing Alloy authors is serif; the browser and any long-form reading surface fall through to the system default (Source Serif 4 or Liberation Serif on Fedora). fontconfig alias covers the fallback chain politely without adopting a serif font as an Alloy commitment. | |
| 371 | 385 | ||
| 386 | + | ### Emoji: **not shipped** | |
| 387 | + | ||
| 388 | + | No emoji font is installed, and the fontconfig `emoji` alias is gone rather than pointing at one. Alloy uses no emoji in its own copy, so nothing it draws needs the coverage. Emoji in a web page or a third-party notification render as missing glyphs; that is the accepted cost, not an oversight. | |
| 389 | + | ||
| 390 | + | The alias used to name Noto Color Emoji, which was never in the package list. That is the shape of bug this stack keeps producing: a config naming something the image does not carry, failing quietly. Declining to ship an emoji font is a position; naming one that is absent is a defect. Anyone who wants emoji installs a font and fontconfig picks it up with no change here. | |
| 391 | + | ||
| 372 | 392 | ## Greeter | |
| 373 | 393 | ||
| 374 | - | **greetd + tuigreet.** Rust, minimal, ratatui-rendered. greetd is the daemon that owns VT1; tuigreet is the ratatui client that prompts for user/password and execs `sway` on successful auth. Config at [`etc/greetd/`](../etc/greetd/): `/etc/greetd/config.toml` sets up VT1 with tuigreet + Alloy palette applied via `--theme`. | |
| 394 | + | **greetd + tuigreet.** Rust, minimal, ratatui-rendered. greetd is the daemon that owns VT1; tuigreet is the ratatui client that prompts for user/password and execs `sway` on successful auth. Config at [`etc/greetd/`](../etc/greetd/): `/etc/greetd/config.toml` sets up VT1 with tuigreet and a `--theme` written in ANSI color names. | |
| 395 | + | ||
| 396 | + | **The palette reaches it through the console, not through `--theme`.** tuigreet 0.9.1 parses only the sixteen ANSI names; a hex value is ignored rather than rejected, and the affected element falls back to a default, so `prompt=#8a4530` renders red. This doc claimed an Akari greeter for a while on the strength of a `--theme` that could not deliver one. What delivers it is [`usr/lib/bootc/kargs.d/10-alloy.toml`](../usr/lib/bootc/kargs.d/10-alloy.toml), which sets the Linux console's 16-color table via `vt.default_red/grn/blu`. tuigreet then asks for `white` and gets `surface.page`. The same substitution themes every VT, including the debug shell and any getty, and it costs one boot-time kernel argument rather than a patch to tuigreet. | |
| 375 | 397 | ||
| 376 | 398 | Same ratatui toolkit family as `alloy console` and `bottom`; the login screen reads as a design sibling to the rest of the Alloy chrome. | |
| 377 | 399 |