migrate-clips-to-extensions-codegen-llm-hybrid
Skill15 starsChanged 2 days agoMITView on GitHub
Migrate legacy Azure CLI and Azure PowerShell commands to AzClips extensions using TypeSpec codegen plus LLM-authored customization. Use when porting existing command groups, comparing legacy command shapes and workflows with REST APIs, selecting generated processors, or composing migration customizations.
In this repository13 other files it gives its agents.
- Agent/AGENTS.mdAGENTS.md
- AGENTS.mdAGENTS.md
- .azure-pipelines/AGENTS.mdAGENTS.md
- devops/scripts/AGENTS.mdAGENTS.md
- azclips-custom-code-classifierSkill
- azclips-scenario-test-converterSkill
- extension-test-coverageSkill
- openspec-apply-changeSkill
- openspec-archive-changeSkill
- openspec-exploreSkill
- openspec-proposeSkill
- openspec-sync-specsSkill
- openspec-verify-changeSkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
48 rules. About 0 are common, 25 are distinctive, and 23 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈25
Distinctive · estimate
This author's own choices. Worth a look.
23
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 17
Run terminal commands from <project-root> unless a step explicitly changes the working directory.
- Very specific: line 26
Run ./build.ps1 to build the codegen toolkit.
- Very specific: line 29
Ask user for desired extension name: <extension-name>
- Very specific: line 30
Ask user to provide a temporary output location <output-path>, otherwise fallback to: <output-path> = …
- Very specific: line 31
ensure the output directory exists: mkdir -p <output-path>
- Very specific: line 32
Create aceconfig.yaml under <output-path> following below template
- Distinctive: line 54
Ask user to provide spec path or detail for the API they want to generate extensions for, need to specify management plane or data plane …
- Very specific: line 58
If typespec not found from tsp-location under aceconfig.yaml, search …
- Distinctive: line 66
Ask user to identify the APIs that are required for migration by operation group name.
- Very specific: line 69
Keep any actions the user names with an operation group, such as deployment operations get/list, as its <actions>.
- Distinctive: line 70
No need to compile at this stage
- Very specific: line 84
Write summary in table <interface-table> thoroughly specifying comparison between API shapes, Azure PowerShell shapes and Azure CLI shapes …
- Very specific: line 95
Write summary in table <implementation-table> thoroughly specifying comparison between API usages, Azure PowerShell implementation and …
- Very specific: line 101
Ask user to review your recommendation and accept their modifications as <finalized-shapes> and <finalized-workflows>
- Distinctive: line 103
Ask the user to confirm the resulting processor set, then remove generated processors outside that set.
- Very specific: line 107
Delete the processor files that are not part of the selected <operation-groups> from <output-path>, confirm with user before deleting, but …
- Distinctive: line 109
Read following links and learn the convention.
- Distinctive: line 117
Read the complete server URL or endpoint template, including template parameters, defaults, and alternative server declarations.
- Very specific: line 118
If the server is a fixed URL, expose an overridable Endpoint or Url property, the property name should be inferred from spec.
- Distinctive: line 119
If the URL contains parameters, expose each required server parameter as a typed property and construct the endpoint from the template.
- Very specific: line 120
If multiple @server declarations apply, ask user to choose, fallback to the first one if empty input provided.
- Distinctive: line 121
Ensure each processor combines the resolved endpoint with its operation path and that every server-template placeholder is bound.
- Distinctive: line 122
No need to compile at this stage.
- Very specific: line 128
Follow the custom-code workflow in <project-root>/eng-docs/howto/integrate-custom-code-agent.md:
- Distinctive: line 150
Keep the table's feature ID in each heading, so the OpenSpec review can name the features it covers.
- Distinctive: line 151
Ask the user to review the generated OpenSpec artifacts.
- Very specific: line 152
Ask whether the user wants to retain the OpenSpec change.
- Very specific: line 159
When customization engages multiple processors, strictly follow the CreateExtendedProcessor usage in …
- Distinctive: line 160
If external API needed for customization, see step 11.
- Distinctive: line 161
do not compile yet
- Distinctive: line 168
Make sure external processors and models behave exactly as network withs compute
- Very specific: line 173
Make sure aceconfig.yaml is also copied into <project-root>/src/Extensions/<extension-name>
- Very specific: line 174
Ask user to manually merge if <project-root>/src/Extensions/<extension-name> exists and not empty.
- Distinctive: line 180
If not able to perform successful compilation, ask user for manual fix and wait for confirmation before proceeding.
- Distinctive: line 187
Ask user to review each sub-step and accept user modification on the fly.
- Very specific: line 194
Run <project-root>/build/build.ps1 -GenerateHelpArtifacts and fix all errors.
- Distinctive: line 200
Before any archive, make sure the user has been asked whether to record, then let them review the recordings.
- Very specific: line 204
Delete everything under <output-path> except <output-path>/finalized-shapes.md and <output-path>/finalized-workflows.md
- Distinctive: line 205
Delete the output path for external API if any
- Distinctive: line 216
Treat the current implementation as authoritative when the private-preview guide is stale.
- Distinctive: line 217
Keep generated-style atomic processors separate from handwritten customization code.
- Distinctive: line 218
Do not hand-roll authentication, retry, polling, serialization, or event publication already owned by the runtime or processor base.
- Distinctive: line 219
Do not expose commands or parameters that were not requested.
- Very specific: line 220
When something a step depends on is absent from the Azclips surface, stop and report it.
- Distinctive: line 221
Keep API versions explicit and grounded in the selected specification.
- Very specific: line 222
Read upstream evidence from remote branches only: Azure/azure-rest-api-specs@main, Azure/azure-powershell@main, Azure/azure-cli@dev.
- Distinctive: line 223
Follow nullable C#, namespace, file layout, and naming conventions from the chosen reference extension.
- Distinctive: line 224
Avoid unrelated refactors and preserve public behavior outside the requested extension surface.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Migrate Legacy Clips Commands to AzClips Extensions
Migrate existing legacy clips commands to AzClips extensions while following the repository's current processor, registration, and packaging patterns.
Input: The request should identify an extension or Azure service and the operations to expose. Useful optional details include TypeSpec URL, API version, command group, command names, and legacy CLI, PowerShell links.
Workflow
- Resolve paths
<project-root>is the absolute path to the AzClips repository root containingazclips.slnx.- Resolve it from the workspace before running commands.
- Run terminal commands from
<project-root>unless a step explicitly changes the working directory.
- Install Node libraries and build codegen toolkit
- skip if present
- Install nvs (Node Version Switcher) to manage Node.js versions.
- Install node 24 using nvs:
nvs add 24 - Use node 24:
nvs use 24 - Locate into codegen toolkit directory:
cd <project-root>/toolkit - Run
npm ci - Run
./build.ps1to build the codegen toolkit.
- Create template aceconfig.yaml
- Ask user for desired extension name:
<extension-name> - Ask user to provide a temporary output location
<output-path>, otherwise fallback to:<output-path> = <project-root>/migration-tmp/tsp-output/<extension-name> - ensure the output directory exists:
mkdir -p <output-path> - Create
aceconfig.yamlunder<output-path>following below template
schema-version: 1 # Run inputs: the CLI copies the spec; tsp-emit compiles each entrypoint. output-dir: . # default: this file's folder tsp-location: https://github.com/Azure/azure-rest-api-specs/tree/main/specification/compute/resource-manager/Microsoft.Compute/Compute # additional-directories: # folders the compile needs, not under tsp-location # - ../Shared # relative to tsp-location, or absolute entrypoints: # relative to tsp-location - path: ./Compute api-version: 2026-03-01 # Document facts: what the spec cannot provide; seed-ir writes them into the IR's target. service-name: Compute root-namespace: Microsoft.Azure.Azclips.Extensions.Compute project-name: Microsoft.Azure.Azclips.Extensions.Compute description: Compute extension for AzClips - Ask user for desired extension name:
- Generate extensions from selected API using raw codegen toolkit
- Replace
service-nameinaceconfig.yamlwith<extension-name>and updateroot-namespace,project-name, anddescriptionaccordingly. - Ask user to provide spec path or detail for the API they want to generate extensions for, need to specify management plane or data plane explicitly.
- Locate API spec:
- management plane:
<spec-path> = https://github.com/Azure/azure-rest-api-specs/tree/main/specification/<rp-name>/resource-manager/<rp-full-name>/<service-name> - data plane:
<spec-path> = https://github.com/Azure/azure-rest-api-specs/tree/main/specification/<rp-name>/data-plane/<service-name>
- management plane:
- If typespec not found from
tsp-locationunderaceconfig.yaml, searchhttps://github.com/Azure/azure-rest-api-specs/tree/main/specification/<rp-name>for typespec, and let user choose if found any. Once confirmed, updatetsp-locationaccordingly. - Let user decide which API version to use for the extension. Fallback to latest stable version if not specified. Update
aceconfig.yamlaccordingly. cd <output-path>- generate raw extensions:
node <project-root>/toolkit/packages/cli/dist/src/cli.js compile - confirm raw extensions are generated under
<output-path>, no need to compile right now.
- Replace
- Select APIs needed for migration
- Review the generated raw extensions under
<output-path>. - Ask user to identify the APIs that are required for migration by operation group name.
- example of operation group name: "storage account" represents PUT/GET/DELETE/PATCH/POST ... all operations related to storage account resource.
- eventually you will have a list of operation group names:
<operation-groups> = [<operation-group-1>, <operation-group-2>, ...]
- Keep any actions the user names with an operation group, such as
deployment operations get/list, as its<actions>. - No need to compile at this stage
- Review the generated raw extensions under
- Learn extension basic
- Learn extension development instruction:
<project-root>\eng-docs\howto\Extension-Development-For-Private-Preview.md - reference
<project-root>/src/Extensions/, everything under exceptCustomizationshould be considered as generated content
- Learn extension development instruction:
- Analyze API interfaces
- Infer module names from
<operation-groups>and verify the following URIs. - Learn Azure-PowerShell from
<ps-path> = https://github.com/Azure/azure-powershell/tree/main/src/<ps-module-name>:- learn the interfaces: parameters, return types
- Learn Azure-CLI from
<cli-path> = https://github.com/Azure/azure-cli/tree/dev/src/azure-cli/azure/cli/command_modules/<cli-module-name>:- learn the interfaces: parameters, return types
- Learn REST API from
<spec-path>resolved in step 3:- learn API shapes of
<operation-groups>at<spec-path>
- learn API shapes of
- Write summary in table
<interface-table>thoroughly specifying comparison between API shapes, Azure PowerShell shapes and Azure CLI shapes for user to review- table should be able to indicate gaps, intersections, overlaps between API shapes, Azure PowerShell shapes and Azure CLI shapes
- export
<interface-table>to<output-path>/interface-table.md
- Infer module names from
- Analyze API implementation
- Learn Azure-PowerShell:
- learn implementation of
<operation-groups>from<ps-path>
- learn implementation of
- Learn Azure-CLI:
- learn implementation of
<operation-groups>from<cli-path>
- learn implementation of
- Learn REST API:
- learn API usage of
<operation-groups>from<spec-path>
- learn API usage of
- Write summary in table
<implementation-table>thoroughly specifying comparison between API usages, Azure PowerShell implementation and Azure CLI implementation for user to review- table should describe each usage as a workflow, for example, in PS implementation, each parameter set is a workflow, equivalent in CLI implementation as well. And Table should be able to indicate gaps, intersections, overlaps between API usages, Azure PowerShell workflows and Azure CLI workflows
- export
<implementation-table>to<output-path>/implementation-table.md
- Learn Azure-PowerShell:
- Finalize Shapes for processors
- Give your recommendation from
<implementation-table>and<interface-table>for minimum viable shapes+workflows for each processor and justify your choices. - Ask user to review your recommendation and accept their modifications as
<finalized-shapes>and<finalized-workflows> - From the accepted workflows, identify every processor required directly or transitively by customization.
- Ask the user to confirm the resulting processor set, then remove generated processors outside that set. Keep unrelated generated models because they are not customer-facing and may be shared dependencies.
- export the
<finalized-shapes>and<finalized-workflows>to<output-path>/finalized-shapes.mdand<output-path>/finalized-workflows.md
- Give your recommendation from
- Polish boilerplate code
- Delete the processor files that are not part of the selected
<operation-groups>from<output-path>, confirm with user before deleting, but strongly encourage the deletion - Defer models that are not part of the selected
<operation-groups>for later stages. Keep them for now but track in a list<deferred-models> - Read following links and learn the convention. Include file names, class names, namespace, assembly names and so on. You name it:
<project-root>/src/Extensions/Compute/Models<project-root>/src/Extensions/Compute/Processors<project-root>/src/Extensions/Compute/Extensions.Compute.csproj
- Apply the learned conventions to the new extension code. Before starting, show your plan to user and ask for confirmation.
- Include the missing
<project-root>/src/Extensions/Compute/Compatibility.csin the new extension code. - The generated
.csprojhas no<Version>: add<Version>0.1.0</Version>as the new extension's initial version. The release pipeline requires one and bumps it from there. - For data-plane APIs, locate the applicable TypeSpec
@serverdeclaration under<spec-path>. - Read the complete server URL or endpoint template, including template parameters, defaults, and alternative server declarations.
- If the server is a fixed URL, expose an overridable
EndpointorUrlproperty, the property name should be inferred from spec. On the non-generic processor base with that URL as its default. - If the URL contains parameters, expose each required server parameter as a typed property and construct the endpoint from the template. Do not collapse template parameters into one opaque endpoint.
- If multiple
@serverdeclarations apply, ask user to choose, fallback to the first one if empty input provided. - Ensure each processor combines the resolved endpoint with its operation path and that every server-template placeholder is bound.
- No need to compile at this stage.
- Delete the processor files that are not part of the selected
- Write customization
- User can jump straight into this step if they have uncustomized extension ready. When user ask to go with step 10 directly, ask for working directory of their extension as
<output-path>, and<project-root>. - Once get working directory, ask for what specific customization the user wants to perform. Otherwise fallback to
<output-path>/finalized-workflows.md - The OpenSpec flow below is optional. Once the user has selected features in 10.2, ask whether to skip OpenSpec and apply them directly, recommending that they keep it. Skipping replaces
/custom-code-spec, 10.3, and 10.4: implement the assembled features directly as customization code, following the rules below, and ask the user to review the code. - Follow the custom-code workflow in
<project-root>/eng-docs/howto/integrate-custom-code-agent.md:- For each of
<operation-groups>, run/integrate-comparewith<extension-name>as the service module, that operation group, and its<actions>if it has any, to compare the upstream implementations and identify their custom-code logic. - Ask the user only which feature IDs to migrate. Assemble the selected features into the
Input Formatof<project-root>/.github/prompts/custom-code-spec.prompt.md, run/custom-code-specwith that content as its argument to create or update the OpenSpec change, and capture the change ID it reports as<change-id>. Assemble it like this:/custom-code-spec Target: <the compared Module / operation group, and actions if any> Commands: - CLI: <Azclips CLI command, from target_mapping> - PowerShell: <Azclips PowerShell command, from target_mapping> ## F1 <feature title> Surface: <both | cli-only | powershell-only, from the row's route> Action: <add behavior | update behavior, from the row's Current Azclips evidence> Business logic: - <copied from the comparison's Business logic section> Reference: <the row's source links>- Copy each feature's business logic as written. Never derive it again from the table's code snippets, and never add behavior the comparison does not state. When a selected feature has no entry, ask instead of writing one.
Surfaceisbothforshared-customization, andcli-onlyorpowershell-onlyfor the surface routes. A Surface note from the user, such asF10 powershell-only, overrides it. Adrop:row the user selects anyway is an explicit blacklist override.Actionisadd behaviorwhen nothing in Azclips covers the behavior yet, andupdate behaviorwhen something partly does.- Omit
Commandswhile the extension has noExtensionIndex.csyet. - Keep the table's feature ID in each heading, so the OpenSpec review can name the features it covers.
- Ask the user to review the generated OpenSpec artifacts. If the user requests changes, update the spec and ask for review again. Repeat until the user gives explicit affirmative approval, then run
/opsx:apply <change-id>to implement the approved spec as customization code. - Ask whether the user wants to retain the OpenSpec change. If yes, run
/opsx:archive <change-id>; otherwise, leave it unarchived.
- For each of
- Customization should strickly follow
<project-root>/eng-docs/howto/Extension-Development-For-Private-Preview.mdand<project-root>/src/Extensions/Compute/Customization - Customization should be placed under
<output-path>/Customization - Customization folder can contain any kinds of C# code. But those classes implement or inherited processors are the customer facing "commands". That is to say, if there is a finalized workflow requires customization, there has to be a customized class implementing or inheriting the relevant processor.
- Inherit processor only when the interface covers all parameters from the parent processor. It can have more but no less.
- Customization never owns the endpoint: no
Method,CreateRequestUri(), api-version, or request URL underCustomization/. Every route comes from an atomic processor, inherited or composed withCreateExtendedProcessor<T>— never copied. - Customization should only write those entries provided by processors to wire with runtime. Otherwise should be private helper functions only.
- When customization engages multiple processors, strictly follow the
CreateExtendedProcessorusage in<project-root>/src/Extensions/Compute/Customization. - If external API needed for customization, see step 11.
- do not compile yet
- User can jump straight into this step if they have uncustomized extension ready. When user ask to go with step 10 directly, ask for working directory of their extension as
- Customize with external APIs engaged
- See
<project-root>/src/Extensions/Compute. Creating VM requires APIs from network RP. - Repeat step 2, 3, 4, 9 to create "extension" for external API. Keep variables in this session referring to the original API not external. At step 9, polish external API extensions with the original name not external name.
- External processors don't need to be compared with PS/CLI, only keep the minimum shapes required by
<extension-name>and perform flatten accordingly - Copy external prosessors and models into
<output-path>/Processorswith base processor excluded and<output-path>/Modelsrespectively. - Make sure external processors and models behave exactly as network withs compute
- do not compile yet
- See
- Move to source
- Copy contents under
<output-path>into<project-root>/src/Extensions/<extension-name>, create<project-root>/src/Extensions/<extension-name>if it does not exist, make sure<extension-Name>CamelCase. Exclude<output-path>/finalized-shapes.mdand<output-path>/finalized-workflows.md - Make sure
aceconfig.yamlis also copied into<project-root>/src/Extensions/<extension-name> - Ask user to manually merge if
<project-root>/src/Extensions/<extension-name>exists and not empty. Hanging in prompt waiting for user provide merged path as confirmation, fallback to<project-root>/src/Extensions/<extension-name>if empty input provided. Create if not exists. - Revisit
<deferred-models>from step 9, verify are they irrelevant indeed. Delete those that are not needed from<project-root>/src/Extensions/<extension-name>/Modelsnot<output-path>/Models
- Copy contents under
- Compile
- Compile the merged extension to ensure there are no syntax or reference errors.
- Try resolve any compilation or reference errors that arise.
- If not able to perform successful compilation, ask user for manual fix and wait for confirmation before proceeding.
- Create PS and CLI
- Compose
<project-root>/src/Extensions/<extension-name>/ExtensionIndex.csto expose CLI/PS syntax that maps to processors or customization classes. - Generally speaking if one processor has a corresponding customization, that processor should be hidden, expose customization instead.
- External API produced processors should be hidden. External API only customizations should be hidden as well if they have been referrenced in other customizations.
- Produce corresponding PS module under
<project-root>/src/PS, see<project-root>/src/PS/Computeas reference. - Ask user to review each sub-step and accept user modification on the fly.
- Rebuild solution at
<project-root>with PS project added
- Compose
- Write command help
- Follow
<project-root>/eng-docs/howto/help.md. - Scaffold and complete CLI help for each changed verb.
- Scaffold and complete PowerShell help after rebuilding the cmdlets.
- Run
<project-root>/build/build.ps1 -GenerateHelpArtifactsand fix all errors.
- Follow
- Write scenario tests
- For each of
<operation-groups>, run/integrate-scenario-testwith<extension-name>as the service module, that operation group, and its<actions>if it has any, to summarize the upstream live tests into test cases. - Ask the user whether to skip OpenSpec and write the tests directly, recommending that they keep it. With OpenSpec, run
/scenario-test-specwith the summary's wholeTest casessection as its argument, as written, and capture the change ID it reports as<test-change-id>. Do not ask the user to choose cases: the coverage rules already decided them. - With OpenSpec, ask the user to review the generated OpenSpec artifacts, repeating until they give explicit affirmative approval, then run
/opsx:apply <test-change-id>to write the tests. Without it, write them straight from theTest casessection by followingApplying A Scenario-Test Changein<project-root>/.github/skills/azclips-scenario-test-converter/SKILL.md. Either way, for a new extension theExtensionUnderTestentry andProjectReferencewill be missing: add them rather than reporting a gap. - Before any archive, make sure the user has been asked whether to record, then let them review the recordings.
- With OpenSpec, ask whether the user wants to retain the OpenSpec change. If yes, run
/opsx:archive <test-change-id>once the recordings are reviewed; otherwise, leave it unarchived.
- For each of
- Final cleanup
- Delete everything under
<output-path>except<output-path>/finalized-shapes.mdand<output-path>/finalized-workflows.md - Delete the output path for external API if any
- Delete everything under
Output
Summarize:
- Folder structure of
<project-root>/src/Extensions/<extension-name> - Exposed CLI/PS commands and their mappings to processors or customization classes, and their mapping to APIs.
- Tests and builds run, including any validation that could not be completed
Guardrails
- Treat the current implementation as authoritative when the private-preview guide is stale.
- Keep generated-style atomic processors separate from handwritten customization code.
- Do not hand-roll authentication, retry, polling, serialization, or event publication already owned by the runtime or processor base.
- Do not expose commands or parameters that were not requested.
- When something a step depends on is absent from the Azclips surface, stop and report it; never work around it with a raw HTTP passthrough or an out-of-band resource.
- Keep API versions explicit and grounded in the selected specification.
- Read upstream evidence from remote branches only:
Azure/azure-rest-api-specs@main,Azure/azure-powershell@main,Azure/azure-cli@dev. Do not treat a local clone, fork, or feature branch as evidence. - Follow nullable C#, namespace, file layout, and naming conventions from the chosen reference extension.
- Avoid unrelated refactors and preserve public behavior outside the requested extension surface.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

