wyattowalsh/iina-plugin-starter · Archived

iina-plugin-dev

Build IINA media player plugins using the React/TypeScript starter kit. Use when the user wants to create, modify, or extend an IINA plugin — including scaffolding new plugins, adding overlay/sidebar/standalone UIs, implementing IINA API features (playback control, subtitles, playlists, menus, file access, HTTP requests), or configuring plugin preferences. Triggers on: "iina plugin", "iina-plugin", "create a plugin for IINA", "media player plugin", or similar requests about IINA plugin developm…

First seen May 11, 2026

Installation

$ npx skills add wyattowalsh/iina-plugin-starter --skill iina-plugin-dev

Stronger alternatives

This repository is archived — consider an actively maintained alternative.

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

License LICENSE
Default branch main
Open issues 0
Status Archived

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 5,756 B
  • docs SUMMARY.md 528 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 2 installs

SKILL.md

IINA Plugin Development Skill

Build plugins for IINA, the modern macOS media player, using the React/TypeScript starter kit in this repository.

Architecture

IINA plugins have two execution environments:

  1. Entry scripts (src/index.ts, src/global.ts) — Run in JavaScriptCore. No DOM. Access IINA APIs via the global iina object.
  2. React webviews (src/ui/*/) — Run in WKWebView. Full DOM + React. Communicate with entry scripts via postMessage/onMessage.
┌───────────────────────────────────────────────────┐
│ IINA Player                                        │
│  ┌──────────────┐    postMessage    ┌────────────┐ │
│  │ Entry Script  │ ◄──────────────► │  Webview   │ │
│  │ (JSContext)   │    onMessage     │  (React)   │ │
│  │               │                  │            │ │
│  │ iina.core     │                  │ Overlay    │ │
│  │ iina.mpv      │                  │ Sidebar    │ │
│  │ iina.event    │                  │ Window     │ │
│  └──────────────┘                  └────────────┘ │
└───────────────────────────────────────────────────┘

Workflow: Creating a New Plugin

  1. Copy this starter into a new directory
  2. Edit Info.json: Set name, identifier, description, author, permissions
  3. Edit src/index.ts: Add IINA API logic (event listeners, mpv observers, webview comms)
  4. Edit React UIs: Modify src/ui/overlay/App.tsx, src/ui/sidebar/App.tsx, and/or src/ui/standalone/App.tsx
  5. Wire the bridge: Use sendToPlugin() and onPluginMessage() from src/ui/bridge.ts
  6. Add message types: Define new messages in src/types.tsEntryToWebviewMessages and WebviewToEntryMessages
  7. Build: pnpm run build
  8. Test: pnpm run link → restart IINA → check Log Viewer

Critical Rules

  • Entry scripts have NO DOM. Never use window, document, fetch, console.log. Use iina.console.log() instead.
  • React code has NO iina global. Use window.iina.postMessage() / window.iina.onMessage() via the bridge.
  • Always declare permissions in Info.json before using APIs that require them.
  • Use mpv.observe() for status updates, not polling with setInterval.
  • Two tsconfigs: tsconfig.entry.json (no DOM) for entry scripts, tsconfig.ui.json (with DOM) for React.

Quick API Reference

Module Purpose Key Methods
iina.core Playback open(), osd(), pause(), resume(), seek(), togglePause()
iina.mpv mpv engine getNumber(), getString(), getFlag(), set(), command(), observe()
iina.event Events on("iina.file-loaded", fn), on("iina.window-will-close", fn)
iina.overlay Video overlay loadFile(), show(), hide(), postMessage(), onMessage()
iina.sidebar Sidebar tab loadFile(), show(), postMessage(), onMessage()
iina.standaloneWindow Window open(), loadFile(), close(), setFrame(), postMessage(), onMessage()
iina.http HTTP get(), post() — needs network-request permission
iina.file File I/O read(), write(), exists(), trash() — needs file-system permission
iina.menu Menus addItem(title, action)
iina.preferences Settings get(key), set(key, value)
iina.console Logging log(), warn(), error()
iina.global Cross-player postMessage(playerID, name, data), onMessage(name, fn)

Permissions

Declare in Info.jsonpermissions array:

  • show-osd — Display OSD messages
  • show-alert — Show native alert dialogs
  • video-overlay — Draw on video overlay
  • network-request — HTTP/WebSocket requests
  • file-system — Read/write files, execute programs

Detailed References

  • [IINA API Reference](references/iina-api-reference.md) — Complete API methods + event names
  • [Starter Structure](references/starter-structure.md) — File tree with modification guidance
  • [Info.json Spec](references/info-json-spec.md) — All manifest fields and examples