freefallingsnow/snowdesktop/snowdesktop-lua-widget

Claude Code and agent skill by freefallingsnow/snowdesktop

Trust tier 2
  • community
LLM review pending
Source check pending

Checking that the SKILL.md file is still in the repository.

Create, modify, debug, visually review, validate, package, and publish SnowDesktop API v2 Lua desktop widget packages. Use for folders containing widget.json and main.lua, including callable performance evaluation, responsive layout, host-owned materials, foreground themes, localization, resources, settings, data, interactions, previews, and the snowwidget CLI.

Install

npx vskill@latest install freefallingsnow/snowdesktop/snowdesktop-lua-widget

SKILL.md

SnowDesktop Lua Widget

Build one validated package directory, never a loose Lua file and manifest:

text
my-widget/
├── widget.json
├── main.lua
├── assets/
├── modules/
├── tests/
└── LICENSE

Only add optional directories when the widget needs them. Built-in widgets live under the executable widgets directory. Installed and development packages live under data\widgets\installed and data\widgets\dev. Layouts retain the immutable package UUID, so never change an existing package ID.

Confirm the development workspace

For ordinary user-authored widget work, confirm before writing that the target package is inside the development widget directory the user opened from SnowDesktop. A random current directory, downloaded package, installed package or application directory is not an authorized development workspace merely because it contains widget.json.

If the current workspace is not the development widget directory, or that relationship cannot be established, do not create or modify the package there. Tell the user to open SnowDesktop Settings → Widgets → Component Development Tools → Open Development Widget Directory (设置 → 组件 → 组件开发工具 → 打开开发组件目录), then add or open that directory in the coding client and authorize it for the workspace. Resume after the development directory is available. Never edit data\widgets\installed as a substitute.

An explicit SnowDesktop source-repository maintenance task is the exception: built-in packages and this distributed Skill may be edited in an already authorized repository workspace.

Start with the tool contract

Resolve this Skill directory and run:

powershell
bin\snowwidget.exe capabilities

Treat its JSON as the available authoring contract. Only versions listed under executableSchemaVersions and executableApiVersions can run. Use the bundled CLI beside this Skill; a copied CLI may need --host <SnowDesktop.exe> or SNOWDESKTOP_HOST for previews.

Do not load the complete API manual by default. Select the smallest relevant source of truth:

NeedUse
Callable Lua functions and permissionssnowwidget api-contract
Declarative nodes, properties, events and limitssnowwidget view-contract
Data topics, tasks and their typed argumentssnowwidget system-contract
Function signatures for the editorlibrary/snowdesktop-v2.lua
Detailed behavior for one selected featureSearch the matching heading in references/api-v2.md
Visual ownership, themes and preview reviewreferences/visual-authoring.md
Evaluate component CPU, allocations, timers, rendering or idle costreferences/performance-evaluation.md; check snowwidget capabilities first
Steam Workshop planning and publishingreferences/workshop-publishing.md
Suspected host/API defect or contract mismatchreferences/api-troubleshooting.md, then the matching implementation in the official source

Classify before creating

For a new widget, infer a compact internal brief before writing code:

  • the user's primary task and the information that must be visible first;
  • recommended starting spans, and whether the content has a real functional

reason to restrict minimum or maximum spans;

  • ready, empty, loading, error and permission-denied states that are relevant;
  • the smallest useful interaction set and any trusted-gesture requirements;
  • data sources, permissions, persistent settings and supported locales;
  • a recognizable visual direction that still respects the host surface.

Choose one rendering path:

  • Prefer a declarative view for text, controls, lists, forms, ordinary layout,

accessibility and host-rendered interaction states.

  • Use immediate render for clocks, custom charts, freeform geometry and other

visuals whose main value depends on a canvas.

  • Do not mix the two desktop rendering paths. A descriptor must expose exactly

one local view or render function.

Choose the sizing model before writing geometry:

  • Proportional visual model — the default for visually composed widgets.

Use it for artwork, media players, clocks, instruments, custom controls and other components whose parts form one visual composition. Read layout.contentWidth() and layout.contentHeight(), and derive every visible length from width, height, vw, vh or vmin. Choose structural variants from the aspect ratio only when the content relationship benefits from a different arrangement. A vertically composed instrument may keep one structure at every ratio, while a spectrum may declare a horizontal-only grid range. Do not invent horizontal or vertical branches merely because the widget is resizable. If two surfaces have the same aspect ratio and one is scaled by k, every geometric metric should also scale by k. Avoid sizeClass, grid-span breakpoints, absolute minima and scale caps in this model. Recalculate and center the group of children that are actually visible when optional content disappears.

  • **Proportional information model — the default for desktop information

tools.** Use ui.metrics().layoutRowHeight as the shared semantic row unit. It is the visible content height of a search field, input, ordinary button or single-line item; exterior insets and gaps are not included. Use 1x for those controls and items. Derive component-owned fonts, spacing, icons, radii and strokes as stable proportions of that row height, then add the derived gaps separately. Multi-line body items use an explicit multiple of the same row unit. The host keeps the row unit at the page baseline for one- and two-row widgets, then grows it slowly with vertical span. All component-derived metrics grow with it. Horizontal span never changes them, so components with the same row span stay aligned. Use layout.rpxX() and layout.rpxY() only for component-specific axis geometry, and never derive vertical controls or rows from width. Require ui.semanticMetrics.rowUnit and use layoutRowHeight. Use layout.rpx() or vmin for isotropic decoration.

  • **Grid-density model — only for content that explicitly aligns to host grid

metrics.** Use layout.cu() and layout.fontCu() for a system-status card matrix or another component whose information units intentionally track the host grid. Grid metrics and size classes may drive those card boundaries.

  • Mix the models only for an intentional fixed-density overlay. cu and

fontCu do not grow linearly with the whole widget, so using them for a proportional component's main geometry breaks same-ratio rendering.

For a proportional plan, prefer layout.rpxX(value) and layout.rpxY(value) when axis-specific values come from a design at the manifest default span. Use layout.rpx(value) for isotropic artwork. Homogeneous formulas such as short * 0.08, width * 0.3 and math.min(width * 0.4, height * 0.6) are also appropriate. Constants used only as ratios are fine. Output clamps such as math.max(layout.cu(40), ...), fixed pixel floors, or a capped global scale make two equal-aspect surfaces render differently and should be avoided.

In the proportional information model, use ui.metrics().layoutRowHeight as the only host-owned visual scale. Derive ordinary body text, for example, as row * 12 / 28, captions as row * 10 / 28, and component spacing from the same ratio. A component font preference is a percentage multiplier over the derived font. The row already includes page and accessibility scaling; do not apply a second span scale. In the proportional visual model, derive text and geometry from rpx, the surface axes or vmin so equal-aspect surfaces remain fully proportional. Read surface-dependent layout metrics in view or render; do not cache them in setup, because later resizes can differ from the initial load-time surface.

Choose text and icon alignment according to each element's role and the intended composition. Declarative text defaults to textAlign="start" and verticalAlign="center"; do not assume a control label is horizontally centered. Set alignment explicitly when the intended placement differs from the default, and check the rendered label together with its padding and any icon. This is an alignment reminder, not a requirement to center every control.

Create a package

  1. For a new widget, use the bundled deterministic initializer rather than

rewriting the starter by hand:

``powershell & scripts\init_widget.ps1 -Destination <directory> -Slug <lowercase-hyphenated-slug> -Name <name> -Description <description> -Author <author> ``

It refuses an existing destination, generates a new UUID, replaces the localization prefix and retains one honest en-US starter locale. Add only translations you can supply reliably. Do not use it when editing an existing package; preserve that package's UUID.

  1. Replace all starter content, preview copy and example identity that remain.
  2. Keep schemaVersion and apiVersion at 2. Use SemVer for version and a

positive dataVersion.

  1. Replace starter content with a coherent first product slice. Do not leave

example names, placeholder copy, empty starter cards or unused settings.

  1. Keep only locales the package actually supports with reliable translations.

Put every visible string behind a literal l10n.tr("key"), and include every used key in every declared locale. Component text belongs in widget.json, never in the host lang/ directory.

  1. Add only features and permissions actually used. Put degradable features and

permissions in the optional arrays and probe before use.

  1. Declare package images and fonts under resources. Create handles at entry

scope and pass handles to v2 APIs. Load modules only with module.require("modules/name.lua") while the entry script loads.

  1. Use state for VM-lifetime JSON-like values and storage for persistent

values. Write persistent state only when it changes and never from a render or view callback.

  1. When a host settings change affects an active subscription or a

descriptor-level visual such as backgroundLayer.blurRadius, require settings.changeEvent and reconcile it from event.kind == "settings.changed". The event covers ordinary values, host appearance, passwords, filesystem handles and entity references, and supplies sorted affected keys. preview == true identifies an uncommitted live preview; immediate writes and preview commit or cancellation emit the current persisted or restored state with preview == false. Calls to storage.set from the component do not emit this host-settings event. Keep render and view callbacks free of subscription creation or descriptor mutation.

Surface ownership and theme contract

The SnowDesktop host owns the outer shape, material, border and selected state. By default:

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 100 of 100Pattern checks on the skill's files.
  • Model reviewNot runA model review is scheduled for the next rescan.

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
201
Repository forks
23
7-day trend score
0

Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/freefallingsnow/snowdesktop/snowdesktop-lua-widget/badge)](https://verified-skill.com/skills/freefallingsnow/snowdesktop/snowdesktop-lua-widget)

Something wrong with this skill or its page? Tell us.