Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 23 additions & 6 deletions .github/agents/zsh-plugin-standard-reviewer.agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ description: Use to audit a Zsh plugin file (or a whole plugin directory) agains
model: sonnet
---

You audit Zsh plugins against the [Z-Shell Plugin Standard](https://wiki.zshell.dev/community/zsh_plugin_standard) and this workspace's `AGENTS.md` conventions. You are **read-only**: you find and report violations with file:line references and exact fixes. You do not edit files.
You audit Zsh plugins against the
[Zsh Plugin Standard](https://wiki.zshell.dev/community/zsh_plugin_standard)
and this workspace's `AGENTS.md` conventions. Official Zsh documentation is
authoritative for shell semantics. You are **read-only**: you find and report
violations with file:line references and exact fixes. You do not edit files.

## What to check

Expand All @@ -24,16 +28,23 @@ Run through this checklist for the plugin entry file and supporting files. Repor
0="${${(M)0:#/*}:-$PWD/$0}"
```

3. **Plugins hash** — `typeset -gA Plugins` then `Plugins[KEY]="${0:h}"` with a sensible upper-case KEY.
3. **Portable state discipline** — plugin-owned functions, parameters, aliases,
hooks, widgets, and other mutable state are namespaced; option changes are
scoped or restored.

4. **PMSPEC fpath guard** — any `fpath+=(...)` for the plugin's own `functions/` dir must be guarded by `if [[ $PMSPEC != *f* ]]; then ... fi`.
4. **Optional manager profile** — when the plugin uses manager capabilities,
verify that the integration is capability-guarded and follows that manager's
current documented API. Do not require or recommend a shared `Plugins`
registry, and do not fail portable compliance because an optional profile is
absent.

5. **Unload function** — `<plugin-name>_plugin_unload` exists and:
- removes its own `functions/` entry from `fpath`
- removes a `functions/` entry from `fpath` only when the plugin added it
- unsets every global variable the plugin created
- removes aliases / hooks / options it set, restoring prior state
- `unfunction`s the plugin's own functions
- unsets its `Plugins[KEY]` entry
- reverses manager-profile state only when the plugin created that state,
using the manager's documented lifecycle API when one exists
- self-destructs (`unfunction <plugin-name>_plugin_unload`)

6. **Handler functions** (files under `functions/`) — start with strict emulation:
Expand All @@ -47,9 +58,15 @@ Run through this checklist for the plugin entry file and supporting files. Repor

8. **Syntax** — run `zsh -n <file>` on each Zsh file and report any failures.

9. **Load safety** — load performs no network activity, side effects are
explicit, and unload reverses plugin-owned changes.

## How to work

- Use Glob/Grep to locate the entry file and supporting files; Read them fully.
- Run `zsh -n` via Bash for syntax verification.
- Cross-reference an existing compliant plugin (e.g. `z-shell/zsh-eza:zsh-eza.plugin.zsh`) when a pattern is ambiguous.
- Output a single compact report: a checklist table, then a numbered list of concrete fixes ordered by severity (standard-breaking first, style last).
- Classify findings as official-Zsh semantics, portable-standard requirements,
optional manager-profile defects, or repository conventions.
- Output a single compact report: a checklist table, then a numbered list of
concrete fixes ordered by severity (standard-breaking first, style last).
58 changes: 51 additions & 7 deletions .github/instruction-surfaces.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,14 @@
"kind": "shared-policy",
"authority": "canonical-detail",
"consumers": ["codex", "claude-code", "copilot", "gemini-cli", "human"],
"tasks": ["implementation", "review"],
"tasks": [
"implementation",
"review",
"zsh-plugin-creation",
"zsh-plugin-review",
"zsh-plugin-code-change",
"zsh-plugin-template"
],
"file_patterns": ["**"],
"required": true,
"review_owner": "z-shell maintainers",
Expand Down Expand Up @@ -147,6 +154,39 @@
"review_owner": "z-shell maintainers",
"canonical_for": ["shell"]
},
{
"id": "instruction-zsh-plugin-standard",
"path": ".github/instructions/zsh-plugin-standard.instructions.md",
"kind": "scoped-guidance",
"authority": "canonical-detail",
"consumers": ["codex", "claude-code", "copilot", "gemini-cli", "human"],
"tasks": [
"zsh-plugin-creation",
"zsh-plugin-review",
"zsh-plugin-code-change",
"zsh-plugin-template",
"zsh-plugin-documentation",
"zsh-plugin-scaffolding"
],
"file_patterns": ["**"],
"required": true,
"review_owner": "z-shell maintainers",
"canonical_for": ["zsh-plugin-standard-application"]
},
{
"id": "instruction-zsh-plugin-standard-aliases",
"path": ".github/instructions/zsh-plugin-standard-aliases.instructions.md",
"kind": "scoped-guidance",
"authority": "canonical-detail",
"consumers": ["codex", "claude-code", "copilot", "gemini-cli", "human"],
"tasks": ["code-review", "readme-authoring", "zsh-plugin-scaffolding"],
"file_patterns": [
"**/*.plugin.zsh,**/init.zsh,templates/readme/zsh-plugin.md,.github/skills/new-zsh-plugin/**,.github/agents/zsh-plugin-standard-reviewer.agent.md"
],
"required": true,
"review_owner": "z-shell maintainers",
"canonical_for": []
},
{
"id": "instruction-testing",
"path": ".github/instructions/testing.instructions.md",
Expand Down Expand Up @@ -237,7 +277,7 @@
"kind": "agent",
"authority": "advisory",
"consumers": ["copilot"],
"tasks": ["zsh-plugin-review"],
"tasks": ["zsh-plugin-review", "code-review"],
"file_patterns": ["**"],
"required": false,
"review_owner": "z-shell maintainers",
Expand All @@ -261,7 +301,7 @@
"kind": "skill",
"authority": "advisory",
"consumers": ["copilot"],
"tasks": ["readme-authoring"],
"tasks": ["readme-authoring", "zsh-plugin-documentation"],
"file_patterns": ["**"],
"required": false,
"review_owner": "z-shell maintainers",
Expand Down Expand Up @@ -333,7 +373,7 @@
"kind": "skill",
"authority": "advisory",
"consumers": ["copilot"],
"tasks": ["zsh-plugin-scaffolding"],
"tasks": ["zsh-plugin-scaffolding", "zsh-plugin-creation"],
"file_patterns": ["**"],
"required": false,
"review_owner": "z-shell maintainers",
Expand Down Expand Up @@ -417,7 +457,7 @@
"kind": "runbook",
"authority": "canonical-detail",
"consumers": ["codex", "claude-code", "copilot", "gemini-cli", "human"],
"tasks": ["instruction-change"],
"tasks": ["instruction-change", "zsh-plugin-standard-governance"],
"file_patterns": ["**"],
"required": true,
"review_owner": "z-shell maintainers",
Expand Down Expand Up @@ -516,12 +556,16 @@
"tasks": [
"recurring-operations",
"scheduled-workflow-audit",
"automation-review"
"automation-review",
"zsh-plugin-standard-review"
],
"file_patterns": ["**"],
"required": true,
"review_owner": "z-shell maintainers",
"canonical_for": ["recurring-operations"]
"canonical_for": [
"recurring-operations",
"zsh-plugin-standard-review"
]
},
{
"id": "runbook-release",
Expand Down
9 changes: 9 additions & 0 deletions .github/instructions/documentation.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,21 @@ identical prose or artwork. Zi remains the first installation path. Include a
screenshot or short demo only when it materially explains behavior, and keep
long-form ecosystem guidance in the wiki.

The
[Zsh Plugin Standard](https://wiki.zshell.dev/community/zsh_plugin_standard)
is the canonical public plugin-authoring standard and should be linked from
plugin documentation where authoring or lifecycle behavior is discussed.
Summarize only repository-specific behavior. Official Zsh documentation remains
authoritative for shell semantics, and manager-specific profiles must be
identified as optional integrations rather than portable requirements.

## LLM/agent files

Keep shared organization guidance in z-shell/.github. Keep child-repository AGENTS.md or .github/instructions files only for concise repository-specific behavior, and link to public canonical guidance rather than duplicating it.

## See also

- `decisions/0006-wiki-content-root-boundaries.md`
- [Zsh Plugin Standard](https://wiki.zshell.dev/community/zsh_plugin_standard)
- `z-shell/wiki:.github/copilot-instructions.md` (wiki-local authoring rules)
- `z-shell/wiki:.github/instructions/docs-authoring.instructions.md`
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
description: "Route generic review and README tasks on plugin-shaped files to the canonical Zsh plugin guidance"
applyTo: "**/*.plugin.zsh,**/init.zsh,templates/readme/zsh-plugin.md,.github/skills/new-zsh-plugin/**,.github/agents/zsh-plugin-standard-reviewer.agent.md"
---

# Zsh Plugin Standard Task Aliases

For plugin-shaped code, plugin scaffolding, and the plugin README template,
apply the mandatory
[Zsh Plugin Standard instructions](zsh-plugin-standard.instructions.md).
The canonical public standard remains the
[Zsh Plugin Standard](https://wiki.zshell.dev/community/zsh_plugin_standard),
and official Zsh documentation remains authoritative for shell semantics.

Generic `code-review` and `readme-authoring` tasks do not imply that every Zsh
file or README is a plugin. Apply this route only to the plugin-specific paths
declared in this instruction's `applyTo` scope.
58 changes: 58 additions & 0 deletions .github/instructions/zsh-plugin-standard.instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
---
description: "Canonical Z-Shell requirements for authoring, changing, documenting, and reviewing Zsh plugins"
applyTo: "**"
---

# Zsh Plugin Standard Instructions

The canonical public plugin-authoring standard is the
[Zsh Plugin Standard](https://wiki.zshell.dev/community/zsh_plugin_standard).
Read the current page before creating, changing, documenting, or reviewing a
Zsh plugin. Link to it instead of copying its full rules into repositories,
templates, reviews, or agent guidance.

Official Zsh documentation remains authoritative for shell syntax, expansion,
options, builtins, and other language semantics. If the standard, a plugin
manager, or an example conflicts with the Zsh manual for the supported Zsh
version, follow the manual and report the documentation drift.

## Organization requirements

- Write Zsh-first code; do not substitute Bash syntax or portability advice for
documented Zsh behavior.
- Namespace plugin-owned functions, parameters, aliases, hooks, widgets, and
other mutable shell state.
- Scope option changes with `emulate -L zsh` or save and restore the prior
option state when a change must outlive one function call.
- Make load-time side effects explicit, minimal, and documented.
- Provide lifecycle cleanup that reverses plugin-owned side effects, including
hooks, functions, parameters, aliases, widgets, path entries, and temporary
resources.
- Do not perform network activity during plugin load. Network access must be an
explicit user action.
- Validate syntax with native Zsh and exercise load and unload behavior in a
clean Zsh process.

## Portable requirements and manager profiles

Keep portable plugin requirements separate from optional plugin-manager
profiles. Manager APIs such as Zi metadata, `PMSPEC`, or a manager-maintained
plugin registry may improve integration, but they are not portable Zsh
requirements. Use them only behind an intentional profile or capability guard,
and never present one manager's API as shell semantics.

Zi is the Z-Shell reference manager for examples and testing under
`decisions/0002-zi-as-canonical-plugin-manager.md`. This affects defaults, not
the definition of portable plugin behavior.

## Review output

Identify whether each finding is:

1. an official-Zsh semantic error;
2. a portable Plugin Standard violation;
3. an optional manager-profile defect; or
4. a repository-specific convention.

Do not fail portable compliance solely because an optional manager integration
is absent.
4 changes: 3 additions & 1 deletion .github/skills/create-readme/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@ Create an accurate, concise, and visually intentional repository landing page.
model, and linked organization policy before drafting.
2. Classify the repository. For a Zsh plugin, use
[`templates/readme/zsh-plugin.md`](../../../templates/readme/zsh-plugin.md)
as the canonical structure.
as the canonical structure and read the
[Zsh Plugin Standard](https://wiki.zshell.dev/community/zsh_plugin_standard).
3. Verify every feature, setting, default, alias, lifecycle claim, command, and
branch statement against the current implementation.
4. Lead Zsh-plugin installation guidance with Zi. Keep other manager examples
concise and include only intentionally supported or verified paths.
Distinguish optional manager profiles from portable plugin requirements.
5. Keep long-form ecosystem guidance in the wiki and link to it.
6. Preserve meaningful visual identity: a clear header, a restrained maintained
badge set, accessible alt text, and an optional behavior-focused screenshot
Expand Down
17 changes: 14 additions & 3 deletions .github/skills/new-zsh-plugin/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
---
name: new-zsh-plugin
description: Scaffold a new Z-Shell-Standard-compliant Zsh plugin. Use when the user asks to create a new Zsh plugin, start a plugin from scratch, or add a plugin skeleton. Generates a compliant entry file (modeline, ZERO handling, Plugins hash, fpath guard, unload function) plus functions/ and docs/ layout.
description: Scaffold a new Z-Shell-Standard-compliant Zsh plugin. Use when the user asks to create a new Zsh plugin, start a plugin from scratch, or add a plugin skeleton. Generates a compliant entry file (modeline, ZERO handling, capability-aware fpath setup, unload function) plus functions/ and docs/ layout.
disable-model-invocation: true
---

# Create a new Zsh plugin

Scaffold a plugin that conforms to the [Z-Shell Plugin Standard](https://wiki.zshell.dev/community/zsh_plugin_standard), `z-shell/.github/AGENTS.md`, and the owning repository's local `AGENTS.md` when present.

Official Zsh documentation is authoritative for shell semantics. The scaffold
honors the optional `PMSPEC` capability signal without requiring a shared
manager registry.

## Steps

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, e.g. `zsh-foo` → entry file `zsh-foo.plugin.zsh`.
- Derive `PLUGIN_KEY` = upper-snake of the name without a `zsh-` prefix, e.g. `zsh-foo` → `ZSH_FOO`.

2. **Create the layout**:

Expand All @@ -26,7 +29,10 @@ Scaffold a plugin that conforms to the [Z-Shell Plugin Standard](https://wiki.zs
docs/
```

3. **Write the entry file** from `templates/plugin.plugin.zsh`, replacing `__NAME__` (kebab name), `__KEY__` (PLUGIN_KEY), and `__FPATH_VAR__` (`<KEY>_FPATH`). Keep the modeline as the first two lines verbatim.
3. **Write the entry file** from `templates/plugin.plugin.zsh`, replacing
`__NAME__` (kebab name) and `__FPATH_VAR__` (a namespaced upper-snake
parameter such as `ZSH_FOO_FPATH`). Keep the modeline as the first two lines
verbatim.

4. **Verify**: run `zsh -n <name>.plugin.zsh`. It must pass before reporting done. Source it in a subshell to confirm the unload function is defined:

Expand All @@ -45,4 +51,9 @@ Scaffold a plugin that conforms to the [Z-Shell Plugin Standard](https://wiki.zs
builtin setopt extended_glob warn_create_global typeset_silent no_short_loops rc_quotes no_auto_pushd
```
- The unload function must reverse **every** side effect and self-destruct.
- Namespace plugin-owned state, scope option changes, and perform no network
activity during load.
- Keep portable behavior usable without optional manager capabilities. Track
whether the plugin changed shared state so unload preserves manager- or
user-owned state.
- No build system — verify by sourcing in a Zsh session, not by running a build.
22 changes: 12 additions & 10 deletions .github/skills/new-zsh-plugin/templates/plugin.plugin.zsh
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
# -*- mode: zsh; sh-indentation: 2; indent-tabs-mode: nil; sh-basic-offset: 2; -*-
# vim: ft=zsh sw=2 ts=2 et
#
# Zsh Plugin Standard
# Zsh Plugin Standard portable path handling
# https://wiki.zshell.dev/community/zsh_plugin_standard#zero-handling
0="${ZERO:-${${0:#$ZSH_ARGZERO}:-${(%):-%N}}}"
0="${${(M)0:#/*}:-$PWD/$0}"

# https://wiki.zshell.dev/community/zsh_plugin_standard#standard-plugins-hash
typeset -gA Plugins
Plugins[__KEY__]="${0:h}"

# https://wiki.zshell.dev/community/zsh_plugin_standard#funtions-directory
# Optional manager capability: PMSPEC=f means the manager owns fpath setup.
# https://wiki.zshell.dev/community/zsh_plugin_standard#functions-directory
typeset -g __FPATH_VAR__="${0:h}/functions"
if [[ $PMSPEC != *f* ]]; then
typeset -gi __FPATH_VAR___ADDED=${__FPATH_VAR___ADDED:-0}
if [[ ${PMSPEC-} != *f* ]] && (( ! ${fpath[(Ie)${__FPATH_VAR__}]} )); then
fpath+=( "${__FPATH_VAR__}" )
__FPATH_VAR___ADDED=1
fi

# --- Plugin body -------------------------------------------------------------
Expand All @@ -23,13 +22,16 @@ fi

# https://wiki.zshell.dev/community/zsh_plugin_standard#unload-function
__NAME___plugin_unload() {
# Remove our functions/ dir from fpath
fpath=("${fpath[@]:#${__FPATH_VAR__}}")
local fpath_index
if (( __FPATH_VAR___ADDED )); then
fpath_index=${fpath[(Ie)${__FPATH_VAR__}]}
(( fpath_index )) && fpath[$fpath_index]=()
fi

# TODO: unset variables, remove aliases, remove hooks, unfunction helpers,
# and restore any options/state this plugin changed.

unset __FPATH_VAR__ 'Plugins[__KEY__]'
unset __FPATH_VAR__ __FPATH_VAR___ADDED

unfunction __NAME___plugin_unload
}
3 changes: 3 additions & 0 deletions .github/workflows/agent-instructions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ jobs:
with:
python-version: "3.10"

- name: Install Zsh
run: sudo apt-get update && sudo apt-get install --yes zsh

- name: Run agent policy unit tests
run: python3 -m unittest scripts/test_validate_agent_policy.py -v

Expand Down
Loading
Loading