Skip to main content

zsh-plugin

Zsh plugins under the Z-Shell Zsh Plugin Standard 2. Use when creating a new Zsh plugin or plugin skeleton, or when maintaining an existing one, including bringing it to Standard 2, adding or changing functions, completions, configuration or unload, and wiring ZUnit and zsh-lint CI. Writing the ZUnit tests themselves belongs to zunit; a read-only compliance review belongs to the zsh-plugin-reviewer agent in z-shell/.github.

Source facts

Repository
z-shell/agent-skills
Last source activity
October 7, 2026 at 02:26
Detected SKILL.md language
English
Stars
0
Forks
0

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

File Explorer
2 files

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
zsh-plugin
description
Zsh plugins under the Z-Shell Zsh Plugin Standard 2. Use when creating a new Zsh plugin or plugin skeleton, or when maintaining an existing one, including bringing it to Standard 2, adding or changing functions, completions, configuration or unload, and wiring ZUnit and zsh-lint CI. Writing the ZUnit tests themselves belongs to zunit; a read-only compliance review belongs to the zsh-plugin-reviewer agent in z-shell/.github.
# Create and maintain Zsh plugins Work against the canonical Zsh standard and the owning repository's local contract. The skill supplies plugin-specific procedure, not independent Zsh semantics. ## Establish the contract Before creating or changing a plugin: 1. Read the canonical standards in `z-shell/.github` first: the Zsh standard, [`.github/instructions/zsh/scripting.instructions.md`](https://github.com/z-shell/.github/blob/main/.github/instructions/zsh/scripting.instructions.md), its policy, [`knowledge/domains/zsh/data/zsh-standard-policy.json`](https://github.com/z-shell/.github/blob/main/knowledge/domains/zsh/data/zsh-standard-policy.json), and the [Zsh Plugin Standard](https://wiki.zshell.dev/community/zsh_plugin_standard). 2. Read root `AGENTS.md` and the owning repository's local `AGENTS.md` when present. 3. Identify the repository compatibility floor. 4. Select `sourced-library` for the plugin entry point and `autoload-function` for files beneath `functions/`. ## Create a plugin 1. **Gather inputs** (ask only if not supplied): - An explicit target repository root. The caller must supply it; do not infer or default to a multi-repository checkout path. - Plugin name in kebab-case, for example `zsh-foo` with entry file `zsh-foo.plugin.zsh`. - One portable ASCII project identifier, for example `zsh_foo`. This owns every persistent public and private shell name and the `:zsh_foo:config` style context. 2. **Create the layout**. Create only the authoritative entrypoint initially. Add each optional directory only when its execution role is required: ```text <target-repository-root>/ <name>.plugin.zsh lib/ # optional private eager sources functions/ # optional autoload functions completions/ # optional native completion functions bin/ # optional user-invoked executables ``` 3. **Write the entry file** from `templates/template.plugin.zsh` in this skill, a copy of the canonical `knowledge/domains/plugins/templates/template.plugin.zsh` in `z-shell/.github`, replacing `__IDENTIFIER__` with the ASCII project identifier. Keep the modelines as the first two lines verbatim. Do not create shared `Plugins` state, scattered public configuration parameters, or a second legacy namespace. Add manager-specific behavior only when the user requests and identifies that optional profile, and keep it outside the portable contract. 4. **Write autoload function bodies**: begin each generated function body with `builtin emulate -L zsh`. Select only the correctness-affecting options that function needs. Apply `zsh/autoload/initialize`, `zsh/options/localize`, and the repository compatibility floor; do not copy a universal option bundle. 5. **Verify syntax and lifecycle** as described under [Verify every change](#verify-every-change). 6. **Report** the created tree, execution profiles, syntax result, lifecycle result, and any repository-floor decision. ## Maintain an existing plugin Read the plugin's entry file, `functions/`, `completions/`, documented configuration, unload function and tests before changing anything. List every side effect the plugin performs at load time; that list is what unload must reverse. ### Bring a plugin to Standard 2 Version 2 is one clean portable contract. A refactored plugin does not keep an older namespace, shared registry, configuration parameter or directory convention as a compatibility path. 1. Choose the one portable ASCII project identifier if the plugin has none, and rename every persistent shell-visible name to derive from it, with a leading underscore for private state and callbacks. 2. Replace configuration globals and environment variables with the project's `zstyle` context, and document each style. 3. Remove reads and writes of shared manager or plugin state such as a global `Plugins` parameter. Keep manager-specific behavior in an optional profile only when the user names it. 4. Make the entry file preserve caller state under `zsh/sourced/preserve-caller-state`, using the template's loader shape. 5. Write or complete `<identifier>_plugin_unload` so it reverses every owned side effect and self-destructs. 6. Record the change for users: renamed functions, styles and removed parameters belong in the release notes and README. ### Add or change functions - Put a public function in `functions/` as an autoload function named from the identifier, beginning with `builtin emulate -L zsh`. Keep setup-only helpers local to the loader. - Add the plugin's own resolved `functions/` directory to `fpath` only after checking that the exact path is absent, under `zsh/security/trust-paths`, and remove exactly that entry on unload. - Document each new public function as part of the load surface under `zsh/plugin/document-load-surface`. ### Add or change completions - Put each native completion in `completions/` as a file named `_<command>`. Add the directory to `fpath` the same way as `functions/`, before completion initialization. - Do not run `compinit` during loading, and never `compinit -u`; the user's configuration, framework or manager owns completion initialization. If a feature needs completion after `compinit` has already run, document the integration step. ### Change configuration - Read scalars with `zstyle -s`, arrays with `zstyle -a` and booleans with `zstyle -t` from the project context. Supply defaults as local lookup fallbacks; do not register them in the global style database. - Document each new style in the README: default, value type, accepted values, and when it is read. ### Keep unload exact Every new side effect needs a matching reversal in `<identifier>_plugin_unload` under `zsh/plugin/exact-lifecycle`: remove only what the plugin owns, restore pre-load state only while the plugin's value is still installed, and preserve the user's newer state. Unload ends by removing itself. ### Wire CI - **ZUnit**: add or extend `.zunit` tests under `tests/` with the `zunit` skill, and run them in CI. Pin ZUnit only to an exact commit from a published release. - **zsh-lint**: call the organization reusable workflow `z-shell/.github/.github/workflows/zsh-lint.yml` as a job with `contents: read`, passing the plugin's reviewed Zsh source roots as `paths` and a published analyzer release commit as `zsh-lint-ref`. Pin the workflow and the analyzer independently to full commit SHAs. Its contract is [`knowledge/domains/ci/zsh-lint-ci.md`](https://github.com/z-shell/.github/blob/main/knowledge/domains/ci/zsh-lint-ci.md). - Keep native syntax checking (`zsh -n`) as its own step; lint does not replace it. ## Verify every change - Run `zsh -f -n <name>.plugin.zsh` for native syntax validation under `zsh/validation/native-authority`, and the same for each changed autoload function. - In an isolated shell with temporary `HOME` and `ZDOTDIR`, prime the ZUnit lifecycle observer, snapshot the baseline, source the entry file, and assert the exact documented load allowlist. - Test repeated source, partial initialization failure, hostile caller options, non-interactive loading, and post-load user changes. Invoke `<identifier>_plugin_unload` and assert ownership-aware restoration. - Remove the temporary directory. `zsh -f` suppresses normal RCS processing, but a system `zshenv` may still execute. - Run the plugin's existing ZUnit suite and lint before reporting. Report what changed, the execution profiles, syntax, lifecycle and test results, and any repository-floor decision. ## Canonical links for plugin decisions - Caller-state preservation: `zsh/sourced/preserve-caller-state`. - Autoload body initialization: `zsh/autoload/initialize`. - Stable namespace: `zsh/plugin/stable-namespace`. - Coherent configuration: `zsh/plugin/coherent-configuration`. - Documented plugin effects: `zsh/plugin/document-load-surface`. - Owned-effect cleanup: `zsh/plugin/exact-lifecycle`. - Controlled autoload paths: `zsh/security/trust-paths`. Keep the rule rationale in the canonical instruction. A plugin must reverse every owned side effect and self-destruct; syntax success alone is not a behavioral result.
View on GitHub