Repository navigation
feat: support Claude Code and Codex with upstream sync #638
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
aff6cc5
a37612f
252f978
8491d3a
cbc4793
8a911ae
17e35db
c2c6c6e
e761c3c
5f83e92
384e721
e7e0221
721810a
2b3794a
37b65a8
2ad948e
40433ea
a99b428
f755e1f
f5474b4
2595adf
03fe759
9b10e1c
a57e1f0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| { | ||
| "name": "yxhta-pstack", | ||
| "interface": { | ||
| "displayName": "pstack" | ||
| }, | ||
| "plugins": [ | ||
| { | ||
| "name": "pstack", | ||
| "source": { | ||
| "source": "local", | ||
| "path": "./portable/pstack" | ||
| }, | ||
| "policy": { | ||
| "installation": "AVAILABLE", | ||
| "authentication": "ON_INSTALL", | ||
| "products": [ | ||
| "CODEX" | ||
| ] | ||
| }, | ||
| "category": "Developer Tools" | ||
| }, | ||
| { | ||
| "name": "thermos", | ||
| "source": { | ||
| "source": "local", | ||
| "path": "./portable/thermos" | ||
| }, | ||
| "policy": { | ||
| "installation": "AVAILABLE", | ||
| "authentication": "ON_INSTALL", | ||
| "products": [ | ||
| "CODEX" | ||
| ] | ||
| }, | ||
| "category": "Developer Tools" | ||
| } | ||
| ] | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,14 +1,24 @@ | ||
| { | ||
| "name": "cursor-plugins", | ||
| "name": "yxhta-pstack", | ||
| "description": "Upstream pstack and Thermos adapted for Claude Code and Codex.", | ||
| "owner": { | ||
| "name": "Cursor", | ||
| "email": "[email protected]" | ||
| "name": "yxhta" | ||
| }, | ||
| "plugins": [ | ||
| { | ||
| "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": "./portable/pstack", | ||
| "description": "Upstream pstack workflows adapted for Claude Code and Codex." | ||
| }, | ||
| { | ||
| "name": "thermos", | ||
| "source": "./portable/thermos", | ||
| "description": "Independent correctness and code-quality branch reviews." | ||
| }, | ||
| { | ||
| "name": "pstack-mods", | ||
| "source": "./portable/pstack-mods", | ||
| "description": "Opt-in Claude Mods bug-fix evidence gates. Validated against Claude Code 2.1.289." | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Mods listing descriptions do not matchMedium Severity · Bugbot Rules Plugin listing Additional Locations (1)Triggered by learned rule: Plugin listing copy must match plugin.json and marketplace.json Reviewed by Cursor Bugbot for commit a57e1f0. Configure here. |
||
| } | ||
| ] | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| pstack/** -whitespace | ||
| README.md -whitespace | ||
| portable/pstack/** -whitespace linguist-generated=true | ||
| thermos/** -whitespace | ||
| portable/thermos/** -whitespace linguist-generated=true | ||
| portable/pstack-mods/** -whitespace linguist-generated=true |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| name: Sync pstack upstream | ||
|
|
||
| on: | ||
| workflow_dispatch: | ||
| schedule: | ||
| - cron: '23 2 * * *' | ||
|
|
||
| permissions: | ||
| contents: write | ||
| pull-requests: write | ||
|
|
||
| concurrency: | ||
| group: pstack-upstream-sync | ||
| cancel-in-progress: false | ||
|
|
||
| jobs: | ||
| sync: | ||
| if: github.repository == 'yxhta/pstack' | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| ref: main | ||
| fetch-depth: 0 | ||
| token: ${{ secrets.UPSTREAM_SYNC_TOKEN || github.token }} | ||
| - uses: actions/setup-python@v5 | ||
| with: | ||
| python-version: '3.12' | ||
| - run: python -m pip install PyYAML==6.0.3 | ||
| - name: Configure commit identity | ||
| run: | | ||
| git config user.name 'github-actions[bot]' | ||
| git config user.email '41898282+github-actions[bot]@users.noreply.github.com' | ||
| - name: Merge, validate, and open a sync PR | ||
| env: | ||
| GH_TOKEN: ${{ secrets.UPSTREAM_SYNC_TOKEN || github.token }} | ||
| GH_REPO: ${{ github.repository }} | ||
| run: bash tools/portable/sync-upstream.sh |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,79 @@ | ||
| name: Validate portable pstack, Thermos, and Mods | ||
|
|
||
| on: | ||
| push: | ||
| paths: | ||
| - 'pstack/**' | ||
| - 'thermos/**' | ||
| - 'cursor-team-kit/skills/deslop/**' | ||
| - 'cursor-team-kit/LICENSE' | ||
| - 'portable/**' | ||
| - 'README.md' | ||
| - 'README_PORTABLE.md' | ||
| - 'docs/thermos-*.md' | ||
| - 'docs/pstack-mods*.md' | ||
| - '.gitattributes' | ||
| - 'tools/portable/**' | ||
| - '.claude-plugin/**' | ||
| - '.agents/plugins/**' | ||
| - '.github/workflows/*pstack*.yml' | ||
| pull_request: | ||
| paths: | ||
| - 'pstack/**' | ||
| - 'thermos/**' | ||
| - 'cursor-team-kit/skills/deslop/**' | ||
| - 'cursor-team-kit/LICENSE' | ||
| - 'portable/**' | ||
| - 'README.md' | ||
| - 'README_PORTABLE.md' | ||
| - 'docs/thermos-*.md' | ||
| - 'docs/pstack-mods*.md' | ||
| - '.gitattributes' | ||
| - 'tools/portable/**' | ||
| - '.claude-plugin/**' | ||
| - '.agents/plugins/**' | ||
| - '.github/workflows/*pstack*.yml' | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| jobs: | ||
| validate: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| fetch-depth: 0 | ||
| - uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: '20' | ||
| - uses: actions/setup-python@v5 | ||
| with: | ||
| python-version: '3.12' | ||
| - run: python -m pip install PyYAML==6.0.3 | ||
| - run: python3 tools/portable/validate.py | ||
| - run: python3 -m unittest discover -s tools/portable -p 'test_*.py' | ||
| - name: Validate Mods with pinned native Claude Code | ||
| env: | ||
| DISABLE_AUTOUPDATER: '1' | ||
| CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: '1' | ||
| run: | | ||
| curl -fsSL https://claude.ai/install.sh -o "$RUNNER_TEMP/install-claude.sh" | ||
| bash "$RUNNER_TEMP/install-claude.sh" 2.1.289 | ||
| export PATH="$HOME/.local/bin:$PATH" | ||
| test "$(claude --version)" = '2.1.289 (Claude Code)' | ||
| bash tools/portable/check-mods.sh | ||
| - run: bash -n tools/portable/sync-upstream.sh | ||
| - run: sh -n portable/pstack/hooks/session-start.sh | ||
| - name: Install the skills for both agents in an isolated project | ||
| run: | | ||
| mkdir -p "$RUNNER_TEMP/pstack-skills-smoke" | ||
| cd "$RUNNER_TEMP/pstack-skills-smoke" | ||
| npx --yes skills add "$GITHUB_WORKSPACE/portable/pstack" --skill '*' --agent claude-code codex --copy --yes | ||
| python3 "$GITHUB_WORKSPACE/tools/portable/check-install.py" "$RUNNER_TEMP/pstack-skills-smoke" | ||
| - name: Install Thermos for both agents in an isolated project | ||
| run: | | ||
| mkdir -p "$RUNNER_TEMP/thermos-skills-smoke" | ||
| cd "$RUNNER_TEMP/thermos-skills-smoke" | ||
| npx --yes skills add "$GITHUB_WORKSPACE/portable/thermos" --skill '*' --agent claude-code codex --copy --yes | ||
| python3 "$GITHUB_WORKSPACE/tools/portable/check-install.py" "$RUNNER_TEMP/thermos-skills-smoke" --package thermos |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,107 @@ | ||
| # pstack for Claude Code and Codex | ||
|
|
||
| This is a fork of [cursor/plugins](https://github.com/cursor/plugins), maintained for the pstack and Thermos skills. Upstream's playbooks and principles are shared by both runtimes. The original [pstack README](pstack/README.md) remains the Cursor guide; the instructions here apply to this fork. | ||
|
|
||
| For Thermos installation and review commands, see [Thermos for Claude Code and Codex](docs/thermos-portable.md). | ||
|
|
||
| For an optional Claude-only bug-fix evidence pipeline, see [pstack Mods](docs/pstack-mods.md). It runs only after explicit opt-in and leaves the existing portable workflows unchanged. | ||
|
|
||
| ## Install | ||
|
|
||
| ### Skills CLI (Claude Code and Codex) | ||
|
|
||
| ```sh | ||
| npx skills add yxhta/pstack/portable/pstack --skill '*' --agent claude-code codex | ||
| ``` | ||
|
|
||
| This installs the shared skill bundle for both agents in the current project. Add `--global` for a personal installation. Install all pstack skills together: the entry points share the runtime adaptation and other resources under poteto-mode. The bundle includes the adaptation and agent reference prompts, but it does not register plugin agent types or plugin namespaces. Use `/poteto-mode` on Claude Code and `$poteto-mode` on Codex; the adaptation describes the general-purpose agent fallback. | ||
|
|
||
| ```sh | ||
| npx skills update | ||
| ``` | ||
|
|
||
| Upstream synchronization updates this fork through PRs. After merging a sync PR, update the installed skills separately with the command above. | ||
|
|
||
| If this fork was installed before the portable package split, reinstall it once from the explicit portable path. Old lock entries point to `pstack/skills/`, which now contains untouched Cursor source. Updating those entries can install Cursor instructions or fail to match normalized names such as `poteto-mode` and `make-bot-ui`. | ||
|
|
||
| For an existing global installation: | ||
|
|
||
| ```sh | ||
| npx skills add yxhta/pstack/portable/pstack --skill '*' --agent claude-code codex --global --yes | ||
| ``` | ||
|
|
||
| Include any other agents that already use this bundle. For a project installation, omit `--global`. Reinstallation refreshes the skill contents and records `portable/pstack/skills/<name>/SKILL.md` as the update path. Subsequent `npx skills update` calls use that path. | ||
|
|
||
| ### Native plugins | ||
|
|
||
| Claude Code: | ||
|
|
||
| ```text | ||
| /plugin marketplace add yxhta/pstack | ||
| /plugin install pstack@yxhta-pstack | ||
| ``` | ||
|
|
||
| Codex CLI: | ||
|
|
||
| ```sh | ||
| codex plugin marketplace add yxhta/pstack | ||
| codex plugin add pstack@yxhta-pstack | ||
| ``` | ||
|
|
||
| Start with `/pstack:poteto-mode` on Claude Code. On Codex, select the installed `pstack:poteto-mode` skill or ask to use poteto-mode. Run setup-pstack to configure roles. Missing roles inherit the session model; multi-model diversity needs models that your runtime actually exposes. Native plugins supply startup context when their hook is enabled and trusted. | ||
|
|
||
| For a skills-only installation, clone this repository and keep it in place, then link each directory under `portable/pstack/skills/` into your runtime's user skill directory. Install all skill directories together so the shared runtime adaptation and other relative references stay reachable. Existing skill names such as `swarm` and `architect` may collide: inspect existing installations before replacing them. | ||
|
|
||
| Read [runtime adaptation](tools/portable/assets/skills/poteto-mode/references/runtime-adaptation.md) for the tool mappings, paths, and limitations. Cursor-only `make-bot-ui`, Benny automations, cloud workers, and transcript parsers are not ported. Deslop is bundled at the same upstream pin. Other optional cursor-team-kit dependencies are not included. Installation and structural validation do not establish that every workflow runs correctly; check a real task in each runtime. | ||
|
|
||
| ## Runtime parity and limits | ||
|
|
||
| The adapter preserves upstream review roles, participant counts, fresh-agent policy, and completion gates. The shared bundle intentionally removes `disable-model-invocation` from workflow skills so poteto-mode can route to them. The poteto-help and ketchup entry points retain upstream's explicit-only invocation, including matching Codex policies. This changes discovery and invocation availability; it does not grant permission for side effects. Capacity limits queue participants in waves. If the host cannot provide an independent reviewer or isolated context, that gate remains unverified. A self-review or a missing transcript does not count as passing evidence. | ||
|
|
||
| Portable Comment Sicko is read-only. Its parent applies accepted, scoped comment deletions and checks the resulting diff before completing no-comments. A findings-only report does not complete the edit workflow. | ||
|
|
||
| For worktree discovery, use `python3 <skills-root>/poteto-mode/scripts/portable-worktree-audit.py --repo <repo> --base <verified-ref>`. The script returns local Git evidence as JSON without fetching, reading chats, or deleting anything. Every worktree's usage remains unknown until independently checked. Clean or merged worktrees are not automatically safe to remove. | ||
|
|
||
| For portable multi-phase plans, run `node <skills-root>/poteto-mode/scripts/check-portable-plan.mjs <plan.md>`. Add the runtime contract described in the adaptation under the program's Arm the program section. The companion preserves upstream structural gates and reports actual runtime assertions separately as unverified or blocked. | ||
|
|
||
| The [parity report](docs/parity-report.md) separates source preservation, executable checks, and host-dependent behavior. Read the runtime adaptation before using bundled scripts. Their presence does not establish installed dependencies, scheduler persistence, or authorization for external actions. | ||
|
|
||
| ## Upstream updates | ||
|
|
||
| The **Sync pstack upstream** GitHub Actions workflow checks daily and can be run manually. It merges upstream main into a dedicated branch, records the upstream SHA, regenerates the portable package, validates it, and opens a draft PR. It never merges into main automatically. The complete repository history is retained because this is a GitHub fork. The PR body separates raw pstack paths from other changed paths, which include generated output, fork tooling, and other upstream plugins. | ||
|
|
||
| Enable GitHub Actions in this fork and allow Actions to create pull requests under **Settings → Actions → General**. Scheduled workflows may be disabled by GitHub after prolonged inactivity; run or re-enable the workflow when needed. If Actions is not allowed to create PRs, supply a suitably scoped repository secret `UPSTREAM_SYNC_TOKEN`; do not commit credentials. A PR opened with the default GITHUB_TOKEN does not trigger other PR workflows, so the sync job runs validation itself. | ||
|
|
||
| The sync script requires a clean dedicated checkout at the latest `origin` default branch. Only one sync PR is kept open. If an open sync PR blocks a newer upstream revision, the job fails and names both the branch and pending SHA. Review and merge or close that PR before retrying. An already-current fork succeeds even if an old sync PR remains open. A merge conflict or validation failure fails the workflow with logs instead of overwriting the local adaptation. Retries use an unused branch suffix when a closed PR or interrupted run left a branch behind; they never force-push that branch. Resolve the conflicting upstream change on a branch and run the checks below. New upstream skills receive the same adaptation automatically. | ||
|
|
||
| ```sh | ||
| python3 tools/portable/prepare.py | ||
| python3 tools/portable/validate.py | ||
| python3 -m unittest discover -s tools/portable -p 'test_*.py' | ||
| git diff --check | ||
| claude plugin validate ./portable/pstack | ||
| ``` | ||
|
|
||
| The raw `pstack/` tree and root `README.md` match `tools/portable/upstream.json` byte for byte, including executable modes. Do not edit these source paths. The generator copies the complete upstream package to `portable/pstack/`, adds runtime mappings, and normalizes skill names there. It copies agents, licenses, scripts, and references. It rejects input symlinks and overlay collisions instead of overwriting unfamiliar upstream files. | ||
|
|
||
| Edit fork-owned inputs under `tools/portable/assets/` and rerun `python3 tools/portable/prepare.py`. Never edit `portable/pstack/` by hand. The generated package is committed intentionally so every installation works without a build. `python3 tools/portable/prepare.py --check` detects missing, stale, modified, or mode-changed output. Root marketplaces point to this single package. Source files remain unpatched when upstream changes a skill header. | ||
|
|
||
| Native plugin versions include the upstream pin and a digest of the package contents and executable modes. Adapter-only changes receive a new version without a manual bump. Template version fields are excluded from the digest. | ||
|
|
||
| Git whitespace checks apply to fork-owned inputs. `.gitattributes` exempts the upstream source paths and generated package so upstream whitespace remains intact. Source integrity and generation checks cover those paths. | ||
|
|
||
| Use `$sync-pstack-upstream` on Codex or `/sync-pstack-upstream` on Claude Code to review and integrate upstream changes from a source checkout. A native Claude plugin exposes `/pstack:sync-pstack-upstream`. The skill reads the recorded pin and full upstream diff, reviews changed runtime assumptions, regenerates, verifies, and prepares a PR. It does not merge automatically. Consumer installation updates still use `npx skills update`. | ||
|
|
||
| Mechanical merge conflicts in raw `pstack/` are avoided by keeping it pristine. Conflicts in root marketplaces or fork-owned automation can still occur. Semantic changes to upstream workflows still require review and actual execution on the affected runtime. Automated sync PRs report this review gap rather than claiming complete runtime compatibility. | ||
|
|
||
| ## Native runtime support | ||
|
|
||
| Native plugin installation includes a read-only SessionStart hook. Claude Code discovers `hooks/hooks.json`; Codex uses the explicitly registered `hooks/codex-hooks.json`. Claude also receives fresh native poteto-agent and read-only comment-sicko wrappers with low, medium, high, xhigh and max effort variants. Each variant inherits the model. Support for the requested effort still depends on the chosen model. | ||
|
|
||
| The runtime adaptation has separate Claude and Codex dispatch contracts. They consume confirmed session models, preserve the upstream role labels and panel counts, and disclose unsupported model or effort choices. Native wrapper Markdown links use the host-substituted `${CLAUDE_PLUGIN_ROOT}` so required reading resolves from the installed plugin root. Skills-only installations use general-purpose agents with the required reading in their brief. They do not register hooks or native agents. | ||
|
|
||
| The startup hook reads only the `session hook` directive in the runtime model sheet. Add `session hook: off` to `${CLAUDE_CONFIG_DIR:-$HOME/.claude}/pstack-models.md` or `${CODEX_HOME:-$HOME/.codex}/pstack-models.md` to disable it. Missing sheets leave startup context enabled. Unreadable sheets or conflicting directives suppress context and print a warning. No setting is written automatically. | ||
|
|
||
| Codex hooks require review and trust through `/hooks`. Installing or enabling the plugin does not grant that trust. Changed hook definitions require another review. SessionStart supplies parent context only; delegated agents still receive explicit reading instructions. | ||
|
|
||
| Deslop is generated directly from `cursor-team-kit/skills/deslop/SKILL.md` at the recorded upstream pin. Both the standalone skill and the poteto-mode reference use the same source. `DESLOP_SOURCE.md` and `LICENSE-CURSOR-TEAM-KIT` carry its provenance and MIT license in the native package and inside both skill folders, so skills-only copies retain them. All upstream pstack skill bodies and playbooks remain unchanged. |


There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thermos listing descriptions do not match
Medium Severity · Bugbot Rules
Plugin listing
descriptionmust match verbatim across Claude listing surfaces. The marketplace Thermos entry saysIndependent correctness and code-quality branch reviews.while.claude-plugin/plugin.json(template and generated package) saysThermos correctness and code-quality reviews for Claude Code and Codex.That split listing copy leaves marketplace and install UI out of sync.Additional Locations (1)
tools/portable/thermos-assets/.claude-plugin/plugin.json#L3-L4Triggered by learned rule: Plugin listing copy must match plugin.json and marketplace.json
Reviewed by Cursor Bugbot for commit a57e1f0. Configure here.