Introduction
How Kody works
Official Kody doc
Let's say you use as your regular coding agent, as your chat agent on your phone, and as another agent you sometimes use. Here's an example of conversations you might have with them when they're connected to Kody.
You start on the computer with OpenCode.
Ask once
You What did my favorite bot ship recently on GitHub?
OpenCode Reasoning: I will look up GitHub user activity and any memory that names your favorite bot.
searchFind a saved GitHub token for user activitymemoryContext{ "task": "What did my favorite bot ship recently on GitHub?", "entities": [ "favorite bot" ] }query"github user activity"ReturnsconversationId: 3k7n2p9q4r8w Tool conversation id; pass it back on subsequent search/execute calls. # Search results For full detail on entity-backed hits, call `search` with `entity: "{id}:{type}"`. 1. **secret** `githubAccessToken` — github OAuth access token. Entity: `githubAccessToken:secret` ## Relevant memories - **Favorite bot** — kody-bot is my favorite bot. I'm really interested in what it ships on githubOpenCode Reasoning: Favorite bot is the GitHub account kody-bot. I will fetch its public events with the saved token.
executeFetch public events with the saved token and keep only real shipsconversationId"3k7n2p9q4r8w"memoryContext{ "task": "What did my favorite bot ship recently on GitHub?", "entities": [ "favorite bot" ] }codeexport default async function main() { const response = await fetch( 'https://api.github.com/users/kody-bot/events/public', { headers: { Accept: 'application/vnd.github+json', Authorization: 'Bearer {{secret:githubAccessToken}}', 'X-GitHub-Api-Version': '2022-11-28', }, }, ) if (!response.ok) throw new Error(`GitHub ${response.status}`) const events = await response.json() return events.flatMap((event) => { if ( event.type === 'ReleaseEvent' && event.payload.action === 'published' ) { return [{ id: event.id, kind: 'release', title: `${event.repo.name} ${event.payload.release.tag_name}`, }] } if ( event.type === 'CreateEvent' && event.payload.ref_type === 'repository' ) { return [{ id: event.id, kind: 'repository', title: `New repo ${event.repo.name}`, }] } return [] }) }ReturnsconversationId: 3k7n2p9q4r8w Tool conversation id; pass it back on subsequent search/execute calls. [ { "id": "51284920123", "kind": "release", "title": "kody-bot/lantern v1.4.0" }, { "id": "51279004401", "kind": "repository", "title": "New repo kody-bot/quiet-days" } ] ## Relevant memories - **Favorite bot** — kody-bot is my favorite bot. I'm really interested in what it ships on githubOpenCode Two things since the last look: kody-bot/lantern v1.4.0, and a new public repo kody-bot/quiet-days. Want this as a package so I can get you the answer quicker next time?
You Yes
OpenCode Reasoning: I will load the package authoring guides, then save the filter as an export you own.
searchFind the official package authoring guidesconversationId"3k7n2p9q4r8w"query"package authoring lifecycle"domain"coding"ReturnsconversationId: 3k7n2p9q4r8w Tool conversation id; pass it back on subsequent search/execute calls. # Search results For full detail on entity-backed hits, call `search` with `entity: "{id}:{type}"`. 1. **guide** Package authoring guide — START HERE when creating or materially changing a Kody package. Entity: `package_authoring:guide` 2. **guide** Durable package lifecycle guide — Choose reuse vs temporary execute vs a new durable package. Entity: `package_lifecycle:guide`
searchOpen the package authoring and lifecycle guidesconversationId"3k7n2p9q4r8w"entity[ "package_authoring:guide", "package_lifecycle:guide" ]ReturnsconversationId: 3k7n2p9q4r8w Tool conversation id; pass it back on subsequent search/execute calls. # Guide — `package_authoring` START HERE when creating or materially changing a Kody package. ## Summary - Entity: `package_authoring:guide` - Category: `platform` - Web: `/docs/package-authoring` # Package authoring guide Use this guide when creating a new Kody package or materially changing an existing one. ## Choose an authoring lane … --- # Guide — `package_lifecycle` Choose between invoking existing behavior, temporary execute exploration, and creating a durable repo-backed package. ## Summary - Entity: `package_lifecycle:guide` - Category: `platform` - Web: `/docs/package-lifecycle` # Durable package lifecycle Use this guide to decide whether to reuse existing behavior, explore with `execute`, or create durable repo-backed package code. Use it before scheduling new package behavior. ## Choose the smallest durable surface …OpenCode Reasoning: The authoring guide prefers the git lane. I will register a stub, clone it, write the export, push, and publish.
executeRegister the stub and mint a clone remoteconversationId"3k7n2p9q4r8w"memoryContext{ "task": "What did my favorite bot ship recently on GitHub?", "entities": [ "favorite bot" ] }codeimport { kody } from 'kody:runtime' export default async function main() { return await kody.packageGetGitRemote({ kody_id: 'kody-bot-shipped', create: true, description: 'What kody-bot shipped since you last asked.', }) }ReturnsconversationId: 3k7n2p9q4r8w Tool conversation id; pass it back on subsequent search/execute calls. { "package_id": "pkg_kody_bot_shipped", "kody_id": "kody-bot-shipped", "created": true, "remote": "https://acct.artifacts.cloudflare.net/git/default/package-pkg_kody_bot_shipped.git", "authenticated_remote": "[REDACTED SECRET]", "git_extra_header": "[REDACTED SECRET]", "scope": "write", "expires_at": "2026-08-13T18:52:00.000Z", "git_author": { "name": "You", "email": "you@example.com" }, "setup_commands": [ "git -c http.extraHeader='Authorization: Bearer [REDACTED SECRET]' clone 'https://acct.artifacts.cloudflare.net/git/default/package-pkg_kody_bot_shipped.git' 'pkg_kody_bot_shipped'", "cd 'pkg_kody_bot_shipped'", "git config --local user.email -- 'you@example.com'", "git config --local user.name -- 'You'", "git remote add kody 'https://acct.artifacts.cloudflare.net/git/default/package-pkg_kody_bot_shipped.git'", "git config remote.kody.fetch '+refs/heads/*:refs/remotes/kody/*'", "git config --add remote.kody.fetch '+refs/notes/*:refs/notes/*'", "git -c http.extraHeader='Authorization: Bearer [REDACTED SECRET]' fetch kody 'refs/notes/*:refs/notes/*'", "git -c http.extraHeader='Authorization: Bearer [REDACTED SECRET]' push kody HEAD:'main'" ] }filesWrite the export in the temporary clone
package.jsonExport only — no job yet
{ "name": "@you/kody-bot-shipped", "private": true, "exports": { "./whatShipped": "./src/what-shipped.ts" }, "kody": { "id": "kody-bot-shipped", "description": "What kody-bot shipped since you last asked." } }README.mdWhy this package exists
# kody-bot-shipped ## Intent Tell me what kody-bot shipped — published releases and new public repos — since I last asked.src/what-shipped.tsFilter public events and advance the cursor
import { packageStorage } from 'kody:runtime' const login = 'kody-bot' const seenKey = 'lastSeenEventId' export default async function whatShipped() { const storage = packageStorage() const sinceId = (await storage.get(seenKey)) as string | null const shipped = await listShipped(sinceId) if (shipped[0]) await storage.set(seenKey, shipped[0].id) return shipped.length === 0 ? { shipped, message: 'Nothing new.' } : { shipped, message: shipped.map((item) => item.title).join('\n') } } async function listShipped(sinceId: string | null) { const response = await fetch( `https://api.github.com/users/${login}/events/public`, { headers: { Accept: 'application/vnd.github+json', Authorization: 'Bearer {{secret:githubAccessToken}}', 'X-GitHub-Api-Version': '2022-11-28', }, }, ) if (!response.ok) throw new Error(`GitHub ${response.status}`) const events = (await response.json()) as Array<{ id: string type: string repo: { name: string } payload: { action?: string ref_type?: string release?: { tag_name?: string } } }> const shipped = [] for (const event of events) { if (sinceId && event.id === sinceId) break if ( event.type === 'ReleaseEvent' && event.payload.action === 'published' ) { shipped.push({ id: event.id, kind: 'release', title: `${event.repo.name} ${event.payload.release?.tag_name ?? 'release'}`, }) } if ( event.type === 'CreateEvent' && event.payload.ref_type === 'repository' ) { shipped.push({ id: event.id, kind: 'repository', title: `New repo ${event.repo.name}`, }) } } return shipped }
executePublish Artifacts HEAD as the owned packageconversationId"3k7n2p9q4r8w"memoryContext{ "task": "What did my favorite bot ship recently on GitHub?", "entities": [ "favorite bot" ] }codeimport { kody } from 'kody:runtime' export default async function main() { return await kody.packagePublishExternalPush({ kody_id: 'kody-bot-shipped', }) }ReturnsconversationId: 3k7n2p9q4r8w Tool conversation id; pass it back on subsequent search/execute calls. { "status": "published", "previous_commit": "4c1a0e8b2d91", "published_commit": "7f3a91c2e8b4", "manifest": { "name": "@you/kody-bot-shipped", "private": true, "exports": { "./whatShipped": "./src/what-shipped.ts" }, "kody": { "id": "kody-bot-shipped", "description": "What kody-bot shipped since you last asked." } }, "checks": [ { "kind": "manifest", "ok": true, "message": "ok" } ], "hosted_app_url": null, "static_dependents": { "total": 0, "items": [] }, "pending_secret_package_approvals": null }OpenCode You now have `@you/kody-bot-shipped`. Ask again from any agent and I will invoke the export instead of walking GitHub by hand.
Later, on your phone with Grok Bot.
Ask again. Now safer, cheaper, and more reliable.
You Anything interesting shipped by my favorite bot recently?
Grok Bot Reasoning: I will search for a package that already answers this.
searchFind the owned package, not a new GitHub walkmemoryContext{ "task": "Anything interesting shipped by my favorite bot recently?", "entities": [ "favorite bot" ] }query"anything interesting shipped favorite bot"ReturnsconversationId: 5h8m2q7t1v4x Tool conversation id; pass it back on subsequent search/execute calls. # Search results For full detail on entity-backed hits, call `search` with `entity: "{id}:{type}"`. 1. **package** @you/kody-bot-shipped (`kody-bot-shipped`) — What kody-bot shipped since you last asked. Entity: `kody-bot-shipped:package` ## Relevant memories - **Favorite bot** — kody-bot is my favorite bot. I'm really interested in what it ships on github
executeInvoke the export — no model rewriting the filterconversationId"5h8m2q7t1v4x"memoryContext{ "task": "Anything interesting shipped by my favorite bot recently?", "entities": [ "favorite bot" ] }codeimport whatShipped from 'kody:@you/kody-bot-shipped/whatShipped' export default async function main() { return await whatShipped() }ReturnsconversationId: 5h8m2q7t1v4x Tool conversation id; pass it back on subsequent search/execute calls. { "shipped": [], "message": "Nothing new." } ## Relevant memories - **Favorite bot** — kody-bot is my favorite bot. I'm really interested in what it ships on githubGrok Bot Nothing interesting has shipped.
Later still, with Codex.
Ask to be notified.
You Update me when kody-bot does something.
Codex Reasoning: I will search for how to notify you when this package has something new.
searchFind how to notify when the export has newsmemoryContext{ "task": "Update me when kody-bot does something.", "entities": [ "kody-bot" ] }query"notify when github user ships"ReturnsconversationId: 8w3k6n1p5r9t Tool conversation id; pass it back on subsequent search/execute calls. # Search results For full detail on entity-backed hits, call `search` with `entity: "{id}:{type}"`. 1. **guide** Durable package lifecycle guide — Choose reuse vs temporary execute vs a new durable package. Entity: `package_lifecycle:guide` 2. **capability** `webhookUrlMint` (`webhooks`) — Mint an inbound webhook URL for a package-declared webhook. Entity: `webhookUrlMint:capability` 3. **capability** `jobList` (`jobs`) — List scheduled jobs for the signed-in user. Entity: `jobList:capability` ## Relevant memories - **Favorite bot** — kody-bot is my favorite bot. I'm really interested in what it ships on github
searchOpen the package lifecycle guideconversationId"8w3k6n1p5r9t"entity"package_lifecycle:guide"ReturnsconversationId: 8w3k6n1p5r9t Tool conversation id; pass it back on subsequent search/execute calls. # Guide — `package_lifecycle` Choose between invoking existing behavior, temporary execute exploration, and creating a durable repo-backed package. ## Summary - Entity: `package_lifecycle:guide` - Category: `platform` - Web: `/docs/package-lifecycle` # Durable package lifecycle Use this guide to decide whether to reuse existing behavior, explore with `execute`, or create durable repo-backed package code. Use it before scheduling new package behavior. ## Choose the smallest durable surface …Codex Reasoning: Inbound webhooks are URLs I host, not a GitHub feed of one person’s public activity. Recurring schedules belong on a package under `kody.jobs`. I will open a repo session, patch in a daily cron wrapper, test it, then enable the job.
executePatch the package in a repo session, job left offconversationId"8w3k6n1p5r9t"memoryContext{ "task": "Update me when kody-bot does something.", "entities": [ "kody-bot" ] }codeimport { kody } from 'kody:runtime' const dailyDigest = `import { kody } from 'kody:runtime' import whatShipped from './what-shipped.ts' export default async function dailyDigest() { const result = await whatShipped() if (result.shipped.length === 0) return { emailed: false } await kody.emailSend({ subject: result.shipped.length === 1 ? 'kody-bot shipped something' : \`kody-bot shipped \${result.shipped.length} things\`, text: result.message, }) return { emailed: true, count: result.shipped.length } } ` export default async function main() { const session = await kody.repoOpenSession({ target: { kind: 'package', kody_id: 'kody-bot-shipped' }, conversation_id: '8w3k6n1p5r9t', }) await kody.repoEditFiles({ session_id: session.id, edits: [ { kind: 'write', path: 'src/daily-digest.ts', content: dailyDigest, }, { kind: 'replace', path: 'package.json', search: ' "./whatShipped": "./src/what-shipped.ts"', replacement: ' "./whatShipped": "./src/what-shipped.ts",\n "./daily-digest": "./src/daily-digest.ts"', }, { kind: 'replace', path: 'package.json', search: ' "description": "What kody-bot shipped since you last asked."', replacement: ` "description": "What kody-bot shipped since you last asked.", "jobs": { "daily-digest": { "entry": "./src/daily-digest.ts", "schedule": { "type": "cron", "expression": "0 8 * * *" }, "timezone": "America/Denver", "enabled": false } }`, }, { kind: 'replace', path: 'README.md', search: 'since I last asked.', replacement: 'since I last asked. Email me only when that list is not empty.', }, ], }) await kody.repoCommit({ session_id: session.id, message: 'Add a quiet daily digest job', }) const checks = await kody.repoRunChecks({ session_id: session.id }) const published = await kody.repoPublishSession({ session_id: session.id, }) return { session_id: session.id, checks, published } }ReturnsconversationId: 8w3k6n1p5r9t Tool conversation id; pass it back on subsequent search/execute calls. { "session_id": "rs_kody_bot_shipped", "checks": { "ok": true, "results": [ { "kind": "manifest", "ok": true, "message": "ok" }, { "kind": "typecheck", "ok": true, "message": "ok" } ], "manifest": { "name": "@you/kody-bot-shipped", "kody_id": "kody-bot-shipped", "description": "What kody-bot shipped since you last asked.", "has_app": false } }, "published": { "status": "ok", "session_id": "rs_kody_bot_shipped", "published_commit": "c8e2b1a04f73", "message": "Published session to main." } }
executeTest the no-argument wrapper the scheduler will callconversationId"8w3k6n1p5r9t"memoryContext{ "task": "Update me when kody-bot does something.", "entities": [ "kody-bot" ] }codeimport dailyDigest from 'kody:@you/kody-bot-shipped/daily-digest' export default async function main() { return await dailyDigest() }ReturnsconversationId: 8w3k6n1p5r9t Tool conversation id; pass it back on subsequent search/execute calls. { "emailed": false }
executeEnable the daily job after the wrapper succeedsconversationId"8w3k6n1p5r9t"memoryContext{ "task": "Update me when kody-bot does something.", "entities": [ "kody-bot" ] }codeimport { kody } from 'kody:runtime' export default async function main() { const session = await kody.repoOpenSession({ target: { kind: 'package', kody_id: 'kody-bot-shipped' }, conversation_id: '8w3k6n1p5r9t', }) await kody.repoEditFiles({ session_id: session.id, edits: [ { kind: 'replace', path: 'package.json', search: '"enabled": false', replacement: '"enabled": true', }, ], }) await kody.repoCommit({ session_id: session.id, message: 'Enable the daily digest job', }) const checks = await kody.repoRunChecks({ session_id: session.id }) const published = await kody.repoPublishSession({ session_id: session.id, }) return { session_id: session.id, checks, published } }ReturnsconversationId: 8w3k6n1p5r9t Tool conversation id; pass it back on subsequent search/execute calls. { "session_id": "rs_kody_bot_shipped", "checks": { "ok": true, "results": [ { "kind": "manifest", "ok": true, "message": "ok" }, { "kind": "typecheck", "ok": true, "message": "ok" } ], "manifest": { "name": "@you/kody-bot-shipped", "kody_id": "kody-bot-shipped", "description": "What kody-bot shipped since you last asked.", "has_app": false } }, "published": { "status": "ok", "session_id": "rs_kody_bot_shipped", "published_commit": "e1d9c70b3a26", "message": "Published session to main." } }Codex It will check every morning. If kody-bot shipped something, you get mail. If not, nothing hits your inbox.
Something shipped.
Email kody-bot shipped 2 things
kody-bot/lantern v1.4.1 kody-bot/quiet-days v0.1.0
The package
What your agents , , and wrote
Same implementation for “ask again” and the morning job. The job calls emailSend only when the list is not empty.
package.jsonExport plus a daily job
{
"name": "@you/kody-bot-shipped",
"private": true,
"exports": {
"./whatShipped": "./src/what-shipped.ts",
"./daily-digest": "./src/daily-digest.ts"
},
"kody": {
"id": "kody-bot-shipped",
"description": "What kody-bot shipped since you last asked.",
"jobs": {
"daily-digest": {
"entry": "./src/daily-digest.ts",
"schedule": { "type": "cron", "expression": "0 8 * * *" },
"timezone": "America/Denver",
"enabled": true
}
}
}
}README.mdWhy this package exists
# kody-bot-shipped
## Intent
Tell me what kody-bot shipped — published releases and new public repos —
since I last asked. Email me only when that list is not empty.
AGENTS.mdImports, smoke tests, and edge cases
# kody-bot-shipped
## Imports
```ts
import whatShipped from 'kody:@you/kody-bot-shipped/whatShipped'
```
## Smoke tests
Call `whatShipped` from `execute` after publish. The daily job wrapper
sends mail only when that list is not empty.
## Edge cases
A quiet day must skip email. The `lastSeenEventId` cursor lives in
`packageStorage()`.
src/what-shipped.tsFilter public events and advance the cursor
import { packageStorage } from 'kody:runtime'
const login = 'kody-bot'
const seenKey = 'lastSeenEventId'
export default async function whatShipped() {
const storage = packageStorage()
const sinceId = (await storage.get(seenKey)) as string | null
const shipped = await listShipped(sinceId)
if (shipped[0]) await storage.set(seenKey, shipped[0].id)
return shipped.length === 0
? { shipped, message: 'Nothing new.' }
: { shipped, message: shipped.map((item) => item.title).join('\n') }
}
async function listShipped(sinceId: string | null) {
const response = await fetch(
`https://api.github.com/users/${login}/events/public`,
{
headers: {
Accept: 'application/vnd.github+json',
Authorization: 'Bearer {{secret:githubAccessToken}}',
'X-GitHub-Api-Version': '2022-11-28',
},
},
)
if (!response.ok) throw new Error(`GitHub ${response.status}`)
const events = (await response.json()) as Array<{
id: string
type: string
repo: { name: string }
payload: {
action?: string
ref_type?: string
release?: { tag_name?: string }
}
}>
const shipped = []
for (const event of events) {
if (sinceId && event.id === sinceId) break
if (
event.type === 'ReleaseEvent' &&
event.payload.action === 'published'
) {
shipped.push({
id: event.id,
kind: 'release',
title: `${event.repo.name} ${event.payload.release?.tag_name ?? 'release'}`,
})
}
if (
event.type === 'CreateEvent' &&
event.payload.ref_type === 'repository'
) {
shipped.push({
id: event.id,
kind: 'repository',
title: `New repo ${event.repo.name}`,
})
}
}
return shipped
}
src/daily-digest.tsSkip mail on a quiet day
import { kody } from 'kody:runtime'
import whatShipped from './what-shipped.ts'
export default async function dailyDigest() {
const result = await whatShipped()
if (result.shipped.length === 0) return { emailed: false }
await kody.emailSend({
subject:
result.shipped.length === 1
? 'kody-bot shipped something'
: `kody-bot shipped ${result.shipped.length} things`,
text: result.message,
})
return { emailed: true, count: result.shipped.length }
}