# CONVENTIONS — the rules for writing our own skills

> Read this file before writing any new skill. Every skill in this folder must pass rules 1-8.

---

## 1. File format (required)

One skill = one folder, always containing a `SKILL.md` file.

```
dev-skills/{phase}/{skill-name}/
├── SKILL.md            <- required: frontmatter + instructions
├── references/         <- optional: sub-files the skill tells the AI to read when needed
└── assets/             <- optional: templates, sample files, checklists
```

`SKILL.md` frontmatter — two keys are always required:

```markdown
---
name: skill-name                    # required, must match the folder name, kebab-case
description: what it does + when to use it   # required — this is what decides whether the AI picks this skill
---
```

Beyond those two required keys, there's a further set of real, standard optional keys — some only work inside
Claude Code, some work everywhere (claude.ai, Claude Desktop, Skills API). Check this table every time before adding one:

| Key | What it does | Works outside Claude Code? |
|---|---|---|
| `license` | The skill's license | Yes |
| `compatibility` | Declares which platforms/versions it supports | Yes |
| `metadata` | Free-form extra key-value data | Yes |
| `allowed-tools` | Restricts which tools this skill can call | Yes |
| `model` | Forces a model (`opus`/`sonnet`/`haiku`/`fable`/full-id/`inherit`) | **No** — Claude Code only |
| `effort` | Forces an effort level (`low`/`medium`/`high`/`xhigh`/`max`) | **No** — Claude Code only |
| `context` | `fork` = run in a separate sub-agent context | **No** — Claude Code only |
| `agent` | Specifies a subagent type (used with `context: fork`) | **No** — Claude Code only |
| `background` | Run as a background task | **No** — Claude Code only |
| `disable-model-invocation` | Blocks the AI from calling this skill on its own (still callable via a direct command) | **No** — Claude Code only |
| `argument-hint` | Hints the argument shape when typing the command | **No** — Claude Code only |
| `paths` | Restricts which paths this skill may operate on | **No** — Claude Code only |
| `shell` | Which shell runs commands inside this skill | **No** — Claude Code only |
| `hooks` | Attaches a hook to the skill | **No** — Claude Code only |

**Portability rule:** the routing-related keys (`model`, `effort`, `context`, `agent`, `background`, etc.) are
**performance boosters, never correctness requirements** — a skill must still work "correctly" the exact same
way even on a platform that ignores these keys entirely (as genuinely happens on the claude.ai web app). If
stripping these keys out breaks the skill or changes its behavior, it was written wrong from the start — correct
logic always belongs in the body of `SKILL.md`, never in the frontmatter.

> Any key not in the table above (e.g. `triggers:`, `permissions:`) **doesn't exist in this standard** — don't add it.

### How to choose a model

- **opus** = work where misjudging people or making a mistake causes real damage (talking with the owner, security, bug hunting, database design, data migration).
- **sonnet** = the default — work with a clear spec already in hand.
- **haiku** = pure checklist-comparison work, no judgment calls required.

> Note: **`fable` is never the default** — it burns roughly twice the quota of `opus`.

---

## 2. `description` is the whole ballgame — write it so the AI can decide

The AI sees only `name` + `description` when picking a skill — it hasn't read the body yet.
So the description must state **what it does + when to use it + the words a user is likely to say**.

Bad: `description: helps design UI`
Good: `description: turns requirements into a screen spec a dev can build from directly. Use when the user mentions wanting a certain look, building a screen, designing a form, laying out a page — even if not stated directly, if the context is "I have a picture in my head but can't describe it," use this skill.`

---

## 3. Portable first — never lock in to one specific tool

Our skills must work on claude.ai, ChatGPT, Gemini, Claude Desktop, Codex, Zcode, and the terminal.
So the body of `SKILL.md` splits into 2 parts:

| Part | Contents | Works where |
|------|---------|--------------|
| **Core** (most of it) | Reasoning steps, questions to ask, output format, checklists | Everywhere, including web chat |
| **Tooling** (at the end, under `## Tooling (if tools are available)`) | Bash commands, real paths, file read/write | CLI/Desktop only |

Rule: **the skill must still work correctly if the Tooling section is stripped out entirely.** If it can't, it was written wrong.

Not allowed in Core:
- Machine-specific paths (`/Users/nitigon/...`) -> ask the user instead
- Tool-specific names (`Grep`, `Playwright`) -> write "search the code" / "open the screen" instead
- MCP servers / hooks that other people won't have

---

## 4. Language

Skill bodies, `references/` content, and the three runtime standards (`DESIGN-SYSTEM.md`, `PROJECT-STRUCTURE.md`, `HANDOFF-PROTOCOL.md`) are all English — the AI reads these on every invocation, follows English more precisely, and it costs roughly half the tokens Thai does.

Only three things stay Thai:

| What | Language | Why |
|---|---|---|
| **Everything the end user sees** (questions, reports, on-screen text, delivered documents) | **Thai — simple, short** | The person commissioning the work is a business owner, not a developer |
| **Thai trigger phrases inside frontmatter `description`** | **English description + the Thai phrases a user would actually type** | Without the Thai phrases, the AI won't match when a user types in Thai |
| **The handoff contract file names** (e.g. `README-สำหรับนักพัฒนา.md`, `เปิดดู.command`) | **Thai, exact, never renamed** | These names are a fixed contract between the owner side and the dev side — renaming any of them breaks the receiving skill |

Skill names, file names, field names, and code stay English, as the universal standard.

So every skill must include this line in its body, to force the AI to answer in Thai:

```markdown
**Output language:** always reply to the user in simple, short Thai. Never reply in English.
No jargon unless you explain it in one clause. Short sentences. Never refer to yourself with
a pronoun ("หนู", "ผม", "ฉัน", "เรา") — write sentences that don't need a self-reference.
No emoji anywhere, including chat replies. Multiple-choice options are NUMBERED 1. 2. 3. 4.,
each on its OWN LINE, never run together in one paragraph, no skipped number, at most 4 options. This applies to every question you ask, every
report you write, and every document you produce.
```

Principle for writing the Thai the user sees: **short, direct, not overly formal** — one idea per sentence.
Technical terms with no good Thai equivalent may be used as-is (API, deploy, database), but briefly explained the first time they appear.

### Tone and pronouns

- **Never use a self-referring pronoun** ("หนู", "ผม", "ฉัน", "เรา" when the AI refers to itself) — write sentences that avoid the need entirely.
  E.g. instead of "หนูเสนอไว้แบบนี้" (I'm proposing this), write "ข้อนี้เป็นข้อเสนอ ยังไม่ได้ยืนยัน" (this is a proposal, not yet confirmed).
- Address the user as **"คุณ"** only when necessary — not in every single sentence.
- **No emoji** in any reply to the user (same rule as `DESIGN-SYSTEM.md` section 1b).
- **Delivered documents must be more neutral in tone than a live chat reply** — documents get passed on to other people (devs, teams, the company),
  so no trace of conversational tone or AI self-reference may leak into a delivered document, ever.
- **Multiple-choice options are numbered, and each sits on its own line.** Use `1.` `2.` `3.` `4.` — not Thai letters, which force the user to switch keyboard layouts to answer. Numbers are also easier to say out loud and to quote back.
- **Never run the options together in a single paragraph.** Each option gets its own line. Options crammed into one line are unreadable and the user cannot tell where one ends and the next begins. Write it like this:

```
ตอนนี้ที่เจ็บที่สุดตอนคัดคน คืออะไรคะ

1. ข้อมูลผู้สมัครกระจัดกระจาย หาเมลหรือเรซูเม่ไม่เจอ
2. ไม่รู้ว่าแต่ละคนค้างอยู่รอบไหน ต้องไล่ถามทีละคน
3. ลืมว่าใครผ่านหรือตกที่รอบไหน เพราะคุยกันหลายคน
4. อย่างอื่น — เล่ามาได้เลย
```

- Numbers run consecutively with no gaps, and there are never more than 4 options.

---

## 5. Always know who's using it — label it at the very top of the body

Every skill's body opens with this exact line:

```markdown
**สำหรับ:** เจ้าของงาน | นักพัฒนา | ทั้งคู่   ·   **ส่งต่อไปยัง:** {next skill}
```

This lets the user immediately know where they are in the pipeline and what the next step is.

---

## 6. Every skill must end with a "tangible result"

Never end with "and then keep going" — always state exactly what came out of it.
E.g. a `SPEC.md` file, an openable HTML file, a zip folder, a markdown report.

### Always offer the next step — never dead-end

A skill that finishes by saying "done" leaves the user holding a file and wondering what now. **The last line of
every skill must offer to continue**, so the work feels like one flow rather than a series of separate errands.

Close with the confirmation and the next step together, as a numbered choice (per section 7's option rules):

```
ตรงไหมคะ มีอะไรจะเพิ่มไหม

1. ตรงแล้ว ไปต่อเลย — {ขั้นถัดไปได้อะไร}
2. ขอแก้ตรงนี้ก่อน
```

- Name what the next step produces, not just its command — "ไปต่อเลย จะได้เห็นหน้าจอจริง" beats "รัน /app-show".
- If the next step is optional or there is a real choice of paths, present the paths — do not pick for them.
- If this genuinely is the end of the line, say so plainly rather than inventing a next step.
- Never end on a bare statement of completion with nothing to do next.

---

## 7. Ask before guessing — but ask sparingly

- **Ask one topic at a time.** Never dump several unrelated questions at once — a non-technical person reading five questions in a row answers none of them well. Two or three tightly-related sub-questions can share a turn.
- **Budget: about 5-8 questions per skill.** A confirmation prompt does not count against this: asking "does this look right" after showing something, or "is this default acceptable" after the user said they don't know, is part of the answer, not a new question.
- **A budget is a ceiling, never a quota.** "At most N questions" does not mean N questions get asked — a skill that can finish without asking anything must finish without asking anything. Write question limits as ceilings and state the default is zero, or the number gets read as a target to fill.
- **Never ask what the files already answer.** Before asking anything, look for the answer in what earlier steps produced (`BRIEF.md`, `HISTORY.md`, `LEVEL.md`, folder names, existing documents). Derive it, state the derived value in one line so it can be corrected, and keep going. Asking the user to confirm something already written down is how a finished job turns into another round trip.
- **Never ask a filler question.** "Anything else to add?", "anything to tell the developer?", "is there anything I missed?" — a question with no wrong answer collects nothing and costs the user a turn. If the work can be redone cheaply afterwards, do the work and let them react to it instead.
- If the user can't answer, **propose a sensible default** and keep moving — never get stuck.
- Never fill in information the user didn't provide into a handoff document without flagging it as "unconfirmed."

---

## 8. Checklist before calling it done

Every skill must end with a closing checklist section, required before announcing completion.
UI work must be visually verified before done - code work must run successfully before done - doc work must be read back before done.

---

## 9. Size

- `SKILL.md` stays under ~200 lines, readable in one pass.
- Anything deeper belongs in `references/xxx.md`, with `SKILL.md` instructing "if you hit case X, read `references/x.md`."

---

## 10. Naming

- kebab-case, a clear verb or outcome: `app-send`, `security-review`, `app-show`.
- No name so generic it collides with something else: `helper`, `utils`, `main`.
- The folder name always equals the `name:` value in frontmatter.
