Crystallize a session into a skill
Use this whenever the user asks to capture work as a reusable skill —
"crystallize this", "create a skill", "save this as a skill", "make this
reusable", or "turn this into a skill". This is the on-demand counterpart to
the automatic post-session skill generation: the user is telling you now that
the work is worth keeping.
Two modes, chosen from the user's wording:
- Candidate (default). Stage the skill in the pending queue for human
approval. Every phrasing above means this unless the user says otherwise.
- Live (explicit only). Write the skill straight to a live,
immediately-loadable location, bypassing approval. Take this path ONLY
when the user explicitly says "create a live skill" or "create an active
skill" (or confirms it when asked). Never infer it from a plain "create a
skill" — that stays a candidate.
When to use
- The user says any trigger phrase above (candidate mode), or explicitly asks
for a "live" / "active" skill (live mode).
- The session demonstrated a procedure that will recur — one a future
session, working on a DIFFERENT target, would run again substantially
unchanged: a repeatable debugging method for a class of error, a fixed
command/API sequence, a verification technique, a research-synthesis flow.
Apply the same recurrence test the automatic pass uses: name the future session
that would load this skill and the different target it would run against. If the
only honest answer reuses this session's own artifact — this bug, this file,
this component, this one question — the procedure does not recur. Effort is not evidence of recurrence: a long, many-step, genuinely difficult session is still one-off if its steps were chosen for one target.
Do not crystallize a task done once and now finished (a specific bug's fix,
a one-time audit or trace of one component, a migration, a probe run to answer a
question that is now answered), a design or planning discussion, a narrative of
what happened in this session, a trivial one-shot answer, a one-off failure, or
a session that touched credentials / sensitive paths. Being asked does not make a one-off reusable — but the call is the user's, not yours. When the session carries no recurring procedure, say so and name what makes it one-off, then let them decide; if they still want it captured, crystallize it. Never silently decline a direct request.
Procedure
Reconstruct the procedure from the whole session — including sub-agents.
Read back over the conversation and, critically, parse any
[Subagent completion event] messages: each carries what a sub-agent was
tasked with and the working path it found. Fold those into the procedure so
the skill captures the successful route, not the dead ends.
Check for an existing skill first (cross-source dedup). Look at the
current auto-generated skills (Skills tab → the auto/ group, or ask). If
this procedure essentially duplicates one that already exists, freshen
that existing skill instead of creating a near-duplicate — and if a
consolidation pass would also capture this same session, don't stage a
second copy.
Write prose by default; add a script only when determinism earns it.
Most skills are judgment or workflow guidance and should be plain prose
steps — that is the expected shape. Reach for a helper script only when
part of the procedure is genuinely deterministic and error-prone to
re-improvise: a fixed multi-command chain, a set API sequence, or a fiddly
file transform. If prose captures it clearly, do not write a script. When a
script truly is warranted, it must be Python (so it runs on
macOS/Linux/Windows), must not access credentials, wipe files, or call
unknown network hosts, and must stay under 4 KB. A staged candidate's script
is statically validated and requires human approval before it can run; a
live-mode script (step 4b) gets no such check, so you must hold it to these
same limits yourself.
Choose the destination — candidate by default, live only on an explicit
request. First resolve your KiroCrew skills directory — the SAME directory
that holds the auto/ group you inspected in step 2 (honor $KIROCREW_HOME
if set; do not assume a literal ~/.kirocrew, since migrated installs
live elsewhere).
(a) Candidate — the default. For "crystallize", "create a skill",
"save this as a skill", "make this reusable" and every other phrasing, stage
to the pending queue so a human approves before anything loads. Create
<skills-dir>/auto/.pending/<slug>/ (<slug> kebab-case, 3–64 chars,
starting and ending with a letter or digit — a name outside that shape is
silently skipped by the pending list and cannot be approved) with
SKILL.md:
---
name: auto/<slug>
description: <=150 chars, starts with a verb
triggers: <3-8 comma-separated keywords/phrases>
source: auto
session_key: <this session>
created_at: <ISO-8601 UTC>
---
# <slug> (auto-generated)
## When to use
...
## Steps
...
## Gotchas
...
Always add a .meta.json next to SKILL.md — the pending list/detail API
reads the candidate's description, triggers, name, and source from it
(there is no SKILL.md-frontmatter fallback), so without it the candidate
shows blank in Skills → Pending review and dedup loses its match data:
{"slug": "<slug>", "name": "auto/<slug>", "source": "crystallize", "created_at": "<ISO>", "description": "...", "triggers": "...", "has_scripts": <bool>, "scripts": [...], "kind": "new"}.
Only scripts/ is conditional: if you generated a script, put it under
scripts/<name>.py in that folder, set "has_scripts": true, and list it in
scripts; for a prose-only candidate use "has_scripts": false, "scripts": [].
Freshening an existing live auto-skill is an UPDATE candidate, not a new
one. Same pending folder, but set "kind": "update", "target": "<the live slug>" and "base_version": "<the version you merged from>".
Approving an update snapshots the live file to
auto/<slug>/.versions/v<N>-SKILL.md before overwriting it and keeps the 20
newest snapshots, so the human can roll back.
Staging a candidate whose slug is already PENDING is safe: the loader claims a
distinct slug (<slug>-2, <slug>-3, …) and stages beside the existing
candidate rather than overwriting it. That guard covers the pending path only —
the live path in (b) has none.
(b) Live: ONLY when the user explicitly says "live" / "active" or confirms
it when asked. Write <skills-dir>/<slug>/SKILL.md directly, with no
auto/ prefix, .meta.json, or pending stage.
Reuse (a)'s template with name: <slug>, source: crystallize, and title
# <slug>; omit session_key and created_at. Keep the same description,
triggers, and When to use / Steps / Gotchas sections.
Do not overwrite an existing skill: if <skills-dir>/<slug>/ already
exists (a live or builtin skill), pick a different slug or ask the user —
the live path has no collision guard, so writing blindly clobbers it, and
unlike the pending path nothing claims a distinct slug for you. Put
any script under scripts/<name>.py and, since no approval step runs for
you, mark it executable yourself — on POSIX, chmod +x; skip that on
Windows, where the executable bit is a no-op.
In BOTH cases: do not include absolute paths, credentials, tokens, or
user PII in the body or the script.
Hand off.
- Candidate: tell the user it is staged and they can review it in
Skills → Pending review — approve to make it live (and mark any script
executable), or dismiss it. Nothing loads until they approve.
- Live: tell the user it is active immediately and discoverable by its
triggers (no approval needed), and point them at the file in case they want
to edit or remove it.
Gotchas
- Default to the pending queue. Only write directly to a live location
(
<skills-dir>/<slug>/) when the user explicitly asked for a "live" or
"active" skill — otherwise always stage under auto/.pending/ so a human
reviews it first.
- One skill per distinct procedure — don't bundle unrelated workflows.
- Keep the description trigger-class-focused (it is matched on, and truncated
in the system-prompt skill index).
1---2name: crystallize3description: Capture the current session as a reusable skill — staged as a candidate by default, or live only when the user explicitly asks for a live/active skill.4---56# Crystallize a session into a skill78Use this whenever the user asks to capture work as a reusable skill —9"crystallize this", "create a skill", "save this as a skill", "make this10reusable", or "turn this into a skill". This is the **on-demand** counterpart to11the automatic post-session skill generation: the user is telling you *now* that12the work is worth keeping.1314**Two modes, chosen from the user's wording:**1516- **Candidate (default).** Stage the skill in the pending queue for human17 approval. Every phrasing above means this unless the user says otherwise.18- **Live (explicit only).** Write the skill straight to a live,19 immediately-loadable location, bypassing approval. Take this path **ONLY**20 when the user explicitly says "create a live skill" or "create an active21 skill" (or confirms it when asked). Never infer it from a plain "create a22 skill" — that stays a candidate.2324## When to use2526- The user says any trigger phrase above (candidate mode), or explicitly asks27 for a "live" / "active" skill (live mode).28- The session demonstrated a procedure that will **recur** — one a future29 session, working on a DIFFERENT target, would run again substantially30 unchanged: a repeatable debugging method for a class of error, a fixed31 command/API sequence, a verification technique, a research-synthesis flow.3233Apply the same recurrence test the automatic pass uses: name the future session34that would load this skill and the different target it would run against. If the35only honest answer reuses this session's own artifact — this bug, this file,36this component, this one question — the procedure does not recur. Effort is not evidence of recurrence: a long, many-step, genuinely difficult session is still one-off if its steps were chosen for one target.3738Do **not** crystallize a task done once and now finished (a specific bug's fix,39a one-time audit or trace of one component, a migration, a probe run to answer a40question that is now answered), a design or planning discussion, a narrative of41what happened in this session, a trivial one-shot answer, a one-off failure, or42a session that touched credentials / sensitive paths. Being asked does not make a one-off reusable — but the call is the user's, not yours. When the session carries no recurring procedure, say so and name what makes it one-off, then let them decide; if they still want it captured, crystallize it. Never silently decline a direct request.4344## Procedure45461. **Reconstruct the procedure from the whole session — including sub-agents.**47 Read back over the conversation and, critically, parse any48 `[Subagent completion event]` messages: each carries what a sub-agent was49 tasked with and the working path it found. Fold those into the procedure so50 the skill captures the *successful* route, not the dead ends.51522. **Check for an existing skill first (cross-source dedup).** Look at the53 current auto-generated skills (Skills tab → the `auto/` group, or ask). If54 this procedure essentially duplicates one that already exists, **freshen55 that existing skill** instead of creating a near-duplicate — and if a56 consolidation pass would also capture this same session, don't stage a57 second copy.58593. **Write prose by default; add a script only when determinism earns it.**60 Most skills are judgment or workflow guidance and should be plain **prose61 steps** — that is the expected shape. Reach for a helper script *only* when62 part of the procedure is genuinely deterministic and error-prone to63 re-improvise: a fixed multi-command chain, a set API sequence, or a fiddly64 file transform. If prose captures it clearly, do not write a script. When a65 script truly is warranted, it must be **Python** (so it runs on66 macOS/Linux/Windows), must not access credentials, wipe files, or call67 unknown network hosts, and must stay under 4 KB. A staged candidate's script68 is statically validated and requires human approval before it can run; a69 live-mode script (step 4b) gets no such check, so you must hold it to these70 same limits yourself.71724. **Choose the destination — candidate by default, live only on an explicit73 request.** First resolve your KiroCrew skills directory — the SAME directory74 that holds the `auto/` group you inspected in step 2 (honor `$KIROCREW_HOME`75 if set; do **not** assume a literal `~/.kirocrew`, since migrated installs76 live elsewhere).7778 **(a) Candidate — the default.** For "crystallize", "create a skill",79 "save this as a skill", "make this reusable" and every other phrasing, stage80 to the pending queue so a human approves before anything loads. Create81 `<skills-dir>/auto/.pending/<slug>/` (`<slug>` kebab-case, 3–64 chars,82 starting and ending with a letter or digit — a name outside that shape is83 silently skipped by the pending list and cannot be approved) with84 `SKILL.md`:8586 ```87 ---88 name: auto/<slug>89 description: <=150 chars, starts with a verb90 triggers: <3-8 comma-separated keywords/phrases>91 source: auto92 session_key: <this session>93 created_at: <ISO-8601 UTC>94 ---9596 # <slug> (auto-generated)9798 ## When to use99 ...100 ## Steps101 ...102 ## Gotchas103 ...104 ```105106 Always add a `.meta.json` next to `SKILL.md` — the pending list/detail API107 reads the candidate's `description`, `triggers`, `name`, and `source` from it108 (there is **no** SKILL.md-frontmatter fallback), so without it the candidate109 shows blank in **Skills → Pending review** and dedup loses its match data:110 `{"slug": "<slug>", "name": "auto/<slug>", "source": "crystallize",111 "created_at": "<ISO>", "description": "...", "triggers": "...",112 "has_scripts": <bool>, "scripts": [...], "kind": "new"}`.113 Only `scripts/` is conditional: if you generated a script, put it under114 `scripts/<name>.py` in that folder, set `"has_scripts": true`, and list it in115 `scripts`; for a prose-only candidate use `"has_scripts": false, "scripts": []`.116117 **Freshening an existing live auto-skill is an UPDATE candidate, not a new118 one.** Same pending folder, but set `"kind": "update"`, `"target":119 "<the live slug>"` and `"base_version": "<the version you merged from>"`.120 Approving an update snapshots the live file to121 `auto/<slug>/.versions/v<N>-SKILL.md` before overwriting it and keeps the 20122 newest snapshots, so the human can roll back.123124 Staging a candidate whose slug is already PENDING is safe: the loader claims a125 distinct slug (`<slug>-2`, `<slug>-3`, …) and stages beside the existing126 candidate rather than overwriting it. That guard covers the pending path only —127 the live path in (b) has none.128129 **(b) Live: ONLY when the user explicitly says "live" / "active" or confirms130 it when asked.** Write `<skills-dir>/<slug>/SKILL.md` directly, with no131 `auto/` prefix, `.meta.json`, or pending stage.132133 Reuse (a)'s template with `name: <slug>`, `source: crystallize`, and title134 `# <slug>`; omit `session_key` and `created_at`. Keep the same description,135 triggers, and When to use / Steps / Gotchas sections.136137 **Do not overwrite an existing skill:** if `<skills-dir>/<slug>/` already138 exists (a live or builtin skill), pick a different slug or ask the user —139 the live path has no collision guard, so writing blindly clobbers it, and140 unlike the pending path nothing claims a distinct slug for you. Put141 any script under `scripts/<name>.py` and, since no approval step runs for142 you, mark it executable yourself — on POSIX, `chmod +x`; skip that on143 Windows, where the executable bit is a no-op.144145 In BOTH cases: do **not** include absolute paths, credentials, tokens, or146 user PII in the body or the script.1471485. **Hand off.**149 - **Candidate:** tell the user it is staged and they can review it in150 **Skills → Pending review** — approve to make it live (and mark any script151 executable), or dismiss it. Nothing loads until they approve.152 - **Live:** tell the user it is active immediately and discoverable by its153 triggers (no approval needed), and point them at the file in case they want154 to edit or remove it.155156## Gotchas157158- **Default to the pending queue.** Only write directly to a live location159 (`<skills-dir>/<slug>/`) when the user explicitly asked for a "live" or160 "active" skill — otherwise always stage under `auto/.pending/` so a human161 reviews it first.162- One skill per distinct procedure — don't bundle unrelated workflows.163- Keep the description trigger-class-focused (it is matched on, and truncated164 in the system-prompt skill index).