Add combined pulumi plugin for one-install marketplace distribution (#50)

* Add combined pulumi plugin for one-install marketplace distribution

The Claude marketplace 'pulumi' entry now points at a combined plugin
defined at the repo root, whose skills field bundles the authoring,
migration, and delegation skill groups. A single '/plugin install pulumi'
covers all 14 end-user skills; granular plugins remain for subset
installs. Also adds the official square logo asset for marketplace
listings, raises pulumi-delegation to three Codex starter prompts, and
updates the install docs.

* Review fixes: version 2.0.0 + displayName, doc counts, missing skill listing

Bump the combined plugin to 2.0.0 since it replaces the granular
'pulumi' plugin (also 1.0.0) with different contents, and add a
displayName. Fix the README wording that implied pulumi-package-
maintenance is part of the combined plugin. Correct stale skill counts
(migration 4 to 5, pulumi 7 to 8) and list pulumi-debug-failed-operation
in both docs; it was missing from README and AGENTS.md.

* Reword combined plugin description to say what Pulumi is

* Add HCL to the combined plugin language list

* Extend the combined pulumi plugin to Codex with a root .codex-plugin manifest

The Codex catalog still pointed the pulumi entry at ./pulumi (8 skills)
while the Claude marketplace pointed it at ./ (14 skills), so the same
plugin name installed different contents per ecosystem. Add a root
.codex-plugin/plugin.json mirroring the combined Claude manifest and
point the catalog at ./.

Verified with codex-cli 0.146.0: the skills array registers all 14
skills under the pulumi namespace (checked via codex debug
prompt-input). Manifest tests now cover the root manifests and accept
both string and array skills fields.
This commit is contained in:
Mark
2026-08-07 11:31:56 -06:00
committed by GitHub
parent acd34dc899
commit d083ad2cc8
9 changed files with 130 additions and 30 deletions
+1 -1
View File
@@ -20,7 +20,7 @@
"name": "pulumi",
"source": {
"source": "local",
"path": "./pulumi"
"path": "./"
},
"policy": {
"installation": "AVAILABLE"
+2 -2
View File
@@ -16,8 +16,8 @@
},
{
"name": "pulumi",
"source": "./pulumi",
"description": "Entry-point and specialized skills for writing and operating Pulumi infrastructure",
"source": "./",
"description": "Teach your agent Pulumi: infrastructure as code in TypeScript, Python, Go, C#, Java, YAML, or HCL. Skills for writing and operating cloud infrastructure, migrating from Terraform, CloudFormation, CDK, and ARM, and delegating work to Pulumi Neo, Pulumi's AI platform engineer.",
"category": "development"
},
{
+33
View File
@@ -0,0 +1,33 @@
{
"name": "pulumi",
"displayName": "Pulumi",
"version": "2.0.0",
"description": "Teach your agent Pulumi: infrastructure as code in TypeScript, Python, Go, C#, Java, YAML, or HCL. Skills for writing and operating cloud infrastructure, migrating from Terraform, CloudFormation, CDK, and ARM, and delegating work to Pulumi Neo, Pulumi's AI platform engineer.",
"author": {
"name": "Pulumi",
"url": "https://github.com/pulumi"
},
"homepage": "https://www.pulumi.com/docs/",
"repository": "https://github.com/pulumi/agent-skills",
"license": "Apache-2.0",
"keywords": [
"pulumi",
"infrastructure",
"iac",
"terraform",
"cloudformation",
"cdk",
"arm",
"bicep",
"migration",
"esc",
"secrets",
"automation-api",
"neo"
],
"skills": [
"./pulumi/skills",
"./migration/skills",
"./delegation/skills"
]
}
+46
View File
@@ -0,0 +1,46 @@
{
"name": "pulumi",
"version": "2.0.0",
"description": "Teach your agent Pulumi: infrastructure as code in TypeScript, Python, Go, C#, Java, YAML, or HCL. Skills for writing and operating cloud infrastructure, migrating from Terraform, CloudFormation, CDK, and ARM, and delegating work to Pulumi Neo, Pulumi's AI platform engineer.",
"skills": [
"./pulumi/skills",
"./migration/skills",
"./delegation/skills"
],
"author": {
"name": "Pulumi",
"url": "https://github.com/pulumi"
},
"homepage": "https://www.pulumi.com/docs/",
"repository": "https://github.com/pulumi/agent-skills",
"license": "Apache-2.0",
"keywords": [
"pulumi",
"infrastructure",
"iac",
"terraform",
"cloudformation",
"cdk",
"arm",
"bicep",
"migration",
"esc",
"secrets",
"automation-api",
"neo"
],
"interface": {
"displayName": "Pulumi",
"shortDescription": "Write, migrate, and operate Pulumi infrastructure",
"developerName": "Pulumi",
"category": "Coding",
"websiteURL": "https://www.pulumi.com/docs/",
"defaultPrompt": [
"Use $pulumi-overview to set up an S3 bucket and a Cloudflare DNS record",
"Use $pulumi-overview to provision a database for this app",
"Use $pulumi-best-practices to review this Pulumi code",
"Use $pulumi-terraform-to-pulumi to convert this Terraform module",
"Use $pulumi-neo-handoff to hand off this Pulumi program to Neo to preview and deploy"
]
}
}
+17 -9
View File
@@ -25,6 +25,7 @@ Entry-point and specialized skills for writing and operating Pulumi infrastructu
- **pulumi-component**: Guide for authoring ComponentResource classes
- **pulumi-automation-api**: Best practices for using Pulumi Automation API
- **pulumi-esc**: Guidance for working with Pulumi ESC (Environments, Secrets, and Configuration)
- **pulumi-debug-failed-operation**: Debug a failed `pulumi up` or `pulumi preview` from the failure Pulumi already recorded
- **provider-upgrade**: Safe workflows for upgrading Pulumi providers without unintended infrastructure changes
- **package-usage**: Track which stacks across an organization use a package and at what versions
@@ -47,10 +48,15 @@ Skills for handing off in-progress work from coding agents to Pulumi Neo for del
```bash
/plugin marketplace add pulumi/agent-skills
/plugin install pulumi-migration
/plugin install pulumi
/plugin install pulumi-delegation
/plugin install pulumi-package-maintenance
/plugin install pulumi # all end-user skills (authoring + migration + Neo handoff)
```
The `pulumi` plugin is the combined plugin defined at the repo root: `.claude-plugin/plugin.json` and `.codex-plugin/plugin.json` list `pulumi/skills/`, `migration/skills/`, and `delegation/skills/` in their `skills` fields. Granular alternatives (do not combine with `pulumi`, which already includes the first two):
```bash
/plugin install pulumi-migration # migration skills only
/plugin install pulumi-delegation # Neo handoff skill only
/plugin install pulumi-package-maintenance # provider-repo maintenance skills
```
### OpenAI Codex
@@ -59,7 +65,7 @@ Skills for handing off in-progress work from coding agents to Pulumi Neo for del
codex plugin marketplace add pulumi/agent-skills
```
After the marketplace registers, install plugins from the Codex TUI: run `codex`, open the plugin marketplace with `/plugins`, and pick `pulumi-migration`, `pulumi`, `pulumi-delegation`, or `pulumi-package-maintenance`.
After the marketplace registers, install plugins from the Codex TUI: run `codex`, open the plugin marketplace with `/plugins`, and pick `pulumi-migration`, `pulumi`, `pulumi-delegation`, or `pulumi-package-maintenance`. As in Claude Code, `pulumi` is the combined plugin with all end-user skills; do not combine it with `pulumi-migration` or `pulumi-delegation`.
### Universal (all agents)
@@ -72,8 +78,8 @@ npx skills add pulumi/agent-skills --skill '*'
Or install individual plugin groups:
```bash
npx skills add pulumi/agent-skills/migration --skill '*' # 4 migration skills
npx skills add pulumi/agent-skills/pulumi --skill '*' # 7 pulumi skills (overview + specialized)
npx skills add pulumi/agent-skills/migration --skill '*' # 5 migration skills
npx skills add pulumi/agent-skills/pulumi --skill '*' # 8 pulumi skills (overview + specialized)
npx skills add pulumi/agent-skills/delegation --skill '*' # 1 delegation skill
npx skills add pulumi/agent-skills/package-maintenance --skill '*' # 2 package-maintenance skills
```
@@ -145,7 +151,7 @@ The test loads every `use_cases.yaml` across the tree and asserts that each quer
### Skill quality review (`test_skill_quality.py`)
An LLM judge reads each `SKILL.md` and checks it against a quality rubric (description clarity and trigger precision, lean body, explains WHY not just what, progressive disclosure). The test fails on HIGH-severity findings and prints all issues including medium and low for visibility.
An LLM judge reads each `SKILL.md` and checks it against a quality rubric (description clarity and trigger precision, lean body, explains WHY not just what, progressive disclosure). The test fails on HIGH-severity findings and prints all issues (including medium and low) for visibility.
### Running locally
@@ -176,7 +182,7 @@ uv run pytest tests/ -v
4. Add `use_cases.yaml` with representative trigger queries (see [Testing](#testing) above)
5. Update this AGENTS.md file to list the new skill in the appropriate plugin section
6. Update [README.md](README.md) to add the skill to the skills table
7. Bump the containing plugin's patch version in both `<plugin>/.claude-plugin/plugin.json` and `<plugin>/.codex-plugin/plugin.json`
7. Bump the containing plugin's patch version in both `<plugin>/.claude-plugin/plugin.json` and `<plugin>/.codex-plugin/plugin.json`. For skills in an end-user group (`pulumi/`, `migration/`, `delegation/`), also bump the root combined manifests `.claude-plugin/plugin.json` and `.codex-plugin/plugin.json`, which ship the same skill
8. Submit a pull request
The skill will automatically be included in its plugin group, but installed plugin users need a plugin version bump to receive changed plugin contents. Any change under an existing plugin directory that affects shipped skills, references, agents, hooks, MCP config, or install-surface metadata must bump that plugin's version in both ecosystem manifests. Use a patch bump for skill-content and routing changes unless the change is intentionally breaking or feature-sized.
@@ -191,6 +197,8 @@ Examples:
Each plugin group ships a manifest for both Claude Code and OpenAI Codex. The skill content is shared; only the per-ecosystem manifest files differ.
If the new group is end-user facing (not maintainer tooling), also add its `skills/` directory to the `skills` lists in both root combined plugin manifests, [.claude-plugin/plugin.json](.claude-plugin/plugin.json) and [.codex-plugin/plugin.json](.codex-plugin/plugin.json), so installing `pulumi` picks it up in both ecosystems.
1. Create the plugin directory structure:
```
<plugin-name>/
+16 -11
View File
@@ -49,6 +49,7 @@ Entry-point and specialized skills for writing and operating Pulumi infrastructu
| [pulumi-component](pulumi/skills/pulumi-component) | Guide for authoring ComponentResource classes |
| [pulumi-automation-api](pulumi/skills/pulumi-automation-api) | Best practices for using Pulumi Automation API |
| [pulumi-esc](pulumi/skills/pulumi-esc) | Guidance for working with Pulumi ESC (Environments, Secrets, and Configuration) |
| [pulumi-debug-failed-operation](pulumi/skills/pulumi-debug-failed-operation) | Debug a failed `pulumi up` or `pulumi preview` from the failure Pulumi already recorded |
| [provider-upgrade](pulumi/skills/provider-upgrade) | Safe workflows for upgrading Pulumi providers without unintended infrastructure changes |
| [package-usage](pulumi/skills/package-usage) | Track which stacks across an organization use a package and at what versions |
@@ -75,15 +76,20 @@ Hand off in-progress work from coding agents to Pulumi Neo:
```bash
/plugin marketplace add pulumi/agent-skills
/plugin install pulumi-migration # Install migration skills
/plugin install pulumi # Install Pulumi skills (overview + specialized)
/plugin install pulumi-delegation # Install delegation skills (Neo handoff)
/plugin install pulumi-package-maintenance # Install provider-repo maintenance skills
/plugin install pulumi # All end-user skills: authoring, migration, and Neo handoff
```
The `pulumi` plugin bundles the authoring, migration, and delegation skill groups in one install. Prefer a subset? Install `pulumi-migration` or `pulumi-delegation` instead (not alongside `pulumi`, which already includes both). `pulumi-package-maintenance` is separate: it targets provider authors and combines fine with any of the others.
```bash
/plugin install pulumi-migration # Migration skills only
/plugin install pulumi-delegation # Neo handoff skill only
/plugin install pulumi-package-maintenance # Provider-repo maintenance skills (for provider authors)
```
#### Declarative install via `settings.json`
To register the marketplace and enable plugins automatically (for a team or CI), add this to `.claude/settings.json`. The marketplace key **must** be `pulumi-agent-skills` it has to match the `name` field in this repo's [`.claude-plugin/marketplace.json`](.claude-plugin/marketplace.json), and the same name is used as the `@<marketplace>` suffix in `enabledPlugins`:
To register the marketplace and enable plugins automatically (for a team or CI), add this to `.claude/settings.json`. The marketplace key **must** be `pulumi-agent-skills`: it has to match the `name` field in this repo's [`.claude-plugin/marketplace.json`](.claude-plugin/marketplace.json), and the same name is used as the `@<marketplace>` suffix in `enabledPlugins`:
```json
{
@@ -93,14 +99,13 @@ To register the marketplace and enable plugins automatically (for a team or CI),
}
},
"enabledPlugins": {
"pulumi-migration@pulumi-agent-skills": true,
"pulumi@pulumi-agent-skills": true,
"pulumi-delegation@pulumi-agent-skills": true,
"pulumi-package-maintenance@pulumi-agent-skills": true
"pulumi@pulumi-agent-skills": true
}
}
```
The `pulumi` plugin covers authoring, migration, and delegation. Swap in `pulumi-migration` or `pulumi-delegation` for a subset, or add `pulumi-package-maintenance` for provider-repo maintenance.
If you name the marketplace anything else (e.g. `pulumi-skills`), the plugins fail to resolve with `Plugin '…' not found in marketplace '…'`.
### OpenAI Codex
@@ -109,7 +114,7 @@ If you name the marketplace anything else (e.g. `pulumi-skills`), the plugins fa
codex plugin marketplace add pulumi/agent-skills
```
Once the marketplace is registered, install plugins from the Codex TUI: run `codex`, open the plugin marketplace with `/plugins`, and pick `pulumi-migration`, `pulumi`, `pulumi-delegation`, or `pulumi-package-maintenance`.
Once the marketplace is registered, install plugins from the Codex TUI: run `codex`, open the plugin marketplace with `/plugins`, and pick `pulumi-migration`, `pulumi`, `pulumi-delegation`, or `pulumi-package-maintenance`. As in Claude Code, `pulumi` is the combined plugin with all end-user skills; do not combine it with `pulumi-migration` or `pulumi-delegation`.
### Universal (all agents)
@@ -123,7 +128,7 @@ Or install individual plugin groups:
```bash
npx skills add pulumi/agent-skills/migration --skill '*' # 5 migration skills
npx skills add pulumi/agent-skills/pulumi --skill '*' # 7 pulumi skills (overview + specialized)
npx skills add pulumi/agent-skills/pulumi --skill '*' # 8 pulumi skills (overview + specialized)
npx skills add pulumi/agent-skills/delegation --skill '*' # 1 delegation skill
npx skills add pulumi/agent-skills/package-maintenance --skill '*' # 2 package-maintenance skills
```
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

+3 -1
View File
@@ -25,7 +25,9 @@
"category": "Coding",
"websiteURL": "https://www.pulumi.com/docs/",
"defaultPrompt": [
"Use $pulumi-neo-handoff to package the current conversation and launch a Pulumi Neo task"
"Use $pulumi-neo-handoff to package the current conversation and launch a Pulumi Neo task",
"Use $pulumi-neo-handoff to hand off this Pulumi program to Neo to preview and deploy",
"Use $pulumi-neo-handoff to continue this infrastructure debugging in Pulumi Neo"
]
}
}
+12 -6
View File
@@ -20,11 +20,15 @@ CLAUDE_REQUIRED_FIELDS = ("name", "version", "description")
def _codex_manifests() -> list[Path]:
return sorted(REPO_ROOT.glob("*/.codex-plugin/plugin.json"))
return sorted(REPO_ROOT.glob(".codex-plugin/plugin.json")) + sorted(
REPO_ROOT.glob("*/.codex-plugin/plugin.json")
)
def _claude_manifests() -> list[Path]:
return sorted(REPO_ROOT.glob("*/.claude-plugin/plugin.json"))
return sorted(REPO_ROOT.glob(".claude-plugin/plugin.json")) + sorted(
REPO_ROOT.glob("*/.claude-plugin/plugin.json")
)
def _rel(path: Path) -> str:
@@ -36,10 +40,12 @@ def test_codex_plugin_manifest(manifest: Path) -> None:
data = json.loads(manifest.read_text())
for field in CODEX_REQUIRED_FIELDS:
assert field in data, f"{_rel(manifest)}: missing field `{field}`"
skills_path = (manifest.parent.parent / data["skills"].lstrip("./")).resolve()
assert skills_path.is_dir(), (
f"{_rel(manifest)}: skills path `{data['skills']}` does not resolve to a directory"
)
skills = data["skills"]
for skills_entry in skills if isinstance(skills, list) else [skills]:
skills_path = (manifest.parent.parent / skills_entry.lstrip("./")).resolve()
assert skills_path.is_dir(), (
f"{_rel(manifest)}: skills path `{skills_entry}` does not resolve to a directory"
)
@pytest.mark.parametrize("manifest", _claude_manifests(), ids=_rel)