Skip to content
Draft
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
5 changes: 5 additions & 0 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -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."
}
]
}
6 changes: 6 additions & 0 deletions .github/workflows/validate-plugins.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@ on:
pull_request:
paths:
- ".cursor-plugin/marketplace.json"
- ".claude-plugin/marketplace.json"
- "**/plugin.json"
- "schemas/**"
- "scripts/validate-plugins.mjs"
- ".github/workflows/validate-plugins.yml"

jobs:
validate:
Expand All @@ -22,3 +25,6 @@ jobs:

- name: Validate plugin definitions
run: node scripts/validate-plugins.mjs

- name: Validate Claude Code plugin definitions
run: npx --yes @anthropic-ai/claude-code@2.1.299 plugin validate .
21 changes: 21 additions & 0 deletions pstack/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -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.23",
"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/"
}
15 changes: 12 additions & 3 deletions pstack/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ there's a growing sense that ai writes too much slop code. i agree. i don't want

**pstack gives you fearless parallelism.** when you can go deep on one agent and trust it to write good, verifiable code, you can truly parallelize with confidence. start multiple agents up with `poteto-mode` and trust that they'll apply rigorous engineering principles to their work.

**cursor gives you the best of all worlds.** every frontier model has its strengths and weaknesses. use any model with pstack. in fact, many of my skills use multi-model workflows to take advantage of each model's unique strengths.
**use the models your harness can actually run.** every frontier and open model has its strengths and weaknesses. pstack uses native subagents where the active harness exposes them, and confirmed external runners for read-only cross-family review when it does not. [`/setup-pstack`](./skills/setup-pstack/SKILL.md) detects that boundary instead of assuming cursor's catalog is the whole model set.

fork it. improve it. make it yours. PRs are welcome!

Expand All @@ -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`. the [harness reference](./docs/model-routing.md#harness-reference) lists every other difference.

## get started

two steps:
Expand Down Expand Up @@ -258,15 +267,15 @@ cursor already has a great plan mode which works great with pstack. but personal

type [`/automate-me`](./skills/automate-me/SKILL.md). it mines your recent transcripts, drafts a `<your-name>-mode` skill from how you've actually worked, and routes through pstack underneath. you keep pstack as the base and end up with your own routing skill alongside `poteto-mode`.

models are configurable too. type [`/setup-pstack`](./skills/setup-pstack/SKILL.md). it detects the models you have access to and writes a small always-applied rule mapping each role (code, judgment, the review panels) to a model. every skill reads it and falls back to sensible defaults when the rule is absent, so you override only what you want.
models are configurable too. type [`/setup-pstack`](./skills/setup-pstack/SKILL.md). it detects the active harness, confirms runnable models and runners, and writes a [harness profile](./docs/model-routing.md) mapping each role to a runner, model, and effort. every skill reads the matching profile and falls back to its existing defaults when one is absent. the cursor rule remains a compatibility export.

when a default changes, a rule written before the change still pins the old default. delete those role lines, or delete the file, then run `/setup-pstack` again. a rerun keeps any role whose model differs from the default.

## automations

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

Expand Down
3 changes: 2 additions & 1 deletion pstack/agents/poteto-agent.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
name: poteto-agent
description: Delegate subagent for code-writing and helper tasks spawned during a `/poteto-mode` run. Use for delegates, not as the runner for `/poteto-mode` itself. Spawn a fresh `poteto-agent` for each new task, and resume one only in the strict cases that poteto-mode's Subagents section names. Reads the `poteto-mode` skill's `SKILL.md` in full before any work, including its inline Principles index. Substituting `generalPurpose` skips that read and drifts.
is_background: true
background: true
---

# Poteto subagent

You are operating as poteto-mode's full agent style. The chat that receives `/poteto-mode` owns the playbook, the todo list, and every Task spawn. You are one of its delegates. Read the `poteto-mode` skill's `SKILL.md` in full before doing any work, including its inline Principles index. Use the absolute path your parent gave you. With no path, before any other work, search `~/.cursor/plugins/` for a file whose path ends in `skills/poteto-mode/SKILL.md`. If more than one file matches, use the copy whose `.cursor-plugin/plugin.json` has the highest `version`. Your skill catalog hides this skill, so a missing catalog entry does not mean pstack is absent. If no such file exists, stop and tell your parent. Navigate to a leaf `principle-*` skill whenever you apply that principle.
You are operating as poteto-mode's full agent style. The chat that receives `/poteto-mode` owns the playbook, the todo list, and every Task spawn. You are one of its delegates. Read the `poteto-mode` skill's `SKILL.md` in full before doing any work, including its inline Principles index. Use the absolute path your parent gave you. With no path, before any other work, search `~/.cursor/plugins/` for a file whose path ends in `skills/poteto-mode/SKILL.md`. If more than one file matches, use the copy whose `.cursor-plugin/plugin.json` has the highest `version`. In another harness, search that harness's plugin install root and manifest from the Harness reference in pstack's `docs/model-routing.md` instead (Claude Code: `~/.claude/plugins/` and `.claude-plugin/plugin.json`). Your skill catalog hides this skill, so a missing catalog entry does not mean pstack is absent. If no such file exists, stop and tell your parent. Navigate to a leaf `principle-*` skill whenever you apply that principle.
141 changes: 141 additions & 0 deletions pstack/docs/model-routing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
# Harness-aware model routing

Pstack reads `~/.config/pstack/models.json` at the start of a workflow. Select the
profile for the **active harness**, identified from the tools in this session
(for example Cursor `Task`, Claude Code `Task`, Codex `spawn_agent`, or OpenCode
agents). A CLI installed on the machine does not make it the active harness.
When no matching profile exists, use the legacy Cursor rule
(`~/.cursor/rules/pstack-models.mdc`) and skill defaults **only in Cursor**.
In another harness, use native `inherit-parent` entries until setup confirms
models for that harness. Never feed Cursor model slugs to a different harness
merely because the legacy rule exists.

The profile is a JSON object with `schemaVersion: 1` and `profiles` keyed by
`cursor`, `claude-code`, `codex`, or `opencode`. Each profile has a `budget`, a
native `fallback`, and `roles`. Every role value is an ordered array, including
single-model roles. An entry has `runner`, `model`, and `effort` fields:

```json
{
"schemaVersion": 1,
"profiles": {
"codex": {
"budget": "medium",
"fallback": { "runner": "native", "model": "inherit-parent", "effort": null },
"roles": {
"feature, refactoring": [
{ "runner": "native", "model": "gpt-6-sol", "effort": "high" }
],
"interrogate reviewers": [
{ "runner": "native", "model": "gpt-6-astra", "effort": "high" },
{ "runner": "claude-cli", "model": "opus", "effort": "high" }
]
}
}
}
}
```

The example illustrates the format; setup must verify each real model and
runner before writing it. `inherit-parent` and `auto` are always valid **native**
models and omit the model override. A panel role runs one reviewer per entry;
`arena cross-judge pool` instead selects one entry, preferring a family different
from the parent when available. `swarm workers` is one default entry unless a
race explicitly names other arms.

## Resolve an entry

1. Prefer `native` when this harness's subagent tool accepts the chosen model.
Pass model and effort using that tool's actual schema. Codex has separate
`model` and `reasoning_effort` inputs; do not invent an effort-suffixed slug.
Cursor may encode effort in a model variant. Omit unsupported effort fields.
The consuming skills' `Task` examples may contain Cursor-only options such
as `subagent_type`, `readonly`, `environment`, and `run_in_background`.
In Cursor, pass them as written. In another harness, translate them with
[Harness reference](#harness-reference) rather than passing unsupported
fields.
2. `claude-cli`, `codex-cli`, `cursor-cli`, and `opencode-cli` are external runners.
Use them for read-only review, investigation, or adversarial work only when
the CLI is authenticated, the model is confirmed runnable, and a read-only
mode is available. Check the installed CLI's `--help` before invoking it:
Claude Code supports print mode and plan permissions; Codex supports
`exec --sandbox read-only`; Cursor Agent supports print and plan modes;
OpenCode supports `run --agent plan`. Set model and effort/variant only with
options that CLI actually supports. Capture the result in a local artifact,
report tool failures, and do not put credentials or private data in command
arguments or logs.
Give an external reviewer only source and context approved for that provider
under the project's data rules. If a native tool cannot enforce read-only
access, use a confirmed read-only external runner or verify its checkout
remained unchanged after an explicitly no-edit native review.
3. Open-source models can use a native subagent, an authenticated OpenCode
provider, or a loaded local Codex/Ollama/LM Studio provider. A catalog entry
alone does not prove access. Record the runner that actually accepts it.
4. Code-writing roles use `native` by default. An external writer needs explicit
user selection, an isolated checkout, and a documented write boundary.
Never run multiple writers against one checkout.
5. If a configured runner or model is unavailable, say which entry failed and
use the profile's confirmed native fallback. Do not silently substitute a
different model family or claim a cross-family review occurred.

For Codex, favor confirmed GPT models for implementation and use a confirmed
Claude, Grok, or other family for read-only review when it has a runnable entry.
For Claude Code, favor confirmed Claude models for implementation and use a
confirmed GPT, Grok, or other family for review. Cursor and OpenCode select
their native primary family from the active session. When the native subagent
tool exposes all desired families, use it for the whole panel; external CLIs
are a fallback for families absent from that tool.

## Harness reference

Skills and agents are written with Cursor's names, fields, and paths. In
Cursor, use them exactly as written. In another harness, translate each one
with the tables below. Drop a field with no row here and say you dropped it;
never invent a field or value the active tool's schema does not accept.

### Subagent fields

| Cursor | Claude Code |
| --- | --- |
| `subagent_type: generalPurpose` | `subagent_type: "general-purpose"` |
| `subagent_type: poteto-agent`, `comment-sicko`, or another pstack agent | Prefix the plugin name: `pstack:poteto-agent`, `pstack:comment-sicko` |
| `readonly: true` | `subagent_type: "Explore"`. It denies `Write` and `Edit` but keeps shell access, so also instruct no edits and confirm the checkout is unchanged afterward. |
| `readonly: false` (for MCP access) | `general-purpose`, which inherits the session's MCP servers |
| `environment: "cloud"` | `isolation: "remote"` when the tool offers it, else `isolation: "worktree"`. A worktree branches from the default branch, not the parent's `HEAD`, so tell the subagent which branch or commit to check out. |
| `environment: "local"` | Omit the field. |
| `run_in_background: true` | Omit the field. Claude Code runs subagents in the background in interactive sessions. |
| Effort-suffixed model slug, such as `claude-opus-5-5-xhigh` | Separate `model` and `effort` (`low` through `max`). The call's `model` accepts only the aliases `opus`, `sonnet`, `haiku`, and `fable`. |
| `inherit-parent` or `auto` | Omit `model`. Never pass `inherit` on a call; only agent frontmatter accepts it. |

### Agent frontmatter

Claude Code ignores frontmatter keys it does not recognize, so an agent file
carries both harnesses' keys side by side.

| Cursor | Claude Code |
| --- | --- |
| `is_background: true` | `background: true` |
| `readonly: true` | `disallowedTools: Write, Edit`. Plugin agents ignore `permissionMode`. |
| `model: inherit` | `model: inherit` |

### Paths and names

| | Cursor | Claude Code |
| --- | --- | --- |
| Plugin install root | `~/.cursor/plugins/` | `~/.claude/plugins/` |
| Installed plugin manifest | `.cursor-plugin/plugin.json` | `.claude-plugin/plugin.json` |
| Project skills | `.cursor/skills/` | `.claude/skills/` |
| User skills | `~/.cursor/skills/` | `~/.claude/skills/` |
| Slash command | `/poteto-mode` | `/pstack:poteto-mode` |
| Transcript directory | `~/.cursor/projects/<slug>/agent-transcripts/`, named in the system prompt | `~/.claude/projects/<slug>/`, not named in the system prompt |
| Transcript file | `<uuid>/<uuid>.jsonl` | `<uuid>.jsonl`; subagents under `<uuid>/subagents/agent-<id>.jsonl` |
| Workspace slug | Workspace path without the leading `/`, with each `/` turned into `-` | Workspace path with each `/` and `.` turned into `-`, keeping the leading `-` |
| Slug example for `/Users/you/proj` | `Users-you-proj` | `-Users-you-proj` |

In Claude Code, the current session's transcript is the most recently modified
`.jsonl` directly under the workspace's project directory. Claude Code deletes
transcripts after `cleanupPeriodDays` (30 days by default). As in Cursor, read
only the active workspace's directory; never glob across every project.

Cursor Automations (`automations/`) have no Claude Code equivalent and stay
Cursor-only.
2 changes: 1 addition & 1 deletion pstack/skills/architect/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Skip Phase A only when the work is genuinely greenfield with no surrounding syst

Run the **arena** skill with the design-sketch task and the Phase A grounding artifacts. Pass `references/runner-prompt.md` as each runner's prompt.

Take the runners from the `architect runners` line in the `pstack-models.mdc` rule, in place of the `arena runners` line. If the rule or that line is missing, use `claude-opus-5-5-xhigh` and `grok-4.7-xhigh-fast`. Alias and rejected entries follow the runner rules in the **arena** skill's Phase A.
Take runners from the matching harness profile's `architect runners` entries using [model routing](../../docs/model-routing.md), in place of `arena runners`. Without a profile, use the legacy `pstack-models.mdc` line or `claude-opus-5-5-xhigh` and `grok-4.7-xhigh-fast` in Cursor; in another harness use native `inherit-parent` seats. Native aliases and rejected entries follow **arena** Phase A; external writers require the same explicit selection and separate checkout.

Design it twice. Require at least two structurally distinct candidates before synthesis, even when the first looks sufficient. This is the **exhaust-the-design-space** principle skill made concrete. Whole-shape alternatives, not point fixes inside one shape.

Expand Down
Loading