Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ go build -o bin/plugin-kit-ai ./cli/cmd/plugin-kit-ai
| OpenCode workspace-config lane | `opencode` |
| Cursor plugin package lane | `cursor` |
| Qoder plugin package lane | `qoder` |
| Grok plugin package lane | `grok` |
| Kimi plugin package lane | `kimi` |

Choose the lane that matches the delivery model you need today. Expand later from the same repo when the product needs more outputs.

Expand Down Expand Up @@ -178,7 +180,7 @@ For migrating current Claude/Codex/Gemini/OpenCode/Cursor native files into the

Current behavior and contract details:

- `init`: package-standard scaffold for `codex-runtime`, `codex-package`, `claude`, `gemini`, `opencode`, or `cursor`; launcher-based targets support Go-first or executable runtimes, Gemini defaults to launcher-less packaging but also supports `--runtime go` for the promoted 9-hook runtime lane, while Codex package, OpenCode, and Cursor stay launcher-less; Codex package extras now include first-class `interface.json`, `app.json`, and `manifest.extra.json` starters alongside richer package metadata authoring, and the empty Codex app starter stays inactive until you replace it with a real app manifest
- `init`: package-standard scaffold for `codex-runtime`, `codex-package`, `claude`, `gemini`, `opencode`, `cursor`, `qoder`, `grok`, or `kimi`; launcher-based targets support Go-first or executable runtimes, Gemini defaults to launcher-less packaging but also supports `--runtime go` for the promoted 9-hook runtime lane, while Codex package, OpenCode, Cursor, Qoder, Grok, and Kimi stay launcher-less; Codex package extras now include first-class `interface.json`, `app.json`, and `manifest.extra.json` starters alongside richer package metadata authoring, and the empty Codex app starter stays inactive until you replace it with a real app manifest
- `bootstrap`: stable repo-local first-run helper for `python` and `node` launcher-based projects on `codex-runtime` and `claude`; `public-beta` for `shell`; no-op for `go`, `codex-package`, and `gemini`
- `doctor`: stable read-only readiness check for `python` and `node` launcher-based projects on `codex-runtime` and `claude`; `public-beta` for `shell`
- `dev`: `public-beta` watch loop for launcher-based runtime targets; auto-generates, performs runtime-aware rebuilds, runs strict validation, and reruns the selected stable fixtures; supports `--once` for a single cycle
Expand All @@ -198,8 +200,11 @@ Current behavior and contract details:
- `init --platform gemini`: richer packaging starter with `targets/gemini/package.yaml` and `targets/gemini/contexts/GEMINI.md`; add `--runtime go` for the optional Gemini Go production-ready 9-hook runtime lane
- `init --platform opencode`: workspace-config starter with `targets/opencode/package.yaml`, optional OpenCode command/agent/theme starters, and an OpenCode-compatible skill stub when `--extras` is used; OpenCode extras now use official-style named async plugin exports, and helper-based custom tools belong in `targets/opencode/package.json`; no launcher/runtime scaffold
- `init --platform cursor`: packaged Cursor plugin starter with `plugin/plugin.yaml`, root boundary docs `CLAUDE.md` and `AGENTS.md`, optional portable `plugin/mcp/servers.yaml` and `plugin/skills/**` when `--extras` is used, and generated `.cursor-plugin/plugin.json`; `cursor-workspace` stays the secondary repo-local `.cursor/` config lane
- `generate`: generate native Claude artifacts, Codex package/runtime lane artifacts, Gemini CLI extension packaging artifacts, OpenCode workspace config artifacts, packaged Cursor plugin artifacts, and the secondary Cursor workspace config artifacts from canonical `plugin/plugin.yaml`, optional `plugin/mcp/servers.yaml`, optional `plugin/skills/**`, and `plugin/targets/<platform>/...`. When `plugin/publish/codex/marketplace.yaml` is authored for `codex-package`, `generate` also produces repo-level `.agents/plugins/marketplace.json`, and when `plugin/publish/claude/marketplace.yaml` is authored for `claude`, `generate` also produces `.claude-plugin/marketplace.json`
- `import`: create the package-standard authored layout from current native Claude/Codex/Gemini/OpenCode/Cursor artifacts; Gemini import preserves the extension package lane and optional Go runtime metadata when present, OpenCode import remains workspace-config-only with explicit `--include-user-scope` support for home-dir OpenCode sources, and Cursor import remains workspace-config-only for the documented `.cursor` subset
- `init --platform qoder`: packaged Qoder plugin starter with `plugin/plugin.yaml`, root boundary docs, optional portable `plugin/mcp/servers.yaml` and `plugin/skills/**` when `--extras` is used, and generated `.qoder-plugin/plugin.json`
- `init --platform grok`: packaged Grok plugin starter with `plugin/plugin.yaml`, root boundary docs, optional portable `plugin/mcp/servers.yaml` and `plugin/skills/**` when `--extras` is used, and generated `.grok-plugin/plugin.json`; portable MCP is projected as a wrapped `.mcp.json` sidecar referenced from the manifest
- `init --platform kimi`: packaged Kimi plugin starter with `plugin/plugin.yaml`, root boundary docs, optional portable `plugin/mcp/servers.yaml` and `plugin/skills/**` when `--extras` is used, and generated `.kimi-plugin/plugin.json`; Kimi requires MCP servers inline in the manifest and does not resolve external MCP file refs
- `generate`: generate native Claude artifacts, Codex package/runtime lane artifacts, Gemini CLI extension packaging artifacts, OpenCode workspace config artifacts, packaged Cursor plugin artifacts, the secondary Cursor workspace config artifacts, packaged Qoder plugin artifacts, packaged Grok plugin artifacts, and packaged Kimi plugin artifacts from canonical `plugin/plugin.yaml`, optional `plugin/mcp/servers.yaml`, optional `plugin/skills/**`, and `plugin/targets/<platform>/...`. When `plugin/publish/codex/marketplace.yaml` is authored for `codex-package`, `generate` also produces repo-level `.agents/plugins/marketplace.json`, and when `plugin/publish/claude/marketplace.yaml` is authored for `claude`, `generate` also produces `.claude-plugin/marketplace.json`
- `import`: create the package-standard authored layout from current native Claude/Codex/Gemini/OpenCode/Cursor/Qoder/Grok/Kimi artifacts; Gemini import preserves the extension package lane and optional Go runtime metadata when present, OpenCode import remains workspace-config-only with explicit `--include-user-scope` support for home-dir OpenCode sources, Cursor import remains workspace-config-only for the documented `.cursor` subset, and Grok/Kimi import recovers portable skills plus portable MCP from the packaged plugin manifests
- `inspect`: explain the discovered package graph, target class, managed artifacts, and the publication summary; `--format json` now includes a `publication` block with publication-capable package targets and any authored `publish/...` channels discovered in the repo, including channel metadata such as Codex policies and Gemini gallery distribution hints
- `publish`: first-class bounded publish workflow for documented publication channels; `publish --channel codex-marketplace|claude-marketplace --dest <marketplace-root>` materializes the corresponding local marketplace root, `--dry-run` previews the write, `publish --channel gemini-gallery --dry-run` emits a repository/release publication plan with bounded Git and GitHub readiness diagnostics instead of pretending Gemini has a local marketplace-root flow, `publish --all --dry-run` orchestrates all authored `publish/...` channels in one combined plan, and `publish --format json` emits the versioned `plugin-kit-ai/publish-report` contract; `publish --all` apply mode stays intentionally absent because local materialization channels and repository/release planning channels still have different execution semantics
- `publication`: focused publication-layer view for package-capable targets and authored `publish/...` channels; use it when you want only package/channel publication data without the broader inspect surface; `publication --format json` emits the versioned `plugin-kit-ai/publication-report` contract, `publication doctor --format json` emits `plugin-kit-ai/publication-doctor-report` for readiness gating, `publication doctor --dest <marketplace-root>` also verifies an already materialized local Codex/Claude marketplace root, `publication materialize --target codex-package|claude --dest <marketplace-root>` builds a safe local marketplace root with a copied package bundle plus merged catalog artifact, `publication remove --target codex-package|claude --dest <marketplace-root>` prunes that materialized plugin back out of the local marketplace root, and `--dry-run` on materialize/remove previews those local marketplace mutations without writing
Expand Down Expand Up @@ -251,6 +256,9 @@ Production-ready target boundary in the current contract:
- Gemini: full Gemini CLI extension lane through `generate|import|validate` and local `extensions link|config|disable|enable`, plus an optional production-ready Go runtime lane for `SessionStart`, `SessionEnd`, `BeforeModel`, `AfterModel`, `BeforeToolSelection`, `BeforeAgent`, `AfterAgent`, `BeforeTool`, and `AfterTool`, with dedicated opt-in real CLI runtime smoke via `make test-gemini-runtime-live`
- OpenCode: workspace-config-only lane through `generate|import|validate`, package refs, inline MCP, validated portable skills, first-class workspace commands/agents/themes, beta standalone tools, stable local plugin code plus stable shared package metadata for tools and plugins, JSON/JSONC plus explicit user-scope import, permission-first passthrough config semantics, and beta `custom_tools` spanning standalone tools and plugin code
- Cursor: packaged plugin lane through `generate|import|validate`, `.cursor-plugin/plugin.json`, root `skills/**`, and optional shared `.mcp.json`, with `cursor-workspace` retained only as the secondary repo-local `.cursor/` subset
- Qoder: packaged plugin lane through `generate|import|validate`, `.qoder-plugin/plugin.json`, root `skills/**`, and optional shared `.mcp.json`
- Grok: packaged plugin lane through `generate|import|validate`, `.grok-plugin/plugin.json`, root `skills/**`, and optional wrapped `.mcp.json` sidecar
- Kimi: packaged plugin lane through `generate|import|validate`, `.kimi-plugin/plugin.json` (root `kimi.plugin.json` wins when both exist), root `skills/**`, and inline-only `mcpServers`

Canonical production plugin lane:

Expand Down
4 changes: 2 additions & 2 deletions cli/cmd/plugin-kit-ai/compat.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,9 @@ func newCompatCmd(runner compatRunner) *cobra.Command {
}
},
}
cmd.Flags().StringVar(&compatTarget, "target", "all", `compatibility target ("all", "claude", "codex-package", "codex-runtime", "gemini", "opencode", "cursor", "cursor-workspace", or "qoder")`)
cmd.Flags().StringVar(&compatTarget, "target", "all", `compatibility target ("all", "claude", "codex-package", "codex-runtime", "gemini", "opencode", "cursor", "cursor-workspace", "qoder", "grok", or "kimi")`)
cmd.Flags().StringVar(&compatFormat, "format", "text", "output format: text or json")
cmd.Flags().StringVar(&compatFrom, "from", "", `source platform ("claude", "codex-package", "codex-runtime", "gemini", "opencode", "cursor", "cursor-workspace", or "qoder"; omit to auto-detect current native layouts)`)
cmd.Flags().StringVar(&compatFrom, "from", "", `source platform ("claude", "codex-package", "codex-runtime", "gemini", "opencode", "cursor", "cursor-workspace", "qoder", "grok", or "kimi"; omit to auto-detect current native layouts)`)
cmd.Flags().BoolVar(&compatIncludeUserScope, "include-user-scope", false, "include explicit user-scope native sources when supported by the detected import target")
return cmd
}
Expand Down
2 changes: 1 addition & 1 deletion cli/cmd/plugin-kit-ai/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,6 @@ Cursor generation now defaults to the packaged plugin lane: it produces .cursor-
}

func init() {
generateCmd.Flags().StringVar(&generateTarget, "target", "all", `generate target ("all", "claude", "codex-package", "codex-runtime", "gemini", "opencode", "cursor", "cursor-workspace", or "qoder")`)
generateCmd.Flags().StringVar(&generateTarget, "target", "all", `generate target ("all", "claude", "codex-package", "codex-runtime", "gemini", "opencode", "cursor", "cursor-workspace", "qoder", "grok", or "kimi")`)
generateCmd.Flags().BoolVar(&generateCheck, "check", false, "fail if generated artifacts are out of date")
}
2 changes: 1 addition & 1 deletion cli/cmd/plugin-kit-ai/import.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ Use --source to import from a remote or external source reference such as github

func init() {
importCmd.Flags().StringVar(&importSource, "source", "", "native source reference to import from (local path, github:owner/repo@ref//subdir, or git URL with optional #ref)")
importCmd.Flags().StringVar(&importFrom, "from", "", `source platform ("claude", "codex-package", "codex-runtime", "gemini", "opencode", "cursor", "cursor-workspace", or "qoder"; omit to auto-detect current native layouts)`)
importCmd.Flags().StringVar(&importFrom, "from", "", `source platform ("claude", "codex-package", "codex-runtime", "gemini", "opencode", "cursor", "cursor-workspace", "qoder", "grok", or "kimi"; omit to auto-detect current native layouts)`)
importCmd.Flags().BoolVarP(&importForce, "force", "f", false, "overwrite plugin/plugin.yaml if it already exists")
importCmd.Flags().BoolVar(&importIncludeUserScope, "include-user-scope", false, "include explicit user-scope native sources when supported by the import target")
}
4 changes: 2 additions & 2 deletions cli/cmd/plugin-kit-ai/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ Already have native config:

Public flags:
--template Recommended start: "online-service", "local-tool", or "custom-logic".
--platform Advanced override: "codex-runtime" (default), "codex-package", "claude", "gemini", "opencode", "cursor", "cursor-workspace", or "qoder".
--platform Advanced override: "codex-runtime" (default), "codex-package", "claude", "gemini", "opencode", "cursor", "cursor-workspace", "qoder", "grok", or "kimi".
--runtime Supported: "go" (default), "python", "node", "shell" for launcher-based targets only.
--typescript Generate a TypeScript scaffold on top of the node runtime lane (requires --runtime node).
--runtime-package
Expand All @@ -74,7 +74,7 @@ func newInitCmd(runner initCommandRunner) *cobra.Command {
},
}
cmd.Flags().StringVar(&flags.template, "template", "", `recommended start ("online-service", "local-tool", or "custom-logic")`)
cmd.Flags().StringVar(&flags.platform, "platform", "codex-runtime", `target lane ("codex-runtime", "codex-package", "claude", "gemini", "opencode", "cursor", "cursor-workspace", or "qoder")`)
cmd.Flags().StringVar(&flags.platform, "platform", "codex-runtime", `target lane ("codex-runtime", "codex-package", "claude", "gemini", "opencode", "cursor", "cursor-workspace", "qoder", "grok", or "kimi")`)
cmd.Flags().StringVar(&flags.runtime, "runtime", "go", `runtime ("go", "python", "node", or "shell")`)
cmd.Flags().BoolVar(&flags.typescript, "typescript", false, "generate a TypeScript scaffold on top of the node runtime lane")
cmd.Flags().BoolVar(&flags.runtimePackage, "runtime-package", false, "for --runtime python or --runtime node, import the shared plugin-kit-ai-runtime package instead of vendoring the helper file")
Expand Down
4 changes: 3 additions & 1 deletion cli/cmd/plugin-kit-ai/init_run.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ func runInit(cmd *cobra.Command, runner initCommandRunner, flags initFlagState,
strings.EqualFold(strings.TrimSpace(flags.platform), "opencode") ||
strings.EqualFold(strings.TrimSpace(flags.platform), "cursor") ||
strings.EqualFold(strings.TrimSpace(flags.platform), "cursor-workspace") ||
strings.EqualFold(strings.TrimSpace(flags.platform), "qoder")) &&
strings.EqualFold(strings.TrimSpace(flags.platform), "qoder") ||
strings.EqualFold(strings.TrimSpace(flags.platform), "grok") ||
strings.EqualFold(strings.TrimSpace(flags.platform), "kimi")) &&
!cmd.Flags().Changed("runtime") {
runtime = ""
}
Expand Down
2 changes: 1 addition & 1 deletion cli/cmd/plugin-kit-ai/init_success.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func formatInitSuccess(outDir string, opts app.InitOptions) string {
return strings.Join(lines, "\n") + "\n"
}

if platform == "gemini" || platform == "codex-package" || platform == "opencode" || platform == "cursor" || platform == "cursor-workspace" || platform == "qoder" {
if platform == "gemini" || platform == "codex-package" || platform == "opencode" || platform == "cursor" || platform == "cursor-workspace" || platform == "qoder" || platform == "grok" || platform == "kimi" {
if opts.Extras {
lines = append(lines, " Portable MCP starter: plugin/mcp/servers.yaml")
}
Expand Down
26 changes: 25 additions & 1 deletion cli/cmd/plugin-kit-ai/init_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func TestInitHelpIncludesScenarioLanesAndDefaults(t *testing.T) {
"Already have native config",
"plugin-kit-ai import",
`--template Recommended start: "online-service", "local-tool", or "custom-logic".`,
`--platform Advanced override: "codex-runtime" (default), "codex-package", "claude", "gemini", "opencode", "cursor", "cursor-workspace", or "qoder".`,
`--platform Advanced override: "codex-runtime" (default), "codex-package", "claude", "gemini", "opencode", "cursor", "cursor-workspace", "qoder", "grok", or "kimi".`,
`--runtime Supported: "go" (default), "python", "node", "shell" for launcher-based targets only.`,
"--typescript Generate a TypeScript scaffold on top of the node runtime lane",
"--runtime-package",
Expand Down Expand Up @@ -217,6 +217,30 @@ func TestInitSuccessOutputByLane(t *testing.T) {
"See plugin/README.md for the full first run",
},
},
{
name: "grok",
args: []string{"demo", "--platform", "grok"},
wantRuntime: "",
wantPlatform: "grok",
want: []string{
"plugin-kit-ai generate .",
"plugin-kit-ai generate --check .",
"plugin-kit-ai validate . --platform grok --strict",
"See plugin/README.md for the full first run",
},
},
{
name: "kimi",
args: []string{"demo", "--platform", "kimi"},
wantRuntime: "",
wantPlatform: "kimi",
want: []string{
"plugin-kit-ai generate .",
"plugin-kit-ai generate --check .",
"plugin-kit-ai validate . --platform kimi --strict",
"See plugin/README.md for the full first run",
},
},
{
name: "config-lane-extras",
args: []string{"demo", "--platform", "cursor", "--extras"},
Expand Down
2 changes: 1 addition & 1 deletion cli/cmd/plugin-kit-ai/inspect.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func newInspectCmd(runner inspectRunner) *cobra.Command {
}
},
}
cmd.Flags().StringVar(&inspectTarget, "target", "all", `inspect target ("all", "claude", "codex-package", "codex-runtime", "gemini", "opencode", "cursor", "cursor-workspace", or "qoder")`)
cmd.Flags().StringVar(&inspectTarget, "target", "all", `inspect target ("all", "claude", "codex-package", "codex-runtime", "gemini", "opencode", "cursor", "cursor-workspace", "qoder", "grok", or "kimi")`)
cmd.Flags().StringVar(&inspectFormat, "format", "text", "output format: text or json")
cmd.Flags().BoolVar(&inspectAuthoring, "authoring", false, "show a plain-language authoring view instead of the raw contract view")
return cmd
Expand Down
4 changes: 4 additions & 0 deletions cli/cmd/plugin-kit-ai/inspect_authoring_summary.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ func inspectAuthoringTargetLabel(target string) string {
return "Cursor workspace (cursor-workspace)"
case "qoder":
return "Qoder (qoder)"
case "grok":
return "Grok Build (grok)"
case "kimi":
return "Kimi Code (kimi)"
default:
trimmed := strings.TrimSpace(target)
if trimmed == "" {
Expand Down
2 changes: 1 addition & 1 deletion cli/cmd/plugin-kit-ai/release_compat.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ func rejectV1(in commands.Invocation) error {
for _, value := range in.Values["target"] {
for _, target := range strings.Split(value, ",") {
switch target {
case "claude", "codex", "gemini", "opencode", "cursor", "qoder":
case "claude", "codex", "gemini", "opencode", "cursor", "qoder", "grok", "kimi":
default:
supported = false
}
Expand Down
2 changes: 1 addition & 1 deletion cli/cmd/plugin-kit-ai/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ explicit outcome of "passed", "failed", or "failed_strict_warnings".`,
},
}

cmd.Flags().StringVar(&platform, "platform", "", `target override ("codex-package", "codex-runtime", "claude", "gemini", "opencode", "cursor", "cursor-workspace", or "qoder")`)
cmd.Flags().StringVar(&platform, "platform", "", `target override ("codex-package", "codex-runtime", "claude", "gemini", "opencode", "cursor", "cursor-workspace", "qoder", "grok", or "kimi")`)
cmd.Flags().BoolVar(&strict, "strict", false, "treat validation warnings as errors")
cmd.Flags().StringVar(&format, "format", "text", `output format ("text" or "json")`)
return cmd
Expand Down
Loading
Loading