diff --git a/.agents/skills/plugin-creator/SKILL.md b/.agents/skills/plugin-creator/SKILL.md index 28d47b75..5c9cb206 100644 --- a/.agents/skills/plugin-creator/SKILL.md +++ b/.agents/skills/plugin-creator/SKILL.md @@ -1,6 +1,6 @@ --- name: plugin-creator -description: Create and scaffold plugin directories for Codex with a required `.codex-plugin/plugin.json`, optional plugin folders/files, and baseline placeholders you can edit before publishing or testing. Use when Codex needs to create a new local plugin, add optional plugin structure, or generate or update repo-root `.agents/plugins/marketplace.json` entries for plugin ordering and availability metadata. +description: Create and scaffold plugin directories for Codex with a required `.codex-plugin/plugin.json`, optional plugin folders/files, and baseline placeholders you can edit before publishing or testing. Use when Codex needs to create a new personal plugin, add optional plugin structure, or generate or update personal or repo-root `.agents/plugins/marketplace.json` entries for plugin ordering and availability metadata. --- # Plugin Creator @@ -13,23 +13,36 @@ description: Create and scaffold plugin directories for Codex with a required `. # Plugin names are normalized to lower-case hyphen-case and must be <= 64 chars. # The generated folder and plugin.json name are always the same. # Run from repo root (or replace .agents/... with the absolute path to this SKILL). -# By default creates in /plugins/. +# By default creates in ~/plugins/. python3 .agents/skills/plugin-creator/scripts/create_basic_plugin.py ``` 2. Open `/.codex-plugin/plugin.json` and replace `[TODO: ...]` placeholders. -3. Generate or update the repo marketplace entry when the plugin should appear in Codex UI ordering: +3. Generate or update the personal marketplace entry when the plugin should appear in Codex UI ordering: ```bash -# marketplace.json always lives at /.agents/plugins/marketplace.json +# Personal marketplace entries default to ~/.agents/plugins/marketplace.json. python3 .agents/skills/plugin-creator/scripts/create_basic_plugin.py my-plugin --with-marketplace ``` +If the current Git repo already has `.agents/plugins/marketplace.json` and the user has not said +whether the plugin is personal or shared with their team, ask before generating a marketplace entry. +When they choose the repo marketplace, use: + +```bash +python3 .agents/skills/plugin-creator/scripts/create_basic_plugin.py my-plugin \ + --path ./plugins \ + --marketplace-path ./.agents/plugins/marketplace.json \ + --with-marketplace +``` + 4. Generate/adjust optional companion folders as needed: ```bash -python3 .agents/skills/plugin-creator/scripts/create_basic_plugin.py my-plugin --path \ +python3 .agents/skills/plugin-creator/scripts/create_basic_plugin.py my-plugin \ + --path \ + --marketplace-path \ --with-skills --with-hooks --with-scripts --with-assets --with-mcp --with-apps --with-marketplace ``` @@ -37,10 +50,14 @@ python3 .agents/skills/plugin-creator/scripts/create_basic_plugin.py my-plugin - ## What this skill creates +- Default marketplace-backed scaffolds are personal: `~/plugins//` plus + `~/.agents/plugins/marketplace.json`. +- If the current Git repo already has `.agents/plugins/marketplace.json` and the user has not said + personal vs team, ask which marketplace to update before generating a marketplace entry. - Creates plugin root at `///`. - Always creates `///.codex-plugin/plugin.json`. - Fills the manifest with the full schema shape, placeholder values, and the complete `interface` section. -- Creates or updates `/.agents/plugins/marketplace.json` when `--with-marketplace` is set. +- Creates or updates the selected marketplace when `--with-marketplace` is set. - If the marketplace file does not exist yet, seed top-level `name` plus `interface.displayName` placeholders before adding the first plugin entry. - `` is normalized using skill-creator naming rules: - `My Plugin` → `my-plugin` @@ -57,7 +74,8 @@ python3 .agents/skills/plugin-creator/scripts/create_basic_plugin.py my-plugin - ## Marketplace workflow -- `marketplace.json` always lives at `/.agents/plugins/marketplace.json`. +- Personal plugins use `~/.agents/plugins/marketplace.json`. +- Repo/team plugins use `/.agents/plugins/marketplace.json`. - Marketplace root metadata supports top-level `name` plus optional `interface.displayName`. - Treat plugin order in `plugins[]` as render order in Codex. Append new entries unless a user explicitly asks to reorder the list. - `displayName` belongs inside the marketplace `interface` object, not individual `plugins[]` entries. @@ -95,7 +113,7 @@ python3 .agents/skills/plugin-creator/scripts/create_basic_plugin.py my-plugin - ``` - Use `--force` only when intentionally replacing an existing marketplace entry for the same plugin name. -- If `/.agents/plugins/marketplace.json` does not exist yet, create it with top-level `"name"`, an `"interface"` object containing `"displayName"`, and a `plugins` array, then add the new entry. +- If the selected marketplace file does not exist yet, create it with top-level `"name"`, an `"interface"` object containing `"displayName"`, and a `plugins` array, then add the new entry. - For a brand-new marketplace file, the root object should look like: @@ -131,7 +149,16 @@ python3 .agents/skills/plugin-creator/scripts/create_basic_plugin.py my-plugin - - Preserve any existing marketplace `interface.displayName`. - When generating marketplace entries, always write `policy.installation`, `policy.authentication`, and `category` even if their values are defaults. - Add `policy.products` only when the user explicitly asks for that override. -- Keep marketplace `source.path` relative to repo root as `./plugins/`. +- Keep marketplace `source.path` relative to the selected marketplace root as `./plugins/`. +- When the workflow created or updated a marketplace-backed plugin, end the final user-facing + response with these two Markdown links, in this order, and do not add any text after them: + - `[View ](codex://plugins/view-local?marketplacePath=&pluginName=)` + - `[Share ](codex://plugins/share-local?marketplacePath=&pluginName=)` +- Replace the link-label placeholder and both deeplink placeholders with the real normalized plugin + name plus the real absolute marketplace path from the scaffolded plugin. URL-encode query + parameter values when needed. +- Do not emit the `View ` or `Share ` links when no marketplace entry was + created or updated. ## Reference to exact spec sample diff --git a/.agents/skills/plugin-creator/references/plugin-json-spec.md b/.agents/skills/plugin-creator/references/plugin-json-spec.md index ba0f04cd..ee66dfe4 100644 --- a/.agents/skills/plugin-creator/references/plugin-json-spec.md +++ b/.agents/skills/plugin-creator/references/plugin-json-spec.md @@ -97,7 +97,10 @@ # Marketplace JSON sample spec -`marketplace.json` always lives at `/.agents/plugins/marketplace.json`. +`marketplace.json` depends on where the plugin should live: + +- Personal plugin: `~/.agents/plugins/marketplace.json` +- Repo/team plugin: `/.agents/plugins/marketplace.json` ```json { @@ -112,8 +115,10 @@ "source": "local", "path": "./plugins/linear" }, - "installPolicy": "AVAILABLE", - "authPolicy": "ON_INSTALL", + "policy": { + "installation": "AVAILABLE", + "authentication": "ON_INSTALL" + }, "category": "Productivity" } ] @@ -137,7 +142,11 @@ - `name` (`string`): Plugin identifier. Match the plugin folder name and `plugin.json` `name`. - `source` (`object`): Plugin source descriptor. - `source` (`string`): Use `local` for this repo workflow. - - `path` (`string`): Relative plugin path, always `./plugins/`. + - `path` (`string`): Relative plugin path based on the marketplace root. + - Personal plugin in `~/.agents/plugins/marketplace.json`: `./plugins/` + - Repo/team plugin: `./plugins/` + - The same relative path convention is used for both personal and repo/team marketplaces. + - Example: with `~/.agents/plugins/marketplace.json`, `./plugins/` resolves to `~/plugins/`. - `policy` (`object`): Marketplace policy block. Always include it. - `installation` (`string`): Availability policy. - Allowed values: `NOT_AVAILABLE`, `AVAILABLE`, `INSTALLED_BY_DEFAULT` @@ -156,3 +165,9 @@ - Treat `policy.products` as an override and omit it unless explicitly requested. - Append new entries unless the user explicitly requests reordering. - Replace an existing entry for the same plugin only when overwrite is intentional. +- Default new plugin creation to the personal marketplace. +- If the current Git repo already has `.agents/plugins/marketplace.json` and the user has not said + personal or team, ask which marketplace to update before creating the entry. +- Choose marketplace location to match the selected destination: + - Personal plugin: `~/.agents/plugins/marketplace.json` + - Repo/team plugin: `/.agents/plugins/marketplace.json` diff --git a/.agents/skills/plugin-creator/scripts/create_basic_plugin.py b/.agents/skills/plugin-creator/scripts/create_basic_plugin.py index 020ad676..dcb24562 100755 --- a/.agents/skills/plugin-creator/scripts/create_basic_plugin.py +++ b/.agents/skills/plugin-creator/scripts/create_basic_plugin.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -"""Scaffold a plugin directory and optionally update repo-root marketplace.json.""" +"""Scaffold a plugin directory and optionally update marketplace.json.""" from __future__ import annotations @@ -11,8 +11,8 @@ MAX_PLUGIN_NAME_LENGTH = 64 -DEFAULT_PLUGIN_PARENT = Path(__file__).resolve().parents[4] / "plugins" -DEFAULT_MARKETPLACE_PATH = Path(__file__).resolve().parents[2] / "plugins" / "marketplace.json" +DEFAULT_PLUGIN_PARENT = Path.home() / "plugins" +DEFAULT_MARKETPLACE_PATH = Path.home() / ".agents" / "plugins" / "marketplace.json" DEFAULT_INSTALL_POLICY = "AVAILABLE" DEFAULT_AUTH_POLICY = "ON_INSTALL" DEFAULT_CATEGORY = "Productivity" @@ -191,7 +191,10 @@ def parse_args() -> argparse.Namespace: parser.add_argument( "--path", default=str(DEFAULT_PLUGIN_PARENT), - help="Parent directory for plugin creation (defaults to /plugins)", + help=( + "Parent directory for plugin creation (defaults to /plugins). " + "Use /plugins when creating a repo/team plugin." + ), ) parser.add_argument("--with-skills", action="store_true", help="Create skills/ directory") parser.add_argument("--with-hooks", action="store_true", help="Create hooks/ directory") @@ -202,12 +205,19 @@ def parse_args() -> argparse.Namespace: parser.add_argument( "--with-marketplace", action="store_true", - help="Create or update repo-root .agents/plugins/marketplace.json", + help=( + "Create or update /.agents/plugins/marketplace.json by default. " + "Marketplace entries always point to ./plugins/ relative to the " + "marketplace root." + ), ) parser.add_argument( "--marketplace-path", default=str(DEFAULT_MARKETPLACE_PATH), - help="Path to marketplace.json (defaults to /.agents/plugins/marketplace.json)", + help=( + "Path to marketplace.json (defaults to /.agents/plugins/marketplace.json). " + "Use /.agents/plugins/marketplace.json for a repo/team plugin." + ), ) parser.add_argument( "--install-policy",