"Load to create, change or review a v2 shell plugin: a bar widget, a bar, a panel, an overlay, a menu, a window, a service or a background."
Resources
5Install
npx skillscat add vanillagreencom/vgs/vgs-plugin Install via the SkillsCat registry.
Project Instructions
Problems with a kendex-owned skill go through kendex report; check ownership in the file first.
VGS delivery policy overrides the shared workflow's mandatory review, CI-wait, branch-size and commit-hook gates. Work targets main. Reviews and PRs are optional; push directly or merge a PR immediately with gh, without a review loop, queue or CI wait. Do not arm git guards. Run scripts/validate once on the final relevant diff; use --changed for a fix round, and reuse passing results while those inputs are unchanged. Do not rerun a full battery at commit, push or submission. Use --full only for an explicit full sweep or an unmapped dependency. Keep the live-session safety rules.
vgs-plugin
Write a plugin for the v2 shell. The contract is `docs/architecture/plugins.md`; this skill holds the steps, the scaffold command and the templates.
.agents/skills/vgs-plugin/scripts/vgs-plugin new acme.weather --kinds bar-widget,service
.agents/skills/vgs-plugin/scripts/vgs-plugin check shell/plugins/acme.weatherRules
- One directory, one
manifest.jsonat its root, one QML entry point per kind. Copy the templates. The field table is `docs/architecture/plugin-manifest.md` § Manifest; an unknown key is refused. - Declare surfaces, never dependencies. Every external command the plugin runs goes in the manifest's
requirements, with its package per manager,optionalwhen the plugin works without it, and a one-linepurpose; a requirement names a command, never another plugin: `docs/architecture/requirements.md`. The core shows its notice when the plugin is installed or enabled without a command it needs; a button that asks the user to install one of the plugin's own commands callsshell.requirements.offer, never a package manager. - Imports and names: the allowed table in `references/api.md` § Allowed imports, and nothing else.
scripts/check-plugin-boundary.pyrefuses the rest. - Every entry point declares
property var shell: nullor inherits it fromBarWidget. Capabilities come fromshell.<name>after naming them incapabilities; a widget never reads them frombar. - Settings default in the manifest's
settingsand arrive asshell.settingsfor every kind; a bar widget also reads them withsetting(name, fallback). A change reaches the running instance as a newshell; hold no copy. - The manifest is the plugin's settings page: name an
iconfrom the shipped Lucide set, and give every setting a user would reasonably change, and the plugin reads, aschemaentry, withmin,maxandstepon a number and agroupfor its section; a constant earns an entry only when a user has a reason to change it. A key ishyprland.binds, never a schema entry. The Settings window draws the page from these alone: `docs/architecture/plugin-manifest.md` § Manifest, D032. - A bar widget extends
BarWidgetfromqs.Uiand sizes itself withimplicitWidthandimplicitHeight. The core assignsbar,moduleNameandsettingsafter creation; the widget sets none of them. - A bar declares
leftSection,centerSectionandrightSection. The core mounts every plugin widget; a widget the bar draws itself registers throughshell.builtins. - A surface the user works in, moves or tiles, such as a settings or tools window, is kind
window, a Hyprland window; a flyout from a widget is an anchoredpanelormenu, which closes on a click outside it: `docs/architecture/surfaces.md`, D044. - Compose the components of
qs.Ui(`references/api.md` § Components in `qs.Ui`) before drawing anything by hand. Every colour, size, font, radius, opacity and duration reads a token throughThemeinqs.Commons.scripts/check-design-tokens.pyrefuses aThemepath that names no token and reports each literal it finds. - A list whose rows each take one selection declares one
ListCursorfromqs.Uiand names it in each row'scursor; keys and hover write the list's one selection, and no row draws its own hover or highlight fill: `docs/architecture/motion.md`. - A plugin whose design must look the same under every theme owns its look instead: the manifest's
appearancenames a table of its own, every value islook.<path>fromTheme.appearance(TOKENS, LIGHT), and the theme reaches it through its mode, accent and motion scale alone. `docs/architecture/appearance.md` is the contract; it reads no otherThememember. - One owner per timer, watcher, poller and subprocess, inside the entry point's tree. A
Processgets its stdout parser before it starts. - A value the plugin's widgets, flyout or Settings page show is plugin status: declare it in the manifest's
status, name capabilitystatus, write it from the one instance that owns its source, the service, withshell.status.set, and read it fromshell.status.values. One writer per key; a credential's value never enters status, only its presence. `docs/architecture/status.md`, D037. - A plugin that needs a Hyprland key or a blur rule declares it as data in the manifest's
hyprlandkey and never writes Hyprland configuration: the core renders it into the one Hyprland layer, `docs/architecture/hyprland.md`. - No manual commands (D061): a setup step is automatic or one click. Give the status entry that shows it an
action, the plugin's own TUI or its own requirement commands, and publish when it applies; a credential is apresenceListitem naming its account of the manifest'ssecrets, which the Settings page connects through a masked field. A command a user could run shows only as the entry'scommand, behind Show command, never in a README step, a hint or a notice: `docs/architecture/status-actions.md` § Actions and secrets.vgs-plugin checkrunsscripts/check-user-commands.py. - A command the user must see or answer runs in a floating TUI: a script under the plugin's
tui/, declared as data in the manifest'stuikey and opened withshell.tui.run, never a command string: `docs/architecture/tui-capability.md` § The capability. - No cache keyed by data other applications supply without a ceiling.
- Every Quickshell type, property and signal comes from the 0.3.1 reference on Context7:
ctx7 docs /websites/quickshell_v0_3_1 <query>. - A first-party plugin's README shows a screenshot made by
scripts/readme-shots.sh, with its row indocs/images/plugins/shots.tsv: `docs/architecture/readme-images.md`. - Land with
scripts/validate manifests,scripts/validate boundaryandscripts/validate qmlclean, the last with the readback rows `workflows/new-plugin.md` step 9 names.
Workflows
| Workflow | Trigger |
|---|---|
| `workflows/new-plugin.md` | Creating a plugin from nothing |
| `workflows/review-plugin.md` | Reviewing or changing an existing plugin |
References
- `references/api.md`: what a plugin receives and may call, per kind.
- `templates/`:
manifest.json.tmpl,BarWidget.qml,Service.qml,Panel.qml,Window.qml,Bar.qml,Background.qml,tui.sh.