Plugin manifest reference
Field-by-field reference for the Gardn plugin manifest, command execution model, compatibility checks, and runtime limits.
Plugin manifest reference
This page specifies the manifest format accepted by Gardn plugin v1. It describes what Gardn validates and supplies; it is not an endorsement of any plugin or command.
Trust boundary: A manifest is executable configuration. Every build, action, event, and pane
commandruns as the current user, without a plugin sandbox. Commands can read or modify any resource that user can access and can start other processes. Review the complete manifest and its source before linking or installing it. The install preview and--yesbehavior are described in Install and operate plugins and integrations.
Manifest file and top-level fields
The manifest filename is gardn-plugin.toml at the plugin root.
The top-level table has these fields:
| Field | TOML type | Required | Meaning |
|---|---|---|---|
id | string | yes | Stable plugin identifier. It is trimmed, must be non-empty, and may contain ASCII letters, digits, :, ., _, and -; maximum 120 characters. |
name | string | yes | Human-readable plugin name. It is trimmed and must be non-empty. |
version | string | yes | Plugin version label. It is trimmed and must be non-empty; Gardn does not require this field to be a semantic version. |
min_gardn_version | string | yes | Semantic Gardn version required by the plugin. It must parse as a version and cannot be newer than the running Gardn release. |
description | string | no | Optional trimmed description. Blank descriptions are discarded. |
platforms | array of strings | no | Plugin-level platform allowlist: linux, macos, or windows. Omit it when support is not declared; Gardn warns that support is unknown. An empty array is invalid. |
build | array of tables | no | Build commands run during a remote GitHub install, before the checkout is moved into managed plugin storage. |
startup | array of tables | no | Commands run once when an enabled plugin is loaded during server startup. |
actions | array of tables | no | User-invokable commands, optionally scoped by action context and platform. |
events | array of tables | no | Lifecycle hook commands. |
panes | array of tables | no | Terminal pane entrypoints. |
link_handlers | array of tables | no | URL-pattern handlers that dispatch an existing action. |
min_gardn_version is required. It must be a semantic version and cannot be newer than the running Gardn release.
This fixture shows the shape of the fields without asserting that its commands are appropriate for a particular plugin:
id = "example.smoke"
name = "Smoke Plugin"
version = "0.1.0"
min_gardn_version = "0.1.0"
description = "Portable plugin smoke fixture"
platforms = ["linux", "macos", "windows"]
[[startup]]
command = ["gardn", "agent", "list"]
[[actions]]
id = "workspace-list"
title = "List workspaces"
contexts = ["workspace"]
command = ["gardn", "workspace", "list"]
[[events]]
on = "workspace.created"
command = ["gardn", "plugin", "log", "list", "--plugin", "example.smoke"]
[[panes]]
id = "board"
title = "Board"
placement = "overlay"
command = ["gardn", "workspace", "list"]Command tables
Every command is a non-empty TOML string array. Gardn trims each argument and rejects an empty argument. The first string is the executable; later strings are argv arguments. The array is passed directly to process spawning—there is no shell parsing, shell interpolation, implicit sh -c, or automatic quoting.
| Table | Required fields | Optional fields |
|---|---|---|
[[build]] | command | platforms |
[[startup]] | command | platforms |
[[actions]] | id, title, command | description, contexts, platforms |
[[events]] | on, command | platforms |
[[panes]] | id, title, command | description, platforms, placement |
[[link_handlers]] | id, title, pattern, action | platforms |
[[build]]
build entries are used by the GitHub installer only. platforms, when present, limits the build to the listed host platforms. The command runs with the manifest root as its working directory and with the current user's permissions. Build stdout and stderr are capped at 64 KiB in the failure record. Gardn checks that the manifest is unchanged after the build; a changed manifest aborts installation.
[[startup]]
startup entries run asynchronously once during server startup for enabled plugins whose effective platform list contains the host. They use the same direct argv command format and plugin-root working directory as other runtime commands. A manifest refresh does not replay them; restart the server to run startup entries again.
Startup commands receive the protected plugin environment and a context whose invocation source is startup. They appear in plugin command logs with the action id startup.
[[actions]]
idis a trimmed, non-empty local identifier of at most 120 characters. It may contain ASCII letters, digits,:,_, and-; action IDs must be unique within the plugin.titleis a trimmed, non-empty display title.descriptionis optional.contextsis an optional array ofglobal,workspace,tab,pane, orselection. It describes where the action can be offered. An action invocation can receive workspace, tab, focused-pane, selected-text, agent-state, invocation-source, correlation, or clicked-link context when those values exist.platformsoverrides the plugin-level platform list when present.commandis the direct argv command to run asynchronously.
A CLI invocation can identify an action as PLUGIN_ID.ACTION_ID; the qualified form disambiguates identical local action IDs from different plugins.
[[events]]
onis a non-empty lifecycle event name.platformsoverrides the plugin-level list when present.commandis the direct argv command to run asynchronously.
The supported event names are:
workspace.created,workspace.updated,workspace.closed,workspace.renamed,workspace.focusedtab.created,tab.closed,tab.renamed,tab.focusedpane.created,pane.closed,pane.focused,pane.moved,pane.exitedpane.agent_detected,pane.agent_status_changed
layout.updated is an internal event name but is not in the plugin hook allowlist. An unknown event is retained with a warning and is not a supported hook target.
[[panes]]
idis a unique local entrypoint identifier using the same character and length rules as an action ID.titleis a trimmed, non-empty pane title.descriptionis optional.platformsoverrides the plugin-level list when present.placementdefaults tooverlayand may beoverlay,split,tab, orzoomed.commandis the direct argv command for the pane process.
The pane command's default working directory is the plugin root. A pane-open request can select a working-directory override, placement, focus behavior, split target/direction, workspace, and additional environment entries. Gardn rejects placement parameters that do not apply to the selected placement.
Plugin pane commands run only on the Local execution host in plugin v1. If the selected Workspace or source pane resolves to an SSH execution host, Gardn rejects the request with unsupported_execution_host before it creates a pane.
[[link_handlers]]
idis a unique local identifier.titleis a trimmed, non-empty display title.patternis a non-empty regular expression; malformed regular expressions are invalid.actionis an existing action ID in the same manifest.platformsoverrides the plugin-level list when present.
A link handler does not contain a command. It dispatches its referenced action with the clicked URL and handler ID in the invocation context when the pattern matches.
Platform resolution and compatibility
Valid platform names are lowercase linux, macos, and windows. A non-empty platforms list at the plugin level is inherited by a build, startup entry, action, event, pane, or link handler that does not declare its own list. An item's list replaces, rather than extends, the plugin list. An item whose effective list does not contain the current host platform is rejected or skipped as unsupported before launch; builds and startup entries are skipped on that platform, while an action or pane request returns a platform error. The manifest loader cannot infer support when the plugin-level list is omitted, so it emits an unknown-platform warning.
The current compatibility key is min_gardn_version. A required version newer than the running release is rejected.
Execution environment and protected context
Builds and runtime commands use the plugin root as their working directory unless a pane request supplies cwd. Startup, action, and event commands receive a protected environment containing the plugin identity and context, including:
GARDN_PLUGIN_ID,GARDN_PLUGIN_ROOT,GARDN_PLUGIN_CONFIG_DIR, andGARDN_PLUGIN_STATE_DIR;GARDN_PLUGIN_CONTEXT_JSON, containing the invocation or lifecycle context;GARDN_BIN_PATHandGARDN_SOCKET_PATH, pointing to the running Gardn executable and local API socket when available;- action/event metadata such as
GARDN_PLUGIN_ACTION_ID,GARDN_PLUGIN_EVENT, andGARDN_PLUGIN_EVENT_JSONwhen applicable; GARDN_WORKSPACE_ID,GARDN_TAB_ID,GARDN_PANE_ID,GARDN_PLUGIN_CLICKED_URL, andGARDN_PLUGIN_LINK_HANDLER_IDwhen those context values exist.
GARDN_PLUGIN_CONFIG_DIR and GARDN_PLUGIN_STATE_DIR are per-plugin directories for configuration and state. Gardn also supplies GARDN_ENV=1.
For pane launches, request-supplied GARDN_* environment keys that identify the plugin, root, config/state directories, entrypoint, context, or binary are discarded and replaced with protected values. Environment keys must not be empty, contain =, or contain NUL bytes; values must not contain NUL bytes. These checks prevent malformed entries, not arbitrary plugin code execution.
Installation, scope, and persistence
A linked plugin stores its source path in the registry; linking does not copy the directory or run a build. A GitHub plugin is checked out under managed plugin storage, records its owner/repository/subdirectory/ref and resolved commit, and is registered after the preview, confirmation, and optional build succeed. A GitHub install can replace an existing GitHub installation with the same plugin identity, but cannot silently replace a locally linked plugin.
The registry is stored as plugins.json in the user's Gardn config directory and is shared by the default and named sessions. Existing per-session registries are migrated into it and deduplicated by plugin id. The managed GitHub checkout is stored in that same global config area. Installation, uninstallation, linking, and listing use the registry directly when no server is running; per-session servers load the global entries and refresh them across live handoff.
Plugin command logs and ordinary plugin-pane attribution are runtime state for a session. Per-plugin config and state directories are derived from the user-level config/state directories and remain after uninstall; uninstall removes a managed GitHub checkout but does not delete those directories. Unlinking does not delete a linked source directory.
Runtime limits and security posture
Gardn v1 intentionally provides trust and process boundaries, not a sandbox:
- at most 32 plugin commands may be in flight concurrently;
- stdout and stderr captured for a plugin command are capped at 64 KiB each;
- only the latest 200 command log records are retained in the session;
- startup entries, actions, and event hooks run asynchronously; a failed startup entry does not block server startup, and a failed event hook does not roll back the workspace change that triggered it;
- disabling or unlinking prevents new actions and hooks, but a running plugin process or pane is not automatically killed by unlinking;
- manifest identity, compatibility, command, duplicate-ID, event, platform, and link-handler references are validated before use.
Windows support in v1 is best-effort. Platform names and command/path resolution are Windows-aware, but raw socket and process-lifecycle parity with Unix-like hosts is not promised beyond behavior that has been tested on the current release. Do not infer Windows support from an omitted platforms field; declare it explicitly and test the commands on that host.
For failure symptoms and bounded diagnostics, see Troubleshoot Gardn.
Last updated on