1---2name: ase-meta-workflow3description: Generate a new agent tool skill, written in the style of ASE skills, which orchestrates a workflow of sequential actions, parallel actions, sub-agent calls, and skill calls. Use when the user wants to "generate a skill", create a "workflow", "orchestrate" or "chain" multiple ASE skills, or automate a recurring multi-step procedure.4---5
6@${CLAUDE_SKILL_DIR}/../../meta/ase-control.md
7@${CLAUDE_SKILL_DIR}/../../meta/ase-skill.md
8@${CLAUDE_SKILL_DIR}/../../meta/ase-getopt.md
9
10<purpose name="ase-meta-workflow">
11Generate a Workflow Skill
12</purpose>
13
14<expand name="getopt"
15 arg1="ase-meta-workflow"
16 arg2="--scope|-s=(local|user) --force|-f">
17 $ARGUMENTS
18</expand>
19
20<objective>
21*Generate* a new skill for the current *agent tool* <ase-agent-tool/>,
22written in the style of *ASE* skills, which orchestrates the workflow
23described by:
24<arguments><getopt-arguments/></arguments>
25</objective>
26
27References
28----------
29
30- The following <sample/> is a *reference skill* demonstrating the
31 usual *layout* of a generated workflow skill -- its frontmatter, its
32 `ase meta` preamble, and the indentation of its `<flow>`:
33
34 <sample>
35 @${CLAUDE_SKILL_DIR}/sample.md
36 </sample>
37
38 *IMPORTANT*: <sample/> is authoritative for the usual *layout* only.
39 The *syntax* of every control construct is defined *exclusively* by
40 the `Control Flow Constructs` section above, and its frontmatter and
41 preamble show the `claude` flavor only -- the actual frontmatter
42 fields and the actual preamble are dispatched on <ase-agent-tool/> as
43 defined by the `Generated Skill Contract` below.
44
45- The following <graph/> is the *ASE workflow graph*, carrying one
46 `<from/> -> <to/>` transition per line, where each side is either an
47 `ase-xxx-xxx` skill or an upper-case logical state (`START`, `SKETCH`,
48 `APPROACHES`, `TASK`, `ARTIFACT`, `END`):
49
50 <graph>
51 @${CLAUDE_SKILL_DIR}/workflow.txt
52 </graph>
53
54 The <graph/> tells which ASE skill sequences are *usually
55 meaningful*. It *guides* the workflow, but it does *not* restrict
56 it: a workflow may contain arbitrary *non-ASE* actions, and it may
57 contain ASE transitions the <graph/> does not list.
58
59- The following <catalog/> is the *accumulated help* of all ASE skills --
60 the concatenation of every skill's `help.md` file -- and is the
61 *sole* source for the options and arguments of every `<skill/>`
62 invocation (for an `ase-xxx-xxx` skill) you emit:
63
64 <catalog>
65 @${CLAUDE_SKILL_DIR}/../ase-help-intent/data.md
66 </catalog>
67
68Generated Skill Contract
69------------------------
70
71A generated skill is a *regular* skill of the current agent tool
72<ase-agent-tool/> which is *independent* of the *ASE plugin*
73installation path. It therefore *MUST* strictly follow this contract:
74
75- **Frontmatter**: `name: <new-skill-name/>` and a `description` of one
76 to three sentences summarizing the workflow and its trigger phrases.
77
78 The *remaining* frontmatter fields are *tool-specific*, because every
79 agent tool accepts its own field set and its own `allowed-tools`
80 grammar, and hence have to be dispatched on <ase-agent-tool/>:
81
82 <if condition="<ase-agent-tool/> is `codex`">
83 Emit *only* an `allowed-tools` field, carrying the space-separated
84 string `Bash(ase meta *)`, because *OpenAI Codex* accepts *no*
85 frontmatter fields besides `name`, `description`, `license`,
86 `allowed-tools`, and `metadata`.
87 </if>
88
89 <elseif condition="<ase-agent-tool/> is `copilot`">
90 Emit an `argument-hint` derived from the declared options and
91 arguments, plus `user-invocable: true`, `disable-model-invocation:
92 false`, and an `allowed-tools` list which *always* contains
93 `"shell(ase:*)"` plus any further tool the workflow actually uses.
94 *IMPORTANT*: *GitHub Copilot* uses the permission pattern grammar
95 `shell(<command/>:*)`, `write(<path/>)`, and `<mcp-server/>(<tool/>)`
96 -- a `Bash(...)` entry would be misread as an unknown MCP server, and
97 plain tool names like `Skill` or `Agent` are *no* permission patterns
98 at all and hence *MUST NOT* be emitted.
99 </elseif>
100
101 <else>
102 Emit an `argument-hint` derived from the declared options and
103 arguments, plus `user-invocable: true`, `disable-model-invocation:
104 false`, and an `allowed-tools` list which *always* contains
105 `"Bash(ase meta *)"` plus `"Skill"` and/or `"Agent"` whenever the
106 workflow emits `<skill/>` and/or `<agent/>` invocations, plus any
107 further tool the workflow actually uses.
108 </else>
109
110- **Preamble**: the generated skill has to pull in the ASE meta
111 definitions through the `ase meta` command, because it resolves them
112 from the bundled tool package, whereas the
113 `@${CLAUDE_SKILL_DIR}/../../meta/` includes used *inside* the ASE
114 plugin have *no* resolvable path from outside of it. Append further
115 meta names only when the workflow needs them (`dialog` for a
116 `custom-dialog`, `tenets`, `format-task`, ...).
117
118 *How* the command is pulled in is *tool-specific*, because only
119 *Anthropic Claude Code* expands the ``!`<command/>` `` construct
120 before the skill content reaches the model, hence dispatch on
121 <ase-agent-tool/>:
122
123 <if condition="<ase-agent-tool/> is `copilot` or `codex`">
124 Emit the following <preamble-block/> as the first body element,
125 because the ``!`<command/>` `` construct would otherwise reach the
126 model *verbatim* and silently stay unexpanded:
127
128 <preamble-block>
129 *IMPORTANT*: *Before* anything else, run the shell command...
130
131 `ase meta control skill getopt`
132
133 ...and treat its *entire* output as if it were written here. It
134 defines the control flow constructs, the skill conventions, and the
135 option parsing used below. Do *not* proceed before you have done this.
136 </preamble-block>
137 </if>
138
139 <else>
140 Emit the *single* line ``!`ase meta control skill getopt` `` as the
141 first body line.
142 </else>
143
144- **Identification**: a `<purpose name="<new-skill-name/>">` block
145 carrying a short title-case purpose.
146
147- **Argument Parsing**: an `<expand name="getopt" arg1="<new-skill-name/>"
148 arg2="<spec/>">$ARGUMENTS</expand>` block -- but *only* when the
149 workflow wants to declare options.
150
151- **Objective**: an optional `<objective/>` block declaring the
152 official objective of the workflow skill.
153
154- **Body**: usually the `<flow>` derived in `STEP 3` below.
155 But everything is allowed here.
156
157Procedure
158---------
159
160<flow>
161
1621. <step id="STEP 1: Reason About Workflow">
163
164 1. Set <new-skill-name/> to the *first* whitespace-separated token of
165 <getopt-arguments/> and <workflow-description/> to the *entire
166 remainder*. Do not output anything.
167
168 2. <if condition="<new-skill-name/> does not match the regexp `^[a-zA-Z][a-zA-Z0-9_-]*$`">
169 Ask the user interactively, without a special tool, for the skill
170 name with a single question:
171
172 `**No valid skill name given. What should the generated skill be named?**`
173
174 Then set <new-skill-name/> to the response of the user and set
175 <workflow-description/> to the *entire* original
176 <getopt-arguments/>.
177 Repeat this question until the response matches the regexp
178 `^[a-zA-Z][a-zA-Z0-9_-]*$`, so that no path separator or traversal
179 segment can ever reach <target-skill/>.
180 </if>
181
182 3. <if condition="<workflow-description/> is empty">
183 Ask the user interactively, without a special tool, for the
184 workflow with a single question:
185
186 `**No workflow description yet. Which workflow should the skill perform?**`
187
188 Then set <workflow-description/> to the response of the user.
189 </if>
190
191 4. Determine the *skill locations* of the current agent tool, because
192 every agent tool discovers its skills in its *own* directories:
193
194 <skill-dir-user>~/.claude/skills</skill-dir-user>
195 <skill-dir-local>.claude/skills</skill-dir-local>
196 <if condition="<ase-agent-tool/> is `copilot`">
197 <skill-dir-user>~/.copilot/skills</skill-dir-user>
198 <skill-dir-local>.github/skills</skill-dir-local>
199 </if>
200 <if condition="<ase-agent-tool/> is `codex`">
201 <skill-dir-user>~/.codex/skills</skill-dir-user>
202 <skill-dir-local>.agents/skills</skill-dir-local>
203 </if>
204
205 <if condition="<getopt-option-scope/> is equal `user`">
206 Set <dir><skill-dir-user/></dir>.
207 </if>
208 <else>
209 Set <dir><skill-dir-local/></dir>.
210 </else>
211
212 Then set <target-skill><dir/>/<new-skill-name/>/SKILL.md</target-skill>.
213 Expand a leading `~` in <target-skill/> into the absolute home
214 directory of the user, as the file tools accept absolute paths only.
215 Do not output anything.
216
217 5. Check whether <target-skill/> already exists.
218
219 <if condition="<target-skill/> exists and <getopt-option-force/> is not equal `true`">
220 Only output the following <template/> and then immediately *STOP*
221 processing the entire current skill:
222
223 <template>
224 ⧉ **ASE**: ✪ skill: **ase-meta-workflow**, ▶ ERROR: target already exists: **<target-skill/>**
225 </template>
226
227 Directly *after* this error <template/>, and *before* stopping,
228 give the corrective hint by expanding the following:
229
230 <ase-tpl-hint level="minimal">
231 Re-run with `--force`/`-f` to overwrite the existing skill.
232 </ase-tpl-hint>
233 </if>
234
235 6. Report the workflow with the following <template/>:
236
237 <template>
238 ⧉ **ASE**: ✪ workflow: **<new-skill-name/>**, ⎈ tool: **<ase-agent-tool/>**, ◉ target: **<target-skill/>**
239 ⧉ **ASE**: ✪ workflow: **<new-skill-name/>**, ⇌ description: **<workflow-description/>**
240 </template>
241
242 7. Do not output anything else in this STEP 1, unless you asked the user.
243
244 </step>
245
2462. <step id="STEP 2: Internalize ASE Capabilities">
247
248 1. Absorb the <catalog/> to know which ASE skills exist and which
249 options and arguments each of them accepts.
250
251 2. Absorb the <graph/> to know which ASE skill sequences are usually
252 meaningful, and treat every transition it does *not* list as
253 merely *unusual*, never as *forbidden*.
254
255 3. Do not output anything in this STEP 2.
256
257 </step>
258
2593. <step id="STEP 3: Derive Workflow Structure">
260
261 1. Decompose <workflow-description/> into an *ordered* list of
262 *top-level* actions. Each top-level action becomes a numbered
263 list item wrapping a `<step id="STEP <n/>: <title/>">` element,
264 and all of them together are wrapped into a single `<flow>`
265 element.
266
267 2. Map every action of <workflow-description/> onto the matching
268 control construct:
269
270 - *sequential* actions become consecutive `<step/>` elements,
271 - *concurrent* actions become a `<parallel>` element,
272 - *sub-agent* invocations become `<agent/>` elements,
273 - *ASE skill* invocations become `<skill name="ase:ase-xxx-xxx"
274 args="..."/>` elements, whose options and arguments are taken
275 *verbatim* from the <catalog/> and never invented,
276 - *foreign skill* invocations become `<skill name="..." args="..."/>`
277 elements, whose options and arguments are taken *verbatim*,
278 - *repetitions* become `<while/>` or `<for/>` elements,
279 - *conditional* actions become `<if/>`/`<elseif/>`/`<else/>` elements,
280 - all *remaining* actions become plain instruction prose inside
281 their `<step/>`.
282
283 Every *top-level* `<skill/>` element -- one which is not already
284 placed inside an `<agent/>` element -- *MUST* be enclosed in
285 its own dedicated `<agent/>` element, always *without* an
286 `isolation` attribute and always with `run_in_background=false`,
287 because the `TaskCreate` and `TaskUpdate` tool calls of the
288 called skill would otherwise interfere with the task tracking of
289 the generated workflow skill itself.
290
291 3. For *every* `<parallel>` element which contains at least one
292 `<agent isolation="worktree">`, you *MUST* append a *dedicated*
293 consolidation `<step/>` directly after the `<step/>` holding that
294 `<parallel>` element, and this consolidation step *MUST* contain
295 an `<agent-consolidation/>` element, so the Git WorkTrees of the
296 concurrent sub-agents are merged and removed again.
297
298 4. Determine the *options* of the generated skill: declare an option
299 only when <workflow-description/> actually asks for it, and
300 express it in the `--<long/>[|-<short/>][=<default/>|=(<c1/>|<c2/>|...)[...]]`
301 spec syntax of the `getopt` definition, which also covers the fixed
302 *choice* form and the comma-separated *list* form.
303
304 5. Do not output anything in this STEP 3.
305
306 </step>
307
3084. <step id="STEP 4: Generate Workflow Skill">
309
310 1. <if condition="<ase-project-boxing/> is not equal `black`">
311 Set <structure/> to a compact rendering of the derived workflow --
312 one line per `<step/>`, prefixed with its number, and one indented
313 line per contained `<parallel/>`, `<agent/>`, `<skill/>`, or
314 `<agent-consolidation/>` element -- and report it with the
315 following <template/>:
316
317 <template>
318 <ase-tpl-boxed title="WORKFLOW" subtitle="<new-skill-name/>">
319 <structure/>
320 </ase-tpl-boxed>
321 </template>
322 </if>
323
324 2. Assemble <skill-content/> from the derived workflow, strictly
325 following the `Generated Skill Contract` above.
326
327 3. Write <skill-content/> to <target-skill/>, creating the directory
328 `<dir/>/<new-skill-name/>` if it does not exist yet. Calculate the
329 number of words <words/> of <skill-content/>.
330
331 4. Report the result with the following <template/>:
332
333 <template>
334 ⧉ **ASE**: ✪ workflow: **<new-skill-name/>**, ✎ skill: **<words/>** words, ▶ status: **skill generated**
335 ⧉ **ASE**: ✪ workflow: **<new-skill-name/>**, ◉ files: **<target-skill/>**
336 </template>
337
338 5. Give the follow-up pointer, dispatched on <ase-agent-tool/>,
339 because every agent tool reloads and invokes its skills
340 differently, by expanding the following:
341
342 <if condition="<ase-agent-tool/> is `copilot`">
343 <ase-tpl-hint level="minimal">
344 Run `/skills reload` to reload all skills.
345 Run `/<new-skill-name/>` to execute the new generated workflow.
346 </ase-tpl-hint>
347 </if>
348 <elseif condition="<ase-agent-tool/> is `codex`">
349 <ase-tpl-hint level="minimal">
350 Run `/skills` to check that the new skill was picked up.
351 Mention `$<new-skill-name/>` to execute the new generated workflow.
352 </ase-tpl-hint>
353 </elseif>
354 <else>
355 <ase-tpl-hint level="minimal">
356 Run `/reload-skills` to reload all skills.
357 Run `/<new-skill-name/>` to execute the new generated workflow.
358 </ase-tpl-hint>
359 </else>
360
361 6. Do not output anything else in this STEP 4.
362
363 </step>
364
365</flow>