diff options
Diffstat (limited to 'website/src/content/docs/plugins.mdx')
| -rw-r--r-- | website/src/content/docs/plugins.mdx | 294 |
1 files changed, 294 insertions, 0 deletions
diff --git a/website/src/content/docs/plugins.mdx b/website/src/content/docs/plugins.mdx new file mode 100644 index 00000000..09d89bc0 --- /dev/null +++ b/website/src/content/docs/plugins.mdx @@ -0,0 +1,294 @@ +--- +title: Plugins +description: Author local Herdr plugins with manifest actions, event hooks, and panes. +--- + +Herdr plugins are shareable, executable workflow packages. A plugin can be a +Bash script, JavaScript app, Lua script, Rust binary, or any other argv command +your machine can run. Herdr owns the host surface: installation, manifest +validation, keybindings, terminal panes, events, invocation context, and socket +access. The plugin owns its implementation language, dependencies, files, and +durable state. + +Plugins exist so Herdr can stay lean. The core stays focused on terminal +workspaces, panes, agents, and a stable CLI/socket API. Plugins turn that +existing extension surface into reusable workflows that people can build, +install, and share without adding every workflow to Herdr itself. + +A plugin is not an SDK integration. It is a directory with a +`herdr-plugin.toml` manifest and commands Herdr can launch. Herdr validates the +manifest, injects runtime context, starts the declared commands, and records +logs. The commands call back into Herdr through the CLI or socket when they need +to do more work. + +There is no separate plugin SDK or restricted command set. The entire Herdr CLI +is the plugin API: every command in the [CLI reference](/docs/cli-reference/) is +available to a plugin, and anything you can run as `herdr ...` yourself a plugin +can run too. Most plugins should call Herdr through `HERDR_BIN_PATH`, which +points at the running Herdr binary. That keeps plugins portable across Unix +sockets and Windows named pipes. Use the [socket API](/docs/socket-api/) when +you want to send raw JSON requests yourself. + +Runtime action registration and native non-terminal plugin UI are not part of +plugin v1. Actions, event hooks, panes, and link handlers are all declared in +the manifest. + +## Manifest + +The manifest is the contract between Herdr and the plugin. It declares package +metadata, supported platforms, optional build commands, and the entrypoints +Herdr can run. + +```toml +id = "example.layout" +name = "Layout" +version = "0.1.0" +min_herdr_version = "0.7.0" +description = "Apply project layouts" +platforms = ["linux", "macos", "windows"] + +[[build]] +command = ["npm", "ci"] + +[[build]] +command = ["npm", "run", "build"] +platforms = ["linux", "macos"] + +[[actions]] +id = "apply" +title = "Apply layout" +contexts = ["workspace"] +command = ["node", "dist/apply.js"] + +[[events]] +on = "worktree.created" +command = ["herdr", "workspace", "list"] + +[[panes]] +id = "board" +title = "Project board" +placement = "overlay" +command = ["herdr-board"] + +[[link_handlers]] +id = "github-issue" +title = "Open GitHub issue" +pattern = "^https://github\\.com/[^/]+/[^/]+/(issues|pull)/[0-9]+$" +action = "apply" +``` + +Top-level `id`, `name`, `version`, and `min_herdr_version` are required. +Set `min_herdr_version` to the oldest Herdr version that supports the plugin +APIs, event names, and manifest fields your plugin uses. Herdr refuses to link +or install a plugin when its minimum version is newer than the current binary. +`description` is optional. Plugin ids may use ASCII letters, digits, dot, +colon, underscore, and hyphen. + +Action ids, pane ids, and link handler ids are local ids inside the plugin. +They may use ASCII letters, digits, colon, underscore, and hyphen, but not +dots. Each id type must be unique inside a plugin. Herdr qualifies action ids +as `plugin.id.action` when it needs a globally unique name. + +Use `platforms = ["linux", "macos", "windows"]` to declare where the plugin +can run. Build commands, actions, event hooks, panes, and link handlers can +also declare their own `platforms`; item-level platforms override the top-level +list. Local plugins without top-level `platforms` link with a warning. + +`command` values are argv arrays. Herdr does not run them through a shell, so +there is no shell expansion unless your command starts a shell itself. Put +language-specific behavior in your script or binary. + +## First plugin + +Start with a directory that contains `herdr-plugin.toml` and one executable +script or program: + +```text +my-plugin/ + herdr-plugin.toml + index.js +``` + +```toml +id = "example.workspace-tools" +name = "Workspace Tools" +version = "0.1.0" +min_herdr_version = "0.7.0" +description = "Small workspace helpers" +platforms = ["linux", "macos", "windows"] + +[[actions]] +id = "list-workspaces" +title = "List workspaces" +contexts = ["workspace"] +command = ["node", "index.js"] +``` + +Inside the command, call back into Herdr with `HERDR_BIN_PATH`: + +```js +const { spawnSync } = require("node:child_process"); + +const herdr = process.env.HERDR_BIN_PATH ?? "herdr"; +const result = spawnSync(herdr, ["workspace", "list"], { + encoding: "utf8", + stdio: ["ignore", "pipe", "pipe"], +}); + +process.stdout.write(result.stdout); +process.stderr.write(result.stderr); +process.exit(result.status ?? 1); +``` + +This example uses Node, but nothing about plugins requires Node. The manifest +could launch Bash, PowerShell, Python, Rust, Go, Lua, Bun, or any other command +available on the user's machine. + +## Install and link + +Install an example plugin: + +```bash +herdr plugin install ogulcancelik/herdr-plugin-examples/agent-telegram-notify +herdr plugin config-dir examples.agent-telegram-notify +herdr plugin list +herdr plugin action list --plugin examples.agent-telegram-notify +``` + +When you are authoring a local plugin, link the working directory instead: + +```bash +herdr plugin link /path/to/plugin +herdr plugin config-dir example.layout +herdr plugin action list --plugin example.layout +herdr plugin action invoke example.layout.apply +herdr plugin pane open --plugin example.layout --entrypoint board +herdr plugin log list --plugin example.layout +``` + +`plugin install` accepts GitHub shorthand only, such as +`owner/repo/subdir`. It clones with `git`, shows a preview in interactive +terminals, runs supported build commands, then stores the checkout under +Herdr-managed plugin data and registers it. Use `--yes` for noninteractive +installs. Reinstalling a GitHub-managed plugin replaces that managed checkout. +Installing over a locally linked plugin is refused; unlink or uninstall the +local plugin first. `plugin install` and `plugin link` create the plugin's +config and state directories, and `plugin config-dir <id>` prints the config +directory for setup docs and shell scripts. + +`plugin uninstall <id-or-source>` unregisters the plugin. For GitHub-managed +installs it also removes the managed checkout, and it accepts either the plugin +id or the same `owner/repo[/subdir...]` shorthand used by install. +`plugin unlink <id>` only unregisters a plugin and leaves files alone, which is +useful for local development. There is no separate `plugin update` in v1; +reinstall from GitHub to refresh a managed plugin. + +The example cookbook repo is `ogulcancelik/herdr-plugin-examples`. It contains +separate example plugins in subdirectories, including `agent-telegram-notify`, +`github-link-preview`, and `dev-layout-bootstrap`. These are examples to copy, +not maintained official plugins. + +## Build commands + +Build commands run during GitHub `plugin install` after confirmation and before +Herdr registers the plugin. If a build command fails, install aborts and the +plugin is not registered. `plugin link` does not run build commands; local +authors build their working tree themselves. Build commands may generate files, +but changing `herdr-plugin.toml` after the install preview aborts install. Build +failures show the plugin id, build index, working directory, command, exit +status or spawn error, and capped stdout/stderr without interpreting tool output. + +Build commands are plain argv commands too, but they do not receive runtime +plugin context or Herdr socket env. Plugin authors should document required +system tools such as `cargo`, `npm`, `bun`, or `lua`; Herdr reports build +failures but does not install missing toolchains. + +## Commands and environment + +Runtime commands run with the plugin directory as their working directory. Herdr +injects `HERDR_SOCKET_PATH`, `HERDR_BIN_PATH`, `HERDR_ENV=1`, +`HERDR_PLUGIN_ID`, `HERDR_PLUGIN_ROOT`, `HERDR_PLUGIN_CONFIG_DIR`, +`HERDR_PLUGIN_STATE_DIR`, `HERDR_PLUGIN_CONTEXT_JSON`, and any available +`HERDR_WORKSPACE_ID`, `HERDR_TAB_ID`, and `HERDR_PANE_ID`. Action commands also +receive `HERDR_PLUGIN_ACTION_ID`; event hooks receive `HERDR_PLUGIN_EVENT` and +`HERDR_PLUGIN_EVENT_JSON`; pane commands receive `HERDR_PLUGIN_ENTRYPOINT_ID`. + +`HERDR_PLUGIN_ROOT` is the installed or linked plugin directory. Do not store +user credentials or durable state there, because GitHub-installed plugin roots +are managed source checkouts. Put user-editable config such as `.env` files +under `HERDR_PLUGIN_CONFIG_DIR`, and put local runtime state under +`HERDR_PLUGIN_STATE_DIR`. Herdr creates those directories and seeds +`HERDR_PLUGIN_CONFIG_DIR` from the legacy plugin config locations when present, +but it does not validate, sync, or delete their contents. The plugin owns the +file format and lifecycle. + +`HERDR_PLUGIN_CONTEXT_JSON` can include workspace, tab, focused pane, worktree, +agent, selected text, clicked URL, and link handler fields when they are +available for that invocation. Shell plugins can read the individual env vars +for common ids, or parse the context JSON for the full shape. + +Use `HERDR_BIN_PATH` when a plugin needs to call Herdr portably from Node, +PowerShell, Bash, or another runtime. The raw socket transport behind +`HERDR_SOCKET_PATH` is OS-specific: Unix clients connect to a Unix socket path, +while Windows clients connect to a named pipe. CLI calls through +`HERDR_BIN_PATH` avoid that transport difference. See the +[CLI reference](/docs/cli-reference/) for available commands and +[socket API](/docs/socket-api/) for raw request shapes. + +## Panes + +Manifest pane `placement` defaults to `overlay`, which opens a temporary zoomed +overlay over the active pane and restores the previous focus and zoom when it +closes. A `plugin.pane.open` request can override the manifest placement with +`overlay`, `split`, `tab`, or `zoomed`. + +Plugin panes are normal Herdr panes after they open. Plugins can call standard +pane APIs such as `pane.move`, `pane.swap`, `pane.resize`, and `pane.zoom` +through the socket or CLI; Herdr keeps plugin pane ownership attached to the +underlying pane when it moves across tabs or workspaces. + +On Windows, build commands, action commands, and event commands resolve common +`PATHEXT` shims such as `npm.cmd`, `bun.cmd`, and `pnpm.cmd` when the bare +command is on `PATH`. Pane commands use Herdr's normal Windows pane launcher and +must still be valid Windows argv commands. + +## Keybindings + +Bind a key to an installed plugin action: + +```toml +[[keys.command]] +key = "prefix+l" +type = "plugin_action" +command = "example.layout.apply" +description = "apply layout" +``` + +## Link handlers + +Use `[[link_handlers]]` to route modified clicks on matching terminal URLs to a +plugin action instead of opening the URL in the browser. The modified-click +modifier is Control on every platform, including macOS, because captured +terminal mouse reports do not expose Command/Super separately from a plain +click. `pattern` is a Rust regular expression matched against the clicked URL, +and `action` must +name an action declared by the same plugin. Link handler actions receive +`invocation_source = "link_click"`, `clicked_url`, and `link_handler_id` in +`HERDR_PLUGIN_CONTEXT_JSON`; shell plugins can also read +`HERDR_PLUGIN_CLICKED_URL` and `HERDR_PLUGIN_LINK_HANDLER_ID`. Handlers are +checked in manifest order inside each plugin. + +## Storage + +There is no Herdr-managed plugin storage API in v1. Plugins that need durable +state should own their files or database. + +## Marketplace + +A plugin marketplace is coming. Plugins are already shareable today: publish a +GitHub repository with `herdr-plugin.toml`, then share +`herdr plugin install owner/repo[/subdir]`. + +If you want the plugin to appear in the website marketplace when discovery +launches, add the GitHub topic `herdr-plugin` to the repository now. See +[Marketplace](/docs/marketplace/) for how publishing and discovery will work. |
