Getting Started
Requirements
- Shire 1.14 or newer (the build that contains Plugin API 1.0).
- The interpreter for your language:
- Python 3.10+ for
language: "python"; - Node.js 18+ for
language: "node"/"typescript"; - .NET 8 runtime/SDK for
language: "dotnet"; - Rust or MSVC for
language: "executable"compiled plugins.
- Python 3.10+ for
- Python is also used by the
shire-plugindeveloper CLI.
Five-minute Python plugin
From the Shire repository:
python tools\shire-plugin\shire_plugin.py init `
--lang python `
--name "My First Plugin" `
--id com.example.myplugin `
--dir C:\dev\my-plugin
The generated project contains:
my-plugin/
manifest.json
main.py
shire_sdk.py
main.py creates a plugin, logs a line, shows a notification, adds a text and
a button to the Plugin Manager, and runs the event loop.
Edit main.py, then test it against the standalone mock Host. No Genshin
session is needed:
cd C:\dev\my-plugin
python C:\path\to\Shire-main\tools\shire-plugin\shire_plugin.py test .
The CLI starts shire_mock_host.exe, reads the pipe/token it prints, launches
your plugin as a child process with the SHIRE_PLUGIN_* variables, and reports
whether it stayed connected.
Pack the plugin:
python C:\path\to\Shire\tools\shire-plugin\shire_plugin.py pack .
That writes my-plugin.shiremod, a stored ZIP with manifest.json at the root
and the Python SDK bundled.
Install in Shire
- Open Shire's menu.
- Open Config and click Plugins → Open Plugin Manager, or press
F9. - Click Install .shiremod and choose the package.
- Select the plugin. Its declared permissions are listed. Approve the ones it needs with the checkboxes or Approve all.
- Tick Enabled. The Host launches the plugin process and waits for its handshake.
The plugin's UI appears in the same manager window. The plugin can show notifications, read storage and subscribe to events.
Manifest
{
"id": "com.example.myplugin",
"name": "My First Plugin",
"version": "1.0.0",
"author": "Developer",
"description": "Example Shire plugin",
"apiVersion": "1.0",
"language": "python",
"entrypoint": "main.py",
"permissions": ["player.read", "ui.create", "notifications.show"]
}
The id must be unique and stable. The Host stores the plugin under
%LOCALAPPDATA%\Shire\plugins\<id> and keeps its settings in
data/storage.json.
First useful plugin: player position
from shire_sdk import Plugin
plugin = Plugin()
position = plugin.player_position()
plugin.set_ui([
plugin.text("Player", "title"),
plugin.text(f"X {position['x']:.1f}", "x"),
plugin.text(f"Y {position['y']:.1f}", "y"),
plugin.text(f"Z {position['z']:.1f}", "z"),
plugin.button("refresh", "Refresh"),
])
def on_ui(component, kind, value):
if component == "refresh":
p = plugin.player_position()
plugin.set_ui([
plugin.text("Player", "title"),
plugin.text(f"X {p['x']:.1f}", "x"),
plugin.text(f"Y {p['y']:.1f}", "y"),
plugin.text(f"Z {p['z']:.1f}", "z"),
plugin.button("refresh", "Refresh"),
])
plugin.on_ui_event(on_ui)
plugin.run()
Set "permissions": ["player.read", "ui.create"] and approve both in the
manager. The Host returns copies of numbers; the plugin never receives a game
pointer.
Development loop
shire-plugin test <dir>runs one launch against the mock Host.shire-plugin dev <dir>keeps the mock Host alive; use it while iterating.shire-plugin validate <dir>checks the manifest and entrypoint.shire-plugin build <dir>builds TypeScript, Rust, C++ or C# projects.shire-plugin pack <dir>creates.shiremod.shire-plugin init --lang ...generates a new project.
The production Plugin Manager shows plugin logs. The mock Host writes a local
debug log at %TEMP%\shire_host_debug.log (mock builds only).