Skip to content
Back to skills

Tutorials

ASecurity

**What you'll build:** A standard-compliant skill with valid frontmatter, shaped body, activation evals, output-quality evals, and all four lint gates passing — ready for PR review. **Prerequisites:** `agentbundle`, `core`, `governance-extras`, and `catalogue-curation` packs installed; a clear idea of what the skill does and one situation where using it would be wrong. **Time:** 60–90 minutes. **Goal:** write one standard-compliant skill from scratch and land it in the catalogue. By the end y...

  • 24 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 3, 2026
ai-agentspythongoshellbashapidocumentation

Works with

  • api

Security analysis

A100/100

Pro scans all 4 files and shows the line behind each finding

Scanned September 3, 2026

npx -y skills add eugenelim/agent-ready-repo --skill tutorials --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Tutorials?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Tutorials
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/eugenelim-tutorials/badge)](https://www.skillsdirectory.com/skills/eugenelim-tutorials)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
title: Your first skill
summary: Build and verify a standard-compliant catalogue skill from scratch.
pack: catalogue-curation
kind: tutorial
---

# Your first skill

**What you'll build:** A standard-compliant skill with valid frontmatter, shaped body, activation evals, output-quality evals, and all four lint gates passing — ready for PR review.
**Prerequisites:** `agentbundle`, `core`, `governance-extras`, and `catalogue-curation` packs installed; a clear idea of what the skill does and one situation where using it would be wrong.
**Time:** 60–90 minutes.

**Goal:** write one standard-compliant skill from scratch and land it in the catalogue.
By the end you'll have a skill with valid frontmatter, a shaped body, activation evals, and a definition of done you can verify.

This is the main journey. The side journey — bringing in skills and repos from outside — starts at [Your first assimilation](./first-assimilation.md) after you've completed this one.

**Before you start.** Read [Skill standards](../explanation/skill-standards.md) — one page that names the three standards and tells you what each is checking.
This tutorial introduces each standard at the point where it applies; the standards file is where you verify the full picture before opening your PR.

**Prerequisites:**
- `agentbundle`, `core`, `governance-extras`, and `catalogue-curation` packs installed
- A clear pair in hand: what this skill does, and one situation where using it would be the wrong choice

---

## 1. Understand the workspace your skill lives in

Before writing a line, know where your skill sits in the workspace design.

The workspace has two rooms:

```
Shaping room → [shaping_queue]              Build room → [work].queue
───────────────────────────────             ─────────────────────────
Decide what the skill does.                 Write it. That's this tutorial.
Shape it as a brief with rationale.
```

If you've come from the shaping room with a spec, your `workspace.toml` already has your work item:

```toml
[[work.queue]]
id = "skill-<your-skill-name>"
spec = "docs/specs/<pack>/<your-skill-name>.md"
status = "In Progress"
```

If you're starting ad-hoc — no workspace set up yet — that's fine.
Skills must handle both: a skill that only works when the full arc has already run is fragile.
You'll handle this in Step 3.

Run `workspace-status` at any point to see what the queue currently looks like.

**Where the skill lives on disk:**

```
packs/<pack>/
└── .apm/
    └── skills/
        └── <your-skill-name>/
            ├── SKILL.md                ← write this first
            ├── scripts/                ← cross-platform scripts (add if needed)
            ├── references/             ← context loaded on demand (add if needed)
            └── evals/
                ├── eval_queries.json   ← activation evals (Step 5)
                └── evals.json          ← output-quality evals (Step 6)
```

**Workspace vocabulary** — the verbs you'll see in other skills and in the workspace design:

| Verb | What it does |
|---|---|
| `work-intake` | Materializes a canonical work artifact, then registers lifecycle state |
| `workspace-status` | Surfaces the current queue state without modifying it |
| `author-delivery-brief continue` | Pulls confirmed slices from `[brief_queue]` into `[work].queue` |

Name your skill for what it does, not for internal mechanism.
If a skill in the codebase already uses a similar verb, align with it.

---

## 2. Write the frontmatter

Create `packs/<pack>/.apm/skills/<your-skill-name>/SKILL.md`.

```yaml
---
name: <your-skill-name>
description: >
  Use when <specific trigger situation>.
  Do NOT use when <the near-miss situation that shares keywords but belongs in a different skill>.
license: Apache-2.0
compatibility:
  claude_code: ">=0.2.0"
  kiro: ">=0.10.0"
metadata:
  boundary: filesystem_read
  scope: repo
allowed-tools:
  - Read
  - Bash
---
```

**[Standard 1 — agentskills.io structural]**
Six keys, no others: `name`, `description`, `license`, `compatibility`, `metadata`, `allowed-tools`.
`description:` is a single-line scalar (or a `>` block scalar that collapses to one line), under 1024 characters.
`lint-skill-spec.py` enforces this — it's the authority, not this page.

**[Standard 2 — Catalogue craft] `description:` is the activation signal.**
This is the most important sentence you will write.
The agent reads it to decide whether your skill applies to the user's prompt.
Write it as two sentences: "Use when [specific situation]." and "Do NOT use when [near-miss]."
The second sentence separates your skill from the two or three others that sound similar at first glance.

**[Standard 3 — OWASP AST03] `allowed-tools:` must be minimal.**
List only the tools your skill body actually instructs the agent to invoke.
Start with the smallest plausible set and add only when a step in the body genuinely requires it.
Every tool listed must be justified by the skill's stated purpose.
Over-declaring expands the blast radius of any prompt injection that reaches this skill.

**[Standard 3 — OWASP AST06] `metadata.boundary:`**
If your skill instructs code execution or file writes, declare the containment boundary here.
Accepted values: `filesystem_read`, `filesystem_write`, `network_fetch`, `shell_exec`.
"The agent will have access" without naming the scope is a finding.

---

## 3. Write the body

The body is the procedure the agent follows. Four named sections.

### Opening clause

One to three sentences. What this skill does — and one clear "not": the situation where using it would be the wrong choice.

```markdown
Summarises a thread of agent messages into a human-readable session report.
Does NOT generate new analysis or suggest next actions — use `synthesise-findings` for that.
```

The "not" sentence primes the agent to route correctly when a near-miss prompt arrives.

### Prerequisites

List what must exist before the skill can proceed. Use the three-tier policy:

- **T1 — Declare and detect.** Check for the dependency; if absent, stop cleanly.
- **T2 — Optional, gated, idempotent.** Install only if the user opts in.
- **T3 — Banned.** Never install this from a skill.

**[Craft: graceful ad-hoc handling]**

A skill that silently breaks when an earlier arc step hasn't run is fragile.
Write T1 prerequisites to handle direct invocation gracefully:
detect what's missing, name it explicitly, and stop with a clear message.

```markdown
**Prerequisites**

- Python 3.11+ on PATH.
- `jq` on PATH — detected via `shutil.which("jq")`.
  If absent: stop and tell the user. Do not attempt to install it.
- If a `workspace.toml` exists in the working directory, read the current queue item.
  If no `workspace.toml` is found: note that workspace tracking is inactive and continue
  without updating the queue. Tell the user they can run `work-intake` to create
  the canonical artifact and register lifecycle state.
```

The workspace-absent case shows the pattern: detect, name, proceed-with-note or stop — never silently ignore.

### Instructions

Numbered steps. Each step is one concrete action the agent takes.

**[Craft: progressive disclosure]**
Detail that only matters in one branch of the workflow goes in a `references/` file.
Load it at the point the workflow reaches that branch — not pre-loaded for every invocation.

```markdown
3. Determine the thread format. Load `references/thread-format.md` now.
4. Parse the messages using the shape described in the reference.
5. ...
```

The `references/` file is not in context until Step 3 loads it.
Every invocation that doesn't reach Step 3 never pays for that context.

**[Craft: path discipline]**
Discover context from the workspace's own structure at runtime.
Do not hardcode paths that are only valid in your environment.

Wrong:
```markdown
3. Read from `/Users/yourname/projects/myproject/.agentbundle/state/`.
```

Right:
```markdown
3. Find `.agentbundle/` by walking up from the current working directory.
   If not found, stop: the skill requires an installed pack.
```

This is what makes the skill portable — any workspace with the pack installed gets consistent behavior.

### Arc handoff

When the skill's main work is done, suggest the next step in the arc.
Do not invoke the next skill automatically — name it and let the user choose.

```markdown
## Next steps

The summary has been saved to `<output-file>`.

When you're ready:
- Review the summary, then update the pack's profile or run `agentbundle catalogue package` to produce a release archive.
- Or run `workspace-status` to see the full queue before deciding what's next.
```

The arc handoff pattern is what makes a series of skills feel like a coherent journey
rather than a collection of unrelated commands.
Each skill knows about the next step in its arc and surfaces it — but leaves the choice to the user.

### Status pairing

If your skill modifies shared state — writes to a ledger, updates a queue, creates a record —
pair it with a `<subsystem>-status` skill.

The status skill reads the current state and reports it.
It does not modify state.
It lets the user check where things stand without triggering a side-effect.

Example: `assimilate-primitive` writes to the assimilation ledger.
`catalogue-curation-status` reads that ledger and reports what's been assimilated, what's pending, what failed.

If your skill creates or mutates shared state, check whether a status skill for the subsystem already exists.
If it does, update it to include the new state.
If it doesn't, create one named `<subsystem>-status`.

---

## 4. Write cross-platform scripts (if needed)

Scripts go in `scripts/`. Always Python — not shell scripts.

```python
#!/usr/bin/env python3
"""Format a message thread into a session report."""
from __future__ import annotations
import shutil
import subprocess
import sys
from pathlib import Path


def main() -> None:
    tool = shutil.which("jq")
    if not tool:
        print("jq not found on PATH. Install it and retry.", file=sys.stderr)
        sys.exit(1)

    thread = Path("thread.json")
    if not thread.exists():
        print(f"Expected thread file not found: {thread}", file=sys.stderr)
        sys.exit(1)

    result = subprocess.run(
        [tool, ".messages[]", str(thread)],
        capture_output=True,
        text=True,
        encoding="utf-8",
    )
    if result.returncode != 0:
        print(result.stderr, file=sys.stderr)
        sys.exit(result.returncode)

    print(result.stdout)


if __name__ == "__main__":
    main()
```

Rules: `pathlib` for all paths; `encoding="utf-8"` on every file and subprocess; `subprocess` as a list, never `shell=True`; `shutil.which()` for tool detection, not `command -v`.

---

## 5. Author activation evals

This step verifies your `description:` field actually works as an activation trigger.
Run it before you think you're done — description problems caught here cost far less than ones caught in production.

Create `evals/eval_queries.json`:

```json
[
  {
    "query": "summarise the messages from last session into a report",
    "should_trigger": true
  },
  {
    "query": "what patterns appear across these agent runs",
    "should_trigger": false,
    "note": "cross-run analysis — use synthesise-findings"
  },
  {
    "query": "format the conversation thread for the team to review",
    "should_trigger": true
  },
  {
    "query": "generate action items from the session",
    "should_trigger": false,
    "note": "action generation, not summarisation"
  }
]
```

Write 8–10 `should_trigger: true` cases (the prompts that should activate this skill) and
8–10 `should_trigger: false` near-misses (prompts that share keywords but should route to a different skill).

Register the skill in `pack.toml`:
```toml
[pack.evals]
skills = ["<your-skill-name>"]
```

Run:
```bash
python3 tools/run-pack-evals.py --pack <pack>
```

**Reading the results:**
- `should_trigger: true` query scoring < 0.5: the description is too narrow or too specific — broaden the "Use when" clause.
- `should_trigger: false` query scoring > 0.5: the description bleeds into another skill's territory — strengthen or add the "Do NOT use when" clause.

Both kinds of failures tell you the same thing: the description and the test cases are your primary documentation of what this skill is for. They have to agree.

---

## 6. Author output-quality evals

Create `evals/evals.json` with at least one eval per major workflow branch:

```json
[
  {
    "name": "produces formatted session report",
    "input": "summarise the last session thread",
    "expected_output": "A markdown report with a header, a summary paragraph, and bulleted key points. No action list, no recommendations.",
    "assertions": [
      "Output contains a markdown H1 or H2 header",
      "Output contains a bullet list",
      "Output does not contain a section headed 'Next steps' or 'Actions'"
    ]
  }
]
```

Assertions must be falsifiable behavior-level statements.
"Agent does the right thing" is not an assertion — name what the output contains or does not contain.

---

## 7. Run the gates

All four must pass before the PR.

```bash
python3 tools/lint-skill-spec.py              # Standard 1: agentskills.io structural
make build-self                                # project source → adapters
python3 tools/lint-agent-artifacts.py         # verify projection is clean
python3 tools/run-pack-evals.py --pack <pack> # Standard 2: activation evals
```

After `make build-self`, confirm the skill appears:
```bash
agentbundle show <pack>
```

It should list your new skill by name.
If it doesn't appear, the pack registration is missing — check `pack.toml`.

---

## 8. Open the PR via work-loop

The adversarial review is the last gate and the one that catches what linters cannot:
scope creep, description drift against the spec, missing edge cases, and Standard 3 (OWASP AST) findings.

Load the `work-loop` skill and run the PR flow.
The adversarial review must return `Clean — ready to commit.` before merge.

---

## Definition of done

Check every item before asking for review.
The [full table](../explanation/skill-standards.md#the-definition-of-done--both-paths) is in the standards file;
this is the writing-path subset:

- [ ] `lint-skill-spec.py` passes — no errors; warnings reviewed
- [ ] `make build-self` clean; `lint-agent-artifacts.py` passes
- [ ] Activation evals: all `should_trigger: true` queries > 0.5; all `should_trigger: false` < 0.5
- [ ] `evals/evals.json` exists with at least one output-quality eval
- [ ] `agentbundle show <pack>` lists the skill by name
- [ ] `workspace-status` shows the work item as `Done` (if workspace tracking is active)
- [ ] PR open; adversarial review returned `Clean — ready to commit.`

---

Your skill is live in the catalogue.

The side journey — bringing existing skills and repos from outside into the catalogue — starts at
[Your first assimilation](./first-assimilation.md).
For the full pack arc from survey to publish, see [Catalogue operator journey](../explanation/catalogue-operator-journey.md).

Files in this skill

  • first-assimilation.md4.5 KB
  • your-first-skill.md15 KB
  • your-first-subagent.md7.1 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…