Best practices and examples

Applies to: StablEdge Desktop 0.4.4 and later

Writing principles

Keep it concise

A Skill shares one context window with the system prompt, the conversation history, and the metadata of other Skills. The Agent is already capable enough by default, so write only what it does not know: your team's conventions, steps that easily go wrong, the details of a particular format. For each piece of content, ask: "Without this, would the Agent get it wrong?"

Use short examples rather than long explanations. Write the body in the imperative, stating directly what to do.

Match the detail to how fragile the task is

Task characteristicsHow to write it
Several approaches work, depending on contextProse guidance, giving principles and criteria for judgment
There is a recommended approach, with some variation allowedPseudocode, or a script with parameters
The operations are fragile and order matters strictlyWrite a script and put it in scripts/, with as few parameters as possible

Split content

  • Keep SKILL.md to the core process and the selection guidance, ideally within 500 lines;
  • Put details and variants (different platforms, different frameworks) into separate reference documents, and state clearly in the body which file to read in which case;
  • Reference documents are referenced from SKILL.md one level deep only; do not let reference documents reference one another in chains;
  • For a reference document longer than 100 lines, put a table of contents at the top;
  • Keep each piece of information in one place only, either in SKILL.md or in a reference document;
  • When the body has many topics and each task uses only part of it, switch to the Progressive structure.

Writing process

  1. Collect a few real usage scenarios: what users will say, and what they expect to get;
  2. For each scenario, find the reusable parts: code you write again and again goes into scripts/, material you look up again and again goes into reference documents, templates you use again and again go into assets/;
  3. Write SKILL.md: write name and description first, then the body;
  4. Run the scripts for real and confirm there are no errors;
  5. Install it once with the installer and confirm it passes preview;
  6. Use it in real tasks, and iterate on the places where it gets stuck or goes the wrong way.

You can also simply ask StablEdge for help: the built-in skill-creator Skill provides guidance for creating a Skill.

Example 1: a minimal Skill

Only a SKILL.md, suited to one short fixed process.

release-notes/
└── SKILL.md

release-notes/SKILL.md:

---
name: release-notes
description: "Use when organizing release notes: group commits into the three sections New, Improved, and Fixed, and write user-facing notes. Trigger phrases: release notes, version notes, changelog. Not for marketing copy."
version: "1.0"
metadata:
  category: "Writing"
  tags: "release,docs"
---

# Release notes

1. Read the commit list or change description the user provides; if none is provided, ask for the version and scope first.
2. Drop purely internal changes (refactoring, tests, build scripts) unless they affect users.
3. Output in three sections, ordering each one by impact from high to low:
   - **New**: capabilities users can start using;
   - **Improved**: existing features that became faster, more stable, or easier to use;
   - **Fixed**: problems users noticed that are now fixed.
4. One sentence per item, describing the outcome from the user's point of view, without internal module names.
5. Omit a section when it has no content.

Example 2: a Progressive Skill

A Progressive Skill with reference documents, templates, and scripts, used to generate weekly reports by team conventions.

weekly-report/
├── SKILL.md
├── references/
│   └── style-guide.md
├── assets/
│   └── report-template.md
└── scripts/
    └── collect_stats.py

weekly-report/SKILL.md:

---
name: weekly-report
description: "Use when writing a weekly report by team conventions: summarize what was completed this week and the numbers, plus the plan for next week, and output a Markdown report in a consistent format. Trigger phrases: weekly report, work weekly report, this week's summary, weekly report. Not for monthly reports or quarterly summaries."
version: "1.0"
progressive:
  always:
    - rules
resources:
  - path: references/style-guide.md
    role: reference
  - path: assets/report-template.md
    role: template
  - path: scripts/collect_stats.py
    role: executable
---

# Weekly report

## Rules to follow {#rules}

- A weekly report states facts and numbers only, without summaries padded with adjectives.
- Every item needs an owner and a status (done / in progress / blocked).
- Before output, check against the template whether all sections are present.

## Generation process {#workflow}

1. Copy the template into the Workspace with `skill(action='copy_file', skill_name='weekly-report', path='assets/report-template.md', dest='weekly-report.md')`.
2. When you need statistics, read the `scripts-usage` section and run the statistics script.
3. Fill in the template section by section; see the `style` section for wording requirements.

### Statistics script {#scripts-usage}

Run it with `skill(action='run_script', skill_name='weekly-report', path='scripts/collect_stats.py', argv=['tasks.csv'])`;
the argument is the task export file inside the Workspace. The script writes the statistics as JSON to standard output.

## Wording rules {#style}

The full rules are in `references/style-guide.md`; read them with `skill(action='read_file', skill_name='weekly-report', path='references/style-guide.md')`.
Key points:

- Use the active voice;
- Round numbers to whole numbers, and keep percentages to one decimal place.

weekly-report/scripts/collect_stats.py:

import csv
import json
import sys


def main() -> int:
    if len(sys.argv) != 2:
        print("Usage: collect_stats.py <tasks.csv>", file=sys.stderr)
        return 2
    counts: dict[str, int] = {}
    with open(sys.argv[1], encoding="utf-8", newline="") as handle:
        for row in csv.DictReader(handle):
            status = (row.get("status") or "unknown").strip()
            counts[status] = counts.get(status, 0) + 1
    print(json.dumps({"total": sum(counts.values()), "by_status": counts}, ensure_ascii=False))
    return 0


if __name__ == "__main__":
    sys.exit(main())

Write references/style-guide.md and assets/report-template.md to match your team's actual conventions. When this Skill is loaded, the cover the Agent sees first is: the hint on reading sections, the bundled file list (with roles), the full text of the rules section, and the automatically generated section index below:

## Sections you can read on demand
- `rules` — Rules to follow
- `workflow` — Generation process
  - `scripts-usage` — Statistics script
- `style` — Wording rules

The script reads tasks.csv by a path relative to the Workspace, because the host runs scripts with the current Workspace as the working directory.

Common mistakes

SymptomCauseFix
The Skill does not appear in the list, and the diagnostic says frontmatter is missingThe file has a BOM, or the first line is not ---Save it as UTF-8 without a BOM; the first character must be ---
The diagnostic says the frontmatter is not valid YAMLdescription has no quotes and contains special charactersAdd double quotes around description
The diagnostic says a field is invalidname contains characters that are not allowed; or a metadata value is not a string (for example, tags written as a list)Change it by the Naming rules; write tags as a comma-separated string
Your own Skill is ignoredIt has the same name as a built-in Skill or another installed SkillPick a different name
The Skill is never pickeddescription says only what it does, without trigger phrasesAdd the trigger phrases users really say; see Writing a description
A Progressive Skill returns the whole body after loadingA heading lacks {#id}, IDs repeat, or always / resources reference something that does not existFix each item by the validation rules
resources is written but has no effectThe frontmatter has no progressiveAdd progressive: {}, or switch to the Progressive structure
The Agent cannot find a file mentioned in the bodyThe body tells the Agent to read it with the general file tools, or gives an absolute pathWrite a path relative to the Skill directory, and tell the Agent to read it with the skill tool
run_script reports a path errorThe script is not in the scripts/ directoryMove the script into scripts/
run_script reports that arguments or the timeout exceed the limitsMore than 64 arguments, a single argument over 8 KB, or a timeout over 300 secondsHave the script read an input file from the Workspace instead
The install preview reports that the Skill is ambiguousOne Skill directory nests another SKILL.mdGive each Skill its own directory, with no nesting
On this page