From e116784c515ac799530a5c1706319ab00e41a937 Mon Sep 17 00:00:00 2001 From: Sirine Jnayeh Date: Thu, 15 Oct 2026 19:50:18 +0000 Subject: [PATCH 01/22] feat(pstack): package pstack as a Claude Code plugin Partial cherry-pick of d4d1e65 from #629. It keeps the Claude Code manifest, the marketplace entry, and the README install lines. The manifest version matches the other two manifests. Co-Authored-By: Claude Opus 5.5 --- .claude-plugin/marketplace.json | 5 +++++ pstack/.claude-plugin/plugin.json | 21 +++++++++++++++++++++ pstack/README.md | 11 ++++++++++- 3 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 pstack/.claude-plugin/plugin.json diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 8d18083d7..d1562a0db 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -9,6 +9,11 @@ "name": "origin-apps", "source": "./origin-apps", "description": "Skills for building on the Cursor Origin API. Fetch the live spec first, then follow the Origin rules for credentials, scopes, webhooks, paging, and errors. Includes a skill that plans the port of an existing GitHub App." + }, + { + "name": "pstack", + "source": "./pstack", + "description": "if you want to go fast, go deep first. pstack helps you write less, but higher quality code. rigorous agent workflows you can parallelize with confidence." } ] } diff --git a/pstack/.claude-plugin/plugin.json b/pstack/.claude-plugin/plugin.json new file mode 100644 index 000000000..0f3efea00 --- /dev/null +++ b/pstack/.claude-plugin/plugin.json @@ -0,0 +1,21 @@ +{ + "name": "pstack", + "description": "if you want to go fast, go deep first. pstack helps you write less, but higher quality code. rigorous agent workflows you can parallelize with confidence.", + "version": "0.15.25", + "author": { + "name": "Lauren Tan" + }, + "homepage": "https://github.com/cursor/plugins/tree/main/pstack", + "repository": "https://github.com/cursor/plugins", + "license": "MIT", + "keywords": [ + "pstack", + "poteto-mode", + "workflow", + "principles", + "agent-style", + "subagents", + "unslop" + ], + "skills": "./skills/" +} diff --git a/pstack/README.md b/pstack/README.md index 4e8b8c2a6..379d34f19 100644 --- a/pstack/README.md +++ b/pstack/README.md @@ -18,6 +18,15 @@ fork it. improve it. make it yours. PRs are welcome! /add-plugin pstack ``` +in claude code: + +```bash +/plugin marketplace add cursor/plugins +/plugin install pstack@cursor-plugins +``` + +claude code prefixes plugin commands and agents, so `/poteto-mode` is `/pstack:poteto-mode`. + ## get started two steps: @@ -267,7 +276,7 @@ when a default changes, a rule written before the change still pins the old defa pstack also ships a dormant [benny automation pack](./automations/benny/). benny triages slack issue reports, then reproduces and fixes confirmed bugs with real ui evidence. its files are not registered as slash skills. -to set it up, point cursor at [`FOR_AGENTS.md`](./automations/benny/FOR_AGENTS.md). setup copies the pack into the target repository at `.cursor/automations/benny/`, enables pstack there for shared skills, and keeps user configuration outside the copied pack. +to set it up, point cursor at [`FOR_AGENTS.md`](./automations/benny/FOR_AGENTS.md). setup copies the pack into the target repository at `.cursor/automations/benny/`, enables pstack there for shared skills, and keeps user configuration outside the copied pack. benny runs on cursor automations, so it is cursor-only. ## license From 3cda87125c8bf9b032eb9129faffcf9c84a87e10 Mon Sep 17 00:00:00 2001 From: Sirine Jnayeh Date: Thu, 15 Oct 2026 19:50:18 +0000 Subject: [PATCH 02/22] ci: check Claude Code marketplace entries and manifest version sync Partial cherry-pick of 8543ac8 from #629. It keeps the validate-plugins.mjs checks. The workflow change is left out, as #629 also reverted it in 6bcc06b, so the comment that says CI runs `claude plugin validate` is dropped too. Co-Authored-By: Claude Opus 5.5 --- scripts/validate-plugins.mjs | 57 +++++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/scripts/validate-plugins.mjs b/scripts/validate-plugins.mjs index 6a7870854..e08a5f205 100644 --- a/scripts/validate-plugins.mjs +++ b/scripts/validate-plugins.mjs @@ -92,7 +92,62 @@ for (const entry of marketplace.plugins ?? []) { } } -// 3. Report results +// 3. Validate the Claude Code marketplace entries. +const claudeMarketplacePath = resolve(root, ".claude-plugin/marketplace.json"); +const claudeMarketplace = existsSync(claudeMarketplacePath) + ? loadJSON(claudeMarketplacePath) + : { plugins: [] }; + +for (const entry of claudeMarketplace.plugins ?? []) { + const pluginDir = resolve(root, entry.source); + const pluginJsonPath = resolve(pluginDir, ".claude-plugin/plugin.json"); + + if (!existsSync(pluginJsonPath)) { + fail( + `Plugin "${entry.name}": missing .claude-plugin/plugin.json in "${entry.source}"` + ); + continue; + } + + const pluginJson = loadJSON(pluginJsonPath); + if (pluginJson.name && pluginJson.name !== entry.name) { + fail( + `Plugin "${entry.name}": Claude marketplace name does not match .claude-plugin/plugin.json name "${pluginJson.name}"` + ); + } +} + +// 4. Check that every manifest of a plugin carries the same version, so a +// bump never reaches one harness and misses another. +const manifestPaths = [ + ".cursor-plugin/plugin.json", + ".claude-plugin/plugin.json", + "plugin.json", +]; +const sources = new Map(); +for (const entry of [ + ...(marketplace.plugins ?? []), + ...(claudeMarketplace.plugins ?? []), +]) { + sources.set(resolve(root, entry.source), entry.name); +} + +for (const [pluginDir, name] of sources) { + const versions = manifestPaths + .map((path) => resolve(pluginDir, path)) + .filter((path) => existsSync(path)) + .map((path) => ({ path, version: loadJSON(path).version })) + .filter(({ version }) => version !== undefined); + + if (new Set(versions.map(({ version }) => version)).size > 1) { + fail(`Plugin "${name}": manifest versions differ:`); + for (const { path, version } of versions) { + console.error(` ${path.slice(root.length + 1)}: ${version}`); + } + } +} + +// 5. Report results if (errors > 0) { console.error(`\nValidation failed with ${errors} error(s).`); process.exit(1); From 7beea8825c64a61a6502000302c70b508127871f Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Thu, 15 Oct 2026 19:57:58 +0000 Subject: [PATCH 03/22] feat(pstack): add Claude Code and Codex adapters and a harness check The check fails on this tree until the next commit runs it with --fix. --- pstack/README.md | 2 +- pstack/docs/harness/claude-code.md | 50 +++++++++++ pstack/docs/harness/codex.md | 52 ++++++++++++ scripts/check-pstack-harness.mjs | 128 +++++++++++++++++++++++++++++ 4 files changed, 231 insertions(+), 1 deletion(-) create mode 100644 pstack/docs/harness/claude-code.md create mode 100644 pstack/docs/harness/codex.md create mode 100644 scripts/check-pstack-harness.mjs diff --git a/pstack/README.md b/pstack/README.md index 379d34f19..b16020bac 100644 --- a/pstack/README.md +++ b/pstack/README.md @@ -25,7 +25,7 @@ in claude code: /plugin install pstack@cursor-plugins ``` -claude code prefixes plugin commands and agents, so `/poteto-mode` is `/pstack:poteto-mode`. +claude code prefixes plugin commands and agents, so `/poteto-mode` is `/pstack:poteto-mode`. the [claude code adapter](./docs/harness/claude-code.md) maps every other cursor name. ## get started diff --git a/pstack/docs/harness/claude-code.md b/pstack/docs/harness/claude-code.md new file mode 100644 index 000000000..0f8a81804 --- /dev/null +++ b/pstack/docs/harness/claude-code.md @@ -0,0 +1,50 @@ +# pstack in Claude Code + +pstack skills use Cursor names. In Claude Code, read this file once per session, then map each Cursor name in a skill with the tables below. `` means the folder that holds `skills/` and `docs/`. If a Cursor field has no row, drop it and say so. Never pass a field or value the tool schema rejects. + +## Tools + +| Cursor | Claude Code | +| --- | --- | +| `Task` | `Agent` | +| `AskQuestion` | `AskUserQuestion`. In `-p` mode it is absent, so ask in plain text. | +| Open a todolist | Use `TodoWrite` if the session offers it. Otherwise keep the list in your reply and update it at each phase. | +| Run another pstack skill (`/name` or "the **name** skill") | `Read` `/skills//SKILL.md` and follow it. The `Skill` tool refuses most pstack skills. When you tell the user to type it, write `/pstack:`. | +| `Grep`, `Glob` | `Bash` with `rg` when the session has no `Grep` or `Glob`. | + +## Subagent fields + +| Cursor | Claude Code | +| --- | --- | +| `subagent_type: generalPurpose` | `subagent_type: "general-purpose"` | +| `poteto-agent`, `comment-sicko` | `pstack:poteto-agent`, `pstack:comment-sicko` | +| `readonly: true` | `subagent_type: "Explore"`. It keeps `Bash`, so the brief also says "do not edit files", and you check `git status` afterward. | +| `readonly: false` | `general-purpose`. It keeps the session's MCP servers. | +| `environment: "cloud"` | `isolation: "worktree"`. Name the branch or commit the worker checks out. | +| `environment: "local"` | Omit. | +| `cloud_base_branch: ` | Tell the worker to check out `` first. | +| `run_in_background: true` | Omit. Subagents run in the background by default and notify you when they finish. | +| `resume` | Spawn a new agent and paste the earlier result into its brief. | +| `file_attachments` | List the paths in the brief. | + +## Models + +| Cursor | Claude Code | +| --- | --- | +| `claude---[-fast]`, such as `claude-opus-5-5-xhigh` | `model: "opus"` and `effort: "xhigh"`. `model` takes only `opus`, `sonnet`, `haiku`, `fable`. Drop `-fast`. | +| A `grok-*`, `gpt-*`, or other non-Claude slug | Omit `model` so the agent runs on the session model, and say so. | +| `auto` or `inherit-parent` | Omit `model`. | +| The `pstack-models.mdc` rule | Claude Code does not load it. Use the skill's default slug and map it with these rows. | + +## Paths + +| Cursor | Claude Code | +| --- | --- | +| `.cursor/skills/`, `~/.cursor/skills/` | `.claude/skills/`, `~/.claude/skills/` | +| `~/.cursor/plugins/`, `.cursor-plugin/plugin.json` | `~/.claude/plugins/`, `.claude-plugin/plugin.json` | +| `.cursor/rules/*.mdc`, always-applied rules | `CLAUDE.md`, or `AGENTS.md` when no `CLAUDE.md` exists. Claude Code never reads `.mdc` files. | +| Transcripts in `~/.cursor/projects//agent-transcripts/` | `~/.claude/projects//.jsonl`. The slug is the workspace path with each `/` and `.` changed to `-`, so `/Users/you/proj` is `-Users-you-proj`. The newest file is the current session. Read only this workspace's folder. | + +## Cursor-only features + +Automations, Bugbot, Cursor cloud agents, and Cursor's pull request tool have no Claude Code equivalent. Say so, skip that step, and continue. diff --git a/pstack/docs/harness/codex.md b/pstack/docs/harness/codex.md new file mode 100644 index 000000000..0516728ff --- /dev/null +++ b/pstack/docs/harness/codex.md @@ -0,0 +1,52 @@ +# pstack in Codex + +pstack skills use Cursor names. In Codex, read this file once per session, then map each Cursor name in a skill with the tables below. `` means the folder that holds `skills/` and `docs/`. If a Cursor field has no row, drop it and say so. Never pass a field or value the tool schema rejects. + +## Tools + +| Cursor | Codex | +| --- | --- | +| `Task` | `spawn_agent`. Find it under `collaboration`, or through `tool_search` when it is not listed. Each spawn returns at once. Call `wait_agent` until every final answer has arrived. | +| `AskQuestion` | `request_user_input` in Plan mode. Otherwise ask in plain text. | +| Open a todolist | Keep the list in your reply and update it at each phase. | +| Run another pstack skill (`/name` or "the **name** skill") | Read `/skills//SKILL.md` and follow it. When you tell the user to type it, write `$pstack:`. | +| `Read`, `Grep`, `Glob` | `exec_command` with `sed -n`, `rg`, or `ls`. | + +## Subagent fields + +| Cursor | Codex `spawn_agent` | +| --- | --- | +| A standalone brief | `fork_turns: "none"` and the whole brief in `message`. The default `all` copies this conversation into the worker. | +| `subagent_type: generalPurpose` | Omit `agent_type`. | +| `poteto-agent`, `comment-sicko` | Codex plugins cannot ship agents. Put the body of `/agents/.md` at the top of `message`. | +| `readonly: true` | Codex has no read-only flag. The brief says "do not edit files", and you check `git status` afterward. | +| `readonly: false` | Omit. Workers keep the session's MCP servers. | +| `environment: "cloud"` or `"local"` | Omit. Workers share this checkout, so give each writer its own output path. | +| `cloud_base_branch: ` | Tell the worker to read `` with `git show` or `git worktree`, not to switch this checkout. | +| `run_in_background: true` | Omit. Spawns already run in the background. | +| `resume` | `followup_task` with the agent's task name. It starts a new turn when the agent is idle. If `list_agents` does not show the agent, spawn a new one with the earlier result in `message`. | +| `file_attachments` | List the paths in `message`. | +| More than 6 workers | Codex runs 6 at a time by default. Spawn in waves of 6. | + +## Models + +| Cursor | Codex | +| --- | --- | +| Any slug, such as `grok-4.7-xhigh-fast`, `claude-opus-5-5-xhigh`, or a `gpt-*` slug | Omit `model` so the worker runs on the session model, and say so. Pass `model` only with a slug that the `spawn_agent` description lists. | +| An effort in a slug (`low`, `medium`, `high`, `xhigh`, `max`) | `reasoning_effort` with the same word, if the description lists it for that model. | +| `auto` or `inherit-parent` | Omit `model`. | +| The `pstack-models.mdc` rule | Codex does not load it. Use the skill's default and map it with these rows. | + +## Paths + +| Cursor | Codex | +| --- | --- | +| `.cursor/skills/` | `.agents/skills/` in the repository, or `.codex/skills/` | +| `~/.cursor/skills/` | `~/.agents/skills/` | +| `~/.cursor/plugins/`, `.cursor-plugin/plugin.json` | `~/.codex/plugins/cache/`, root `plugin.json` | +| `.cursor/rules/*.mdc`, always-applied rules | `AGENTS.md`. Codex never reads `.mdc` files. | +| Transcripts in `~/.cursor/projects//agent-transcripts/` | `~/.codex/sessions///
/rollout-
/rollout-
/rollout-
/rollout-
/rollout-