Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions plugins/launchpad/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.DS_Store
*.log
*.tmp
84 changes: 84 additions & 0 deletions plugins/launchpad/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# Agent guide for the launchpad plugin

This folder is a Ryoku shell plugin. If you are an AI agent editing it, follow
every rule below. They are the same rules `ryoku plugin validate` enforces, so
work that breaks one will not install. This file is self-contained: you do not
need any other document to work here.

## The rules

R1 Place. A plugin is one folder named after its id. Author it under
`$(xdg-user-dir DOCUMENTS)/ryoku-plugins/<id>/` (fallback `~/ryoku-plugins/<id>/`);
`ryoku plugin new <id>` creates it there. Never write into
`~/.local/share/ryoku/plugins/` (the store's install root, receipt-owned) or
`~/.config/quickshell/` (the shipped shell).

R2 Shape. `manifest.json` at the root; `service/Main.qml` (logic, no UI);
`content/Widget.qml` (the one view); optional `content/Panel.qml` (a bar panel);
`README.md`; `LICENSE`; `assets/preview-widget.png` (a real capture); scripts
only under `bin/` with a shebang and the exec bit. Every extra file listed in
manifest `files`.

R3 Id. Lowercase `[a-z0-9][a-z0-9-]*`, unique, not a built-in widget id.

R4 Imports. Only `QtQuick*`, `Quickshell*`, `Ryoku.PluginKit`,
`Ryoku.PluginKit.Singletons`, and files inside the plugin folder. Never
`shell.*`, `Ryoku.Ui*` internals, or a relative import that climbs out of the
folder.

R5 Settings. Declared in `metadata.settings` (types the bar renders: toggle,
choice, multi, int, text); read through `pluginApi.pluginSettings` behind a
default; written only through `pluginApi.saveSetting(key, value)`. Never edit
`shell.json` or `plugins.json` directly.

R6 Commands. Every external program the plugin runs is either in its own `bin/`
or listed in `dependencies.commands`. No `sudo`, `doas`, `su`. A privileged
action is allowed only through `pkexec`, only on an explicit click, only when
listed in manifest `capabilities.privileged` (exact command strings) and
explained in README.

R7 Network. Every host the plugin talks to is listed in
`capabilities.network`. No `curl … | sh`, no downloading and running code.

R8 Files. Write only under `pluginApi.stateDir`
(`$XDG_STATE_HOME/ryoku/plugins/<id>`), `$XDG_CACHE_HOME/ryoku/plugins/<id>`, or
a temp dir. Never touch `~/.ssh`, `/etc`, shell rc files, or another plugin's
folder.

R9 Shell. No `sh -c` with a string built from settings or program output
(injection). Pass argv arrays.

R10 Secrets and binaries. No tokens, keys or credentials in the tree; no
compiled binaries (ELF/Mach-O/.so); scripts only.

R11 Honesty. `official` is never true for a community plugin. `author` is
`Name <mail>`. README says what runs, what it reads, what it writes, and every
privileged/network capability.

## The workflow

1. `ryoku plugin new <id>` scaffolds this folder (already done).
2. Edit: `service/Main.qml` for logic, `content/Widget.qml` for the view, and
`content/Panel.qml` for the bar panel. Capture `assets/preview-widget.png`.
3. `ryoku plugin validate <dir>` and fix every blocking finding (warnings are
advisory but read them).
4. `ryoku plugin add <dir> --bar --yes` to install it, then verify it on the bar
and under **QS Bar Settings > Community**.
5. `ryoku plugin share <id>` ONLY when the user asks to publish. Never share a
plugin unless asked.

## What the host sets

Every entry point receives, from the host: `pluginApi` (see below), `s` (a scale
factor), `active`, `density`, and `widthBudget`. Read them; never assign them.

`pluginApi` exposes:

- `mainInstance`: the live `service/Main.qml` instance every view shares.
- `pluginSettings`: the resolved settings object; read behind a default.
- `pluginDir`: this plugin's folder.
- `stateDir`: `$XDG_STATE_HOME/ryoku/plugins/<id>`; the only place to write.
- `saveSetting(key, value)`: persist one setting.
- `panelOpen` (bool), `openPanel()`, `closePanel()`, `togglePanel()`: the bar
panel controls (present but inert off the bar). The sanctioned widget click is
`onClicked: pluginApi.togglePanel()`.
4 changes: 4 additions & 0 deletions plugins/launchpad/CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# CLAUDE.md

Read `AGENTS.md` in this folder before editing anything here.
It holds every rule this plugin must follow and the full authoring workflow.
21 changes: 21 additions & 0 deletions plugins/launchpad/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2026 guyb

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
70 changes: 70 additions & 0 deletions plugins/launchpad/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Launchpad

A Ryoku bar plugin (`launchpad`): one tile mark on the QS Bar that opens a
pinboard panel.

![panel](assets/preview-panel.png) ![edit mode](assets/preview-edit.png)

- **Widgets**: the widgets you pick, as tabs: **Clock, Calendar, Music** (any
MPRIS player), **All-in-one** (clock + weather + visualizer), **System stats**
(CPU, memory, swap, load, uptime), **Weather** (now + 5 days), **Notes** and
**Visualizer** (a cava spectrum), plus every desktop-widget plugin you have
installed from Ryostore, mounted in the panel the way the desktop mounts it.
- **Pinned apps**: your favourite apps as a grid; click to launch.
- **Commands**: one-click chips that run a command.

Click **EDIT** to change any of it:

- every section (Widgets, Pinned, Commands) gets a grip to **drag** it into place
and a **HIDE / SHOW** pill;
- widgets, pinned apps and commands turn into lists: **drag** a row by its grip
to reorder, **×** to remove;
- **Pin an app** opens a search, the widget list offers every widget not yet
picked, and a label + command row adds a command.

Everything is also in QS Bar Settings > Community > Launchpad.

## What it runs, reads and writes

commands, exactly as you typed them, in your terminal (`ryoku-app terminal --`), as an argv split on spaces (quotes group
commands, exactly as you typed them, as an argv split on spaces (quotes group
words). There is **no shell**, so pipes, `&&` and `$VARS` do nothing; point a
command at a script on your `PATH` if you need them. It also runs
`ryoku-shell icons` once (the icon index), and `cava -p <stateDir>/cava.conf`
only while the Visualizer or All-in-one tab is on screen.
- **Reads**: the installed desktop entries, `ryoku plugin list --json` (to find
desktop-widget plugins; their own code then runs inside the panel), the MPRIS
players on the session bus, the shell daemon's `weather` feed over its local
socket (`$XDG_RUNTIME_DIR/ryoku-shell.sock`; Ryoku does the fetch, so set
your location and units in Ryoku Hub), `/proc/loadavg`, `/proc/uptime`, `/proc/stat` and `/proc/meminfo`
(every 2 s, only while the panel is open).
- **Writes**: its own settings, through the bar (`pluginApi.saveSetting`), and
your notes and the cava config to `$XDG_STATE_HOME/ryoku/plugins/launchpad/`. A hosted
desktop-widget plugin writes only to its own state folder, as it does on the desktop.
- **Network**: none. **Privileged**: none.

## Settings

QS Bar Settings > Community > Launchpad.

| key | type | default | description |
| ------------ | ------ | -------------------------------------------------------- | ----------------------------------------- |
| showWidgets | toggle | true | Show the Widgets section |
| showPinned | toggle | true | Show the Pinned section |
| showCommands | toggle | true | Show the Commands section |
| sectionOrder | text | `widgets pinned commands` | Section order |
| widgetList | text | `calendar music notes` | Widget tabs in order: `clock calendar music aio stats weather notes visualizer`, `plugin:<id>` for a store widget |
| apps | text | (empty) | Pinned desktop ids, space-separated |
| columns | int | 5 | App grid columns (3–8) |
| commands | text | `Lock=loginctl lock-session ; Suspend=systemctl suspend` | `Label=command` pairs split by ` ; ` |

## Install

```
ryoku plugin validate .
ryoku plugin add . --bar --yes
```

## Author

guyb <[email protected]>. Community-made (`official` is false). MIT licence.
Binary file added plugins/launchpad/assets/preview-edit.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added plugins/launchpad/assets/preview-panel.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added plugins/launchpad/assets/preview-widget.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading