Загрузка данных


velvet@void ~]$ cat SETUP.md
cat: SETUP.md: No such file or directory
[velvet@void ~]$ cd caelestia-void
[velvet@void caelestia-void]$ cat SETUP.md
# Caelestia on Void Linux — Setup Guide

Caelestia is built for Arch (pacman/AUR, systemd). Void uses XBPS and runit, and
ships **GCC 14** — while current Hyprland assumes GCC 15 (C++26). This guide
documents every step taken to get a fully working Caelestia desktop on Void.

> Run a full system update first: `sudo xbps-install -Suy`

---

## 1. Packages from the Void repos

Toolchain + everything Caelestia/Hyprland needs that *is* packaged:

```
base-devel cmake meson ninja pkgconf git zig
wayland-devel wayland-protocols pixman-devel libdrm-devel libinput-devel
libxkbcommon-devel cairo-devel pango-devel libdisplay-info-devel libseat-devel
libliftoff-devel tomlplusplus tomlplusplus-devel re2 re2-devel muparser-devel
lcms2-devel libuuid-devel hyprutils hyprwayland-scanner glslang-devel
SPIRV-Tools-devel SPIRV-Headers libzip-devel pugixml-devel librsvg-devel
file-devel libmagic fftw-devel iniparser-devel glm libgbm-devel Vulkan-Headers
qt6-base-devel qt6-declarative-devel qt6-shadertools qt6-wayland-devel
qt6-base-private-devel qt6-declarative-private-devel qt6-wayland-private-devel
cli11 jemalloc-devel cpptrace-devel libqalculate-devel aubio-devel pipewire-devel
pam-devel polkit-devel glib-devel mesa mesa-dri xorg-server-xwayland

quickshell-deps + runtime:
ddcutil brightnessctl libqalculate qalculate fish-shell swappy grim slurp
wl-clipboard foot hyprpicker matugen cliphist inotify-tools wireplumber pipewire
trash-cli eza fastfetch starship btop jq papirus-icon-theme dconf libnotify
lm_sensors power-profiles-daemon python3 python3-Pillow python3-pip fuzzel
polkit-gnome gnome-keyring elogind xdg-desktop-portal xdg-desktop-portal-gtk
qt6-svg qt6-wayland qt5ct qt6ct gammastep geoclue2 gsettings-desktop-schemas
gpu-screen-recorder upower bluez psmisc xdg-utils noto-fonts-ttf flatpak
```

---

## 2. Greeter — `ly`

`ly` is not packaged for Void. Built from source:

- Needs **Zig 0.16** — Void ships 0.13, so the official Zig 0.16.0 tarball is
  downloaded and used directly.
- `zig build installexe -Dinit_system=runit -Denable_x11_support=false -Ddefault_tty=2 -Dfallback_tty=2`
- Installs the binary, `/etc/ly/`, `/etc/pam.d/ly` (PAM file is Void-compatible —
  `-` prefixes skip missing modules; `pam_elogind.so` registers the session),
  and the runit service `/etc/sv/ly`.
- Configured for **tty2** (`/etc/sv/ly/conf`). `agetty-tty2` is disabled so ly
  owns tty2; `agetty-tty1` stays as a console.

---

## 3. Hyprland — built from source

Hyprland is **not packaged for Void** at all. The whole ecosystem is built:

### Library chain (CMake, install to `/usr`)

`hyprutils` → `hyprlang` → `hyprgraphics` → `hyprcursor` → `aquamarine` →
`hyprland-protocols` → `hyprwire` → **Hyprland 0.55.1** → `xdg-desktop-portal-hyprland`.

`hyprutils` is rebuilt from source (HEAD ≥ 0.13.1; Void packages 0.11.0).

### GCC 14 / C++26 patches

Hyprland 0.55.1 targets GCC 15. Void has GCC 14, missing three C++26 features:

1. **`operator+(string, string_view)`** (P2591) — provided by a force-included
   shim, `void-build/cxx26compat.hpp`, passed via
   `-DCMAKE_CXX_FLAGS="-include .../cxx26compat.hpp"`.
2. **`insert_range`** — one call in `src/helpers/Monitor.cpp` rewritten to
   `insert(end(), ranges::begin(r), ranges::end(r))`.
3. **`#embed`** — `src/config/lua/DefaultConfig.hpp` `#embed` replaced with the
   literal byte array of `example/hyprland.lua`.

Also: `hyprctl/src/main.cpp` `string + string_view` (fixed by the shim);
`src/xwayland/XWM.hpp:220` ternary type mismatch fixed with an explicit
`static_cast<xcb_connection_t*>`.

**`hyprwire`** (new Hyprland dep) uses `std::vector::append_range` (C++23 lib,
absent in libstdc++ 14) — all call sites rewritten to `insert(end(), …)`.

### Lua 5.5

Hyprland 0.55 requires Lua 5.5; Void ships 5.4. Lua 5.5.0 is built from source
(`make linux MYCFLAGS="-fPIC -O2"`, installed to `/usr`) with a hand-written
`/usr/lib/pkgconfig/lua5.5.pc`.

### libcava

caelestia-shell's beat detector links `libcava`, which Void's `cava` package
doesn't provide. Built from the `LukashonakV/cava` fork (`meson -Dbuild_target=lib`).

`hyprland-qtutils` is also built from source (provides `hyprland-dialog`,
`hyprland-share-picker`, etc.).

---

## 4. Quickshell + caelestia-shell

- **Quickshell**: built from **git master** (caelestia requires the git build,
  not a tagged release). Needs the Qt6 `*-private-devel` packages. The packaged
  `quickshell` is removed first.
- **caelestia-shell**: `git clone` → CMake build → install to `/etc/xdg/quickshell/caelestia`
  + the `Caelestia` QML plugin to `/usr/lib/qt6/qml/Caelestia`.
- **caelestia-cli**: `pip install --break-system-packages .` (pulls `materialyoucolor`).

---

## 5. Void adaptations (the Arch-isms)

| Arch assumption | Void fix |
|-----------------|----------|
| `app2unit` (systemd transient units) | Replaced with a direct-launch script at `/usr/local/bin/app2unit` — apps still launch, minus cgroup scoping |
| Power actions use `systemctl` | Patched to `loginctl` in the shell sources (`sessionconfig.hpp`, `launcherconfig.hpp`, `generalconfig.hpp`, `BatteryMonitor.qml`); VPN daemon start → `sv up` |
| PipeWire via systemd user services | Started from the Hyprland session — see `config/caelestia/hypr-user.conf` |
| `uwsm` (systemd-only) | Skipped; `hyprland-uwsm.desktop` removed |
| Session has no D-Bus bus | Session launched via `dbus-run-session` (the `hyprland.desktop` Exec) |
| polkit-gnome / geoclue paths | Fixed to Void's `/usr/libexec/...` in `hypr/hyprland/execs.conf` |
| GPU autodetect uses `&>` (bash-ism, breaks under dash) | `services.gpuType` forced to `generic` in `shell.json` |

---

## 6. Services (runit)

Enable by symlinking into `/var/service`:

```
elogind  polkitd  power-profiles-daemon  bluetoothd  ly
```

(`dbus`, `NetworkManager`, `udevd` are already enabled on a default install.)

### Seat / device access

elogind installed *after* boot means udev never tagged the DRM/input devices for
`seat0` — Hyprland then can't acquire the GPU. Fix (also correct on every boot
since the rules are now in place):

```
sudo udevadm control --reload
sudo udevadm trigger --action=add
```

---

## 7. Fonts

Installed to `/usr/share/fonts/caelestia/` (+ `fc-cache -f`):

- **Material Symbols Rounded** — the shell's icon font
- **CaskaydiaCove Nerd Font** — shell mono
- **Rubik** — shell UI/clock font
- **JetBrains Mono Nerd Font** — terminal font (foot)
- **Noto Sans Symbols 2** (via `noto-fonts-ttf`) — fallback for the
  Miscellaneous-Technical glyphs Claude Code and others use (`⏵ ⏺ ⎿` …)

---

## 8. Applications

- **Zen Browser (Twilight)** — `/opt/zen`, launcher `zen-browser`
- **Equibop** (Discord) — `/opt/equibop`, launcher `equibop`
- **Spotify** — Flatpak (`com.spotify.Client`)
- **Claude Desktop** — community Linux build (`patrickjaja/claude-desktop-bin`),
  `/opt/claude-desktop`, launcher `claude-desktop` (sets `CLAUDE_DISABLE_SYSTEMD_SCOPE=1`)
- **Thunar** + gvfs/tumbler — file manager
- **Neovim + LazyVim**
- **dart-sass** — `/opt/dart-sass` (for Caelestia's Discord theming)

---

## 9. VPN — sing-box

`system/sing-box/config.json` is a VLESS + REALITY client config for sing-box,
run as the runit service `/etc/sv/sing-box` with a TUN inbound. The Caelestia
shell's VPN tab toggles it.

> **The committed config is sanitized** — `uuid`, `server`, `public_key` and
> `short_id` are placeholders. Fill in your own and place it at
> `/etc/sing-box/config.json`.

---

## 10. Customizations

Set in `config/caelestia/hypr-vars.conf` / `hypr-user.conf` / `cli.json` /
`shell.json`:

- Cursor: **Bibata-Modern-Classic**
- App launcher on **Alt+Space**; Claude toggle on **Super+Shift+F23** (Copilot key)
- Special-workspace toggles wired to installed apps: Spotify (Super+M),
  Equibop (Super+D), Claude Desktop
- 3-finger workspace swipe; **hypr-dynamic-cursors** plugin (tilt mode)
- Square window corners, zero gaps, no transparency
- fastfetch shows the Void logo beside the info box
- Dark mode forced (adw-gtk3-dark, `prefer-dark`, qt6ct)

---

## 11. Power menu — Boot into Windows button

The Caelestia power menu (`modules/session/`) has a custom **Boot into
Windows** button — a one-shot reboot into the Windows install that never
touches the permanent EFI `BootOrder`.

**How it works.** A small root helper sets the EFI `BootNext` variable to
the "Windows Boot Manager" entry, then reboots. `BootNext` is consumed by
the firmware after exactly one boot, so the boot *after* Windows returns to
Void automatically. The button runs the helper through a NOPASSWD `sudo`
rule, so it's a single click with no password prompt.

| Repo file | Deploys to |
|-----------|------------|
| `shell/modules/session/Content.qml` | `/etc/xdg/quickshell/caelestia/modules/session/Content.qml` |
| `system/boot-windows/caelestia-boot-windows` | `/usr/local/bin/caelestia-boot-windows` (root, `0755`) |
| `system/boot-windows/caelestia-boot-windows.sudoers` | `/etc/sudoers.d/caelestia-boot-windows` (root, `0440`) |

Deploy:

```sh
sudo install -m 0755 -o root -g root \
    system/boot-windows/caelestia-boot-windows /usr/local/bin/caelestia-boot-windows
sudo install -m 0440 -o root -g root \
    system/boot-windows/caelestia-boot-windows.sudoers /etc/sudoers.d/caelestia-boot-windows
sudo visudo -c                                       # sanity-check sudoers
sudo cp shell/modules/session/Content.qml \
    /etc/xdg/quickshell/caelestia/modules/session/Content.qml
caelestia shell -k && caelestia shell -d             # restart the shell
```

Test the helper without rebooting:

```sh
sudo -n /usr/local/bin/caelestia-boot-windows --dry-run
```

> `shell/modules/session/Content.qml` is a vendored patch of the upstream
> `caelestia-dots/shell` module (see also §13). `install.sh` mirrors
> everything under `shell/` into `/etc/xdg/quickshell/caelestia/`, so the
> manual `sudo cp` above is only needed for a one-off update. The
> `loginctl` power-action patches from §5 are documented but not vendored.

---

## 12. Custom colour schemes

Two custom Caelestia schemes live in `config/caelestia/schemes/`:

- **goldnight** — shadotheme with the background lifted to `#1a1b1e` and the
  accent recoloured to gold `#f5c518`. The whole neutral/surface ramp is
  shifted uniformly by the background delta so panel depth is preserved.
- **ember** — a port of the `ember` Hyprland shell's palette (Quickshell + Go,
  `aqs`): a cool monochrome ink ramp (`#0e0f11`…`#e8eaec`) with a single warm
  amber accent `#f2a33c`, taken straight from its `qml/Theme/Tokens.qml`.

`install.sh` copies them into caelestia-cli's bundled `data/schemes/` dir, so
they appear in `caelestia scheme set` and the shell's scheme picker:

```sh
caelestia scheme set -n goldnight -f default -m dark
caelestia scheme set -n ember     -f default -m dark
```

> A `caelestia-cli` upgrade wipes the package's `data/schemes/` dir — rerun
> `install.sh` to reinstall the custom schemes.

---

## 13. Control-centre — disable-touchpad-while-typing toggle

A quick toggle in the control-centre "Quick Toggles" card flips Hyprland's
`input:touchpad:disable_while_typing`.

| Repo file | Deploys to |
|-----------|------------|
| `shell/modules/utilities/cards/Toggles.qml` | `/etc/xdg/quickshell/caelestia/modules/utilities/cards/Toggles.qml` |
| `config/caelestia/hypr-dwt.conf` | `~/.config/caelestia/hypr-dwt.conf` (seeded only if absent) |

**How it works.** `Toggles.qml` appends a synthetic `{id:"dwt"}` entry to
its `quickToggles` getter (so no `shell.json` override is needed) plus a
delegate with icon `do_not_touch`. Clicking it calls
`Hypr.extras.applyOptions(...)` for the immediate runtime effect and
rewrites `hypr-dwt.conf`.

**Persistence.** `hypr-dwt.conf` holds `$touchpadDisableTyping = true|false`
and is `source`d from `hypr-vars.conf`. Caelestia's `input.conf` already
does `disable_while_typing = $touchpadDisableTyping`, and `hypr-vars.conf`
is parsed after `variables.conf` but before `input.conf` — so the toggle's
choice survives shell reloads, `hyprctl reload`, scheme changes and reboots.
`hypr-dwt.conf` is a mutable runtime file: `install.sh` copies it (never
symlinks) and only if it does not already exist.

---

## Deploying this repo

```sh
git clone <this-repo> ~/caelestia-void
cd ~/caelestia-void
./install.sh          # symlinks config/ and caelestia/ into place
```

`install.sh` only places the config files — the software in sections 2–4 must
be built first.
[velvet@void caelestia-void]$