@kody/origin
README.md
162 lines · 6.3 KB · Markdown@kody/origin
Intent
Give Kody agents a durable, secret-safe way to call the Cursor Origin REST API (repos, pull requests, installation discovery, and a raw request escape hatch) using an Origin App. Cloud Agents API keys are not Origin credentials.
This package mints short-lived app JWTs through secret_jwt_sign (EdDSA) and
exchanges them for installation tokens. The Ed25519 private key never enters
package or execute code. Writes default to dry-run and require confirm: true.
Jobs are not enabled.
Share this listing at https://kody.codes/@kody/origin
What this package does
After you save an Origin App private key and app/installation ids, agents can:
- Verify the Origin App rate-limit budget (
rate-limit) - List installations and installation-visible repos
- List or fetch repositories and pull requests
- Preview or apply writes (
reposcreate,pullscreate/update/merge, rawrequest) - Persist app and installation ids in this package's storage (
settings)
It does not create an Origin App for you, and it does not back Kody package source. Artifacts remains the durable home for Kody repos.
Setup
Follow coding_guide_get({ guide: "provider_origin" }). Origin Apps live at
cursor.com/codebase/settings/apps.
- Create an Origin App and copy the app id (
app_01…). - Generate an Ed25519 key pair locally. Register only the public key on the app. Keep the PKCS#8 private key out of chat and out of git.
- Install the app into a codebase. After install, copy the installation id (
i_01…). - Save the private key in Kody (do not paste it in chat):
https://kody.codes/account/secrets/new?name=originAppPrivateKey&description=Origin%20App%20Ed25519%20PKCS%238%20private%20key&allowedHosts=api.cursor.com&allowedCapabilities=secret_jwt_sign&scope=userApprove host api.cursor.com and capability secret_jwt_sign.
- Persist the readable ids with
./settings(confirm: true), or passappId/installationIdon each call. Leftover user values namedoriginAppId/originInstallationIdare copied into package storage on first read.
Default helper input: omit account, integrationName, and secretName. The package uses secret originAppPrivateKey and storage keys originAppId / originInstallationId.
There is no Origin OAuth lane. /connect/oauth is not used here.
Multiple Origin Apps
Every export accepts optional account / integrationName (default origin) and secretName. Extra apps use a distinct namespace — for example origin-work — which reads secret originAppPrivateKey-origin-work and storage keys originAppId-origin-work / originInstallationId-origin-work. Or pass secretName explicitly.
import getOriginRateLimit from 'kody:@kody/origin/rate-limit'
export default async function main() {
return await getOriginRateLimit({ integrationName: 'origin-work' })
}account is accepted as an alias for integrationName. There are no hard-coded personal aliases. When more than one installation is visible and none is saved, helpers throw instead of picking one.
Mutations and dryRun
Create/update/merge helpers, settings writes, and REST methods other than GET / HEAD / OPTIONS require:
dryRun: true— validate and return a preview; Origin is not writtenconfirm: true— perform the live write
import { createOriginPull } from 'kody:@kody/origin/pulls'
export default async function main() {
return await createOriginPull({
ownerSlug: 'example-owner',
repoName: 'example',
title: 'Example',
head: 'topic',
base: 'main',
dryRun: true,
})
}Internal installation-token minting is auth, not a caller-facing mutation.
Smoke tests
Run these from execute after the secret exists. Prefer a static
kody:@kody/origin import — packages.invoke({ kodyId: "origin" }) may resolve
a different origin package.
Package overview (no credentials)
import describeOrigin from 'kody:@kody/origin'
export default async function main() {
return await describeOrigin()
}A successful response includes package: "@kody/origin" and secretSetupUrl.
Rate limit (Origin App)
import getOriginRateLimit from 'kody:@kody/origin/rate-limit'
export default async function main() {
return await getOriginRateLimit()
}A 401 that says the request is missing a Bearer token usually means Origin did not accept the credential kind — confirm you are signing with the Origin App private key, not cursorApiKey.
Mutation preview
import originRequest from 'kody:@kody/origin/request'
export default async function main() {
return await originRequest({
method: 'POST',
path: '/repos/example-owner',
body: { name: 'example' },
dryRun: true,
})
}Exports
kody:@kody/origin— package overview and setup URLskody:@kody/origin/accounts— Origin App lane and multi-account guidancekody:@kody/origin/rate-limit— zero-cost rate-limit smoke testkody:@kody/origin/auth— sign an app JWT / mint an installation token (no token value)kody:@kody/origin/installations— list installations and installation reposkody:@kody/origin/repos— list, get, or create repositories (createisdryRun/confirm)kody:@kody/origin/pulls— list, get, create, update, or merge pull requests (writes aredryRun/confirm)kody:@kody/origin/request— raw/v1/originrequest helperkody:@kody/origin/settings— read or persist app / installation idskody:@kody/origin/migrate-from-values— copy leftover user values into package storagekody:@kody/origin/types— shared TypeScript types
Notes
- Origin tokens last at most 15 minutes. This package mints them per call.
- Repositories Origin mirrors in from GitHub are outside the installation.
- Native Origin repos and repos Origin mirrors out to GitHub are in scope.
- Artifacts remains the durable home for Kody package source.
Branding
community-icon.svg is Cursor's official cube mark (white cube on black). Cursor and Origin are trademarks of Anysphere, Inc. This package is not affiliated with or endorsed by Cursor.
Docs
- Origin API
- Connect Origin (
coding_guide_get({ guide: "provider_origin" }))