What this port changes about upstream pstack, and why. If you are wondering whether a difference from upstream is deliberate, it should be listed here.
Everything in ./pstack is generated. port/sync.mjs deletes the tree and
rebuilds it on every run, so a hand edit there survives exactly until the next
one. To change the
output, change a rule in port/rules.mjs or an overlay in
port/overlays/.
Rewrites are the port. Cursor says ~/.cursor/skills/, Claude Code says
~/.claude/skills/. Skipping one leaves an instruction pointing at a path that
does not exist, which an agent will follow anyway.
Overlays are opinion, additions on top of upstream. Skipping one leaves a working plugin without the addition. This port is meant to read as upstream wrote it, so overlays ship off unless the content fixes the port rather than adding to it. See Overlays.
Both are content-addressed. A rewrite matches a token or a shape, never a line number or a hunk of context, so upstream can reword the paragraph around it and the rule still applies. Overlays only append a marked section. They never edit inline and never renumber an upstream list.
That is why this mirror does not rot. Upstream changes constantly. Nothing here is anchored to upstream's line numbering, so those changes do not reach the port.
| Cursor | Claude Code |
|---|---|
~/.cursor/rules/pstack-models.mdc (always-applied) |
~/.claude/pstack-models.md (plain markdown) |
~/.cursor/skills/, ~/.cursor/plugins/ |
~/.claude/skills/, ~/.claude/plugins/ |
~/.cursor/projects/<slug>/agent-transcripts/… |
~/.claude/projects/<slug>/<uuid>.jsonl (flat) |
AskQuestion |
AskUserQuestion |
Task tool / subagent, and bare `Task` |
Agent |
todolist |
todo list, naming TodoWrite where one is opened |
alwaysApply: frontmatter |
dropped, no Claude Code equivalent |
/add-plugin pstack |
/plugin marketplace add … + /plugin install … |
| "Cursor's built-in X" | "your host's built-in X" |
"Cursor's /loop command" |
"the /loop skill" |
MCP discovery via an mcps/ directory |
MCP servers as mcp__<server>__<tool> session tools |
Two of these deserve a note:
- "your host's built-in." Claude Code has no
create-skillorbabysitbuilt-in. Renaming them to Claude Code would assert a skill that is not there, so the attribution goes generic and the sentence stays true on either host. - Frontmatter names. Claude Code requires a skill's frontmatter
nameto be its kebab-case directory slug. Upstream tolerates a display name (name: Poteto Mode). A structural rule fixes every skill rather than patching the strings that are wrong today, so a future upstream skill with the same problem gets fixed on arrival.
The port also repairs grammar it breaks itself. Renaming Task to Agent
strands the article in "a Task subagent", so that rule runs last, on rewritten
text.
Things that are ported but cannot work here. They stay in place rather than getting deleted, because deleting them would break upstream's own cross-references, and because a documented dead end is easier to reason about than a missing file.
- The
orchestrateplaybook (skills/poteto-mode/playbooks/orchestrate.md) is hard-wired to Cursor's cloud platform:CURSOR_API_KEY,Agent.create,environment: "cloud", the Cursor agents dashboard. None of it exists in Claude Code, so poteto-mode's routing to Orchestrate dead-ends. The nearest native equivalent is Claude Code's built-inWorkflowtool. - The benny automation pack (
automations/benny/) targets Cursor Automations and Cursor Slack actions. Upstream ships it dormant, with its files unregistered as skills, and it stays dormant here. It is carried so upstream's README links resolve, not because it runs. - Model slugs. Upstream's inline defaults are Cursor slugs
(
grok-4.6-fast-xhigh,gpt-5.6-sol-max,claude-opus-5-thinking-xhigh). None are valid in Claude Code, and the rewrite layer deliberately does not guess a mapping. Run/pstack:setup-pstackto write~/.claude/pstack-models.md, which overrides them. Thesetup-pstack-claude-modelsoverlay documents the valid values inside the skill itself.
| Overlay | Status | Target(s) |
|---|---|---|
setup-pstack-claude-models |
on | skills/setup-pstack |
user-level-skill-authoring |
off | skills/automate-me, create-verification-skill, maintain-… |
unslop-extra-patterns |
off | skills/unslop |
Two of the three ship disabled, because a faithful mirror should read as upstream
wrote it. unslop-extra-patterns adds pattern entries upstream does not have.
user-level-skill-authoring redirects generated skills to ~/.claude/skills/
instead of the project. That is a defensible preference, but it contradicts
upstream's own docs/guide/06-verify-and-ship.md, which documents the project
path, and shipping both would have put the plugin at odds with itself.
setup-pstack-claude-models stays on because it is not opinion. Upstream's
setup-pstack instructs the agent to write model slugs that do not exist in
Claude Code, which is the same class of defect as a ~/.cursor/ path, an
instruction an agent will follow into a wall. The overlay names the valid values
without guessing a slug-to-slug mapping, which the rewrite layer still refuses to
do.
Turn one on with enabled: true in its frontmatter, then re-sync. Both stay in
port/overlays/, off rather than deleted.
port/verify.mjs is what makes unattended mirroring safe. It
fails the build on any surviving .cursor/ path, agent-transcripts reference,
Cursor-only frontmatter key, or wrong tool name; on a malformed manifest; on a
skill whose frontmatter name does not match its directory; and on a broken
relative link.
Two of its checks look at the committed tree rather than the tree on disk, because both failure modes are invisible locally:
- Executable bits. Upstream ships four runnable scripts.
chmodis a no-op on Windows, soUPSTREAM.jsonrecords the mode and verify asserts it againstgit ls-files -s, printing thegit update-index --chmod=+xfix in the error. A script that arrives mode100644does not run for anyone who installs the plugin. - Tracking. Every generated file must be tracked. A future upstream filename
matching a
.gitignorepattern would be present here and absent for everyone else, and nothing else in the pipeline would notice.
When upstream adds a Cursor-ism no rule covers, verify fails, CI publishes
nothing, and it opens an issue naming the file and line. A mirror one day stale
is recoverable. A mirror that ships instructions pointing at ~/.cursor is worse
than no mirror, because an agent will follow them.
Loose mentions of "Cursor" are warnings rather than errors, since naming Cursor is sometimes correct, as in attribution or documentation of a Cursor-only feature. Every allowlist entry carries a reason, plus a path pattern where the exemption is context-specific, so the allowlist cannot become a place to hide real misses.
pstack is by Lauren Tan (poteto), MIT licensed, from
cursor/plugins. Upstream's own LICENSE
ships in the generated tree at pstack/LICENSE. This repository holds the
porting machinery and the generated output; it does not claim authorship of
pstack.