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
8 changes: 4 additions & 4 deletions build/release-evidence.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
"schema_version": 2,
"module": {
"repository": "NDDev-it-com/nddev-zcode-app",
"setup_digest": "sha256:1ae439320693f777e93ae341cc4b2341a006bb6abe6fa417abdfcba8860bc072"
"setup_digest": "sha256:bba623d9aa81f6934ebe77dd5a635fc3544b5304a211b021401c4568bdffb511"
},
"harness": {
"repository": "NDDev-it-com/nddev-harnesses",
"commit": "1254bf60ddc5e50017b761f837893b85709ebe9f"
"commit": "df99892732c0b9ebaa8906773ec8d36e1521d960"
},
"adapter": {
"id": "zcode",
Expand All @@ -30,8 +30,8 @@
}
],
"lanes": [],
"generated_at_utc": "2026-07-18T01:26:53Z",
"expires_at_utc": "2027-01-14T01:26:53Z",
"generated_at_utc": "2026-07-18T02:35:51Z",
"expires_at_utc": "2027-01-14T02:35:51Z",
"promotion": {
"decision": "pending",
"waivers": []
Expand Down
17 changes: 11 additions & 6 deletions zcode_tools/marketplaces/nddev-builder/plugins/core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,14 @@ the private `nddev-harnesses` control plane.

## Install

Add the local `nddev-builder` marketplace in ZCode Plugin Management, or use the
repository installer to place it under
`~/.zcode/marketplaces/nddev-builder/plugins/core/`.

Plugin manifests are metadata-only; ZCode discovers skills, commands, agents,
references, and tools by convention.
Install with the repository installer (`install.sh install --setup nddev-builder`).
It places the marketplace under `~/.zcode/marketplaces/nddev-builder/` **and**
flattens each plugin's `skills/`, `commands/`, and `agents/` into
`~/.zcode/{skills,commands,agents}` — the flattened copy is what ZCode 3.3.6
loads, because it never reads the `marketplaces/.../plugins/` tree on a headless
install. Adding the marketplace through the ZCode UI (Plugin Management) is the
alternative that registers it as a live plugin.

Plugin manifests are metadata-only. `references/` and `tools/` are authoring
material and are not flattened. See the `nddev-builder-orientation` skill for the
full loading model.
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
description: Author or maintain ZCode AGENTS.md instruction files (user or workspace scope).
---

Add or maintain ZCode AGENTS.md instructions.

Follow the `add-instructions` skill exactly: decide user vs workspace scope from
the rule's reach, edit the marketplace `AGENTS.md` (renders to user scope) or the
workspace `AGENTS.md` (via `/init`), keep instructions concise and imperative,
respect any managed begin/end markers, and keep skills/commands/hooks/MCP out of
the instruction file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
description: Orient in the nddev-builder toolkit and how ZCode actually loads extensions (read this first).
---

Explain how this toolkit and ZCode extension loading work.

Follow the `nddev-builder-orientation` skill exactly: read it and summarize for
the user the marketplace layout, how ZCode 3.3.6 discovers and loads
skills/commands/agents at user scope, what the installer flattens (and what it
does not), the install/remove/switch lifecycle, and the global-uniqueness
collision rule. Then route them to the right `add-*` / `validate-components`
skill for their task.
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
description: Statically pre-check a marketplace's components before install (frontmatter, names, cross-plugin collisions).
---

Validate a marketplace's components before install.

Follow the `validate-components` skill exactly: check skill/command/agent
frontmatter and name patterns, description length (≤1024), JSON validity, and —
most importantly — that no two plugins share a skill/command/agent basename
(the installer flattens to user scope and fails closed on a collision). Finish
with `install.sh install --setup <mp> --plan` as a non-mutating gate.
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,13 @@ skills/<name>/SKILL.md
Frontmatter: `name` (matches dir), `description` (English, trigger-rich). Body is markdown.
The first same-named skill in discovery order wins (user > workspace > plugin).

**Loading reality (ZCode 3.3.6):** ZCode loads skills/commands/agents only from
user scope (`~/.zcode/{skills,commands,agents}`, `~/.agents/skills`), never from
`~/.zcode/marketplaces/.../plugins/`. The installer flattens each plugin's
`skills/`, `commands/`, and `agents/` into user scope; basenames must be unique
across every plugin (the flatten fails closed on a collision). `references/` and
`tools/` are not flattened.

## Commands

```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,17 @@ description: <English. What this agent does and when to delegate to it.>

## Frontmatter rules

- `name` (required) — must match the filename (without `.md`).
- `model` (required) — pin the model. Use `GLM-5.2` (the ZCode runtime baseline)
unless there is a deliberate reason for a different model.
- `description` (recommended) — English, trigger-rich. Explains WHEN to delegate.
- No other fields.
- `name` — must match the filename (without `.md`).
- `model` — pin the model; this toolkit's house rule is `GLM-5.2` (the ZCode
runtime baseline). ZCode publishes no subagent file schema, so treat `model`
as our convention, not a documented ZCode requirement.
- `description` — English, trigger-rich. Explains WHEN to delegate; also drives
automatic selection.

Keep the frontmatter minimal and consistent across the marketplace. A subagent
loads only after the installer flattens it to `~/.zcode/agents/`, so its
basename must be unique across every plugin (the flatten fails closed on a
collision).

## Body: the system prompt

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,12 @@ Recognized keys (all **hyphenated**, NOT snake_case):
- `allowed-tools` (optional) — inline comma list, e.g. `Read, Bash`. NOT multi-line.
- `model` (optional) — model override.
- `skills` (optional) — auto-mounted skills.
- `disable-noninteractive` (optional) — hide the command from headless/
non-interactive runs.

**Do NOT use snake_case** (`allowed_tools`, `argument_hint`) — they are silently
ignored. No `version`, `name`, or `tags`.
ignored. No `version`, `name`, or `tags`. A command whose name collides with a
built-in reserved name is filtered from the live `/` menu.

## Argument substitution

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,18 +100,28 @@ a command hook but 500ms (half a second) for a process hook. Default is 60000ms

### Output and exit codes

- **stdout** is parsed as **strict JSON** — any extra/unknown key fails validation.
Use the documented keys only (e.g. `{"decision": "block", "reason": "..."}`).
- **exit codes**: `0` = pass, `2` = block (deny for PreToolUse/PermissionRequest),
any other non-zero = error. Non-JSON stdout is shown to the model as context.
- **stdout** is parsed as **strict JSON** — any extra/unknown key fails validation
(the effect is discarded and the run marked failed). Emit only the recognized
keys, or emit nothing and rely on exit codes. The documented keys are:
`additionalContext` (injected into the conversation, any event); for
`PreToolUse`, a permission **decision** of `allow` / `ask` / `deny`; for
`Stop`, a continuation request. `decision: "block"` is **not** a recognized
key — use exit code `2` or a `deny` decision to block.
- **exit codes**: `0` = pass, `2` = block (a deny for
`PreToolUse`/`PermissionRequest`), any other non-zero = error. Empty stdout is
fine.

## Procedure

1. Identify the event and the tool to match (if applicable).
2. Write the hook command — a shell one-liner or a script path. If the logic is
non-trivial, put it in a script under the marketplace (e.g.
`zcode_tools/marketplaces/<marketplace>/scripts/<name>.sh`) and reference it
by path.
by its **absolute installed path**
`~/.zcode/marketplaces/<marketplace>/scripts/<name>.sh`. A config-file hook is
merged into `~/.zcode/cli/config.json`; it does not run from the marketplace
directory and does not expand `${CLAUDE_PLUGIN_ROOT}` (that is plugin-hook
only), so a relative path silently fails to resolve.
3. Open `hooks.json` in the active marketplace and add the entry to the matching
event array. Strip the `_comment` key mentally — the installer drops it at
merge time.
Expand All @@ -129,7 +139,7 @@ a command hook but 500ms (half a second) for a process hook. Default is 60000ms
{
"matcher": "Bash",
"hooks": [
{ "type": "command", "command": "scripts/block-dangerous.sh" }
{ "type": "command", "command": "~/.zcode/marketplaces/<marketplace>/scripts/block-dangerous.sh" }
]
}
]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
---
name: add-instructions
description: Author or maintain ZCode AGENTS.md instruction files at user or workspace scope. Use when adding default agent instructions, editing AGENTS.md, deciding user-vs-workspace scope, or understanding the load and merge order of instruction files in ZCode.
---

# Add or maintain AGENTS.md instructions

`AGENTS.md` is ZCode's instruction surface — broad behavior rules injected into
the model context. It is not a skill, command, hook, MCP server, or plugin; it
has its own two scopes and a defined merge order.

## Scopes and load order

| Scope | File | Applies to | Loads |
|---|---|---|---|
| User | `~/.zcode/AGENTS.md` | every workspace | first |
| Workspace | `<repo>/AGENTS.md` | that project only | after user (can narrow/override) |

ZCode injects `~/.zcode/AGENTS.md` first, then the workspace `AGENTS.md` resolved
from the current directory upward to the project root — so workspace rules
appear later and take precedence for that repo.

A marketplace ships its own `AGENTS.md` at its root; the installer renders it to
`~/.zcode/AGENTS.md` (user scope). Edit the marketplace's `AGENTS.md` to change
the installed user-scope defaults.

## Choosing scope

- **User** (`~/.zcode/AGENTS.md`, i.e. the marketplace `AGENTS.md`): personal or
setup-wide defaults — preferred language, review style, local conventions.
- **Workspace** (`<repo>/AGENTS.md`): repository rules shared with the team —
architecture boundaries, logging, testing, commit/MR policy. Create or update
it with ZCode's built-in `/init` (it targets the workspace file, never the
user default).

## Procedure

1. Decide scope from the rule's reach (setup-wide vs repository-specific).
2. Keep it concise and imperative; state rules the model must follow, not prose.
3. If a marketplace uses managed begin/end markers around a generated block,
keep edits inside the markers so the installer can re-render cleanly.
4. Do not put skills, commands, hooks, MCP, or plugin config here — those are
separate resources (see `nddev-builder-orientation`). AGENTS.md is
instructions only.
5. Verify the file is valid Markdown and loads (open ZCode, or check the
rendered `~/.zcode/AGENTS.md` after install).
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,10 @@ demand.

CLI tools live **inside the plugin** in a `tools/` directory. The installer
copies the whole marketplace (including plugins) into `~/.zcode/marketplaces/`,
so tools arrive automatically. At runtime, the agent references them via
`${CLAUDE_PLUGIN_ROOT}/tools/<name>/<script>` (expanded by ZCode for plugin
context) or by their absolute installed path.
so tools arrive there — but `tools/` is **not** flattened to user scope, and
`${CLAUDE_PLUGIN_ROOT}` is unset for a file-installed marketplace. At runtime the
companion skill must reference the tool by its **absolute installed path**,
`~/.zcode/marketplaces/<mp>/plugins/<plugin>/tools/<name>/<script>`.

```text
zcode_tools/marketplaces/<marketplace>/plugins/<plugin>/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,18 @@ Scaffolds a new ZCode-native plugin bundle inside a marketplace in this reposito
## ZCode plugin format (the rules this skill enforces)

Plugins live **inside a marketplace directory** under
`zcode_tools/marketplaces/<marketplace>/plugins/<name>/`. ZCode discovers components
**by convention** — the manifest is metadata-only and does not list components.
`zcode_tools/marketplaces/<marketplace>/plugins/<name>/`, with a metadata-only
manifest and components under convention directories (`skills/`, `commands/`,
`agents/`).

> **How the components actually load.** Convention-discovery from a plugin root
> applies only to marketplaces **added through the ZCode UI**. For this repo's
> headless file-install, ZCode never reads `~/.zcode/marketplaces/.../plugins/`;
> the installer **flattens** each plugin's `skills/`, `commands/`, and `agents/`
> into `~/.zcode/{skills,commands,agents}`, and that flattened copy is what
> loads. `references/` and `tools/` are **not** flattened. Read
> `nddev-builder-orientation` for the full model, and keep component basenames
> unique across every plugin (the flatten fails closed on a collision).

```
zcode_tools/marketplaces/<marketplace>/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,27 @@ Authors a new ZCode skill in the correct place.

## Where skills live

| Scope | Location (source) | Installed to |
Author a skill inside a plugin bundle; the installer is what makes ZCode load
it. **ZCode 3.3.6 never loads skills from `~/.zcode/marketplaces/.../plugins/`** —
it loads user-scope skills only from `~/.zcode/skills/` (and `~/.agents/skills/`).
So the installer **flattens** every plugin's `skills/` into `~/.zcode/skills/`
(`cli-tools/scripts/lib/build.sh`, `flatten_plugin_components`); that flattened
copy is what actually loads.

| Scope | Location (source) | What ZCode loads |
|---|---|---|
| Plugin-scoped | `zcode_tools/marketplaces/<marketplace>/plugins/<plugin>/skills/<skill>/SKILL.md` | `~/.zcode/marketplaces/<marketplace>/plugins/<plugin>/skills/<skill>/` |
| User-scoped | `zcode_tools/marketplaces/<marketplace>/skills/<skill>/SKILL.md` | `~/.zcode/skills/<skill>/` |
| Plugin-scoped | `.../plugins/<plugin>/skills/<skill>/SKILL.md` | `~/.zcode/skills/<skill>/` (installer-flattened) |
| User-scoped | `.../<marketplace>/skills/<skill>/SKILL.md` | `~/.zcode/skills/<skill>/` (copied as-is) |

Prefer **plugin-scoped** for anything tied to a plugin's domain; user-scoped only for
personal cross-project skills.
Prefer **plugin-scoped** so the skill travels with its plugin's domain;
user-scoped only for personal cross-project skills. Either way the loaded copy
lands in `~/.zcode/skills/`.

> **Global uniqueness is mandatory.** Because the flatten collapses every
> plugin's `skills/` into one `~/.zcode/skills/`, a skill basename must be unique
> across *every plugin in the marketplace*, not just within its plugin. A
> cross-plugin name clash makes the install **fail closed** (see the collision
> guard in `flatten_plugin_components`), not silently shadow one.

Slash commands and subagents are different component types with their own
frontmatter contracts: use `add-command` and `add-agent` respectively.
Expand Down Expand Up @@ -71,7 +85,11 @@ ZCode scans in this order; the first same-named skill wins:
4. workspace `.zcode/skills` (deeper cwd location wins) →
5. workspace `.agents/skills` → 6. enabled **plugin** roots.

So a user-scope skill shadows a plugin skill of the same name. Pick unique names.
The installer delivers our skills to level 2 (`~/.zcode/skills`). Level 6
(plugin roots) is reached **only** by marketplaces added through the ZCode UI —
a headless file-install never populates it, which is exactly why the installer
flattens to user scope instead. A user-scope skill shadows any same-named skill
below it, so keep basenames unique.

## Procedure

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,13 @@ plugins/<plugin>/

5. **Companion skill** (recommended): create
`skills/<name>/SKILL.md` with frontmatter (`name`, `description` — explain
WHEN to use it and that it runs `tools/<name>/<script>`). The body should
contain: available commands, when to use each, examples, output format.
WHEN to use it). The body should contain: available commands, when to use
each, examples, output format. **Point it at the absolute installed path**
`~/.zcode/marketplaces/<mp>/plugins/<plugin>/tools/<name>/<script>` — the
`tools/` directory is **not** flattened to user scope, and
`${CLAUDE_PLUGIN_ROOT}` is unset for a file-installed marketplace, so a
relative or `${CLAUDE_PLUGIN_ROOT}`-based path will not resolve. The skill
itself *is* flattened, so it loads and can carry that absolute path.

6. **Secrets**: if the tool needs API keys or tokens:
- Add the supported key to `build/.env.example` with an empty value.
Expand Down
Loading
Loading