Create Windows cursor assets with visual generation separated from deterministic packaging.
-
Inspect references and requirements.
- Preserve the user's visual identity, palette, outlines, and animation intent.
- Inspect existing
.cur, .ani, or scheme folders with cursor_tool.py inspect before modifying them.
- Read references/cursor-design.md when choosing roles, hotspots, sizes, or animation timing.
- Read references/svg-cursor-authoring.md when drawing vector sources, working without image generation, or constructing animations from SVG frames.
-
Prepare transparent source artwork.
- Reuse supplied PNG/SVG artwork when available.
- Choose the authoring path that fits the available environment:
- Raster path: when image generation is available and appropriate, use the host's installed image-generation tool or skill. Generate large transparent PNG sources; do not ask image generation to emit CUR or ANI binaries.
- Vector path: author SVG directly when image generation is unavailable, when exact geometric states matter, or when a code-native and editable result is preferable. Use a square
viewBox="0 0 256 256", declare the hotspot in viewBox coordinates, and install resvg_py for deterministic rasterization.
- Keep each static state on a square transparent canvas. Keep animated frames at identical canvas dimensions and alignment.
- Keep raw generation outputs separate from processed transparent sources. If the OpenAI
imagegen skill is installed and generated artwork has a flat background, its helper can remove the background. Resolve that skill's own directory first and use named arguments; do not pass paths positionally:
python "<imagegen-skill>\scripts\remove_chroma_key.py" --input raw.png --out source.png --auto-key border --soft-matte --transparent-threshold 12 --opaque-threshold 220 --despill
- Verify that border pixels are transparent and that the nontransparent coverage is plausible before bulk generation.
-
Preview source artwork before packaging.
python "$SkillDir\scripts\cursor_tool.py" contact-sheet source\roles\*.svg --output contact-sheet.png
- Pass only finished role artwork, not raw anchors or chroma-key inputs. Review every role on both backgrounds. Reject clipped silhouettes, unintended shadows, opaque fringes, weak contrast, inconsistent scale, and animation jitter.
- For animated roles, include representative frames in the sheet and also review a looping GIF or equivalent playback.
- Functional roles must remain immediately recognizable: the
Crosshair center must expose the exact target, IBeam must stay narrow and centered, resize directions must be unambiguous, and Hand, Pin, and Person must preserve their interaction semantics.
-
Build static cursors.
python "$SkillDir\scripts\cursor_tool.py" cur source.png pointer.cur --sizes 32,48,64,96 --hotspot 3,2
python "$SkillDir\scripts\cursor_tool.py" cur source.svg pointer.cur --sizes 32,48,64,96 --hotspot 16,12
Treat --hotspot X,Y as coordinates on the original raster image or SVG viewBox. The script scales and offsets the hotspot for every output size. Use --hotspot-relative RX,RY only when a normalized location is more reliable. Add --resample nearest for pixel-art rasters; SVG is rendered independently at each target size.
-
Build animated cursors.
- Build each PNG or SVG frame as a multi-resolution CUR first, using the same sizes and semantically identical hotspot.
- For SVG animation, author numbered static frame files such as
frame-00.svg through frame-11.svg. Change pose or transforms between frames; keep the viewBox, alignment, palette, and hotspot fixed. Do not rely on browser-only SMIL or CSS animation because ANI packages sampled cursor frames.
- Assemble frames in display order:
python "$SkillDir\scripts\cursor_tool.py" ani frames\*.cur working.ani --frame-ms 100
- Use comma-separated durations for per-frame timing, such as
--frame-ms 80,80,120,160.
-
Validate every binary and the full theme.
python "$SkillDir\scripts\cursor_tool.py" inspect pointer.cur working.ani --windows-load
python "$SkillDir\scripts\cursor_tool.py" validate-theme theme.json --require-complete --windows-load --json-out validation.json
Require valid structure, in-bounds hotspots, consistent ANI frame geometry, the intended size set, and windows_load: true on Windows. Treat binary validation and visual validation as separate mandatory gates: a loadable cursor can still be invisible on a light background or communicate the wrong interaction.
-
Package a complete scheme only after both gates pass.
python "$SkillDir\scripts\cursor_tool.py" scheme theme.json output\MyTheme
- Inspect the copied files and
Install.inf. Packaging renames cursor files to deterministic, INF-safe ASCII names based on their Windows roles. The generated installer opens Mouse Properties at the Pointers tab after installation so the user can select the new scheme.
- Do not install or activate the scheme without explicit user permission; installation changes Windows cursor configuration.