diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json new file mode 100644 index 000000000..8d18083d7 --- /dev/null +++ b/.claude-plugin/marketplace.json @@ -0,0 +1,14 @@ +{ + "name": "cursor-plugins", + "owner": { + "name": "Cursor", + "email": "plugins@cursor.com" + }, + "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." + } + ] +} diff --git a/.cursor-plugin/marketplace.json b/.cursor-plugin/marketplace.json index 50f8c2710..bf0d0b7a4 100644 --- a/.cursor-plugin/marketplace.json +++ b/.cursor-plugin/marketplace.json @@ -63,6 +63,11 @@ "source": "cursor-sdk", "description": "Build apps, scripts, and automations with the TypeScript SDK." }, + { + "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": "orchestrate", "source": "orchestrate", diff --git a/README.md b/README.md index f5e95e019..59acad9d5 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ Official Cursor plugins for popular developer tools, frameworks, and SaaS produc | `pr-review-canvas` | [PR Review Canvas](pr-review-canvas/) | Cursor | Developer Tools | Render PR diffs as review canvases grouped by importance. | | `docs-canvas` | [Docs Canvas](docs-canvas/) | Cursor | Developer Tools | Render documentation as a navigable canvas. | | `cursor-sdk` | [Cursor SDK](cursor-sdk/) | Cursor | Developer Tools | Build apps, scripts, and automations with the TypeScript SDK. | +| `origin-apps` | [Origin Apps](origin-apps/) | Cursor | Developer Tools | 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. | | `orchestrate` | [Orchestrate](orchestrate/) | Cursor | Developer Tools | Fan large tasks out across parallel cloud agents with planners, workers, verifiers, and structured handoffs. | | `pstack` | [pstack](pstack/) | Lauren Tan | Developer Tools | 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. | | `advisor` | [Advisor](advisor/) | Cursor | Developer Tools | Consult a stronger model before major decisions, when stuck, and before declaring done. | diff --git a/origin-apps/.claude-plugin/plugin.json b/origin-apps/.claude-plugin/plugin.json new file mode 100644 index 000000000..ac67f840d --- /dev/null +++ b/origin-apps/.claude-plugin/plugin.json @@ -0,0 +1,20 @@ +{ + "name": "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.", + "version": "0.1.0", + "author": { + "name": "Cursor", + "email": "plugins@cursor.com" + }, + "homepage": "https://cursor.com/docs/api/origin", + "repository": "https://github.com/cursor/plugins", + "license": "MIT", + "keywords": [ + "origin", + "origin-api", + "origin-app", + "webhooks", + "github-app" + ], + "skills": "./skills/" +} diff --git a/origin-apps/.cursor-plugin/plugin.json b/origin-apps/.cursor-plugin/plugin.json new file mode 100644 index 000000000..bace67665 --- /dev/null +++ b/origin-apps/.cursor-plugin/plugin.json @@ -0,0 +1,29 @@ +{ + "name": "origin-apps", + "displayName": "Origin Apps", + "version": "0.1.0", + "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.", + "author": { + "name": "Cursor", + "email": "plugins@cursor.com" + }, + "homepage": "https://cursor.com/docs/api/origin", + "repository": "https://github.com/cursor/plugins", + "license": "MIT", + "keywords": [ + "cursor-plugin", + "origin", + "origin-api", + "origin-app", + "webhooks", + "github-app" + ], + "category": "developer-tools", + "tags": [ + "origin", + "origin-api", + "webhooks", + "github-app" + ], + "skills": "./skills/" +} diff --git a/origin-apps/CHANGELOG.md b/origin-apps/CHANGELOG.md new file mode 100644 index 000000000..0becd4d61 --- /dev/null +++ b/origin-apps/CHANGELOG.md @@ -0,0 +1,5 @@ +# Changelog + +## 0.1.0 + +Initial release with two skills, `origin-api` and `port-github-app-to-origin`. diff --git a/origin-apps/LICENSE b/origin-apps/LICENSE new file mode 100644 index 000000000..ca2bba771 --- /dev/null +++ b/origin-apps/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Cursor + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/origin-apps/README.md b/origin-apps/README.md new file mode 100644 index 000000000..272a728d8 --- /dev/null +++ b/origin-apps/README.md @@ -0,0 +1,62 @@ +# Origin Apps + +Two skills for building on [Cursor Origin](https://cursor.com/docs/api/origin), +Cursor's code forge. They cover creating an Origin App, calling the API, +receiving webhooks, and moving an existing GitHub App over. The plugin is +skills only, so it runs in Cursor, Claude Code, Codex, and any agent that +reads [Agent Skills](https://agentskills.io). + +## What it includes + +`origin-api` sends the agent to the section of the Origin docs that answers +its question and lists the rules to check first: native versus mirrored +repositories, event subscriptions, webhook verification, scopes from the +spec, opaque tokens and IDs. Use it for any Origin work. + +`port-github-app-to-origin` plans the move of an existing GitHub App. Run it +inside the app's repository. It reads what the app uses out of the code, +maps that onto the live Origin spec, and writes a porting brief with what +carries over and what does not, the webhook fields your handlers read and +where each comes from on Origin, the scopes to request, an end-to-end test +for your app, feedback for Cursor, and the questions your team has to +decide. It plans. It writes no code unless you ask. + +Both skills read the live spec at run time and never name an endpoint from memory. + +## When to use + +Ask about the Origin API, or ask to port a GitHub App, and the matching skill +loads. In Cursor you can also run `/origin-api` or +`/port-github-app-to-origin`. + +## Install in Cursor + +Search for Origin Apps in the Cursor Marketplace +([cursor.com/marketplace/origin-apps](https://cursor.com/marketplace/origin-apps)), +or open Customize, find the plugin, and install it at user or project scope. + +## Use outside Cursor + +The skills use only portable [Agent Skills](https://agentskills.io) +frontmatter. In Claude Code: `/plugin marketplace add cursor/plugins` then +`/plugin install origin-apps@cursor-plugins`. Any other agent: copy +`origin-apps/skills/*` into its skills folder (copy both; the porting skill +refers to `origin-api`). + +## Requirements + +- Network access to `https://cursor.com/docs/api/origin/*` during the run. +- For the porting skill, read access to the app's source. Writing the brief + needs no Origin credentials. You run the brief's end-to-end test + afterwards. + +## Where the brief goes + +The porting skill writes `ORIGIN-PORTING-BRIEF.md` at the repository root and +prints its path. When there is feedback for Cursor, it also writes that +section to `ORIGIN-FEEDBACK.md`, ready to send as is; the rest of the brief +is for your team. + +## License + +MIT diff --git a/origin-apps/plugin.json b/origin-apps/plugin.json new file mode 100644 index 000000000..5f0961dbe --- /dev/null +++ b/origin-apps/plugin.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json", + "name": "origin-apps", + "version": "0.1.0", + "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.", + "author": { + "name": "Cursor", + "email": "plugins@cursor.com" + }, + "homepage": "https://cursor.com/docs/api/origin", + "repository": "https://github.com/cursor/plugins", + "license": "MIT", + "keywords": [ + "origin", + "origin-api", + "origin-app", + "webhooks", + "github-app" + ] +} diff --git a/origin-apps/skills/origin-api/SKILL.md b/origin-apps/skills/origin-api/SKILL.md new file mode 100644 index 000000000..a791bc455 --- /dev/null +++ b/origin-apps/skills/origin-api/SKILL.md @@ -0,0 +1,72 @@ +--- +name: origin-api +description: >- + Routes questions about the Cursor Origin API to the right section of the + Origin docs and names the few rules to check first. Use when a task mentions + Origin, the Origin API, Origin Apps, or Origin webhooks, including creating + an Origin App, authenticating as one, calling Origin endpoints, or handling + Origin webhook deliveries. +license: MIT +compatibility: >- + Needs network access to https://cursor.com/docs/api/origin/* at run time. +--- + +# Origin API + +The docs are the source of truth. Do not name an endpoint, scope, event slug, +header, or limit from memory. Where this file and the docs disagree, the docs +win. + +The docs live under `https://cursor.com/docs/api/origin/`. `llms.txt` is +the index and links every section, endpoint, and webhook payload. +`openapi.yaml` is the contract, and "Endpoint reference" explains its +`x-origin-*` extensions. `llms-full.txt` is the whole reference in one file. +`changelog` says what moved. For one question, start at `llms.txt` and +fetch only the section that answers it. `llms-full.txt` and `openapi.yaml` +are each several hundred kilobytes, too large to read into context whole. +When you need all of them, as a porting brief does, save them locally if you +can, outside any repository you are working in, search them for the section +heading or annotation you need, and read only the matching part. Cite +`operationId`s and section names. + +## Where to look + +| Question | Section | +| --- | --- | +| Which credential for which call; minting and lifetime | "Authentication" and its subsections | +| Install flow and the callback receipt | "Installation", "Installation receipt" | +| Which scope an operation needs | `x-origin-scopes` on the operation; "Scopes" | +| What an installation can do on a mirrored repository | "Mirrored repositories" | +| Webhook headers, signature, delivery format, retries, pausing, recovery | "Webhooks" | +| Which events exist and which arrive without subscribing | "Events" | +| Payload shapes | "Event payloads" | +| Pagination, errors, request IDs, repository paths, IDs | "Common conventions" | +| Rate limits | "Rate limits" | +| Check-run keys, attempts, stale writes | "Check runs" | +| What is not there yet | "Current limitations" | +| A checklist to build against | "Implementation checklist" | + +## Rules to check first + +1. **Native or mirror.** An installation keeps its full scopes only on + native repositories (created on Origin) and stable outbound mirrors + (Origin is the source and pushes to GitHub). A stable outbound mirror is + not a merge target: Merge Pull Request works only on native repositories, + and so does changing the default branch. Read each operation's description + for mirror limits. + On a repository mirrored from GitHub, every event except + `repository.pushed` still arrives, and every call beyond metadata and + contents reads returns `403` ("Mirrored repositories", "Events"). +2. **Subscribe.** Only `installation.*` events arrive without a subscription. + A missing subscription produces silence, not an error ("Events"). +3. **Verify, dedupe, acknowledge.** Verify the signature over the raw body + before parsing, dedupe on the delivery ID, return `2xx`, then process + ("Signature verification", "Retries", "Automatic disable"). Origin signs + a digest, which Standard Webhooks does not, so a generic verifier fails. +4. **Scopes from the spec.** Request the union of `x-origin-scopes.scopes` + over the operations the app calls ("Scopes"). +5. **Opaque tokens and IDs.** Do not build or parse page tokens or IDs + ("Pagination", "IDs"). + +Porting an existing GitHub App: use `port-github-app-to-origin` in this +plugin. diff --git a/origin-apps/skills/port-github-app-to-origin/SKILL.md b/origin-apps/skills/port-github-app-to-origin/SKILL.md new file mode 100644 index 000000000..0002dcf48 --- /dev/null +++ b/origin-apps/skills/port-github-app-to-origin/SKILL.md @@ -0,0 +1,99 @@ +--- +name: port-github-app-to-origin +description: >- + Plans the port of an existing GitHub App to a Cursor Origin App. Use when the + task is to bring a GitHub App to Origin or compare what it uses against the + Origin API. Reads the app's needs out of its code, maps them onto the live + Origin spec, and writes a porting brief with feedback for Cursor. Planning + only. +license: MIT +compatibility: >- + Needs network access to https://cursor.com/docs/api/origin/* at run time. +--- + +# Port a GitHub App to an Origin App + +Run this inside the app's codebase. The output is a porting brief for the +team plus a Feedback for Cursor section they can send as is +(`references/brief.md`). This skill plans. It does not write or change code +unless the user asks for that after reading the brief. Follow the +`origin-api` skill for the docs and the rules to check first. Two more rules: + +1. **Find it in the code, do not ask.** Read what the app uses out of its + source. Anything you cannot find becomes a question for the team. +2. **Feedback describes use cases, not the team's code.** The team's parts of + the brief may cite `file:line`. Feedback for Cursor says only what the app + needs to do and what Origin lacks for it, in Origin terms, with no file + paths, module names, framework details, or repository names. + +## What to find + +Record `file:line` for each item, and note what you looked for but did not +find. + +- Declared permissions and events, from a manifest or infrastructure code + if one is checked in. Otherwise derive them from the calls. +- Every webhook event the app handles, and every payload field each handler + reads, including fields it only logs. +- Every REST and GraphQL call, with the parameters and filters the code + passes, the response fields it reads, whether it runs on every webhook or + in a loop, and how it paginates. +- Authentication: the JWT algorithm, how the app learns the installation ID + after install, how it handles token expiry, any user sign-in and what it is + for, and whether the app clones or pushes git. +- The webhook receiver: how it verifies signatures, whether it has the raw + body when it verifies, and how it deduplicates deliveries. +- Calls a framework or library makes for the app. Probot's receiver, token + cache, and config loader; Octokit `App`'s installation and repository + listing; app-auth libraries. Read the dependency's docs and list these + calls marked "from ``". + +## How to map + +A brief needs the whole spec, but `openapi.yaml` and `llms-full.txt` are +each several hundred kilobytes, too large to read into context whole. Save +them locally if you can, in a temporary location outside the app's +repository so nothing in the working tree is overwritten or left behind, +then search them and read only the matching part: + +- `x-origin-scopes:` in `openapi.yaml` marks every operation with its + scopes; the `operationId` sits a line above. +- `x-origin-webhook-events:` in `openapi.yaml` marks every webhook payload + schema with the event slugs that deliver it. +- `### ` and `### ` headings in `llms-full.txt` + start the section that spells out that endpoint's or payload's fields as + dotted paths; read from the heading to the next `###`. + +For a single question later, start at `llms.txt` and fetch just that +section. + +- A matching name is a candidate, not an answer. Read the operation's + description, parameters, and response fields against what the code passes + and reads. If a parameter or field the code depends on is missing, that is + a workaround or a gap, not a match. +- GitHub's pull request calls that live under `/issues/{n}/…` (comments, + labels) live under the pull request endpoints on Origin. If the code uses + them on real issues, see "Where GitHub features live on Origin" in + `references/brief.md`. +- Origin has no GraphQL. Break each query into REST calls and record the + fan-out. +- The scopes to request are the union of `x-origin-scopes.scopes` over the + operations you named. Do not translate the GitHub manifest. +- Each GitHub event and action pair maps to at most one slug in "Events". The + action is part of the slug. A pair with no slug is not an event on Origin. +- For each payload field the code reads, record whether it is in the + payload, in the delivery envelope around the payload (`event.type` carries + the action), needs an extra read (say which operation and how many calls + per event), can be computed from other fields, or is missing. Payloads are + snapshots. A field the REST resource has but the payload lacks needs an + extra read. +- A capability the docs never mention is not available today. Ask the team + about it. A behavior the docs neither confirm nor deny gets a question plus + a step in the end-to-end test that checks it. Do not assume it works the + way it did on GitHub. + +## Before finishing + +Every claim about Origin points at something in the saved docs. Every gap +has a feedback entry that names its cost. The feedback reveals nothing about +the team's internals. The summary names the native-or-mirror question. diff --git a/origin-apps/skills/port-github-app-to-origin/references/brief.md b/origin-apps/skills/port-github-app-to-origin/references/brief.md new file mode 100644 index 000000000..4117c4f4e --- /dev/null +++ b/origin-apps/skills/port-github-app-to-origin/references/brief.md @@ -0,0 +1,128 @@ +# The brief and the feedback + +## The brief + +Write one Markdown file at the repository root (`ORIGIN-PORTING-BRIEF.md` +unless the team names files differently) and print its path. Aim for about +800 words for a small app and about 2,000 for a large one. Leave out any part +that has nothing to say. Pick whatever table shape fits the app. A good brief: + +- Opens with a summary. The verdict (ports as is, ports with workarounds, or + blocked on X), the question that decides the rest (usually whether the + repositories are native or mirrored), and whether there is feedback for + Cursor and if any of it blocks the port. +- Lists only the capabilities that do not carry over as is. For each, the + Origin operation, event slug, or docs section it maps to, or a note that + nothing does. Closes the list with one line for the rest, such as "14 + operations map directly; see the scopes line". Shows a webhook payload + field only when it is missing or needs an extra API call. Ends with the + scopes to request. +- Describes an end-to-end test for this app when that helps. Which events to + select, how to check the repository's mirror state, the first event that + should arrive and what it should contain, the first write. Skip generic + setup; the docs' "Implementation checklist" covers it. +- Says what makes the port big or small and how to roll it out (run both + versions side by side, or cut over). No time estimates. +- Asks only the questions the team has to decide. Do not turn a finding into + a question. +- Ends with two lines saying which spec version (`info.version` and fetch + time) and which code commit the brief is based on, then Feedback for + Cursor as the last section, without a number. + +Back every claim about the app with `file:line`, or with "from +``" when a library does it for the app. Back every claim about +Origin with something in the saved docs. If you want short labels in a +table, use plain ones: works as is, workaround (say the cost), not available +(ask the team), gap (write feedback). + +## Feedback for Cursor + +Cursor wants to hear what the team needs. Raise anything that blocks the +team's main flow, costs them correctness, security, or scale, or that they +would like Origin to do. The tests below only sort items into feedback (a +capability Origin should add) and questions (decisions the team must make). +They never decide whether to speak up. + +A workaround gets the same result another way, for example an extra read, a +different identifier, a changed path, filtering on the client, or a marker +the app controls. Often it is the right answer. It becomes a gap, and gets a +feedback entry, when it costs one of these: + +- fan-out, meaning extra calls per event, that grows with repository or + activity size at this app's volume; +- a possibly wrong answer, such as guessing which check run or comment is the + app's own, inferring a pull request from a SHA that several versions + share, or building a URL whose format the docs do not promise; +- a broader scope, a longer-lived token, or a user credential where an + installation token should be enough; +- a change to what the team's users see or can do; +- a capability the app's main flow or its first end-to-end test depends on. + +A state change the app exists to react to, with no event for it and no other +way to notice it, is also a gap. Something the docs never mention is not +available today and gets a question; it becomes feedback only if it blocks +the main flow. + +Not feedback, only a question or a note: a field or filter the code does not +use; a convention that differs but has a mechanical substitute; a documented +design choice such as token lifetime or no GraphQL. + +Write one entry per gap, in Origin terms, with nothing that reveals the +team's internals. When there is at least one entry, also write the section +to `ORIGIN-FEEDBACK.md` next to the brief. When there is none, write no file +and say so in one line. The file carries no license header, repository name, +product name, or mention of another forge. If the docs and observed +behavior disagree, put that in a short "Docs questions for Cursor" list at +the end of the feedback, not in the team's questions. A suggested shape: + +```markdown +### Feedback: +- **Use case:** the app needs to , . +- **Origin today:** . +- **Workaround considered:** . +- **Blocking?** yes / no, for which flow. +- **Spec version checked:** , . +``` + +Describe the capability. Do not propose scope, field, or route names. The +team sends the feedback, not you, and they remove anything that reveals +their internals first. + +## Where GitHub features live on Origin + +Check this before calling anything a gap, then confirm in the saved docs. +This list goes stale; the docs win. + +Has an Origin equivalent: install callback parameters → "Installation +receipt"; RS256 app JWT → "App JWT"; long-lived installation tokens → +"Installation access token"; permissions → "Scopes" and `x-origin-scopes`; +numeric IDs and `/repositories/{id}` → "IDs", "Repository paths"; `Link` +pagination and total counts → "Pagination"; commit statuses → check runs +with a stable `key` ("Check runs"); `/issues/{n}/comments` and +`/issues/{n}/labels` on a pull request → the pull request endpoints; +repository webhook CRUD → the app's `events` list on Create App and Update +App; one `pull_request` event with an `action` field → one slug per action +("Events"); `x-github-*` headers and HMAC signatures → "Headers", "Signature +verification"; data GitHub inlines in payloads (changed files, before-SHA, +URLs, user profiles) → extra reads ("Resource references", "Current +limitations"); reviews keyed by commit SHA → `pullRequestVersion`; finding +the app's own check runs or comments by author → the check run `key`, or a +marker the app controls; user sign-in and acting as a user → "Acting on +behalf of users" (user confirmation receipt, installation user tokens). + +Repositories mirrored from GitHub: an installation can only read metadata +and contents until the mirror becomes a stable outbound mirror (Origin is +the source and pushes to GitHub). Merging a pull request and changing the +default branch work only on native repositories, the ones created on Origin +("Mirrored repositories"). + +Not in the current spec (ask the team; feedback only if it blocks the main +flow): GraphQL (break each query into REST calls); Issues (pull request +comments, threads, reviews, and labels cover the pull request half); +OAuth-app token minting; writing arbitrary blobs or trees (commit-from-files +and pushes exist); looking up users, emails, teams, or members (reviewer +identifiers resolve by public id, email, or group slug); reading group +membership or a user's effective permission. For those last two, the +workaround to name is a user token limited to a repository and scopes. +Minting it returns `403` unless the user holds that permission, so it +doubles as a permission check.