fix(kyberforge): bridge apm content to Claude Code's flat plugin discovery
Claude Code's (and Copilot's) native plugin installer has zero awareness of .apm/ nesting -- it convention-scans only flat skills/, agents/, commands/, hooks.json at each plugin's root. Confirmed via strings on the installed claude binary and live installs of git@holocron/gitea@holocron/kyberforge@ holocron, all reporting Skills(0) Agents(0) Hooks(0) post ADR-0015's apm conversion. Root cause (apm_cli/core/plugin_manifest.py): apm's plugin.json compiler deliberately strips skills/agents/commands keys, assuming the host already auto-discovers those convention directories -- it has no model of .apm/ being host-visible at all. Separately, apm's own bundle exporter (apm_cli/bundle/plugin_exporter.py, behind `apm pack --format plugin`) implements the correct .apm/ -> flat mapping, but only ever targeted build/<name>-<version>/, a path nothing in marketplace.json's source: points at. scripts/sync-plugin-content.sh wraps that bundle exporter and copies its agents/, skills/, commands/, instructions/, extensions/, and merged hooks.json back into each plugin's own root as a second tracked compiled-output category -- same governance status as .claude-plugin/plugin.json: generated from .apm/, never hand-edited. tests/ subdirectories are excluded from the mirror (dev fixtures, not host-visible runtime content; several hardcode a relative repo-root walk-up sized for the .apm/-nested depth, which breaks when duplicated one level shallower). Applied for real across all 6 plugins and verified two ways: `claude plugin validate --strict` passes on every real plugin directory, and a live `claude --plugin-dir <path> -p "list skills/agents"` behavioral test confirms content is now actually discovered. Also, from the same issue #90 review round: - scripts/check-manifests.sh pointed at each plugin's root-level plugin.json (checking skills/hooks/mcpServers/agents pointer fields) -- that file was a stale near-duplicate of .claude-plugin/plugin.json nothing else read or wrote, now deleted across all 6 plugins. check-manifests.sh is rewritten to validate .claude-plugin/plugin.json instead, and drops the pointer-field checks entirely (nothing to check -- those fields are correctly absent by design). Content-presence drift is now check-plugin-content-sync's job, a new pre-push hook wired in .pre-commit-config.yaml. docs/adr/0017 records the root cause and decision in full, including two rejected alternatives (patching plugin.json's path fields directly -- apm's compiler strips them on every run; pointing marketplace.json at apm pack's build/ output -- a version-suffixed non-source directory nothing can install from without an extra build step). ADR-0015 and CONTEXT.md are updated to point at it. Refs: #90
This commit is contained in:
54
plugins/kyberforge/skills/skill-author/README.md
Normal file
54
plugins/kyberforge/skills/skill-author/README.md
Normal file
@@ -0,0 +1,54 @@
|
||||
# skill-author
|
||||
|
||||
Author and refine skills conforming to the [agentskills.io](https://agentskills.io) specification — create new skills from scratch or apply improvement signals to existing ones.
|
||||
|
||||
## What it does
|
||||
|
||||
Routes to one of two flows based on context: if no skill directory exists at the target path, it scaffolds the directory from annotated templates, fills in `SKILL.md` and supporting files, and validates the result. If an existing skill directory and improvement signals are both present, it groups those signals by root cause and applies targeted edits, then re-validates. In both flows, bumps the skill's `metadata.version` when present (minor for create, patch for improve).
|
||||
|
||||
## Before you start
|
||||
|
||||
- Run `/grill-me` to resolve design decisions before creating a new skill
|
||||
- Collect domain research, examples, and constraints
|
||||
- Know the skill name (kebab-case) and destination path
|
||||
|
||||
## Placement
|
||||
|
||||
`scripts/new-skill.sh` resolves the mode automatically by walking up from the given path — see `SKILL.md` Step 1 for the full algorithm.
|
||||
|
||||
| Mode | Path | Chosen when |
|
||||
|------|------|-------------|
|
||||
| Standalone | `<path>/<name>/` | No `apm.yml` with a top-level `type:` field is found walking up from `<path>`, before hitting `.git` or the filesystem root |
|
||||
| Package (APM) | `<package-root>/.apm/skills/<name>/` | A type-bearing `apm.yml` is found at or above `<path>` — `<path>` just needs to be somewhere inside the package |
|
||||
|
||||
If the destination resolves inside an APM package, read `references/deployment-modes.md` — self-containment rules apply to `apm compile` output the same way they applied to plugin cache isolation.
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
/skill-author
|
||||
```
|
||||
|
||||
## Files
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `README.md` | Human-readable overview of the skill and its files |
|
||||
| `SKILL.md` | Skill instructions for agents |
|
||||
| `scripts/new-skill.sh` | Walks up from the given path to resolve package vs standalone mode, then copies annotated templates to the resolved destination |
|
||||
| `references/deployment-modes.md` | APM package vs standalone differences and self-containment/cache-isolation rules (loaded on demand) |
|
||||
| `references/scripts.md` | Package runners, inline dependency patterns, and full script contract (loaded on demand) |
|
||||
| `references/sources.md` | Upstream research sources and which skill files each contributed to |
|
||||
| `assets/templates/SKILL.md` | Annotated SKILL.md template |
|
||||
| `assets/templates/README.md` | Annotated README template for the new skill |
|
||||
| `assets/templates/scripts/README.md` | Placeholder for bundled scripts |
|
||||
| `assets/templates/references/README.md` | Placeholder for reference docs |
|
||||
| `assets/templates/references/sources.md` | Sources provenance template for new skills |
|
||||
| `assets/templates/assets/README.md` | Placeholder for static assets |
|
||||
| `assets/templates/tests/README.md` | Placeholder for test files |
|
||||
| `tests/new-skill.bats` | Bats test suite for `scripts/new-skill.sh` |
|
||||
| `tests/README.md` | Setup instructions for bats-support and bats-assert test dependencies |
|
||||
|
||||
## Spec reference
|
||||
|
||||
[agentskills.io specification](https://agentskills.io/specification.md)
|
||||
306
plugins/kyberforge/skills/skill-author/SKILL.md
Normal file
306
plugins/kyberforge/skills/skill-author/SKILL.md
Normal file
@@ -0,0 +1,306 @@
|
||||
---
|
||||
name: skill-author
|
||||
description: >
|
||||
Use when the user wants to create a new skill from scratch ("write a skill
|
||||
for X", "build a skill that does Y", "create a SKILL.md for Z") or improve
|
||||
an existing one ("improve this skill", "fix based on feedback", "apply these
|
||||
audit findings", "update based on grill output"). Also use when the user provides inline feedback
|
||||
about a skill's behavior and wants it applied, or when a grill session, eval
|
||||
run, or audit has produced findings the user wants acted on — even if they
|
||||
don't say "improve" explicitly. Do not use for read-only review — use
|
||||
/skill-audit instead. Do not use to author agent definition files.
|
||||
allowed-tools: Bash Read Write Edit
|
||||
metadata:
|
||||
category: factory
|
||||
source_keys:
|
||||
- agentskills-home
|
||||
- agentskills-spec
|
||||
- agentskills-best-practices
|
||||
- agentskills-optimizing-descriptions
|
||||
- agentskills-evaluating-skills
|
||||
- agentskills-using-scripts
|
||||
- agentskills-quickstart
|
||||
---
|
||||
|
||||
## Gotchas
|
||||
|
||||
- Patching per symptom is the default failure mode. Three eval failures may all trace to one missing instruction — always identify the root cause before editing.
|
||||
- Do not create new scripts unless a signal explicitly calls for it. Writing scripts from scratch requires transcript analysis that is out of scope here; flag the opportunity as a suggestion instead.
|
||||
- Never spawn a subagent to audit or recheck your own work during an authoring pass. Run `/skill-audit` yourself, inline, in the same context as the edits you just made. A *separate* independent recheck via a clean-context subagent is the `/forge` skill's outer-loop responsibility exclusively — delegating it inward here duplicates that layer and introduces a race: a stray self-spawned subagent can have its worktree torn down by concurrent cleanup, destroying an uncommitted draft before it was ever safe.
|
||||
|
||||
## Route
|
||||
|
||||
Determine which flow to follow before touching the filesystem:
|
||||
|
||||
- **No skill directory at the target path** → follow **Creating a new skill**
|
||||
- **Directory exists + at least one improvement signal present** → follow **Improving an existing skill**
|
||||
- **Directory exists + no signals present** → ask: "No improvement signals found. Did you mean to create a new skill, or do you have feedback to apply?"
|
||||
|
||||
Signals include: grill session output, `/skill-audit` findings (PASS/FAIL punch list), inline user feedback, session context describing what went wrong.
|
||||
|
||||
**Before running the scaffold script**, judge whether the destination is meant to be inside an APM package — the script can't tell "no package here" apart from "package not scaffolded yet":
|
||||
|
||||
- Package intent but no `type:`-bearing `apm.yml` found at/above the destination (e.g. "add to my apm package", or a sibling `.apm/`/`apm.yml` exists nearby) → **stop**, tell the user to run `/apm-workflow configure` (`apm plugin init`, from inside the package directory) first, then retry. Don't fall through to standalone mode.
|
||||
- Otherwise (a `~/`-rooted destination, or no package context implied) → run `scripts/new-skill.sh`; it resolves package vs. standalone automatically (see Step 1).
|
||||
|
||||
## Creating a new skill
|
||||
|
||||
### Prerequisites
|
||||
|
||||
Run `/grill-me` on the skill's design and research the target domain first.
|
||||
Share those outputs in this conversation: grill context, research docs, examples, constraints.
|
||||
|
||||
Design for one coherent user intent — skills too narrow force multiple loads per task; too broad are hard to activate precisely.
|
||||
|
||||
**Before touching the filesystem, verify you have:**
|
||||
- [ ] A clear purpose — what specific task will this skill handle?
|
||||
- [ ] Trigger scenarios — when should an agent activate it, including indirect cases?
|
||||
- [ ] Skill name (kebab-case) and destination path
|
||||
- [ ] Capture `git log --oneline -1` now, before touching the filesystem — Step 7 needs it to verify a real commit landed
|
||||
|
||||
If any are missing, stop and ask the user before proceeding.
|
||||
|
||||
**Requires `/skill-audit`** — used in Step 7 for final validation. Both skills ship in the kyberforge plugin and are co-installed. If `/skill-audit` is unavailable, stop and ask the user to install the kyberforge plugin before continuing.
|
||||
|
||||
### Step 1 — Scaffold
|
||||
|
||||
Run the copy script with the skill name and a path inside or at the target:
|
||||
|
||||
```bash
|
||||
bash scripts/new-skill.sh <skill-name> <path>
|
||||
```
|
||||
|
||||
The script walks up from `<path>` for a package boundary: an ancestor `apm.yml` with a top-level `type:` field (`instructions`/`skill`/`hybrid`/`prompts`) means **package mode** — scaffolds into `<package-root>/.apm/skills/<skill-name>/`, not under `<path>` (a subdirectory of the package works fine as `<path>`). A `type:`-less `apm.yml` is a marketplace-only manifest, skipped. Hitting `.git` or the filesystem root first means **standalone mode** — scaffolds directly into `<path>/<skill-name>/`, same as before.
|
||||
|
||||
Examples:
|
||||
```bash
|
||||
# Package mode — packages/my-pkg/apm.yml already has `type: skill`
|
||||
bash scripts/new-skill.sh my-tool packages/my-pkg/
|
||||
|
||||
# Standalone mode — no apm.yml/.git above ~/.agents/skills/
|
||||
bash scripts/new-skill.sh my-tool ~/.agents/skills/
|
||||
```
|
||||
|
||||
The script prints which mode it used and where the skill landed — read its output.
|
||||
|
||||
In package mode, read `references/deployment-modes.md` before adding any file references to SKILL.md.
|
||||
|
||||
### Step 2 — Update `apm.yml` includes (package mode only)
|
||||
|
||||
Skip in standalone mode. In package mode, check the resolved package's `apm.yml`: if `includes:` is an explicit list (not `auto`), append `.apm/skills/<skill-name>/` to it if not already present, preserving YAML formatting. If `includes: auto` or the field is absent, do nothing — `auto` already covers the new skill. Use Read/Edit directly on `apm.yml`; this isn't part of `scripts/new-skill.sh`.
|
||||
|
||||
### Step 3 — Fill in SKILL.md
|
||||
|
||||
Open the new skill's `SKILL.md` (the path Step 1 printed). Replace every `FILL IN:` placeholder.
|
||||
|
||||
**Frontmatter**
|
||||
|
||||
**`name`** — already set by the scaffold script. Must exactly match the directory name. Format: 1–64 characters, lowercase letters/numbers/hyphens only, no leading, trailing, or consecutive hyphens (`--`).
|
||||
|
||||
**`description`** — carries the entire triggering burden. Rules:
|
||||
- Imperative: "Use when..." not "This skill..."
|
||||
- Focus on user intent, not implementation — describe what the user is trying to achieve, not the skill's internal mechanics
|
||||
- Specific about capabilities ("parses and validates OpenAPI specs", not "helps with APIs")
|
||||
- Include indirect triggers: "even if the user doesn't mention X explicitly"
|
||||
- Add "Do not use when..." only if a near-miss skill exists that could steal activations
|
||||
- Hard limit: 1024 characters — count before finalizing
|
||||
|
||||
**Optional fields** — uncomment and fill in or remove entirely:
|
||||
- `license` — include when distributing the skill externally
|
||||
- `compatibility` — include if the skill requires specific tools, runtimes, or network access (max 500 characters)
|
||||
- `metadata` — key-value map; use `author`, `version`, `category`; add `source_keys` now (see below) if research sources are in context
|
||||
- `allowed-tools` — space-separated pre-approved tools; reduces permission prompts (experimental — support varies by client)
|
||||
|
||||
**`metadata.source_keys`** — if research sources are in context, list the relevant slugs here as you write the body; don't defer this to Step 6. Agents that fill in source_keys late tend to omit it entirely. Example:
|
||||
```yaml
|
||||
metadata:
|
||||
source_keys:
|
||||
- my-source-slug
|
||||
- another-slug
|
||||
```
|
||||
|
||||
**Embedding org-specific policy** — if a skill encodes a rule sourced from an org convention file (e.g. `core/instructions/*.md`), inline that content directly into the skill (SKILL.md or a `references/` file) rather than pointing to the file's path. Plugins must be self-contained and portable — the org file may not exist wherever the plugin is installed, and in this repo such files are meant to be deleted once their content is fully embedded downstream. Tag the inlined content with a `source_keys` entry using the same `references/sources.md` schema as Step 6, noting in the `Research doc:` field that the source is an org convention rather than a plugin research corpus entry, so provenance survives after the source file is gone.
|
||||
|
||||
**Body — include only what the agent lacks**
|
||||
|
||||
Rename the placeholder section heading to one that fits the skill's structure — `## Step 1`, `## Workflow`, `## Instructions`, etc.
|
||||
|
||||
Ask of every sentence: "Would the agent get this wrong without it?" Cut anything that answers "no."
|
||||
|
||||
**Include:**
|
||||
- Non-obvious sequences or ordering constraints — the agent may skip or reorder steps without this
|
||||
- Domain conventions the agent cannot infer from general knowledge — this is the core value a skill adds
|
||||
- One default per decision point, plus one escape hatch — never a menu; menus cause the agent to pause or pick arbitrarily
|
||||
- Gotchas — facts that defy reasonable assumptions; the agent will get these wrong every time without them
|
||||
|
||||
**Exclude:**
|
||||
- Concepts the agent already knows (what JSON is, how HTTP works) — adds tokens without changing behavior
|
||||
- Exhaustive option lists — pick a default; the agent doesn't benefit from choosing
|
||||
- Steps the agent handles independently — over-specifying leads agents to follow unproductive paths
|
||||
- Restatements of the description — it's already in context; repeating it wastes the token budget
|
||||
|
||||
**Patterns**
|
||||
|
||||
**Gotchas** — highest value; place near the top:
|
||||
````markdown
|
||||
## Gotchas
|
||||
- <Fact that defies a reasonable assumption>
|
||||
- <Non-obvious naming discrepancy or hidden constraint>
|
||||
````
|
||||
|
||||
**Default with escape hatch** (not a menu):
|
||||
````markdown
|
||||
Use <X> for <task>. For <edge case>, use <Y> instead.
|
||||
````
|
||||
|
||||
**Prescriptive sequence** (when order is critical or fragile):
|
||||
````markdown
|
||||
Run exactly:
|
||||
```bash
|
||||
<command>
|
||||
```
|
||||
Do not modify flags.
|
||||
````
|
||||
|
||||
**Checklist** (multi-step workflows):
|
||||
````markdown
|
||||
- [ ] Step 1: ...
|
||||
- [ ] Step 2: ...
|
||||
````
|
||||
|
||||
**Conditional reference** (progressive disclosure — load only when needed):
|
||||
````markdown
|
||||
If <condition>, read `references/<file>.md`.
|
||||
````
|
||||
|
||||
**Output format template** (when the skill produces structured output):
|
||||
````markdown
|
||||
Output format:
|
||||
```
|
||||
<field>: <value>
|
||||
<field>: <value>
|
||||
```
|
||||
````
|
||||
For longer templates, place in `assets/<name>.md` and reference conditionally.
|
||||
|
||||
**Size budget**
|
||||
|
||||
Keep `SKILL.md` under 500 lines; 5,000 tokens is the recommended body budget. When approaching the limit:
|
||||
- Move reference material to `references/<topic>.md` and load it conditionally
|
||||
- Bundle repeated executable logic into `scripts/` rather than reinventing each run
|
||||
|
||||
### Step 4 — Add scripts (if needed)
|
||||
|
||||
Place executable scripts in `scripts/`. Critical rule: **no interactive prompts** — agents run non-interactive; blocking on TTY input hangs indefinitely. Accept all input via flags, env vars, or stdin.
|
||||
|
||||
If adding a script, read `references/scripts.md` first — it covers the full contract: structured output, pinned versions, self-contained deps, idempotency, exit codes, dry-run, error messages, and output size limits.
|
||||
|
||||
If no scripts are needed, delete `scripts/README.md` and the `scripts/` directory.
|
||||
|
||||
### Step 5 — Add references, assets, and tests (if needed)
|
||||
|
||||
**`references/`** — additional documentation loaded on demand. One topic per file.
|
||||
Reference conditionally from SKILL.md: `If <condition>, read references/<file>.md`.
|
||||
Keep reference chains one level deep — a reference file that references another reference file is rarely loaded correctly.
|
||||
|
||||
**`assets/`** — static resources: templates, schemas, lookup tables.
|
||||
Reference by relative path from SKILL.md.
|
||||
|
||||
**`tests/`** — test files for scripts in `scripts/`. Use when scripts are complex
|
||||
enough to break silently. Test infrastructure (`.bats`, `*_test.*`) belongs here,
|
||||
not in `scripts/`. See `tests/README.md` for setup instructions.
|
||||
|
||||
If not needed, delete the placeholder READMEs and their directories.
|
||||
|
||||
### Step 6 — Populate or delete `references/sources.md`
|
||||
|
||||
If a research `sources.md` is present in the conversation context:
|
||||
|
||||
1. Read it and filter to entries with `` `extracted` `` status only.
|
||||
2. For each entry, determine which skill files it contributed to (SKILL.md and any files in references/ that drew from it). Update `Contributing files` accordingly — list skill files, not research topic files.
|
||||
3. Write the updated content to `references/sources.md`. For each entry, include `- **Research doc:** <path>` where `<path>` is the relative path from the repo root to the plugin-level research sources file this entry was drawn from (e.g. `plugins/myplugin/docs/research/docs/<topic>/sources.md`). This field is required on every entry — it makes the provenance chain explicit and is validated by `/skill-audit`.
|
||||
4. Add `source_keys` to the frontmatter of `SKILL.md` (under `metadata`) listing the slugs of sources that informed it.
|
||||
5. For each file in `references/` that was informed by research sources, add `source_keys` frontmatter (same format as research topic files) listing the relevant slugs.
|
||||
|
||||
If no research `sources.md` is in context, delete `references/sources.md`.
|
||||
|
||||
### Step 7 — Validate and close
|
||||
|
||||
Before running the audit, confirm:
|
||||
- [ ] Skill name matches the directory name exactly
|
||||
- [ ] `description` field is present and non-empty
|
||||
- [ ] Body has at least one non-empty section
|
||||
- [ ] No `FILL IN:` placeholders remain in any file
|
||||
|
||||
Run `/skill-audit` on the skill directory Step 1 reported — either `<package-root>/.apm/skills/<skill-name>/` or `<path>/<skill-name>/`.
|
||||
|
||||
All FAIL findings must be resolved before the skill is considered done.
|
||||
|
||||
If the skill is versioned (`metadata.version`), set it to the next **minor** version (e.g. `0.2.0` → `0.3.0`). New skills without a prior version start at `0.1.0`.
|
||||
|
||||
**Commit verification.** Capture `git log --oneline -1` before Step 1 and keep it. Once the audit is clean, run `git add` and `git commit` for the new skill files — do not stop at staging. Then run `git log --oneline -1` again and confirm the hash changed from the one you captured at the start. A non-empty `git diff --stat` is not sufficient proof of completion: staged-but-uncommitted work isn't part of any commit and can be silently lost if the working tree is cleaned up before a commit lands. Only report the skill as done once the hash has actually changed.
|
||||
|
||||
## Improving an existing skill
|
||||
|
||||
### Step 1 — Verify inputs
|
||||
|
||||
Confirm the skill directory path exists and that at least one improvement signal is present in the conversation or a referenced file.
|
||||
|
||||
If the skill dir is missing, ask for it. If no signals are present, stop: "This skill applies existing signals to a skill. For a blind review without signals, use `/skill-audit` instead."
|
||||
|
||||
Capture `git log --oneline -1` now, before making any edits — Step 5 needs it to verify a real commit landed.
|
||||
|
||||
Signals can come from anywhere in the conversation or referenced files:
|
||||
- Grill session output (most common predecessor in the factory sequence)
|
||||
- `/skill-audit` findings (PASS/FAIL/SUGGESTION punch list)
|
||||
- Human feedback (feedback.json, inline in conversation, PR or issue comments)
|
||||
- Session context describing what went wrong
|
||||
|
||||
Also verify the `name` field in frontmatter matches the skill's directory name exactly.
|
||||
|
||||
### Step 2 — Gather and group signals
|
||||
|
||||
Read the current skill files (SKILL.md and any files in scripts/, references/, assets/, tests/). Then collect all signals from the conversation and any file paths the user has referenced.
|
||||
|
||||
Group signals by **root cause**, not symptom. Ask: "What single gap in the skill causes this cluster of failures?" One root cause → one fix. Do not make a separate edit for each symptom.
|
||||
|
||||
```text
|
||||
Example:
|
||||
- Session context: output format is wrong on every run
|
||||
- Audit finding: no output template defined
|
||||
- User feedback: "I always have to ask it to format the output"
|
||||
→ Root cause: SKILL.md has no output format specification → one fix: add an output template
|
||||
```
|
||||
|
||||
### Step 3 — Announce planned changes
|
||||
|
||||
Before editing, state:
|
||||
- Which root causes were identified and what evidence supports each
|
||||
- Which files will be changed and what will change in each
|
||||
|
||||
Then proceed — edits are reversible via git, no approval checkpoint needed.
|
||||
|
||||
### Step 4 — Apply changes
|
||||
|
||||
Edit any file in the skill directory that the signals point to: SKILL.md, scripts/, references/, assets/, tests/, README.md.
|
||||
|
||||
**Generalize, don't patch.** Find the underlying gap, not the specific example that failed. A fix scoped only to the test cases you've seen will overfit and perform worse on new inputs.
|
||||
|
||||
**Keep it lean.** Remove instructions that aren't pulling their weight. For every sentence you add, ask: "Would the agent get this wrong without it?" A shorter, focused skill consistently outperforms an exhaustive one.
|
||||
|
||||
**Explain the why.** Reasoning-based instructions outperform rigid directives. If you find yourself writing a rule in all caps (ALWAYS/NEVER), reframe it: explain why the behavior matters so the agent can apply judgment in edge cases.
|
||||
|
||||
If a signal points to a script or reference file, edit that file directly rather than adding a workaround in SKILL.md.
|
||||
|
||||
### Step 5 — Validate and close
|
||||
|
||||
Before running the audit, confirm:
|
||||
- [ ] Skill name still matches the directory name
|
||||
- [ ] No `FILL IN:` placeholders were introduced
|
||||
- [ ] No previously-passing audit checks were broken by the edits
|
||||
|
||||
Run `/skill-audit` on the skill directory. Resolve any FAIL findings before considering the improvement complete.
|
||||
|
||||
If the skill is versioned (`metadata.version`), bump the **patch** version (e.g. `0.1.0` → `0.1.1`).
|
||||
|
||||
**Commit verification.** Capture `git log --oneline -1` at the start of Step 1 and keep it. Once the audit is clean, run `git add` and `git commit` for the changed files — do not stop at staging. Then run `git log --oneline -1` again and confirm the hash changed from the one you captured at the start. A non-empty `git diff --stat` is not sufficient proof of completion: staged-but-uncommitted work isn't part of any commit and can be silently lost if the working tree is cleaned up before a commit lands. Only report the improvement as done once the hash has actually changed.
|
||||
@@ -0,0 +1,51 @@
|
||||
# SKILL_NAME
|
||||
|
||||
<!-- FILL IN: One sentence describing what this skill does. -->
|
||||
|
||||
## What it does
|
||||
|
||||
<!-- FILL IN: 2–4 sentences. What task does this skill handle?
|
||||
What does the agent produce or accomplish when it runs? -->
|
||||
|
||||
## Before you start
|
||||
|
||||
<!-- FILL IN: List any prerequisites the user should have ready.
|
||||
Examples: research docs, a grill session, specific input files, credentials.
|
||||
Delete this section if the skill has no meaningful prerequisites. -->
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
/SKILL_NAME
|
||||
```
|
||||
|
||||
<!-- FILL IN: Add any required or common arguments.
|
||||
If the skill takes no arguments, delete the code block above and just keep the slash command. -->
|
||||
|
||||
<!-- OPTIONAL: Manual (human) workflow — include if the skill bundles scripts a human can run directly.
|
||||
|
||||
**Manual workflow:**
|
||||
```bash
|
||||
# FILL IN: step-by-step commands
|
||||
```
|
||||
-->
|
||||
|
||||
## Files
|
||||
|
||||
<!-- FILL IN: List each file individually. Remove rows for directories you deleted.
|
||||
Replace the example rows below with your actual files. -->
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `SKILL.md` | Skill instructions for agents |
|
||||
| `scripts/your-script.sh` | FILL IN: what this script does |
|
||||
| `references/your-doc.md` | FILL IN: what this reference covers |
|
||||
| `assets/your-asset.json` | FILL IN: what this asset is |
|
||||
| `tests/your-test.bats` | FILL IN: what this test covers |
|
||||
|
||||
<!-- OPTIONAL: Spec reference — include if this skill implements or follows an external standard.
|
||||
|
||||
## Spec reference
|
||||
|
||||
[FILL IN: Spec name](FILL IN: URL)
|
||||
-->
|
||||
105
plugins/kyberforge/skills/skill-author/assets/templates/SKILL.md
Normal file
105
plugins/kyberforge/skills/skill-author/assets/templates/SKILL.md
Normal file
@@ -0,0 +1,105 @@
|
||||
---
|
||||
# SKILL.md — agentskills.io skill definition
|
||||
# Fill in all FILL IN: placeholders. Remove comment blocks that don't apply.
|
||||
|
||||
name: SKILL_NAME
|
||||
# Required. Must exactly match the parent directory name.
|
||||
# Valid characters: lowercase letters, numbers, hyphens.
|
||||
# Invalid: uppercase, leading/trailing/consecutive hyphens.
|
||||
# Max length: 64 characters.
|
||||
# Examples: my-tool, data-analyzer, pdf-processor
|
||||
|
||||
description: >
|
||||
FILL IN: What does this skill do? State capabilities specifically
|
||||
(e.g. "parses and validates OpenAPI specs", not "helps with APIs").
|
||||
Use when FILL IN: when should an agent activate this skill?
|
||||
Include indirect triggers: even if the user doesn't mention X explicitly.
|
||||
Do not use when FILL IN: near-miss exclusions — remove this line if none apply.
|
||||
|
||||
# license: MIT
|
||||
# Optional. License name (e.g. MIT, Apache-2.0) or relative path to a bundled
|
||||
# license file. Include when distributing this skill. Omit for private/internal use.
|
||||
|
||||
# compatibility: Requires python3 >= 3.10 and uv
|
||||
# Optional. 1–500 characters. State tool requirements, runtime versions,
|
||||
# and network access needs. Omit for skills with no special environment requirements.
|
||||
|
||||
# metadata:
|
||||
# author: your-name
|
||||
# version: "1.0"
|
||||
# category: general
|
||||
# source_keys:
|
||||
# - source-slug-one
|
||||
# - source-slug-two
|
||||
# Optional. Arbitrary key-value map. Common keys: author, version, category.
|
||||
# source_keys: populated when built from /research output. Lists slugs from references/sources.md.
|
||||
# Also add source_keys to each references/*.md file that was informed by research.
|
||||
|
||||
# allowed-tools: Bash Read Write
|
||||
# Optional (experimental — support varies by client).
|
||||
# Space-separated list of pre-approved tools.
|
||||
# Use when tool usage is known and bounded, to reduce permission prompts.
|
||||
---
|
||||
|
||||
<!-- ============================================================
|
||||
SKILL BODY
|
||||
|
||||
Include only what the agent lacks:
|
||||
- Domain conventions the agent cannot infer from general knowledge
|
||||
- Non-obvious sequences or ordering constraints
|
||||
- One default per decision point + one escape hatch (never a menu)
|
||||
- Gotchas — facts that defy reasonable assumptions
|
||||
|
||||
Omit:
|
||||
- Concepts the agent already knows
|
||||
- Exhaustive option lists
|
||||
- Steps the agent handles independently
|
||||
- Restatements of the description
|
||||
|
||||
Size budget: under 500 lines / 5000 tokens.
|
||||
Move reference material to references/ and load it conditionally.
|
||||
Bundle repeated executable logic into scripts/.
|
||||
|
||||
Delete this comment block before shipping.
|
||||
============================================================ -->
|
||||
|
||||
<!-- OPTIONAL: Gotchas section — highest-value content. Place near the top.
|
||||
Add facts that defy reasonable assumptions or non-obvious constraints.
|
||||
|
||||
## Gotchas
|
||||
|
||||
- FILL IN: fact that defies a reasonable assumption
|
||||
- FILL IN: non-obvious naming discrepancy or hidden constraint
|
||||
-->
|
||||
|
||||
<!-- OPTIONAL: Multi-step workflow checklist.
|
||||
|
||||
## Workflow
|
||||
|
||||
- [ ] Step 1: FILL IN
|
||||
- [ ] Step 2: FILL IN
|
||||
- [ ] Step 3: FILL IN
|
||||
-->
|
||||
|
||||
<!-- OPTIONAL: Output format template — use when the agent must produce a specific format.
|
||||
|
||||
## Output format
|
||||
|
||||
Use this structure:
|
||||
|
||||
```markdown
|
||||
# [FILL IN: Title]
|
||||
|
||||
## FILL IN: Section
|
||||
FILL IN: what goes here
|
||||
```
|
||||
-->
|
||||
|
||||
<!-- OPTIONAL: Conditional reference — load documentation only when needed.
|
||||
|
||||
If FILL IN: condition, read `references/FILL IN: filename.md`.
|
||||
-->
|
||||
|
||||
## FILL IN: <section-name (e.g. Step 1, Workflow, Instructions)>
|
||||
|
||||
FILL IN: Add your skill instructions here. Replace this section header and body with your skill content.
|
||||
@@ -0,0 +1,29 @@
|
||||
# assets/
|
||||
|
||||
Static resources bundled with this skill: templates, schemas, lookup tables,
|
||||
sample data, images.
|
||||
|
||||
## When to add an asset
|
||||
|
||||
Add a file here when the skill needs a static resource that:
|
||||
- Would be tedious to reproduce in instructions (a full JSON schema, a CSV
|
||||
lookup table, a binary template)
|
||||
- Needs to be referenced by path rather than inlined in SKILL.md
|
||||
|
||||
## How to reference from SKILL.md
|
||||
|
||||
Use a relative path from the skill root:
|
||||
|
||||
```markdown
|
||||
Use the schema at `assets/response-schema.json` to validate output.
|
||||
```
|
||||
|
||||
Or instruct the agent to load it conditionally:
|
||||
|
||||
```markdown
|
||||
If validating output format, use `assets/response-schema.json`.
|
||||
```
|
||||
|
||||
## If no assets are needed
|
||||
|
||||
Delete this README and the `assets/` directory entirely.
|
||||
@@ -0,0 +1,31 @@
|
||||
# references/
|
||||
|
||||
Additional documentation agents load on demand. Files here extend SKILL.md
|
||||
without bloating its core context.
|
||||
|
||||
## When to add a reference file
|
||||
|
||||
Move content here when SKILL.md is approaching 500 lines, or when a topic
|
||||
is only relevant in specific circumstances (error handling, edge cases,
|
||||
domain-specific sub-procedures).
|
||||
|
||||
## How to reference from SKILL.md
|
||||
|
||||
Load conditionally — tell the agent exactly when to read each file:
|
||||
|
||||
```markdown
|
||||
If the API returns a non-200 status, read `references/api-errors.md`.
|
||||
```
|
||||
|
||||
Avoid generic "see references/ for details" — the agent loads context on
|
||||
demand, so give it a precise trigger condition.
|
||||
|
||||
## File conventions
|
||||
|
||||
- One topic per file — focused files mean less unnecessary context loaded
|
||||
- Kebab-case filenames (e.g. `api-errors.md`, `output-formats.md`)
|
||||
- Keep files under 200 lines where possible
|
||||
|
||||
## If no reference files are needed
|
||||
|
||||
Delete this README and the `references/` directory entirely.
|
||||
@@ -0,0 +1,14 @@
|
||||
# Sources
|
||||
|
||||
<!-- Populated at Step 5 of skill authoring, after all skill files are written.
|
||||
For each research source with status `extracted`, record which skill files
|
||||
it contributed to under Contributing files.
|
||||
Delete this file if no research sources were provided as input. -->
|
||||
|
||||
## FILL IN: source-slug
|
||||
|
||||
- **URL:** FILL IN
|
||||
- **Description:** FILL IN
|
||||
- **Research doc:** FILL IN: path to the plugin-level research sources file this entry came from (e.g. plugins/myplugin/docs/research/docs/<topic>/sources.md), relative to repo root
|
||||
- **Contributing files:** FILL IN: comma-separated list of skill files this source informed (e.g. SKILL.md, references/foo.md). Use `(none)` if the source was consulted but contributed no file content directly.
|
||||
- **Status:** `extracted`
|
||||
@@ -0,0 +1,47 @@
|
||||
# scripts/
|
||||
|
||||
Executable code bundled with this skill. Agents run scripts in this directory
|
||||
to perform repeatable operations rather than reinventing the logic each run.
|
||||
|
||||
## When to add a script
|
||||
|
||||
Add a script when agents independently reinvent the same logic across runs —
|
||||
building the same parser, chart, or validation routine from scratch each time.
|
||||
Bundle it here once, tested and reliable.
|
||||
|
||||
## Script requirements (agentskills.io)
|
||||
|
||||
Scripts must be designed for non-interactive, agentic execution:
|
||||
|
||||
- **No interactive prompts** — agents run in non-interactive shells.
|
||||
Accept all input via flags, env vars, or stdin. A script that blocks on
|
||||
TTY input hangs indefinitely.
|
||||
- **Expose `--help`** — this is how agents learn your script's interface.
|
||||
Keep the output concise; it enters the agent's context window.
|
||||
- **Structured output** — write data (JSON, CSV, TSV) to stdout.
|
||||
Write progress, warnings, and diagnostics to stderr.
|
||||
- **Idempotent** — prefer "create if not exists" over "create and fail on
|
||||
duplicate". Agents may retry on failure.
|
||||
- **Meaningful exit codes** — `0` for success, non-zero for failure.
|
||||
Use distinct codes for different failure types; document them in `--help`.
|
||||
- **Dry-run support** — add `--dry-run` for destructive operations.
|
||||
|
||||
## Self-contained scripts
|
||||
|
||||
Bundle dependencies inline so the agent can run the script with a single command.
|
||||
|
||||
Python (PEP 723 + uv):
|
||||
```python
|
||||
# /// script
|
||||
# dependencies = ["requests>=2.31,<3"]
|
||||
# requires-python = ">=3.11"
|
||||
# ///
|
||||
import requests
|
||||
```
|
||||
```bash
|
||||
uv run scripts/my-script.py
|
||||
```
|
||||
|
||||
## If no scripts are needed
|
||||
|
||||
Delete this README and the `scripts/` directory entirely.
|
||||
@@ -0,0 +1,55 @@
|
||||
---
|
||||
source_keys:
|
||||
- agentskills-spec
|
||||
---
|
||||
|
||||
# Deployment Modes
|
||||
|
||||
Skills deploy standalone, or as part of a package — either a legacy plugin-mode cache install or an APM (`apm.yml`-governed `.apm/` tree, compiled via `apm compile`). All resolve relative paths from the skill root — the SKILL.md body works the same in any of them. Differences only arise when referencing files *outside* the skill directory.
|
||||
|
||||
## Cache isolation (plugin mode)
|
||||
|
||||
When a plugin is installed, its directory is copied to a cache. Only the plugin's own files are copied. **Any path that leaves the skill directory breaks post-install:**
|
||||
|
||||
```
|
||||
../other-skill/validate.sh # breaks
|
||||
plugins/kyberforge/skills/other-skill/ # breaks
|
||||
../../shared/utils.sh # breaks
|
||||
```
|
||||
|
||||
Fix: duplicate the file into the skill's own `scripts/` or `assets/`. There is no plugin-level `shared/` mechanism — the spec defines no cross-skill sharing, and `../` paths are broken by construction.
|
||||
|
||||
## Compiled output (APM package mode)
|
||||
|
||||
For a package (an `apm.yml`-governed `.apm/` source tree), the deployable artifact is generated by `apm compile` per target harness — not produced by copying the raw `.apm/` directory wholesale the way a plugin cache install copies a plugin directory. The same self-containment rule still applies at the skill level: **file references inside `.apm/skills/<name>/` must not reach outside that skill's own directory.**
|
||||
|
||||
```
|
||||
../other-skill/validate.sh # breaks
|
||||
.apm/skills/other-skill/ # breaks
|
||||
../../shared/utils.sh # breaks
|
||||
```
|
||||
|
||||
Fix: duplicate the file into the skill's own `scripts/` or `assets/`, same as plugin mode. `apm.yml`'s `includes:` list (when explicit, not `auto`) controls what gets published from the package, but it is not a cross-skill sharing mechanism — each skill directory must still stand alone.
|
||||
|
||||
## Env vars (plugin mode only)
|
||||
|
||||
These variables are injected when the plugin is loaded from an install cache. They are **not available in standalone mode.**
|
||||
|
||||
| Variable | Value |
|
||||
|----------|-------|
|
||||
| `${CLAUDE_PLUGIN_ROOT}` | Absolute path to the plugin's install directory. Changes on update. |
|
||||
| `${CLAUDE_PLUGIN_DATA}` | Persistent directory that survives updates. Use for `node_modules`, generated state, caches. |
|
||||
|
||||
Use `${CLAUDE_PLUGIN_ROOT}` only in hook commands and `.mcp.json` configs — not in SKILL.md body text, since standalone deployments won't have it.
|
||||
|
||||
## Standalone mode
|
||||
|
||||
Deployed directly to `~/.agents/skills/<name>/`. No plugin context, no env vars injected. All file references must resolve within the skill directory. Skill invocations (e.g. `/skill-audit`) work if the called skill is also installed.
|
||||
|
||||
## Cross-tool portability
|
||||
|
||||
`SKILL.md` is portable — the same file works in Claude Code and Copilot CLI, whether deployed standalone or compiled from an APM package. `apm.yml` is the source manifest: it is itself tool-agnostic (one file describes the package regardless of target), but `apm compile` produces per-target compiled output — a Claude Code plugin tree, a Copilot CLI tree, etc. — from it. Legacy hand-authored manifest files (`plugin.json`, `hooks.json`) are tool-specific and authored separately per tool; they sit outside the `apm.yml`-based flow.
|
||||
|
||||
## Shared assets between skills
|
||||
|
||||
If two skills in the same plugin need the same file, duplicate it into each skill's `assets/` or `scripts/`. Add a comment in both copies noting the mirror relationship so they stay in sync when the spec changes.
|
||||
89
plugins/kyberforge/skills/skill-author/references/scripts.md
Normal file
89
plugins/kyberforge/skills/skill-author/references/scripts.md
Normal file
@@ -0,0 +1,89 @@
|
||||
---
|
||||
source_keys:
|
||||
- agentskills-using-scripts
|
||||
---
|
||||
|
||||
# Scripts Reference
|
||||
|
||||
## Package runners (no install required)
|
||||
|
||||
When an existing package does what you need, use a runner directly in SKILL.md without writing a script file.
|
||||
|
||||
| Runner | Language | Notes |
|
||||
|--------|----------|-------|
|
||||
| `uvx package@version` | Python | Recommended. Aggressive caching via uv. |
|
||||
| `pipx run 'package==version'` | Python | Broader OS availability. |
|
||||
| `npx package@version` | Node.js | Ships with npm/Node.js. |
|
||||
| `bunx package@version` | Node.js | Bun environments only. |
|
||||
| `deno run npm:package@version` | TypeScript | Requires permission flags (`--allow-read`, etc.). |
|
||||
| `go run golang.org/x/...@version` | Go | Built into Go toolchain. |
|
||||
|
||||
Always pin versions. Never use `pip install` or `npm install -g` at runtime — they are not idempotent and pollute the environment.
|
||||
|
||||
## Inline dependency patterns
|
||||
|
||||
Use these when the script requires packages but should remain a single portable file.
|
||||
|
||||
**Python (PEP 723 + uv):**
|
||||
```python
|
||||
# /// script
|
||||
# dependencies = [
|
||||
# "beautifulsoup4>=4.12,<5",
|
||||
# ]
|
||||
# requires-python = ">=3.12"
|
||||
# ///
|
||||
from bs4 import BeautifulSoup
|
||||
```
|
||||
```bash
|
||||
uv run scripts/extract.py
|
||||
```
|
||||
|
||||
**TypeScript (Deno):**
|
||||
```typescript
|
||||
#!/usr/bin/env -S deno run
|
||||
import * as cheerio from "npm:cheerio@1.0.0";
|
||||
```
|
||||
```bash
|
||||
deno run scripts/extract.ts
|
||||
```
|
||||
|
||||
**TypeScript (Bun):**
|
||||
```typescript
|
||||
#!/usr/bin/env bun
|
||||
import * as cheerio from "cheerio@1.0.0";
|
||||
```
|
||||
```bash
|
||||
bun run scripts/extract.ts
|
||||
```
|
||||
|
||||
**Ruby (bundler/inline):**
|
||||
```ruby
|
||||
require 'bundler/inline'
|
||||
gemfile do
|
||||
source 'https://rubygems.org'
|
||||
gem 'nokogiri', '~> 1.16'
|
||||
end
|
||||
```
|
||||
```bash
|
||||
ruby scripts/extract.rb
|
||||
```
|
||||
|
||||
## Script contract
|
||||
|
||||
Rules for all agentic scripts:
|
||||
|
||||
- **Self-contained** — bundle dependencies inline so the agent can run the script with a single command; do not require a separate install step
|
||||
- **Structured output** — data (JSON, CSV) to stdout; diagnostics and progress to stderr
|
||||
- **Idempotent** — "create if not exists"; agents may retry on failure
|
||||
- **Input constraints** — validate inputs early; reject unknown or ambiguous values with a clear error rather than proceeding silently
|
||||
- **Meaningful exit codes** — `0` success, non-zero failure; document in `--help`
|
||||
- **Dry-run support** — add `--dry-run` for destructive operations; pair with `--confirm`/`--force` for operations that can't be undone
|
||||
- **Error messages** — on failure, state what went wrong, what was expected, and what to try; vague errors leave agents unable to self-correct
|
||||
|
||||
## --help output
|
||||
|
||||
Keep `--help` output concise — it enters the agent's context window. Include: usage line, one-line description, options with defaults, exit codes. Omit prose explanations.
|
||||
|
||||
## Output size
|
||||
|
||||
Many harnesses truncate tool output beyond 10–30K characters. Default to a summary or a reasonable output limit. For scripts that can produce large output: support `--offset N` for pagination, or use `--output FILE` to write to disk and keep stdout clean.
|
||||
70
plugins/kyberforge/skills/skill-author/references/sources.md
Normal file
70
plugins/kyberforge/skills/skill-author/references/sources.md
Normal file
@@ -0,0 +1,70 @@
|
||||
---
|
||||
source_keys:
|
||||
- agentskills-home
|
||||
- agentskills-spec
|
||||
- agentskills-best-practices
|
||||
- agentskills-optimizing-descriptions
|
||||
- agentskills-evaluating-skills
|
||||
- agentskills-using-scripts
|
||||
- agentskills-quickstart
|
||||
---
|
||||
|
||||
# Sources
|
||||
|
||||
<!-- agentskills.io/llms.txt was used for initial source discovery and is not listed below; it contributed no skill file content directly. -->
|
||||
|
||||
## agentskills-home
|
||||
|
||||
- **URL:** https://agentskills.io/home.md
|
||||
- **Research doc:** plugins/kyberforge/docs/research/docs/agentskillsio/sources.md
|
||||
- **Description:** Agent Skills overview — what it is, why it exists, progressive disclosure model, ecosystem of 35+ implementing tools
|
||||
- **Contributing files:** SKILL.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## agentskills-spec
|
||||
|
||||
- **URL:** https://agentskills.io/specification.md
|
||||
- **Research doc:** plugins/kyberforge/docs/research/docs/agentskillsio/sources.md
|
||||
- **Description:** Complete SKILL.md format specification — frontmatter fields, constraints, body content, optional directories, progressive disclosure levels, file references, validation
|
||||
- **Contributing files:** SKILL.md, references/deployment-modes.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## agentskills-best-practices
|
||||
|
||||
- **URL:** https://agentskills.io/skill-creation/best-practices.md
|
||||
- **Research doc:** plugins/kyberforge/docs/research/docs/agentskillsio/sources.md
|
||||
- **Description:** Best practices for skill creators — starting from real expertise, spending context wisely, calibrating control, instruction patterns (gotchas, templates, checklists, validation loops)
|
||||
- **Contributing files:** SKILL.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## agentskills-optimizing-descriptions
|
||||
|
||||
- **URL:** https://agentskills.io/skill-creation/optimizing-descriptions.md
|
||||
- **Research doc:** plugins/kyberforge/docs/research/docs/agentskillsio/sources.md
|
||||
- **Description:** How to systematically test and improve skill descriptions for triggering accuracy — eval queries, trigger rate testing, train/validation splits, optimization loop
|
||||
- **Contributing files:** SKILL.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## agentskills-evaluating-skills
|
||||
|
||||
- **URL:** https://agentskills.io/skill-creation/evaluating-skills.md
|
||||
- **Research doc:** plugins/kyberforge/docs/research/docs/agentskillsio/sources.md
|
||||
- **Description:** Eval-driven skill quality improvement — test case design, workspace structure, assertion writing, grading, benchmarking, human review, iteration loop
|
||||
- **Contributing files:** SKILL.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## agentskills-using-scripts
|
||||
|
||||
- **URL:** https://agentskills.io/skill-creation/using-scripts.md
|
||||
- **Research doc:** plugins/kyberforge/docs/research/docs/agentskillsio/sources.md
|
||||
- **Description:** Using scripts in skills — one-off commands, self-contained scripts with inline dependencies, designing scripts for agentic use (no interactive prompts, --help, structured output, idempotency)
|
||||
- **Contributing files:** SKILL.md, references/scripts.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## agentskills-quickstart
|
||||
|
||||
- **URL:** https://agentskills.io/skill-creation/quickstart.md
|
||||
- **Research doc:** plugins/kyberforge/docs/research/docs/agentskillsio/sources.md
|
||||
- **Description:** Step-by-step guide to creating a first skill (roll-dice example), how discovery/activation/execution work in practice
|
||||
- **Contributing files:** SKILL.md
|
||||
- **Status:** `extracted`
|
||||
189
plugins/kyberforge/skills/skill-author/scripts/new-skill.sh
Executable file
189
plugins/kyberforge/skills/skill-author/scripts/new-skill.sh
Executable file
@@ -0,0 +1,189 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SKILL_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
TEMPLATES_DIR="$SKILL_DIR/../assets/templates"
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: new-skill.sh <skill-name> <path>
|
||||
|
||||
Create a new skill scaffold by copying annotated templates to the resolved
|
||||
destination. <path> is any existing path inside or at the target — a
|
||||
package or a standalone location. It does not have to be a package root
|
||||
itself.
|
||||
|
||||
The script walks up from <path> to pick one of two modes:
|
||||
|
||||
Package mode:
|
||||
If an apm.yml with a top-level 'type:' field (instructions, skill,
|
||||
hybrid, or prompts) is found at or above <path>, the skill is
|
||||
scaffolded into <package-root>/.apm/skills/<skill-name>/ — not under
|
||||
<path> itself. An apm.yml with no 'type:' field is a marketplace-only
|
||||
manifest, not a package; it is skipped and the walk continues upward.
|
||||
|
||||
Standalone mode:
|
||||
If the walk reaches a '.git' directory or the filesystem root without
|
||||
finding a type-bearing apm.yml, the skill is scaffolded directly into
|
||||
<path>/<skill-name>/, exactly as <path> was given.
|
||||
|
||||
Arguments:
|
||||
skill-name Kebab-case skill identifier (e.g. my-tool, data-analyzer).
|
||||
Must match the directory name exactly.
|
||||
path Any existing path inside/at the target. Used to locate the
|
||||
package (package mode) or as the literal parent directory
|
||||
(standalone mode). Must already exist.
|
||||
Examples: ~/.agents/skills/ packages/my-pkg/some/subdir/
|
||||
|
||||
Output:
|
||||
Package mode: <package-root>/.apm/skills/<skill-name>/
|
||||
Standalone mode: <path>/<skill-name>/
|
||||
|
||||
Exit codes:
|
||||
0 Scaffold created successfully, or destination already exists (no-op)
|
||||
1 Invalid arguments, missing path, or templates not found
|
||||
EOF
|
||||
}
|
||||
|
||||
if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then
|
||||
usage
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ $# -lt 2 ]]; then
|
||||
echo "Error: skill-name and path are required." >&2
|
||||
echo "" >&2
|
||||
usage >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
SKILL_NAME="$1"
|
||||
TARGET_INPUT="$2"
|
||||
|
||||
# Validate skill name format
|
||||
if ! echo "$SKILL_NAME" | grep -qE '^[a-z0-9]+(-[a-z0-9]+)*$'; then
|
||||
echo "Error: skill-name must use lowercase letters, numbers, and hyphens only." >&2
|
||||
echo " No leading, trailing, or consecutive hyphens." >&2
|
||||
echo " Received: '$SKILL_NAME'" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Validate templates directory exists
|
||||
if [[ ! -d "$TEMPLATES_DIR" ]]; then
|
||||
echo "Error: templates directory not found at '$TEMPLATES_DIR'." >&2
|
||||
echo " Run this script from its original location inside the skill-author skill." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Validate path exists
|
||||
if [[ ! -d "$TARGET_INPUT" ]]; then
|
||||
echo "Error: path '$TARGET_INPUT' does not exist." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# True if apm_yml's top-level `type:` line names one of the four APM package
|
||||
# types (instructions/skill/hybrid/prompts) — mirrors validate.sh's
|
||||
# APM_TYPE_RE: an optional quote around the value must be closed by the
|
||||
# *same* quote character (a mismatched or unterminated quote is rejected,
|
||||
# not silently stripped), and the value must be followed by whitespace or
|
||||
# end-of-line so `prompts-only` doesn't false-match on the `prompts` prefix.
|
||||
# `|| [[ -n "$line" ]]` in the read condition also processes a final line
|
||||
# that lacks a trailing newline, which `read` alone would otherwise skip.
|
||||
# Identical to agent-author's new-agent.sh copy of this helper.
|
||||
is_apm_package_manifest() {
|
||||
local apm_yml="$1" line
|
||||
while IFS= read -r line || [[ -n "$line" ]]; do
|
||||
if [[ "$line" =~ ^type:[[:space:]]*(instructions|skill|hybrid|prompts)([[:space:]]|$) ]]; then
|
||||
return 0
|
||||
fi
|
||||
if [[ "$line" =~ ^type:[[:space:]]*([\"\'])(instructions|skill|hybrid|prompts)([\"\'])([[:space:]]|$) ]] \
|
||||
&& [[ "${BASH_REMATCH[1]}" == "${BASH_REMATCH[3]}" ]]; then
|
||||
return 0
|
||||
fi
|
||||
done < "$apm_yml"
|
||||
return 1
|
||||
}
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Walk up from <path> looking for a type-bearing apm.yml (package mode) or a
|
||||
# .git boundary / filesystem root (standalone mode). An apm.yml with no
|
||||
# top-level 'type:' field is a marketplace-only manifest — skip it and keep
|
||||
# walking up. Prints one space-separated line: mode, then the resolved root.
|
||||
# ---------------------------------------------------------------------------
|
||||
find_package_root() {
|
||||
local current
|
||||
current="$(cd "$1" && pwd)"
|
||||
while true; do
|
||||
if [[ -f "$current/apm.yml" ]]; then
|
||||
if is_apm_package_manifest "$current/apm.yml"; then
|
||||
echo "package $current"
|
||||
return 0
|
||||
fi
|
||||
# apm.yml exists but has no type: field — marketplace-only manifest.
|
||||
# Not a package match; keep walking up.
|
||||
fi
|
||||
# .git is a directory in a normal checkout but a file (`gitdir: ...`) in
|
||||
# a git worktree — -e covers both.
|
||||
if [[ -e "$current/.git" ]]; then
|
||||
echo "no-package $current"
|
||||
return 0
|
||||
fi
|
||||
local parent
|
||||
parent="$(dirname "$current")"
|
||||
if [[ "$parent" == "$current" ]]; then
|
||||
echo "no-package $current"
|
||||
return 0
|
||||
fi
|
||||
current="$parent"
|
||||
done
|
||||
}
|
||||
|
||||
# `mapfile`/`readarray` are bash 4.0+ builtins with no fallback on macOS's
|
||||
# stock /bin/bash 3.2 — read the single space-separated output line with a
|
||||
# plain `read` instead (bash 3.2-safe). `read` consumes only one line, so
|
||||
# mode and path must be on the same line: MODE first (never contains
|
||||
# whitespace), PKG_ROOT last (safely absorbs a path containing spaces).
|
||||
WALK_OUTPUT="$(find_package_root "$TARGET_INPUT")"
|
||||
read -r MODE PKG_ROOT <<< "$WALK_OUTPUT"
|
||||
|
||||
if [[ "$MODE" == "package" ]]; then
|
||||
TARGET="$PKG_ROOT/.apm/skills/$SKILL_NAME"
|
||||
else
|
||||
TARGET="$TARGET_INPUT/$SKILL_NAME"
|
||||
fi
|
||||
|
||||
# Destination already exists — treat as a no-op so retries are safe
|
||||
if [[ -d "$TARGET" ]]; then
|
||||
echo "Scaffold already exists at '$TARGET' — nothing to do." >&2
|
||||
exit 0
|
||||
fi
|
||||
|
||||
mkdir -p "$(dirname "$TARGET")"
|
||||
|
||||
# Copy templates to destination
|
||||
cp -r "$TEMPLATES_DIR" "$TARGET"
|
||||
|
||||
# Set skill name in templates
|
||||
sed -i "s/SKILL_NAME/$SKILL_NAME/g" "$TARGET/SKILL.md"
|
||||
sed -i "s/SKILL_NAME/$SKILL_NAME/g" "$TARGET/README.md"
|
||||
sed -i "s/SKILL_NAME/$SKILL_NAME/g" "$TARGET/tests/README.md"
|
||||
|
||||
if [[ "$MODE" == "package" ]]; then
|
||||
echo "Mode: package — type-bearing apm.yml found at '$PKG_ROOT'" >&2
|
||||
echo "Scaffold created: $TARGET" >&2
|
||||
echo "" >&2
|
||||
echo "Note: if '$PKG_ROOT/apm.yml' has an explicit 'includes:' list (not 'auto')," >&2
|
||||
echo " add '.apm/skills/$SKILL_NAME/' to it." >&2
|
||||
else
|
||||
echo "Mode: standalone — no type-bearing apm.yml found above '$TARGET_INPUT'" >&2
|
||||
echo "Scaffold created: $TARGET" >&2
|
||||
fi
|
||||
echo "" >&2
|
||||
echo "Next steps:" >&2
|
||||
echo " 1. Fill in $TARGET/SKILL.md — replace all FILL IN: placeholders" >&2
|
||||
echo " 2. Add scripts to scripts/ if needed (or delete the directory)" >&2
|
||||
echo " 3. Add docs to references/ if needed (or delete the directory)" >&2
|
||||
echo " 4. Add resources to assets/ if needed (or delete the directory)" >&2
|
||||
echo " 5. Add tests to tests/ if the skill has scripts (or delete the directory)" >&2
|
||||
echo " 6. Populate references/sources.md with research sources, or delete it" >&2
|
||||
echo " 7. Validate: run /skill-audit on $TARGET" >&2
|
||||
Reference in New Issue
Block a user