diff --git a/AGENTS.md b/AGENTS.md index 634091d..f2d45f0 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -2,7 +2,7 @@ This is the repo-wide rulebook for any agent (or human) editing Ruixen. It's a map, not a tutorial — deeper detail already lives in `README.md`, -`COMPATIBILITY.md`, `docs/CONTROL.md`, `docs/LAUNCHER.md`, `docs/KEYBINDS.md`, +`dev/README.md` (layout, workflow, testing), `COMPATIBILITY.md`, `docs/CONTROL.md`, `docs/LAUNCHER.md`, `docs/KEYBINDS.md`, and the tests themselves. Read those when you need specifics; read this first to know which rules exist at all. diff --git a/README.md b/README.md index dbd4eda..99c5480 100644 --- a/README.md +++ b/README.md @@ -1,454 +1,188 @@ -# Ruixen Shell +

Ruixen

-A connected bar, notch, and settings app for Omarchy — an OLED-black, unified -visual layer that runs as plugins inside the Omarchy shell you already use. +

An integrated desktop suite for Omarchy.

+ +

+A cohesive set of native Omarchy plugins that changes how the desktop looks, +feels and works, without replacing the shell underneath it. +

- - - - - - - - + + +
- -
Bar — Docked -
- -
Bar — Float -
- -
Notch Dashboard -
- -
Launcher -
- -
Settings -
Ruixen with a purple themeRuixen with an amber themeRuixen with a green theme
-## What's included - -- **`ruixen.bar`** — the top bar itself: app launcher, dot-style - workspace indicator, pinned quick-launch apps, weather, clock, and a - settings shortcut, all in one connected pill layout. Fresh installs use - floating glass pills with accent-toned icons. -- **`ruixen.notch`** — a center-notch dashboard with metrics, wallpapers - (and a theme switcher on the same tab: a segmented control above the - search box lists every installed Omarchy theme; clicking one applies it - via Omarchy's own `omarchy-theme-set`), - storage, music control, a notification history card (attaches to - Omarchy's own notification service, adding read/unread tracking and a - deeper backlog on top of it), and a Kanban board (see below), expanding - from the bar. -- **`ruixen.launcher`** — a Raycast/Spotlight-style command palette in a - frosted-glass card (real Hyprland compositor blur, not a fake overlay): - fuzzy-searches Omarchy menu actions and installed apps from one overlay, - plus a dedicated Search Files mode. Searches both filenames (multi-word - queries match across path components, not just the final segment) and - file *contents* (ripgrep-powered, ranked together — content matches - fill in around real filename hits rather than needing a separate mode), - across every auto-discovered drive (an internal HDD, a USB stick) - individually or all at once — plus any custom folder you add yourself, - or exclude, from this plugin's own built-in Settings extension (its - File Search page). Filter by file - type/hidden-files/names-or-contents from a small control row, or type - the same filters directly into the query (`type:image`, `in:Home`, - `hidden:true`, ...). Selecting a file shows a real preview — an - extracted video frame, an image thumbnail, or a text/markdown/JSON - snippet — plus metadata (type, dimensions/duration, created/modified, - permissions), and a contextual action menu (Tab, or right-click a row) - for opening its containing folder or copying its path/name. Its own - built-in Settings extension is also the full settings app for this - shell — Profile, Bar, Audio, Wi-Fi, Bluetooth, Display, Night Light, - Plugins — replacing the default Omarchy settings panel entirely. Full - reference: [`docs/LAUNCHER.md`](docs/LAUNCHER.md). -- **`ruixen.frame-widget`** — the OLED-black screen frame that ties the bar - and notch together visually. -- **`ruixen.pinnedapps`** — quick-launch row for apps pinned in the notch's - own app launcher. -- **`ruixen.pluginpins`** — a pin/unpin dropdown on the bar for any other - installed bar-widget plugin (yours or a third party's) — install - something new, pin it from here, no shell.json editing required. -- **`ruixen.peripherals`** — battery percentage for wireless mice, - keyboards, headsets and controllers (Bluetooth and USB receivers alike), - pin the ones you care about to show inline on the bar. Detection reads - `/sys` directly rather than Quickshell's own Bluetooth/UPower bindings, - which don't reliably cover every wireless peripheral — ported from - [xgborgeso/omarchy-peripheral-batteries](https://github.com/xgborgeso/omarchy-peripheral-batteries) - (MIT license). -- **Tray widgets** — `ruixen.tray`, `ruixen.stayawake`, - `ruixen.quickactions`, `ruixen.weather`, `ruixen.applauncher`, - `ruixen.settingsbutton`. `ruixen.stayawake` (and any stock Omarchy widget - it sits next to, like the AI usage indicator) is pinned on or off through - `ruixen.pluginpins` above, not a separate settings toggle. - -`ruixen.media` backs `ruixen.notch`'s own music control as a background -service — it never shows a bar icon of its own by design (an earlier, -oversized play/pause badge was retired), so it's locked in Settings' Plugins -list with no toggle. - -Every plugin shares the same OLED-black background, corner radii, and motion -language, so they read as one shell instead of a pile of separate widgets. - -## Documentation - -- [`docs/LAUNCHER.md`](docs/LAUNCHER.md) — the Ruixen Launcher command - palette in full: Applications/Commands search, Search Files (multi-word - matching, filters, keyboard-first query operators), the contextual - actions menu, and configuring which folders it actually searches. -- [`docs/KEYBINDS.md`](docs/KEYBINDS.md) — ready-to-use Hyprland keybind - recipes: the Ruixen Launcher command palette, Ruixen Settings (and - jumping straight to one page), the notch dashboard, the app launcher. -- [`docs/CONTROL.md`](docs/CONTROL.md) — how every plugin here is - controllable over a plain CLI call (`omarchy-shell - [args]`), the same mechanism a keybind, a script, or an AI agent all use - identically, plus the Kanban board's full command reference as a worked - example. - -## Install - -Ruixen Shell targets Omarchy `4.0.0-1` and has been live-verified through -Omarchy `4.0.4-1`. -Install from source: - -```bash -git clone https://github.com/gitcoder89431/ruixen-shell.git -cd ruixen-shell -./install.sh -``` - -An AUR package is planned but not yet published — cloning from source is the -only install path right now. - -The installer copies each plugin into `~/.config/omarchy/plugins/`, backs up -anything it would overwrite, merges Ruixen's bar/plugin config into your -existing `shell.json` rather than replacing it outright (any unrelated bar -widgets, plugins, or idle settings you already had survive), applies a -matching Hyprland window look (rounded corners + blur, see below — also -backed up if you already have a `looknfeel.lua`), and restarts the Omarchy -shell. - -After installing, add a keybind of your own for opening the Ruixen Launcher -command palette (nothing opens it out of the box — the installer -deliberately doesn't touch your Hyprland config), Ruixen Settings, or -anything else — the app launcher, jumping straight to one settings page. See -[`docs/KEYBINDS.md`](docs/KEYBINDS.md) for ready-to-use recipes, e.g.: - -```lua -o.bind("SUPER + R", "Ruixen Launcher", "omarchy-shell shell toggle ruixen.launcher") -``` - -If you want the recommended keybinds installed automatically, use the opt-in -flag: - -```bash -./install.sh --with-launcher-keybind -``` - -That flag only appends keys that are free: `SUPER+R` for Ruixen Launcher and -`SUPER+SHIFT+R` for Ruixen Settings. If either key is already bound, the -installer leaves that key untouched and prints the current binding. - -Want to see exactly what it would do first, without changing anything? - -```bash -./install.sh --dry-run -``` - -Reports Omarchy version/dependency status, plugin manifest validation -(run for real, read-only), which plugins would install fresh vs. replace -an existing copy, whether `shell.json` would be created or merged (and -what would actually change), and the Hyprland look'n'feel plan — then -exits having touched nothing. - -### If a previous run was interrupted - -An ordinary failure (a bad plugin, `omarchy restart shell` erroring out) -already rolls back cleanly on its own — you'll see that reported and don't -need to do anything special. A hard interruption is different: a closed -terminal, `kill -9`, a crash, or power loss skips that rollback entirely, -since there's no chance for it to run. If `install.sh`, `update.sh` (which -hands off to `install.sh`) or `uninstall.sh` -detects that its own previous run never reached the end, it refuses to -proceed and tells you exactly which step it had reached: - -``` -refusing to proceed: a previous install run appears to have been interrupted before finishing. - started: 2026-09-30T03:15:00Z - reached: 4/7 applying shell layout -``` - -This is almost always safe to just continue from — every plugin is fully -re-copied from source on each run, and `shell.json`/looknfeel writes are -atomic, so nothing can be left half-written. Run `./ruixen-doctor.sh` -first if you want to double-check (read-only, reports plugin drift and -runtime health), then re-run the same command with -`--acknowledge-interrupted` to continue. All of `install.sh`, `update.sh` -and `uninstall.sh` accept it, and reject any option they don't recognize -(`--help` lists what each takes). - -## Updating - -```bash -./update.sh -``` - -`./update.sh --dry-run` previews it first: current vs. candidate revision, -then the same install plan above for whatever is currently on disk -(pulling itself is skipped, so it can't preview code not yet checked out — -noted explicitly in its own output). - -Pulls the latest changes and reinstalls — same backup-then-merge -behavior as `install.sh` itself, so it's always safe to re-run. Only -works from your existing cloned checkout (it just wraps `git pull` + -`./install.sh`), so don't delete the folder after installing. - -If something looks like it didn't update, or a plugin looks out of -date: - -```bash -./ruixen-doctor.sh -``` - -A read-only diagnostic report — checks nothing changes. Prints your -git status vs the remote, whether each deployed plugin's actual file -content matches this checkout's own source byte-for-byte (catches an -update that silently didn't finish, even when nothing's version number -changed), backup history, the current bar layout (ids only), and basic -runtime health. Safe to paste the output anywhere — no paths, -hostnames, or personal config values are ever printed. +

One desktop, three themes: the bar, notch and frame follow whichever Omarchy theme you pick.

-If doctor finds drift, fix it directly: +## What is Ruixen? -```bash -./ruixen-repair.sh --dry-run # report what's broken, change nothing -./ruixen-repair.sh # actually fix it -``` +Ruixen runs as plugins inside the Omarchy shell you already use. A bar, a +notch dashboard, a launcher, a settings app and a handful of small tools +share one look and one set of behaviors, so they feel like a single desktop +instead of a pile of widgets. -Detects any plugin whose deployed files don't match this checkout -(missing entirely or content mismatch) and a dangling `looknfeel.lua` -symlink, then fixes them by running `install.sh` itself — the same -deploy path every install/update already uses, so `shell.json` and any -third-party bar entries are preserved exactly as they always are. +It is **not** a replacement shell, **not** just a theme, and **not** a +random plugin pack. Turn any piece off, or go back to stock Omarchy in one +command. -## Disabling / going back to Omarchy defaults +## The experience -Nothing here is a one-way door. +### A connected bar and notch -**Turn individual plugins off, keep everything installed:** - -```bash -omarchy plugin disable ruixen.notch -omarchy plugin disable ruixen.frame-widget -# same for any of the tray widgets: ruixen.tray, ruixen.weather, etc. +A bar of floating glass pills (or one docked strip flush with the frame) +wraps the screen in a matching frame, black or following your theme. In the middle, the notch expands +into a dashboard: music, calendar, notifications, quick toggles, volume, +wallpapers with a theme switcher, system health, and a Kanban board. -omarchy plugin enable ruixen.notch # turns it back on -``` + + + + + + +
+Floating bar +
Floating bar +
+Docked bar +
Docked bar +
+Notch dashboard +
Notch dashboard +
-If a plugin stops updating after toggling it a few times, run -`omarchy restart shell` — a full restart always clears it. +The notch also holds a three-column **Kanban board** that you and your coding +agent can both drive from a keybind or a script. -**Switch the bar back to stock Omarchy:** +

+Kanban board in the notch +

-```bash -omarchy bar defaults -``` +### One launcher for apps, commands, files and clipboard -Use `omarchy bar defaults`, not `omarchy plugin enable omarchy.bar` — that -command only swaps the bar engine and leaves Ruixen's widget layout in -place, which looks broken rather than default. `omarchy bar defaults` -resets everything (id, layout, position, transparency) in one shot. +A Raycast/Spotlight-style palette on real compositor blur. Search Omarchy +actions and installed apps, search files by name **and** contents across +every drive with live previews, browse Clipboard History, and browse, preview and +install community themes from the bjarneo collection. -To bring Ruixen's own bar back afterward, just run `./install.sh` again. + + + + + + + + + +
+Search Files with a live preview +
Search Files: names and contents, with previews +
+Clipboard History +
Clipboard History +
+Bjarneo theme browser +
Theme browser +
+Launcher palette +
The palette: actions, apps and extensions +
-**Fully remove a plugin's files:** +### Settings that live in the same place -```bash -omarchy plugin remove ruixen.bar -``` +Profile, bar layout, window look, audio, Wi-Fi, Bluetooth, display, night +light and plugins, in the same overlay as the launcher. -Backs the plugin up rather than deleting it outright (to -`~/.config/omarchy/plugins/..bak.`) — disable/enable and the -bar reset just flip settings, this is the only step that touches files at -all. +

+Ruixen Settings +

-**Uninstall everything in one shot:** +### A drop pocket for files -```bash -./uninstall.sh -``` +Drag files in from any app, drag them back out into another app or a +terminal. The **Shelf** grows out of the frame at the notch, only remembers +paths (it never copies or moves anything), and is readable and writable by +your coding agent. -Switches back to the built-in Omarchy bar, removes every Ruixen plugin's -files for real (unlike a bare `omarchy plugin remove`, which just backs a -plugin up instead of deleting it — see above; this deletes those backups -too, so nothing lingers), restores your original Hyprland window look (or -Omarchy's own default if you never had one), and restarts the shell. Only -works from your existing cloned checkout, same as `update.sh` — the -checkout itself is left alone, delete it yourself afterward if you don't -want it around. Same in-app path also lives in Ruixen Settings' own -Plugins page, behind a typed confirmation. - -`./uninstall.sh --dry-run` previews exactly what would happen first: the -bar host it would restore, which of your own widgets it would preserve, -which Ruixen plugin files it would remove, any leftover Ruixen entry it -would sweep out of `shell.json`'s `plugins[]` array, and the look'n'feel -restore plan — nothing is changed. - -## Docked bar mode (experimental) - -By default the left and right icon groups float as separate pills, inset -from the frame. Docked mode merges each side into one continuous shape -flush with the frame's corners instead — like the notch, just with one -shoulder curve per side instead of two. Not the default look, but worth -trying: +

+The Shelf holding files and images +

-```bash -./dev/ruixen-bar-mode.sh docked # merged pills, flush with the frame -./dev/ruixen-bar-mode.sh floating # back to the default separate pills -./dev/ruixen-bar-mode.sh status # show which one is active -``` +### And more -No restart needed either way — it's a live config reload. +- **Kanban** in the notch: a three-column board you and an agent can both drive. +- **Wallpapers**, including muted looping video, and an audio visualizer. +- **Plugin pinning**: install any Omarchy bar widget, pin it from the bar, no config editing. +- **Peripherals**: battery levels for wireless mice, keyboards, headsets and controllers. +- **Window look**: rounded corners and blur to match the frame, or stock square. -## Bar style +Everything is controllable from a keybind, a script or an agent through +`omarchy-shell`: see [Control](docs/CONTROL.md). -The normal style is `notch`: the center island stays visible and the bar keeps -its center reserved. `fullbar` is the saved full-width statusline skin from the -old sharp+docked experiment. It hides the notch overlay and lets the bar own the -center space again. +## Quick install ```bash -./dev/ruixen-bar-style.sh notch # current island/notch skin -./dev/ruixen-bar-style.sh fullbar # full-width statusline skin, no notch -./dev/ruixen-bar-style.sh status # show which one is active +git clone https://github.com/gitcoder89431/ruixen-shell.git +cd ruixen-shell +./install.sh ``` -This is independent from `./dev/ruixen-bar-mode.sh docked|floating` and independent -from Hyprland sharp/rounded window corners. - -## Kanban board - -`ruixen.notch`'s dashboard has a 4th tab: a fixed 3-column board (Todo / In -Progress / Done — Tab cycles through all 4 tabs, or click the column-icon in -the left rail). It's agent-native — every mutation (add, move, rename, -priority, due date, label, description) is a plain IPC call a script or -agent can drive — and it's fully editable in the notch itself now too: -per-column add buttons, hover edit/delete on each card, and a done/total -progress bar. Renaming a column stays CLI-only. Full command reference and -how the click model works: [`docs/CONTROL.md`](docs/CONTROL.md). - -## Shelf (drop pocket) +Want to see what it will do first? `./install.sh --dry-run` changes nothing. +The installer backs up what it replaces, merges into your existing +`shell.json` instead of overwriting it, and restarts the Omarchy shell. +Details, updating and uninstalling: [Installation](docs/INSTALLATION.md). -`ruixen.shelf` is a panel that grows out of the frame at the notch's position — the notch's expanded silhouette, with concave wing shoulders, hanging from the top edge: drag files in -from any app, drag them back out into another app or a terminal. It -remembers file paths, never copies anything. Drag local files over the -collapsed notch and the Shelf opens so you can drop them in and see them land -(it hides again if you drag back out without dropping). It's -agent-readable too — `omarchy-shell ruixen.shelf list` shows an agent what -you dropped, and `add /abs/path` lets it put a file on the shelf for you to -drag out. It's its own plugin rather than a notch tab so other apps stay -reachable for drag-and-drop. Details: [`docs/CONTROL.md`](docs/CONTROL.md). +## Getting started -## Window look'n'feel (Hyprland) - -Ruixen also rounds window corners and adds blur, to match the frame/bar. -Fresh installs default to the half-radius look (12px). Toggle it -independently of the plugins above: +Nothing opens the launcher out of the box, because the installer doesn't +touch your Hyprland config unless you ask. To install the recommended keys +that are still free: ```bash -hyprland/ruixen-lookfeel.sh on # rounded corners + blur, matches the frame -hyprland/ruixen-lookfeel.sh half # rounded corners at half the radius (12px), same border/blur/shadow/animations -hyprland/ruixen-lookfeel.sh off # stock Omarchy: square corners, no blur -hyprland/ruixen-lookfeel.sh square # square corners, but keeps the thin border/blur/shadow/animations -hyprland/ruixen-lookfeel.sh status # show which one is active +./install.sh --with-launcher-keybind ``` -`half` is the default middle step between `on` and `square` — the same rounded -look at half the corner radius, for when 24px reads too soft and sharp reads -too stark. `square` is for anyone who wants stock Omarchy's own square corners -without giving up the rest of Ruixen's look. The screen frame's own corner -rounding follows whichever of the four is active automatically when the bar is -floating. When the bar is docked, the frame's corner always stays rounded -regardless of which variant is active -- docked mode's own wider gaps already -keep real window corners well clear of that curve, so nothing clips, and it -keeps the docked bar's own corner (always rounded) visually consistent with the -frame right next to it. - -## Requirements +| Key | Opens | +|---|---| +| `SUPER+R` | Ruixen Launcher | +| `SUPER+SHIFT+R` | Ruixen Settings | +| `SUPER+CTRL+SPACE` | Wallpapers picker | +| `SUPER+D` | Shelf | -- Omarchy `4.0.0-1` (or a nearby build of the same shell generation) -- - `install.sh` checks this and warns (doesn't block) if it detects - something outside that range -- Quickshell, as provided by Omarchy -- `jq` -- the installer itself needs it to merge into your existing - `shell.json` rather than overwrite it +Or bind your own: see [Keybinds](docs/KEYBINDS.md). Then take the +[manual](docs/README.md) for a tour. -`install.sh` also checks a few optional, feature-specific dependencies -and warns (without failing) if any are missing, so you know up front -rather than discovering it later when a feature quietly doesn't work: +## Documentation -| Missing | What's unavailable | +| I want to... | Go to | |---|---| -| `ffmpeg` | Video/gif wallpaper poster generation (current/background and the lock screen won't reflect the active video/gif; the moving wallpaper itself is unaffected by this one) | -| `qt6-multimedia` (package, not command -- install a backend with it, e.g. `qt6-multimedia-ffmpeg`) | Video AND gif wallpaper playback both fail silently to start -- not part of Omarchy's own base install, only present if some other app happened to pull it in | -| `curl` | Weather data, avatar image download in Settings | -| `python3` | The bar's docked-mode toggle | -| `fastfetch` | Less detail on the health page's system-info panel | -| `cava` | The Desktop audio visualizer; the rest of Ruixen remains usable | - -## Running tests +| Find my way around | [Manual index](docs/README.md) | +| Install, update, repair or uninstall | [Installation](docs/INSTALLATION.md) | +| Search files, use the clipboard | [Launcher](docs/LAUNCHER.md) | +| Set up keybinds | [Keybinds](docs/KEYBINDS.md) | +| Change the bar or window look | [Customizing](docs/CUSTOMIZATION.md) | +| See what each plugin does | [Plugins and features](docs/PLUGINS.md) | +| Script it or hand it to an agent | [Control](docs/CONTROL.md) | +| Check version support | [`COMPATIBILITY.md`](COMPATIBILITY.md) | +| Build or contribute | [`dev/`](dev/README.md) | +| Rules for coding agents | [`AGENTS.md`](AGENTS.md) | -```bash -./tests/run-all.sh -``` - -Runs almost everything CI runs (`.github/workflows/ci.yml`) in one go: -shell script lint (`bash -n` + ShellCheck, when installed), plugin -manifest validation, the JS model tests, and the installer lifecycle/ -config/uninstall-restore tests. Each suite can also be run on its own -- -see `tests/*.sh`, every file has its own header comment explaining -what it covers. - -CI runs one additional step this doesn't: `tests/host-contract- -regression.sh` (issue #34), which fetches real source from -`github.com/basecamp/omarchy` at the exact commit `COMPATIBILITY.md` -records as reviewed and checks it still matches the host contracts this -repo depends on. Deliberately excluded from `run-all.sh` since it needs -network access and GitHub API auth that a local run shouldn't require -- -run it directly (`./tests/host-contract-regression.sh`) if you want to -check it yourself. - -The installer tests (`tests/install-lifecycle.sh`, `tests/shell-json- -merge.sh`, `tests/looknfeel-preserve.sh`, `tests/uninstall-bar- -restore.sh`) run against a throwaway fake `$HOME`/directory tree, never -your real config, so they're safe to run anywhere including this repo's -own checkout. - -### Manual QA: the Desktop audio visualizer - -`tests/cava-*.sh` cover the visualizer's own state/lifecycle wiring -statically, but a few things only really show up live. A couple of -minutes, not a long soak: +## Requirements -``` -1. Off -> Bars -> Segments -> Wave -2. switch 64 <-> 96 bands -3. pause/resume audio -4. enable/disable a few times -5. enter/exit fullscreen -6. kill cava once and confirm only one replacement process appears -``` +Omarchy `4.0.0-1` or a nearby build of the same shell generation (live-verified +through `4.0.4-1`), Quickshell as provided by Omarchy, and `jq`. A few optional +tools unlock specific features (video wallpapers, the audio visualizer, +weather); the installer warns about any that are missing. Full list: +[Installation](docs/INSTALLATION.md#requirements). ## Credits - **[Omarchy](https://omarchy.org)** ([github.com/basecamp/omarchy](https://github.com/basecamp/omarchy)) — the Arch/Hyprland desktop this whole project is built on top of. `omarchy-shell`, Omarchy's own Quickshell-based bar/notch/notification runtime, is what every plugin here actually loads into. - **[Ambxst](https://github.com/Axenide/Ambxst)** (by Axenide) — UI/UX design inspiration for several `ruixen.notch` panels (the dashboard layout, calendar, metrics page, wallpapers picker). Ambxst's own code is AGPL-3.0 licensed; ruixen-shell's implementations are written independently, not derived from its source. -- **[xgborgeso/omarchy-peripheral-batteries](https://github.com/xgborgeso/omarchy-peripheral-batteries)** (MIT) — `ruixen.peripherals`'s detection logic is ported from this project (see above, and the plugin's own source header for the full attribution). +- **[xgborgeso/omarchy-peripheral-batteries](https://github.com/xgborgeso/omarchy-peripheral-batteries)** (MIT) — `ruixen.peripherals`'s detection logic is ported from this project (see [Plugins](docs/PLUGINS.md), and the plugin's own source header for the full attribution). ## License diff --git a/dev/README.md b/dev/README.md new file mode 100644 index 0000000..11a080a --- /dev/null +++ b/dev/README.md @@ -0,0 +1,137 @@ +# Developing Ruixen + +For people changing Ruixen rather than using it: where things live, how it +plugs into Omarchy, the dev scripts, and how to test. The repo-wide rules for +humans and coding agents are in [`AGENTS.md`](../AGENTS.md) at the repository +root: read that first, it is deliberately short. User-facing docs are in +[`docs/`](../docs/README.md). + +## How Ruixen plugs into Omarchy + +Ruixen is a set of plugins that load **inside Omarchy's existing, long-lived +Quickshell process**. Nothing here starts its own shell. Each plugin is a +directory with a `manifest.json` (an Omarchy plugin id such as `ruixen.bar`) +and a QML entry point that is an `Item`, not a standalone `ShellRoot`. +Overlay-kind plugins (launcher, shelf) expose the lifecycle the host expects: +`open(payloadJson)`, `close()`, `toggle(payloadJson)`. + +Control goes over `omarchy-shell ` (see +[`docs/CONTROL.md`](../docs/CONTROL.md)); shared state lives in small +versioned files under `~/.local/state/ruixen/`. `AGENTS.md` §1-§4 holds the +actual rules, including which Omarchy internals not to depend on. + +## Repository layout + +```text +bars/v2/ruixen.bar/ the bar, the screen frame, docked chrome +bars/widgets/ruixen.*/ bar widgets and the notch (ruixen.notch) +ruixen.launcher/ launcher, Search Files, Settings, Clipboard, Theme browser +ruixen.shelf/ the drop-pocket overlay +ruixen.wallpaper/ video wallpaper support +ruixen.cava/ audio visualizer overlay +hyprland/ window look'n'feel variants + ruixen-lookfeel.sh +theme-overlays/ per-theme tweaks applied on install +lib/ installer helpers (shell.json merge, restore, lock, journal) +install.sh update.sh lifecycle scripts (all have --dry-run) +uninstall.sh +ruixen-doctor.sh read-only diagnostic report +ruixen-repair.sh redeploys drifted plugins via install.sh +dev/ developer helper scripts (below) +tests/ contract, model and lifecycle tests; run-all.sh +docs/ user manual +preview/ README images +``` + +Where a given feature lives: the **bar** and **frame** in +`bars/v2/ruixen.bar/` (`Bar.qml`, `BarPanel.qml`, `FrameWindow.qml`); the +**notch** and its Kanban/wallpapers/health tabs in +`bars/widgets/ruixen.notch/Overlay.qml`; the **launcher** in +`ruixen.launcher/Launcher.qml` with each extension under +`ruixen.launcher/extensions/`; the **Settings** app in +`ruixen.launcher/extensions/settings/`; the **Shelf** in `ruixen.shelf/`. +The bar, notch and Shelf are one visual surface by design: read `AGENTS.md` +§9 before touching any of them. + +## Dev scripts + +| Script | What it does | +|---|---| +| `dev/ruixen-bar-mode.sh docked\|floating\|status` | Switch the bar between merged (docked) and separate (floating) pills; live, no restart | +| `dev/ruixen-bar-style.sh notch\|fullbar\|status` | Switch between the notch skin and the full-width statusline skin | +| `hyprland/ruixen-lookfeel.sh on\|half\|square\|off\|status` | Window corner/blur variants | +| `./ruixen-doctor.sh` | Read-only report: git state, plugin drift by content hash, bar layout, runtime health, clipboard capture | +| `./ruixen-repair.sh [--dry-run]` | Redeploy plugins that drifted from this checkout | + +The first two are described for users in +[`docs/CUSTOMIZATION.md`](../docs/CUSTOMIZATION.md). + +## Local workflow + +1. Edit in a checkout, run `./install.sh --dry-run` to see what a deploy + would change, then `./install.sh` to deploy it. +2. For runtime, QML or IPC changes do a real `omarchy restart shell` + rather than trusting hot reload, and check + `journalctl --user -b 0` for `is not a type`, `Type ... unavailable`, + `TypeError` and binding loops. Neither `omarchy plugin validate` nor the + test suite compiles QML, so a missing `import` only shows up there. +3. `omarchy plugin validate ` after manifest or structure changes. +4. Run the tests (below) before pushing. + +The full checklist, with the incidents behind each item, is `AGENTS.md` §8. + +## Compatibility + +[`COMPATIBILITY.md`](../COMPATIBILITY.md) is the ledger of which Omarchy and +Quickshell versions have actually been reviewed. Don't bump its reviewed +versions until that version has really been reviewed; a bump is a claim of +verification. + +## Running tests + +```bash +./tests/run-all.sh +``` + +Runs almost everything CI runs (`.github/workflows/ci.yml`) in one go: +shell script lint (`bash -n` + ShellCheck, when installed), plugin +manifest validation, the JS model tests, and the installer lifecycle/ +config/uninstall-restore tests. Each suite can also be run on its own -- +see `tests/*.sh`, every file has its own header comment explaining +what it covers. + +CI runs one additional step this doesn't: `tests/host-contract- +regression.sh` (issue #34), which fetches real source from +`github.com/basecamp/omarchy` at the exact commit `COMPATIBILITY.md` +records as reviewed and checks it still matches the host contracts this +repo depends on. Deliberately excluded from `run-all.sh` since it needs +network access and GitHub API auth that a local run shouldn't require -- +run it directly (`./tests/host-contract-regression.sh`) if you want to +check it yourself. + +The installer tests (`tests/install-lifecycle.sh`, `tests/shell-json- +merge.sh`, `tests/looknfeel-preserve.sh`, `tests/uninstall-bar- +restore.sh`) run against a throwaway fake `$HOME`/directory tree, never +your real config, so they're safe to run anywhere including this repo's +own checkout. + +### Live checks + +`tests/live-shelf-ipc.sh` drives the Shelf's real IPC boundary against a +running shell, so it is outside `run-all.sh` and CI (it skips itself when no +shell is running). Run it after a real `omarchy restart shell` when you +change the Shelf. + +### Manual QA: the Desktop audio visualizer + +`tests/cava-*.sh` cover the visualizer's own state/lifecycle wiring +statically, but a few things only really show up live. A couple of +minutes, not a long soak: + +``` +1. Off -> Bars -> Segments -> Wave +2. switch 64 <-> 96 bands +3. pause/resume audio +4. enable/disable a few times +5. enter/exit fullscreen +6. kill cava once and confirm only one replacement process appears +``` diff --git a/docs/CUSTOMIZATION.md b/docs/CUSTOMIZATION.md new file mode 100644 index 0000000..cea8a4b --- /dev/null +++ b/docs/CUSTOMIZATION.md @@ -0,0 +1,63 @@ +# Customizing Ruixen + +Look-and-feel options that sit on top of a working install. Most of these +are also reachable from **Ruixen Settings** (open it with the keybind from +[`KEYBINDS.md`](KEYBINDS.md)); the commands below are the same switches from +a terminal. Back to the [manual index](README.md). + +## Docked bar mode (experimental) + +By default the left and right icon groups float as separate pills, inset +from the frame. Docked mode merges each side into one continuous shape +flush with the frame's corners instead — like the notch, just with one +shoulder curve per side instead of two. Not the default look, but worth +trying: + +```bash +./dev/ruixen-bar-mode.sh docked # merged pills, flush with the frame +./dev/ruixen-bar-mode.sh floating # back to the default separate pills +./dev/ruixen-bar-mode.sh status # show which one is active +``` + +No restart needed either way — it's a live config reload. + +## Bar style + +The normal style is `notch`: the center island stays visible and the bar keeps +its center reserved. `fullbar` is the saved full-width statusline skin from the +old sharp+docked experiment. It hides the notch overlay and lets the bar own the +center space again. + +```bash +./dev/ruixen-bar-style.sh notch # current island/notch skin +./dev/ruixen-bar-style.sh fullbar # full-width statusline skin, no notch +./dev/ruixen-bar-style.sh status # show which one is active +``` + +This is independent from `./dev/ruixen-bar-mode.sh docked|floating` and independent +from Hyprland sharp/rounded window corners. + +## Window look'n'feel (Hyprland) + +Ruixen also rounds window corners and adds blur, to match the frame/bar. +Fresh installs default to the half-radius look (12px). Toggle it +independently of the plugins above: + +```bash +hyprland/ruixen-lookfeel.sh on # rounded corners + blur, matches the frame +hyprland/ruixen-lookfeel.sh half # rounded corners at half the radius (12px), same border/blur/shadow/animations +hyprland/ruixen-lookfeel.sh off # stock Omarchy: square corners, no blur +hyprland/ruixen-lookfeel.sh square # square corners, but keeps the thin border/blur/shadow/animations +hyprland/ruixen-lookfeel.sh status # show which one is active +``` + +`half` is the default middle step between `on` and `square` — the same rounded +look at half the corner radius, for when 24px reads too soft and sharp reads +too stark. `square` is for anyone who wants stock Omarchy's own square corners +without giving up the rest of Ruixen's look. The screen frame's own corner +rounding follows whichever of the four is active automatically when the bar is +floating. When the bar is docked, the frame's corner always stays rounded +regardless of which variant is active -- docked mode's own wider gaps already +keep real window corners well clear of that curve, so nothing clips, and it +keeps the docked bar's own corner (always rounded) visually consistent with the +frame right next to it. diff --git a/docs/INSTALLATION.md b/docs/INSTALLATION.md new file mode 100644 index 0000000..19da130 --- /dev/null +++ b/docs/INSTALLATION.md @@ -0,0 +1,218 @@ +# Installing and maintaining Ruixen + +Everything about getting Ruixen onto your machine, keeping it current, and +getting back out again. For the two-minute version, see the +[README](../README.md#quick-install). Back to the [manual index](README.md). + +## Install + +Ruixen targets Omarchy `4.0.0-1` and has been live-verified through +Omarchy `4.0.4-1`. +Install from source: + +```bash +git clone https://github.com/gitcoder89431/ruixen-shell.git +cd ruixen-shell +./install.sh +``` + +An AUR package is planned but not yet published — cloning from source is the +only install path right now. + +The installer copies each plugin into `~/.config/omarchy/plugins/`, backs up +anything it would overwrite, merges Ruixen's bar/plugin config into your +existing `shell.json` rather than replacing it outright (any unrelated bar +widgets, plugins, or idle settings you already had survive), applies a +matching Hyprland window look (rounded corners + blur, see below — also +backed up if you already have a `looknfeel.lua`), and restarts the Omarchy +shell. + +After installing, add a keybind of your own for opening the Ruixen Launcher +command palette (nothing opens it out of the box — the installer +deliberately doesn't touch your Hyprland config), Ruixen Settings, or +anything else — the app launcher, jumping straight to one settings page. See +[`docs/KEYBINDS.md`](KEYBINDS.md) for ready-to-use recipes, e.g.: + +```lua +o.bind("SUPER + R", "Ruixen Launcher", "omarchy-shell shell toggle ruixen.launcher") +``` + +If you want the recommended keybinds installed automatically, use the opt-in +flag: + +```bash +./install.sh --with-launcher-keybind +``` + +That flag only appends keys that are free: `SUPER+R` for Ruixen Launcher, +`SUPER+SHIFT+R` for Ruixen Settings, `SUPER+CTRL+SPACE` for the wallpapers +picker and `SUPER+D` for the Shelf. If a key is already bound, the installer +leaves that key untouched and prints the current binding. + +Want to see exactly what it would do first, without changing anything? + +```bash +./install.sh --dry-run +``` + +Reports Omarchy version/dependency status, plugin manifest validation +(run for real, read-only), which plugins would install fresh vs. replace +an existing copy, whether `shell.json` would be created or merged (and +what would actually change), and the Hyprland look'n'feel plan — then +exits having touched nothing. + +### If a previous run was interrupted + +An ordinary failure (a bad plugin, `omarchy restart shell` erroring out) +already rolls back cleanly on its own — you'll see that reported and don't +need to do anything special. A hard interruption is different: a closed +terminal, `kill -9`, a crash, or power loss skips that rollback entirely, +since there's no chance for it to run. If `install.sh`, `update.sh` (which +hands off to `install.sh`) or `uninstall.sh` +detects that its own previous run never reached the end, it refuses to +proceed and tells you exactly which step it had reached: + +``` +refusing to proceed: a previous install run appears to have been interrupted before finishing. + started: 2026-09-30T03:15:00Z + reached: 4/7 applying shell layout +``` + +This is almost always safe to just continue from — every plugin is fully +re-copied from source on each run, and `shell.json`/looknfeel writes are +atomic, so nothing can be left half-written. Run `./ruixen-doctor.sh` +first if you want to double-check (read-only, reports plugin drift and +runtime health), then re-run the same command with +`--acknowledge-interrupted` to continue. All of `install.sh`, `update.sh` +and `uninstall.sh` accept it, and reject any option they don't recognize +(`--help` lists what each takes). + +## Updating + +```bash +./update.sh +``` + +`./update.sh --dry-run` previews it first: current vs. candidate revision, +then the same install plan above for whatever is currently on disk +(pulling itself is skipped, so it can't preview code not yet checked out — +noted explicitly in its own output). + +Pulls the latest changes and reinstalls — same backup-then-merge +behavior as `install.sh` itself, so it's always safe to re-run. Only +works from your existing cloned checkout (it just wraps `git pull` + +`./install.sh`), so don't delete the folder after installing. + +If something looks like it didn't update, or a plugin looks out of +date: + +```bash +./ruixen-doctor.sh +``` + +A read-only diagnostic report — checks nothing changes. Prints your +git status vs the remote, whether each deployed plugin's actual file +content matches this checkout's own source byte-for-byte (catches an +update that silently didn't finish, even when nothing's version number +changed), backup history, the current bar layout (ids only), basic +runtime health, and whether Omarchy's clipboard capture is alive (useful when +Clipboard History shows old entries but never new copies). Safe to paste the output anywhere — no paths, +hostnames, or personal config values are ever printed. + +If doctor finds drift, fix it directly: + +```bash +./ruixen-repair.sh --dry-run # report what's broken, change nothing +./ruixen-repair.sh # actually fix it +``` + +Detects any plugin whose deployed files don't match this checkout +(missing entirely or content mismatch) and a dangling `looknfeel.lua` +symlink, then fixes them by running `install.sh` itself — the same +deploy path every install/update already uses, so `shell.json` and any +third-party bar entries are preserved exactly as they always are. + +## Disabling / going back to Omarchy defaults + +Nothing here is a one-way door. + +**Turn individual plugins off, keep everything installed:** + +```bash +omarchy plugin disable ruixen.notch +omarchy plugin disable ruixen.shelf +# same for any of the tray widgets: ruixen.tray, ruixen.weather, etc. + +omarchy plugin enable ruixen.notch # turns it back on +``` + +If a plugin stops updating after toggling it a few times, run +`omarchy restart shell` — a full restart always clears it. + +**Switch the bar back to stock Omarchy:** + +```bash +omarchy bar defaults +``` + +Use `omarchy bar defaults`, not `omarchy plugin enable omarchy.bar` — that +command only swaps the bar engine and leaves Ruixen's widget layout in +place, which looks broken rather than default. `omarchy bar defaults` +resets everything (id, layout, position, transparency) in one shot. + +To bring Ruixen's own bar back afterward, just run `./install.sh` again. + +**Fully remove a plugin's files:** + +```bash +omarchy plugin remove ruixen.bar +``` + +Backs the plugin up rather than deleting it outright (to +`~/.config/omarchy/plugins/..bak.`) — disable/enable and the +bar reset just flip settings, this is the only step that touches files at +all. + +**Uninstall everything in one shot:** + +```bash +./uninstall.sh +``` + +Switches back to the built-in Omarchy bar, removes every Ruixen plugin's +files for real (unlike a bare `omarchy plugin remove`, which just backs a +plugin up instead of deleting it — see above; this deletes those backups +too, so nothing lingers), restores your original Hyprland window look (or +Omarchy's own default if you never had one), and restarts the shell. Only +works from your existing cloned checkout, same as `update.sh` — the +checkout itself is left alone, delete it yourself afterward if you don't +want it around. Same in-app path also lives in Ruixen Settings' own +Plugins page, behind a typed confirmation. + +`./uninstall.sh --dry-run` previews exactly what would happen first: the +bar host it would restore, which of your own widgets it would preserve, +which Ruixen plugin files it would remove, any leftover Ruixen entry it +would sweep out of `shell.json`'s `plugins[]` array, and the look'n'feel +restore plan — nothing is changed. + +## Requirements + +- Omarchy `4.0.0-1` (or a nearby build of the same shell generation) -- + `install.sh` checks this and warns (doesn't block) if it detects + something outside that range +- Quickshell, as provided by Omarchy +- `jq` -- the installer itself needs it to merge into your existing + `shell.json` rather than overwrite it + +`install.sh` also checks a few optional, feature-specific dependencies +and warns (without failing) if any are missing, so you know up front +rather than discovering it later when a feature quietly doesn't work: + +| Missing | What's unavailable | +|---|---| +| `ffmpeg` | Video/gif wallpaper poster generation (current/background and the lock screen won't reflect the active video/gif; the moving wallpaper itself is unaffected by this one) | +| `qt6-multimedia` (package, not command -- install a backend with it, e.g. `qt6-multimedia-ffmpeg`) | Video AND gif wallpaper playback both fail silently to start -- not part of Omarchy's own base install, only present if some other app happened to pull it in | +| `curl` | Weather data, avatar image download in Settings | +| `python3` | The bar's docked-mode toggle | +| `fastfetch` | Less detail on the health page's system-info panel | +| `cava` | The Desktop audio visualizer; the rest of Ruixen remains usable | diff --git a/docs/PLUGINS.md b/docs/PLUGINS.md new file mode 100644 index 0000000..71162f4 --- /dev/null +++ b/docs/PLUGINS.md @@ -0,0 +1,106 @@ +# Plugins and features reference + +What each Ruixen plugin does, and the longer notes on the notch's Kanban +board and the Shelf. The [README](../README.md) shows the product; this is +the inventory. Technical ids (`ruixen.bar`, `ruixen.launcher`, ...) are +unchanged. Back to the [manual index](README.md). + +## What's included + +- **`ruixen.bar`** — the top bar itself: app launcher, dot-style + workspace indicator, pinned quick-launch apps, weather, clock, and a + settings shortcut, all in one connected pill layout. Fresh installs use + floating glass pills with accent-toned icons. +- **`ruixen.notch`** — a center-notch dashboard with metrics, wallpapers + (and a theme switcher on the same tab: a segmented control above the + search box lists every installed Omarchy theme; clicking one applies it + via Omarchy's own `omarchy-theme-set`), + storage, music control, a notification history card (attaches to + Omarchy's own notification service, adding read/unread tracking and a + deeper backlog on top of it), and a Kanban board (see below), expanding + from the bar. +- **`ruixen.launcher`** — a Raycast/Spotlight-style command palette in a + frosted-glass card (real Hyprland compositor blur, not a fake overlay): + fuzzy-searches Omarchy menu actions and installed apps from one overlay, + plus a dedicated Search Files mode. Searches both filenames (multi-word + queries match across path components, not just the final segment) and + file *contents* (ripgrep-powered, ranked together — content matches + fill in around real filename hits rather than needing a separate mode), + across every auto-discovered drive (an internal HDD, a USB stick) + individually or all at once — plus any custom folder you add yourself, + or exclude, from this plugin's own built-in Settings extension (its + File Search page). Filter by file + type/hidden-files/names-or-contents from a small control row, or type + the same filters directly into the query (`type:image`, `in:Home`, + `hidden:true`, ...). Selecting a file shows a real preview — an + extracted video frame, an image thumbnail, or a text/markdown/JSON + snippet — plus metadata (type, dimensions/duration, created/modified, + permissions), and a contextual action menu (Tab, or right-click a row) + for opening its containing folder or copying its path/name. It also hosts +a Clipboard History view (see [`LAUNCHER.md`](LAUNCHER.md#clipboard-history)) +and a browser for the bjarneo community Omarchy themes. Its own + built-in Settings extension is also the full settings app for this + shell — Profile, Bar, Audio, Wi-Fi, Bluetooth, Display, Night Light, + Plugins — replacing the default Omarchy settings panel entirely. Full + reference: [`docs/LAUNCHER.md`](LAUNCHER.md). +- **The screen frame** — the border that ties the bar and notch together + visually, in black or following the active theme. It is part of `ruixen.bar` (an earlier standalone + `ruixen.frame-widget` was merged into it). +- **`ruixen.shelf`** — the drop pocket under the notch (see + [Shelf](#shelf-drop-pocket) below). +- **`ruixen.wallpaper`** — muted looping video wallpaper support, chosen + from the notch's own Wallpapers picker; it sits alongside Omarchy's static + background rather than replacing it. +- **`ruixen.cava`** — a live, edge-docked, audio-reactive spectrum overlay, + controlled from Ruixen Settings. Needs `cava` and PipeWire. +- **`ruixen.workspaces`**, **`ruixen.power`**, **`ruixen.capturestatus`** — + bar widgets: a dots-and-pill workspace indicator, battery/power-profile/ + system stats, and a pinned screen-recording control. +- **`ruixen.pinnedapps`** — quick-launch row for apps pinned in the notch's + own app launcher. +- **`ruixen.pluginpins`** — a pin/unpin dropdown on the bar for any other + installed bar-widget plugin (yours or a third party's) — install + something new, pin it from here, no shell.json editing required. +- **`ruixen.peripherals`** — battery percentage for wireless mice, + keyboards, headsets and controllers (Bluetooth and USB receivers alike), + pin the ones you care about to show inline on the bar. Detection reads + `/sys` directly rather than Quickshell's own Bluetooth/UPower bindings, + which don't reliably cover every wireless peripheral — ported from + [xgborgeso/omarchy-peripheral-batteries](https://github.com/xgborgeso/omarchy-peripheral-batteries) + (MIT license). +- **Tray widgets** — `ruixen.tray`, `ruixen.stayawake`, + `ruixen.quickactions`, `ruixen.weather`, `ruixen.applauncher`, + `ruixen.settingsbutton`. `ruixen.stayawake` (and any stock Omarchy widget + it sits next to, like the AI usage indicator) is pinned on or off through + `ruixen.pluginpins` above, not a separate settings toggle. + +`ruixen.media` backs `ruixen.notch`'s own music control as a background +service — it never shows a bar icon of its own by design (an earlier, +oversized play/pause badge was retired), so it's locked in Settings' Plugins +list with no toggle. + +Every plugin shares the same surface (black or theme-aware, glass or solid), +corner radii, and motion language, so they read as one shell instead of a pile of separate widgets. + +## Kanban board + +`ruixen.notch`'s dashboard has a 4th tab: a fixed 3-column board (Todo / In +Progress / Done — Tab cycles through all 4 tabs, or click the column-icon in +the left rail). It's agent-native — every mutation (add, move, rename, +priority, due date, label, description) is a plain IPC call a script or +agent can drive — and it's fully editable in the notch itself now too: +per-column add buttons, hover edit/delete on each card, and a done/total +progress bar. Renaming a column stays CLI-only. Full command reference and +how the click model works: [`docs/CONTROL.md`](CONTROL.md). + +## Shelf (drop pocket) + +`ruixen.shelf` is a panel that grows out of the frame at the notch's position — the notch's expanded silhouette, with concave wing shoulders, hanging from the top edge: drag files in +from any app, drag them back out into another app or a terminal. It +remembers file paths, never copies anything. Drag local files over the +collapsed notch and the Shelf opens so you can drop them in and see them land +(it hides again if you drag back out without dropping). It's +agent-readable too — `omarchy-shell ruixen.shelf list` shows an agent what +you dropped, and `add /abs/path` lets it put a file on the shelf for you to +drag out. It's its own plugin rather than a notch tab so other apps stay +reachable for drag-and-drop. Details: [`docs/CONTROL.md`](CONTROL.md). diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..436751d --- /dev/null +++ b/docs/README.md @@ -0,0 +1,38 @@ +# Ruixen manual + +Everything beyond the [README](../README.md) lives here. Pick what you need: + +## Getting set up + +- **[Installation and maintenance](INSTALLATION.md)**: install, dry-run, + recovering from an interrupted run, updating, the doctor and repair + scripts, disabling plugins, going back to stock Omarchy, uninstalling, + and requirements. +- **[Keybinds](KEYBINDS.md)**: ready-to-use Hyprland keybind recipes for the + Launcher, Settings, the Shelf, Clipboard History, the notch and the app + launcher. + +## Using Ruixen + +- **[Ruixen Launcher](LAUNCHER.md)**: the command palette in full: + applications and commands, Search Files (names and contents, filters, + query operators), the actions menu, Clipboard History, and choosing which + folders get searched. +- **[Customizing](CUSTOMIZATION.md)**: docked or floating bar, the notch or + full-width bar style, and the Hyprland window look-and-feel. +- **[Plugins and features](PLUGINS.md)**: what each plugin does, plus the + Kanban board and the Shelf drop pocket. + +## Automating Ruixen + +- **[Control from a script or an agent](CONTROL.md)**: every plugin is + controllable over `omarchy-shell `, with the Kanban board + and the Shelf as worked examples. + +## Elsewhere in the repository + +- [`COMPATIBILITY.md`](../COMPATIBILITY.md): which Omarchy and Quickshell + versions have been reviewed. +- [`dev/README.md`](../dev/README.md): building, testing and contributing. +- [`AGENTS.md`](../AGENTS.md): the repo-wide rules for coding agents and + humans editing Ruixen. diff --git a/preview/preview_0.webp b/preview/preview_0.webp new file mode 100644 index 0000000..d885d6a Binary files /dev/null and b/preview/preview_0.webp differ diff --git a/preview/preview_1.webp b/preview/preview_1.webp new file mode 100644 index 0000000..56d854c Binary files /dev/null and b/preview/preview_1.webp differ diff --git a/preview/preview_2.webp b/preview/preview_2.webp new file mode 100644 index 0000000..8c178e9 Binary files /dev/null and b/preview/preview_2.webp differ diff --git a/preview/preview_clipboard.webp b/preview/preview_clipboard.webp new file mode 100644 index 0000000..3b28601 Binary files /dev/null and b/preview/preview_clipboard.webp differ diff --git a/preview/preview_dock.png b/preview/preview_dock.png deleted file mode 100644 index de674b9..0000000 Binary files a/preview/preview_dock.png and /dev/null differ diff --git a/preview/preview_dock.webp b/preview/preview_dock.webp new file mode 100644 index 0000000..28164ce Binary files /dev/null and b/preview/preview_dock.webp differ diff --git a/preview/preview_float.png b/preview/preview_float.png deleted file mode 100644 index 3eb20bb..0000000 Binary files a/preview/preview_float.png and /dev/null differ diff --git a/preview/preview_float.webp b/preview/preview_float.webp new file mode 100644 index 0000000..01245be Binary files /dev/null and b/preview/preview_float.webp differ diff --git a/preview/preview_kanban.webp b/preview/preview_kanban.webp new file mode 100644 index 0000000..5a2a58f Binary files /dev/null and b/preview/preview_kanban.webp differ diff --git a/preview/preview_launcher.webp b/preview/preview_launcher.webp index eab0439..d337c2d 100644 Binary files a/preview/preview_launcher.webp and b/preview/preview_launcher.webp differ diff --git a/preview/preview_launcher_files.webp b/preview/preview_launcher_files.webp new file mode 100644 index 0000000..dcaae6b Binary files /dev/null and b/preview/preview_launcher_files.webp differ diff --git a/preview/preview_notch.png b/preview/preview_notch.png deleted file mode 100644 index af85b31..0000000 Binary files a/preview/preview_notch.png and /dev/null differ diff --git a/preview/preview_notch.webp b/preview/preview_notch.webp new file mode 100644 index 0000000..723cd0e Binary files /dev/null and b/preview/preview_notch.webp differ diff --git a/preview/preview_settings.png b/preview/preview_settings.png deleted file mode 100644 index cd264b6..0000000 Binary files a/preview/preview_settings.png and /dev/null differ diff --git a/preview/preview_settings.webp b/preview/preview_settings.webp new file mode 100644 index 0000000..f4336d8 Binary files /dev/null and b/preview/preview_settings.webp differ diff --git a/preview/preview_shelf.webp b/preview/preview_shelf.webp new file mode 100644 index 0000000..51bf698 Binary files /dev/null and b/preview/preview_shelf.webp differ diff --git a/preview/preview_themes.webp b/preview/preview_themes.webp new file mode 100644 index 0000000..372e450 Binary files /dev/null and b/preview/preview_themes.webp differ diff --git a/tests/bar-style-mode.sh b/tests/bar-style-mode.sh index c2807b8..46a32cb 100755 --- a/tests/bar-style-mode.sh +++ b/tests/bar-style-mode.sh @@ -14,7 +14,7 @@ fullbar_dock_skin_qml="$repo_dir/bars/v2/ruixen.bar/FullbarDockedSkin.qml" notch_qml="$repo_dir/bars/widgets/ruixen.notch/Overlay.qml" barpanel_qml="$repo_dir/bars/v2/ruixen.bar/BarPanel.qml" style_script="$repo_dir/dev/ruixen-bar-style.sh" -readme="$repo_dir/README.md" +readme="$repo_dir/docs/CUSTOMIZATION.md" install_sh="$repo_dir/install.sh" pass=0 @@ -81,7 +81,7 @@ check "bar style helper supports fullbar" \ check "bar style helper writes bar.style" \ "$(grep -m1 -F "d.setdefault('bar', {})['style'] = '\$style'" "$style_script")" "d.setdefault('bar', {})['style'] = '\$style'" -check "README documents fullbar style" \ +check "CUSTOMIZATION.md documents fullbar style" \ "$(grep -m1 './dev/ruixen-bar-style.sh fullbar' "$readme")" './dev/ruixen-bar-style.sh fullbar # full-width statusline skin, no notch' check "install output mentions fullbar helper" \ diff --git a/tests/docs-links.sh b/tests/docs-links.sh new file mode 100755 index 0000000..2e61958 --- /dev/null +++ b/tests/docs-links.sh @@ -0,0 +1,69 @@ +#!/usr/bin/env bash +# Documentation link check. The README, docs/ and dev/ README are a +# three-layer manual that links between itself heavily; a moved or renamed +# file silently breaks those links on GitHub. This resolves every relative +# markdown link and image src in those files (file must exist, and a +# `#fragment` must match a heading in the target) and fails on any that +# does not. External http(s) links are not fetched. +set -Eeuo pipefail + +repo_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)" +cd "$repo_dir" + +python3 - "$repo_dir" <<'PY' +import os +import re +import sys + +root = sys.argv[1] +files = ["README.md", "dev/README.md", "AGENTS.md", "COMPATIBILITY.md"] +files += sorted("docs/" + f for f in os.listdir(os.path.join(root, "docs")) if f.endswith(".md")) + +link = re.compile(r"!?\[[^\]]*\]\(([^)\s]+)(?:\s+\"[^\"]*\")?\)|]+src=\"([^\"]+)\"|]+href=\"([^\"]+)\"") + + +def slug(heading): + s = heading.strip().lower() + s = re.sub(r"[^\w\s-]", "", s) + return re.sub(r"\s", "-", s) + + +def anchors(path): + out = set() + in_code = False + for line in open(path, encoding="utf-8"): + if line.startswith("```"): + in_code = not in_code + elif not in_code and re.match(r"^#{1,6}\s", line): + out.add(slug(re.sub(r"^#{1,6}\s+", "", line))) + return out + + +bad = 0 +checked = 0 +for f in files: + base = os.path.dirname(os.path.join(root, f)) + in_code = False + for n, line in enumerate(open(os.path.join(root, f), encoding="utf-8"), 1): + if line.startswith("```"): + in_code = not in_code + continue + if in_code: + continue + for m in link.finditer(line): + target = next(g for g in m.groups() if g) + if re.match(r"^[a-z][a-z0-9+.-]*:", target): + continue + path, _, frag = target.partition("#") + dest = os.path.normpath(os.path.join(base, path)) if path else os.path.join(root, f) + checked += 1 + if not os.path.exists(dest): + print(f"FAIL {f}:{n} -> {target} (no such file)") + bad += 1 + elif frag and dest.endswith(".md") and frag not in anchors(dest): + print(f"FAIL {f}:{n} -> {target} (no such heading)") + bad += 1 + +print(f"{checked - bad} passed, {bad} failed") +sys.exit(1 if bad else 0) +PY diff --git a/tests/run-all.sh b/tests/run-all.sh index e297e38..860636a 100755 --- a/tests/run-all.sh +++ b/tests/run-all.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # Runs every test in this directory and reports one final pass/fail # summary -- what CI runs (.github/workflows/ci.yml) and what local -# development should run before pushing. See README.md's own +# development should run before pushing. See dev/README.md's own # "Running tests" section for what each individual script covers. set -Eeuo pipefail @@ -19,6 +19,7 @@ suites=( "$script_dir/curvature-half-option.sh" "$script_dir/notch-kanban-gui.sh" "$script_dir/shelf-plugin.sh" + "$script_dir/docs-links.sh" "$script_dir/notch-theme-switcher.sh" "$script_dir/glass-profile-contract.sh" "$script_dir/glass-tint-contract.sh"