@kody/planetscale
README.md
218 lines · 8.2 KB · Markdown@kody/planetscale
Intent
Reusable PlanetScale Insights helpers so a forked Kody package can turn a slow query into the loop people actually want: open a GitHub issue, launch an implementer that opens a PR, let a reviewer agent look at that PR, then ping a human. Success is a dry-run draft you can inspect, then a confirmed run that does not start from scratch each time.
This listing is meant to be forked. After you fork, save your own
planetscaleApiToken, point configure-loop at your org/database/repo, and
keep loopEnabled off until you want webhooks or the poll job to create
issues. No personal organization ids, database names, or tokens are hard-coded.
Share this package as https://kody.codes/@kody/planetscale
(never a /community/{listing_id} URL).
The loop
- PlanetScale Insights reports an anomaly (
branch.anomalywebhook or a poll). draft-loopwrites the GitHub issue body, implementer prompt, reviewer prompt, and human ping.run-loop(afterconfirm: true) opens the issue, launches a Cursor Cloud implementer withautoCreatePR, and asks Cursor to request a reviewer.- The human gets an email ping (and
@kody/notifyif that fork is configured). - Repeat when Insights flags the next slow query.
run-loop remembers the last processed anomaly id in packageStorage(), so the
same signal does not open a new issue every poll.
Auth
PlanetScale service tokens are sent as Authorization: SERVICE_TOKEN_ID:SERVICE_TOKEN
with no scheme. Save that exact id:token value in Kody.
- Create a token in the PlanetScale dashboard
with at least
read_organization,read_database, and Insights read. Addwrite_databaseonly if you will create thebranch.anomalywebhook from this package. - Save it in Kody (do not paste the value in chat):
https://kody.codes/account/secrets/new?name=planetscaleApiToken&description=PlanetScale%20service%20token%20as%20SERVICE_TOKEN_ID%3ASERVICE_TOKEN%20for%20api.planetscale.com&allowedHosts=api.planetscale.com&scope=user- Approve host
api.planetscale.com. - Optional webhook HMAC secret (header
X-PlanetScale-Signature, SHA-256 hex):
https://kody.codes/account/secrets/new?name=planetscaleWebhookSecret&description=PlanetScale%20webhook%20HMAC%20secret%20(X-PlanetScale-Signature)&allowedHosts=api.planetscale.com&scope=userPass account: "work" to use secret planetscaleApiToken-work, or pass
secretName: "planetscaleApiToken-work". There are no hard-coded account aliases.
Hosts
api.planetscale.com— all REST calls (required)
GitHub, Cursor, and notify
Live loop steps call official helpers:
kody:@kody/github/request—POST /repos/{owner}/{repo}/issueskody:@kody/cursor/agents—createAgentwithautoCreatePR: trueand a reviewer requestkody.email_send— ping the signed-in Kody userkody:@kody/notify— extra fanout after you fork notify and save your channels
createAgent has no dry-run. This package never calls it unless confirm: true.
Connect GitHub OAuth (https://kody.codes/connect/oauth?provider=github) and
save a Cursor API key before a live run. @kody/notify platform storage is not
your inbox — fork notify first if you want Slack/Discord/Telegram.
The implementer prompt tells the Cursor agent to open the PR itself with ManagePullRequest. Kody does not open that PR as a substitute.
Mutation safety
configure-loop defaults to { dryRun: true, wouldSave } and writes
packageStorage() only with confirm: true.
run-loop defaults to a preview { dryRun: true, draft, wouldCall }. Live
GitHub issues, Cursor agents, and pings require confirm: true.
create-webhook and mutating request calls throw unless confirm: true.
Pass dryRun: true to preview.
The declared poll-anomalies job starts disabled. The insights webhook
stays draft-only until configure-loop saves loopEnabled: true.
import runLoop from 'kody:@kody/planetscale/run-loop'
const preview = await runLoop({
organization: 'acme',
database: 'app',
branch: 'main',
githubOwner: 'acme',
githubRepo: 'app',
dryRun: true,
})
const live = await runLoop({
organization: 'acme',
database: 'app',
branch: 'main',
githubOwner: 'acme',
githubRepo: 'app',
confirm: true,
})Smoke test
import smokeTest from 'kody:@kody/planetscale/smoke-test'
export default async function main() {
return await smokeTest()
}Without planetscaleApiToken this still returns { ok: true, live: false }
plus setup URLs and a fixture loop draft. With credentials it lists
organizations and does not return billing emails. It never opens issues or
agents.
Quick start after fork
import configureLoop from 'kody:@kody/planetscale/configure-loop'
import runLoop from 'kody:@kody/planetscale/run-loop'
export default async function main() {
await configureLoop({
organization: 'acme',
database: 'app',
branch: 'main',
githubOwner: 'acme',
githubRepo: 'app',
repositoryUrl: 'https://github.com/acme/app',
confirm: true,
})
return await runLoop({ dryRun: true })
}To let the insights webhook or an enabled poll create issues:
import configureLoop from 'kody:@kody/planetscale/configure-loop'
export default async function main() {
return await configureLoop({ loopEnabled: true, confirm: true })
}Then create a PlanetScale webhook for branch.anomaly that POSTs to this
package's insights webhook URL. Preview the PlanetScale side first:
import createWebhook from 'kody:@kody/planetscale/create-webhook'
export default async function main() {
return await createWebhook({
organization: 'acme',
database: 'app',
url: 'https://YOUR-KODY-INSIGHTS-WEBHOOK',
dryRun: true,
})
}Exports
kody:@kody/planetscale— action dispatcher (defaults to overview)kody:@kody/planetscale/accounts— resolve secret name and setup URLskody:@kody/planetscale/smoke-test— credential-optional smoke testkody:@kody/planetscale/list-organizations— list organizations (read-only)kody:@kody/planetscale/list-databases— list databases (read-only)kody:@kody/planetscale/list-branches— list branches (read-only)kody:@kody/planetscale/list-anomalies— list Insights anomalies (read-only)kody:@kody/planetscale/list-queries— list Insights queries, default sortp99_latency(read-only)kody:@kody/planetscale/draft-loop— format issue + prompts (no writes)kody:@kody/planetscale/configure-loop— save org/db/repo targets (dryRun/confirm)kody:@kody/planetscale/run-loop— preview or run the issue → PR → ping loopkody:@kody/planetscale/handle-webhook—branch.anomalywebhook handlerkody:@kody/planetscale/poll-anomalies— scheduled Insights poll (job starts disabled)kody:@kody/planetscale/create-webhook— create a PlanetScale webhook (dryRun/confirm)kody:@kody/planetscale/request— low-level PlanetScale API escape hatchkody:@kody/planetscale/types— shared TypeScript types
Notes
- REST base:
https://api.planetscale.com/v1 - List helpers return
{ items, pageInfo }. - Insights dashboard URLs look like
https://app.planetscale.com/{org}/{db}/{branch}/insights. branch.anomalywebhook bodies includeorganization,database, andresource.name(the branch). The handler then lists Insights anomalies.- This package is not affiliated with or endorsed by PlanetScale.
Branding
community-icon.svg is PlanetScale's official white logomark from
planetscale.com/brand
(planetscale-logo-mark-white.svg on black #000000). Paths are unmodified
except for a square tile so the mark stays legible at 56 pixels.
PlanetScale® is a trademark of PlanetScale, Inc. This package is not
affiliated with or endorsed by PlanetScale.