kody.codes
Human β Agent β Software
Please stand up.
Your π§ needs this
You've got work to do
Do it the hard way first
Pain motivates a move
Agents hide the pain.
Walled Gardens
One shared software ecosystem
Problem
search
search({ query: "close the shades" })
# Search results
For full detail on entity-backed hits, call `search` with `entity: "{id}:{type}"`.
1. **package** @kentcdodds/home-controls (`home-controls`) β Package-first home helpers for TV app launching, TV power, Roku YouTube playback, Frame Art Mode, and Bond shade controls by area or room. Entity: `home-controls:package` Best action: `default` via `import action from "kody:@kentcdodds/home-controls/bond-area-shades"` β Open, close, stop, or position every Bond shade in a named home area. Returns `{ ok, area, affected, results }` on success or `{ ok: false, error }`. @example import bondAreaSha...
2. **package** @kentcdodds/shade-automation (`shade-automation`) β Daily solar shade planning, Bond control, disconnect alerts, and a mobile control-center app. Entity: `shade-automation:package` Best action: `default` via `import action from "kody:@kentcdodds/shade-automation/control"` β Move shades from the control-center app or a package invoke. The hosted app calls Bond in-process; this export is the same write path for MCP and other package runtimes. @exampl...
3. **mcp-server** home (`mcp:home`, 206 tools) β Home MCP server for local-network devices, including an Android phone companion over WebSocket at /phone/ws. Tools stay on this process; Kody connects over Streamable HTTP at /m... Entity: `home:mcp-server`. List tools with `search({ entity: "home:mcp-server" })`. Call via `kody.mcp["home"].tool_name(args)`. Wrapping package: `@kentcdodds/home-controls` (Entity: `home-controls:package`).
4. **capability** `waitingSummary` (`account`) β List things currently waiting on the signed-in human: email verification, OAuth reconnects, expired secrets, MCP reconnects, locked-package publishes, plan caps, wizard resume,... Entity: `waitingSummary:capability`
`kody.waitingSummary(args)` β `type WaitingSummaryInput = Record<string, never>`
5. **secret** `homeMcpOperatorPassword` β HOME_MCP_OPERATOR_PASSWORD for kody-home.doddsfamily.us /authorize. Entity: `homeMcpOperatorPassword:secret`
## Relevant memories
- **Home shade automation intent** β Shade automation maximizes natural light with a daily sun-position planner for privacy, heat, and glare events; weather-sensitive moves decide from current cloud cover at event time (no cloud-watch polling). Office recording protection applies; master suite is never automated; kitchen-door rules preserve door access and vacuum clearance. Canonical behavior spec is INTENT.md in @kentcdodds/shade-automation.
search({ entity: "home-controls:package" })
# Package β `home-controls`
Package-first home helpers for TV app launching, TV power, Roku YouTube playback, Frame Art Mode, and Bond shade controls by area or room.
## Index
- Entity: `home-controls:package`
- Package name: `@kentcdodds/home-controls`
- Tags: `home`, `tv`, `samsung`, `frame-tv`, `roku`, `youtube`, `bond`, `shades`
- Has app: no
- Hidden: no
## Exports
| Subpath | Purpose |
| --- | --- |
| `./bond-area-shades` | Open, close, stop, or position every Bond shade in a named home area. Returns `{ ok, area, affected, results }` on success or `{ ok: false, error }`. @example import bondAreaShades from 'kody:@kentcdodds/home-controls/bond-area-shades' const result = await bondAreaShades({ area: 'back', action: 'close' }) // => { ok: true, area: 'back', affected: ['Kitchen South', ...], results: [...] } |
| `./bond-room-shades` | Open, close, stop, or position Bond shades in one room, optionally filtered by sheer/blackout type. Returns `{ ok, room, type, affected, results }` on success or `{ ok: false, error }`. @example import bondRoomShades from 'kody:@kentcdodds/home-controls/bond-room-shades' const result = await bondRoomShades({ room: 'Office', type: 'sheer', action: 'open' }) // => { ok: true, room: 'Office', type: 'sheer', affected: [...], results: [...] } |
| `./frame-art-mode` | Read or toggle Samsung Frame TV art mode for Kent's living-room Frame. Returns `{ ok, deviceId, deviceName, mode?, result }` or `{ ok: false, error }`. @example import frameArtMode from 'kody:@kentcdodds/home-controls/frame-art-mode' const result = await frameArtMode({ room: 'frame', mode: 'on' }) // => { ok: true, deviceId: 'samsung-tv-uuid-...', deviceName: '65" The Frame', mode: 'on', result: ... } |
| `./roku-play-youtube` | Launch the YouTube app on a named Roku and start playing a video by id or URL. Returns `{ ok, deviceId, deviceName, videoId, result }` or `{ ok: false, error }`. @example import rokuPlayYoutube from 'kody:@kentcdodds/home-controls/roku-play-youtube' const result = await rokuPlayYoutube({ deviceName: 'Theater', videoId: 'dQw4w9WgXcQ' }) // => { ok: true, deviceId: 'roku-x...', deviceName: 'Theater', videoId: 'dQw4w9WgXcQ', result: ... } |
| `./tv-power` | Turn a Samsung Frame TV or named Roku on or off via the home connector. Returns `{ ok, platform, deviceId, deviceName, state, result }` or `{ ok: false, error }`. @example import tvPower from 'kody:@kentcdodds/home-controls/tv-power' const result = await tvPower({ room: 'theater', state: 'on' }) // => { ok: true, platform: 'roku', deviceId: 'roku-x...', deviceName: 'Theater', state: 'on', result: ... } |
| `./tv-watch-app` | Launch a streaming app on a Samsung Frame TV or named Roku by app name or app id. Returns `{ ok, platform, deviceId, deviceName, appId, result }` or `{ ok: false, error }`. @example import tvWatchApp from 'kody:@kentcdodds/home-controls/tv-watch-app' const result = await tvWatchApp({ room: 'frame', app: 'Netflix' }) // => { ok: true, platform: 'samsung', deviceId: 'samsung-tv-uuid-...', appId: '3201907018807', result: ... } |
## Agent docs (`AGENTS.md`)
# @kentcdodds/home-controls β agent notes
Human setup and intent live in [`README.md`](./README.md). This file is for
agents: imports, smoke checks, snippets, and edge cases. Secrets by **name**
only β never paste key values. Do not disable live webhooks or jobs.
## Secrets
None declared via `{{secret:β¦}}` placeholders in this package source. Check README / deps for upstream secrets.
## Import paths
| Export | Import |
| --- | --- |
| bond-area-shades | `kody:@kentcdodds/home-controls/bond-area-shades` |
| bond-room-shades | `kody:@kentcdodds/home-controls/bond-room-shades` |
| frame-art-mode | `kody:@kentcdodds/home-controls/frame-art-mode` |
| roku-play-youtube | `kody:@kentcdodds/home-controls/roku-play-youtube` |
| tv-power | `kody:@kentcdodds/home-controls/tv-power` |
| tv-watch-app | `kody:@kentcdodds/home-controls/tv-watch-app` |
Prefer static `kody:@kentcdodds/home-controls/...` imports from `execute`.
Do not lead with `packages.invoke`.
## Smoke / dry-run
Root/overview (prefer read-only describe when available):
```js
import mod from 'kody:@kentcdodds/home-controls/bond-area-shades'
export default async function main() {
return await mod()
}
```
## Edge casesβ¦
> AGENTS.md was truncated for this index.
## Follow up
If you plan to invoke an export, call packageGet({ package_id: "e24de5c2-8622-40ce-9bf1-6664be204901" }) first for the exact call shape, types, and package-scoped secret metadata. That call does not return files. For the full README.md, AGENTS.md, and source, open a repo session with repoOpenSession({ target: { kind: "package", package_id: "e24de5c2-8622-40ce-9bf1-6664be204901" } }) then repoReadFile({ session_id, path: "README.md" }) and repoReadFile({ session_id, path: "AGENTS.md" }) (browse other files with repoTree). Discard the session with repoDiscardSession when finished. If you have a local git client, call packageGetGitRemote({ package_id: "e24de5c2-8622-40ce-9bf1-6664be204901" }) instead and clone. search({ entity: "package_authoring:guide" }) covers inbound webhooks and maintenance workflows.
search({
entity: "package:home-controls#bond-area-shades",
})
# Package export β `home-controls` / `bond-area-shades`
Open, close, stop, or position every Bond shade in a named home area.
Returns `{ ok, area, affected, results }` on success or `{ ok: false, error }`.
## Summary
- Entity: `package:home-controls#bond-area-shades`
- Package name: `@kentcdodds/home-controls`
- kody_id: `home-controls`
- Import: `kody:@kentcdodds/home-controls/bond-area-shades`
## Execute from `execute`
```ts
import action from "kody:@kentcdodds/home-controls/bond-area-shades"
export default async function main(params) {
return await action(params)
}
```
## Type definition
```ts
export default function bondAreaShades( params?: BondAreaShadesParams, ): Promise<BondAreaShadesResult>
```
## Referenced types
```ts
export type BondAreaShadesParams = {
/** Named home area. */
area?: BondAreaName
/** Shade action: Open, Close, Stop, or SetPosition (aliases accepted). */
action?: string
/** Target position 0β100 when action is SetPosition. */
position?: number
/** Relative position change -100 to 100 instead of an absolute action. */
delta?: number
}
export type BondAreaShadesResult = {
area?: 'back'
ok: boolean
error?: string
availableAreas?: Array<'back'>
affected?: string[]
results?: Array<Record<string, unknown>>
}
export type BondAreaName = 'back' | 'backyard'
```
## Example
```ts
import bondAreaShades from 'kody:@kentcdodds/home-controls/bond-area-shades'
const result = await bondAreaShades({ area: 'back', action: 'close' })
// => { ok: true, area: 'back', affected: ['Kitchen South', ...], results: [...] }
```
## Follow up
packageGet({ package_id: "e24de5c2-8622-40ce-9bf1-6664be204901" }) returns the full export array plus package-scoped secret metadata. That call does not return files.
execute
import bondAreaShades from
"kody:@kentcdodds/home-controls/bond-area-shades"
export default async function main() {
return await bondAreaShades({
area: "back",
action: "close",
})
}
{
ok: true,
area: "back",
affected: ["Kitchen South"],
}
%%{init: {'themeVariables': {'fontSize': 24}, 'sequence': {'mirrorActors': false, 'actorFontSize': 24, 'messageFontSize': 24, 'noteFontSize': 22, 'width': 168, 'height': 54, 'actorMargin': 62, 'messageMargin': 30}}}%%
sequenceDiagram
actor Agent
participant Kody as Kody worker
participant Loader
participant Isolate
Agent->>Kody: execute({ code })
Kody->>Kody: bundler
Kody->>Loader: modules
Loader->>Isolate: load
Isolate->>Kody: code-mode
Kody->>Isolate: code-mode
Kody-->>Agent: result
// worker.ts
const modules = {
"executor.js": codeExecutor,
"entry.ts": bundledCode,
}
const isolate = loader
.get(workerId, () => ({ modules }))
.getEntrypoint()
const dispatchers = {
kody: capabilities, // emailSend, secretList, β¦
}
const { result } = await isolate
.evaluate(dispatchers)
// executor.js
export default class CodeExecutor {
async evaluate(__dispatchers = {}) {
const kody = new Proxy({}, {
get: (_, name) => async (args) => {
const resJson =
await __dispatchers.kody.call(
name,
JSON.stringify(args),
)
const data = JSON.parse(resJson)
if (data.error) {
throw new Error(data.error)
}
return data.result
},
})
return { result: await userCode({ kody }) }
}
}
Problem
export default async function main() {
const response = await fetch(
"https://api.github.com/user/repos?per_page=5",
{
headers: {
Authorization: "Bearer {{secret:githubAccessToken}}",
},
},
)
return response.json()
}
%%{init: {'themeVariables': {'fontSize': 24}, 'sequence': {'mirrorActors': false, 'actorFontSize': 24, 'messageFontSize': 24, 'noteFontSize': 22, 'width': 168, 'height': 54, 'actorMargin': 62, 'messageMargin': 30}}}%%
sequenceDiagram
actor Agent
participant Isolate
participant Gateway
participant GitHub
Agent->>Isolate: execute({ code })
Isolate->>Gateway: fetch + placeholder
Gateway->>Gateway: Replaces the token
Gateway->>GitHub: Bearer token
GitHub-->>Gateway: 200
Gateway-->>Isolate: body
Problem
They're just prompts you pay for every time πΈ
import closeShades from
"kody:@kentcdodds/kitchen-shade-control/close-shades"
import runMorningBriefing from
"kody:@kentcdodds/morning-briefing"
import { getEpisode } from
"kody:@kentcdodds/transistor"
export default async function main(input) {
const shades = await closeShades()
const briefing = await runMorningBriefing({ dryRun: true })
const episode = await getEpisode({ episodeId: input.episodeId })
return { shades, briefing, episode }
}
%%{init: {'themeVariables': {'fontSize': 24}, 'sequence': {'mirrorActors': false, 'actorFontSize': 24, 'messageFontSize': 24, 'noteFontSize': 22, 'width': 168, 'height': 54, 'actorMargin': 62, 'messageMargin': 30}}}%%
sequenceDiagram
actor Agent
participant Kody as Kody worker
participant Loader
participant Isolate
Agent->>Kody: execute({ code })
Kody->>Kody: published commit
Kody->>Kody: bundle + npm + deps
Kody->>Loader: modules
Loader->>Isolate: load
Isolate-->>Kody: result
Problem
import { createAuthenticatedFetch, kody, packageStorage,
workflows } from "kody:runtime"
export default async function main() {
const since = await packageStorage().get("sinceId")
const gh = await createAuthenticatedFetch("github")
const res = await gh("https://api.github.com/user")
const me = await res.json()
await workflows.create({ exportName: "./rebuild-index",
params: { login: me.login, since } })
return kody.emailSend({
subject: `${me.login} digest`,
text: `since ${since ?? "start"}`,
})
}
{
"kody": {
"jobs": {
"daily-digest": {
"entry": "./daily-digest.ts",
"schedule": { "type": "cron", "expression": "0 7 * * *" },
"timezone": "America/Denver"
}
},
"webhooks": [{
"name": "github",
"export": "./on-github",
"verification": {
"type": "hmac-sha256",
"secretName": "githubWebhookSecret"
}
}],
"subscriptions": {
"email.message.received": { "handler": "./on-email.ts" }
}
}
}
Problem
{
"kody": {
"app": {
"entry": "./app/router.ts",
"client": "./app/assets/entry.ts",
"assets": "./public"
}
}
}
package-app-kit
You're awesome
Thank you
kody.codes