GitShow/kentcdodds/kody
kentcdodds

kody

🐨 Your assistant's home — the memory, keys, code, and automations your AI agent keeps, portable across every MCP host. Built on Cloudflare Workers.

by kentcdodds
agentsai-assistantcloudflare-workerscode-modemcppersonal-assistant
Star on GitHubForkWebsitenpm

TypeScript

686 stars66 forks9 contributorsActive · 5h agoSince 2026v2026.09.28

Meet the team

See all 9 on GitHub →
kentcdodds
kentcdodds2.0k contributions
cursor[bot]Bot
cursor[bot]296 contributions
devin-ai-integration[bot]Bot
devin-ai-integration[bot]44 contributions
kody-bot
kody-bot39 contributions
cursoragent
cursoragent16 contributions
sentry[bot]Bot
sentry[bot]7 contributions
vojtaholik
vojtaholik4 contributions
gravitinos
gravitinos1 contribution

Languages

View on GitHub →
TypeScript99.3%
JavaScript0.4%
CSS0.4%
Shell0%

Commit activity

Last 12 weeks · 1762 commits

Full graph →

Community health

4 of 6 standards met

Community profile →
85
✓README✓License✓Contributing○Code of Conduct○Issue Template✓PR Template

Recent PRs & issues

Active · Last activity 5h ago
See all on GitHub →
kentcdodds
Test surgery: remove ~70k lines of redundant tests without dropping use-case coverageOpenPR

Intent Intentional test-debt surgery: remove redundant test code across the repo without dropping use-case coverage. The goal is fewer, higher-signal tests that still pin every product behavior and contract: execute, search, billing/credits, packages, MCP surfaces, auth, migrations, and entitlements. Why The unit test tree had grown to about 314k lines, which slows reviews, , and every future refactor. The fat was not a clone farm. Exact duplication is only about 4%. Most of it is verbose filter matrices (one per row), copy-pasted fixtures, near-duplicate scenario tests, search-stack overlap between layers, and assertions on dead or unreachable code. Why this is about 70k lines, not "hundreds of thousands": the whole unit test tree was 313,868 lines. Cutting 200k+ would mean deleting most real behavior tests. After the first pass over all 21 buckets, a second cross-file pass over the largest remaining files found only 2–5% more to cut, which is good evidence that the redundancy ceiling is roughly where this PR lands. Summary Net: went from 313,868 lines in 1,204 files to 244,089 lines in 1,199 files, about −69,800 lines (−22.2%). Whole-repo diff is +76,106 / −145,854 (net −69,748). Test counts: node-unit went from 3,660 to 3,253 tests (same behaviors, fewer blocks), and workers-unit from 406 to 367. What was done, by technique: Table-driven rows: one-test-per-row filter and parse matrices became tables, asserted as so a failure still names the offending row. Merged workflows: separate tests that set up the same state and then checked one field each became one longer workflow test, per the house testing principles. Shared per-file fixtures: repeated 30–100 line inline env, row, and actor literals became small / builders in the same file. Expected values stay literal. Real SQLite with migrations instead of hand-rolled fake D1 where the fake re-implemented SQL (, , , , , identity tests). Deleted: tautologies, copy pins, tests of dead exports, duplicate worker and node doubles of the same assertion, per-test / boilerplate already covered by the global /, and blanket console silencing (replaced with narrow allowlists where needed). Five files merged away: and merged into . merged into . and merged into . Per-area commits (net lines), one commit per area: No production runtime changes. The only non-test files touched are three test-support helpers, each used only by the tests in its own area: , (which also fixes an undeclared reference), and . Billing, auth, isolation, and metering assertions were not weakened. Exact credit, rate, and count values stay exact. Cross-user isolation checks stay, and several are now stricter (exact , a check on every reset-client scenario, exact redirects). Referenced issues and PRs No issue drives this change. It is intentional test-debt surgery. Related to #2708 (repo-wide break, currently the only red check here) and #2709 (test files are not typechecked, filed from this work). Testing on the branch: format, lint, typecheck, knip, slop-ratchet, primitives, migrations, deploy-guardrails, workflows, docs, mermaid, lockfile, and all worker builds pass. test-node: 1,092 files and 3,253 tests pass. test-mcp passes. test-workers: 365 of 367 pass. The 2 failures were 20s timeouts under full-validate CPU load ( and ). Rerun alone, both files pass (8/8). e2e: 17 of 18 pass. timed out under load and passes when run alone. No e2e spec was edited. worker-startup-time exceeded its budget only under load. Alone it passes: platform 196 ms against a 340 ms budget, runtime 79 ms against 160 ms. Production bundles are unchanged. audit:prod fails on an existing moderate undici advisory that reaches transitively. It is unrelated: this PR doesn't touch . CI on : 🧪 Node, ☁️ Workers, 🔌 MCP, and 🎭 E2E are green. Preview deployed, and is ok at the PR merge SHA. 🧹 Static fails only at the production dependency audit step. Every other Static step passes (format, lint, typecheck, builds, startup, knip, slop-ratchet, and the rest). That audit failure is repo-wide: advisories published 2026-09-28 for undici, ip-address, and esbuild. Filed as #2708. Reviews: Cursor Bugbot found no issues. CodeRabbit skipped the review because 550 files exceeds its 150-file limit. Coverage, measured before and after with on node-unit (installed with ): Lines went from 67.82% (60,549 / 89,273) to 67.83% (60,569 / 89,295). Branches went from 58.77% to 58.78%. A per-line diff against the base tree found 9 source files that lost a few incidental lines or branches. I restored assertions for the meaningful ones (last commit): A provider-mark label-only save succeeds without logo storage and keeps the existing logo. Preview dry-run cleanup works with no Cloudflare credentials. The R2 bucket delete success path. Identity-icon refresh skips stamping for packages and returns early when bindings are missing. Residual risk Merged tests fail as a unit. A failure early in a merged workflow hides later scenarios in the same test until it is fixed. Table diffs and row labels still identify the failing case, but there are fewer test names. Test files are not typechecked by the repo gate. Every worker tsconfig excludes , so fixture and type drift in tests surfaces only at runtime. The agents checked changed files with a throwaway tsconfig and introduced no new errors, but pre-existing ones remain. This existed before the PR. Real SQLite fixtures now couple to the migration chain. A future migration that reshapes , , secrets, or flags tables fails those tests at seed time. That is an intended signal, but a noisier one. Shared per-file builders: changing a default in one builder affects several tests in that file. Defaults mirror the prior inline literals. Global mock config dependency: several files dropped explicit /reset helpers and rely on the Vitest config's + . If that config changes, state could bleed between tests. Some checks are stricter, for example exact spawned-call lists and exact request sequences. Harmless future behavior changes may need test updates. Coverage not restored, all incidental fallbacks or dead code: the dead export in , which has no production callers Thinner end-to-end coverage for webhook HTTP challenges: meta-hub and websub challenges are no longer exercised end to end over HTTP. Coverage relies on the GET path staying generic. System recap — composes existing primitives (low risk, test-only) Mode: recap · Base: @ · Head: Classification:** composes. No primitive is added or changed. The diff touches only files plus three test-support helpers (, , ). No production runtime file, migration, or lockfile changes. Primitives touched Change flow Each unit suite still exercises the same production primitives. This PR only changes how many test blocks and fixture lines it takes to do that. Invariants Per-user isolation, billing and metering, and auth assertions were kept or tightened, not loosened. Where fakes were replaced (fake D1 in , , , , , identity tests), the replacement is real SQLite with the real migration chain.   

kentcdodds · 10h ago
kentcdodds
Add "Personal software, connected to everything" Remotion motion pieceOpenPR

Intent A 43.5s marketing motion piece for Kody that sells personal software, connected to everything, built with Remotion from the product art and tokens already in this repo. Why Every new personal app pays the integration tax again: sign-ins, pasted API keys, MCP configs. The video makes that pain concrete, then resolves it into Kody as the one home for connections, and shows that home turning out app after app that already has them. Summary New standalone project at . It is not an npm workspace and no worker imports it. Composition : 1920×1080, 30fps, H.264 High (bt709) with AAC, 43.5s. After the drop, one piece moves at a time. Beats: 0–10s, integration tax. "You need a new app." A checklist runs through one full cycle: "Wire up integrations" (Google sign-in, Stripe key, GitHub MCP, Slack app, and Linear key modals pile onto the app), then "Build" (the app fills in), then "Deploy" (it goes Live). Then "Now you need another one." and "Wire up integrations… again.", followed by three "and again…" lines, each faster, as more apps pile up with the same modals. It lands on "Ugh 😩" with every window slumping gray, just before the drop. 10–24s, connect once. The lantern lights on the drop. Then the six primitives light one per beat, each with its label. After the labels clear, the services fly into the lantern one at a time. Then "Connect once." lands, then "Keep them in Kody.", then the Secrets and Connections panels open. 24–32s, generate, then many. "Generate software that already has the connections." An agent prompt becomes the Morning HQ dashboard, fed by beams from the lantern. The camera then pulls back to 0.14× while 51 more apps pop in faster and faster around the lantern, and the reprised tallies read Apps ×52, New sign-ins ×0, API keys pasted ×0. The apps are 24 different kinds of interface (): chat, kanban, music player, route map, interval timer, booking, word game, home controls, photo album, invoice form, code review, chores, flashcards, video call, sketchpad, budget sliders, seat picker, poll, terminal, grocery steppers, editor, habit tracker, approvals, and journal. The first 24 to appear are all different, and repeats sit at least five cells from their twin. 32–40s, stays lit. The pull-back finishes and holds for a second, then "Agents come and go." replaces the headline. Next, Cursor, Claude, and ChatGPT each connect in turn on the right. Once the last one leaves, "Your software stays lit." appears, and only then do scheduled triggers wake batches of apps. 40–43.5s, close. "Personal software, connected to everything." plus the koala logo and kody.codes. The only outside visual asset is the 😩 image, a Noto Emoji SVG (Apache 2.0), which is committed so the render never depends on a system emoji font. Reuses the lantern still, the six orb sprites, the homepage orb layout and clip path (), the primitive words (), the dark-mode tokens, the Bricolage and Wix fonts, the logo, the brand pattern, and the in-repo service and agent marks. Sound has two layers, both keyed to the same cue frames as the visuals: is an edit of Kent's Suno track "Personal software" (D major), built by (, needs ffmpeg with librubberband). Its intro didn't fit the "ugh" opening, so the first 10s are sound design instead: a clock tick-tock that doubles its speed with the repeats, a low drone that creeps up, and a tape stop plus deflate on "Ugh". A reverse swell then leads the track in on its own riser, so its drop lands at 10s as the lantern lights. The pre-chorus and chorus play under the app build and zoom-out, and the track's final hit lands under the tagline at 40s. The edit points live in (). Each section is stretched from about 122 BPM onto the 120 BPM grid, and the mix is at -14 LUFS. places Kenney CC0 one-shots () on the cue frames: card pops that climb the D-major scale, window whooshes, checklist ticks on D, F#, and A, "Live", the "and again…" thuds, the "Ugh" slam, in-key pings as each primitive lights, pops as each service lands, a light whoosh per agent, and pings as triggers fire. The opening sits about 8 dB under the drop. holds Beat 1's cue sheet as plain data, so the scene, the effects, and the soundtrack builder all read the same frames. !Opening contact sheet !Beat 2 sequence: primitives, then integrations, then words, then panels !Beat 3: many kinds of app from one home !Beat 3 pull-back contact sheet !Beat 4 sequence: zoom settles, agent copy, agents one at a time, stays lit, triggers, tagline !Soundtrack waveform, one grid line per second The rendered master is in Dropbox at (direct link). Render output () and the downloaded Suno source () are gitignored. renders an MKV with PCM audio and has ffmpeg encode the AAC for the MP4, because Remotion's AAC output left the encoder delay in and played about 43 ms late. Referenced issues and PRs None. Testing in the project, plus the root , , , , , and . Rendered the full master and reviewed frames across every beat, including frame-by-frame through the pull-back and each headline handoff in the reworked opening. Rendered all 24 app screens side by side at close range to check their layouts, and checked that no two identical screens are adjacent in the grid. Audio: measured the final render at -14.3 LUFS integrated with a -1.5 dBFS true peak. Cross-correlated the MP4's audio against the soundtrack at 10s, 20s, 30s, and 40s: 0 ms offset (it was 42.7 ms before the MKV-plus-ffmpeg change). Kick onsets in the drop sit on the 0.5s grid with the same small lag the detector shows on the source. The level arc runs from -38 dB RMS at the start to about -17 at "Ugh", then the drop comes in at -13 and holds around -14 through the chorus. Checked the Dropbox copy against the local file: the SHA-256 of the direct-link download matches the local render. System changes System recap — composes existing primitives (low risk) Mode: recap · Base: @ · Head: Classification:** composes. No runtime primitive is added or changed. The new folder only reads static assets and pure TS modules from at bundle time. Change flow The Remotion bundle imports product art and homepage layout data from the worker package, then renders an MP4 offline.   

kentcdodds · 17h ago

Recent fixes

View closed PRs →
kentcdodds
Add matched YouTube videos to docs pagesMergedPR

Intent Put the agreed YouTube matches on the docs pages they belong to: a player when the video is that page's lesson, and a text link when it is only supporting context. Why Several docs pages teach the same job as a short Kent video. Readers who land on the page should be able to watch that lesson without hunting for it, and denser reference pages should stay scannable. Summary First-party guides can author one block. The docs renderer turns it into the existing lite YouTube player (poster first, privacy-enhanced iframe after click, iframe title set to the real video title). Untrusted markdown still cannot emit an iframe. Interactive docs that replace the prose (How Kody works) still show that block above the walkthrough, including a following "Also watch" paragraph. The guide catalog test rejects a second watch block on the same page. First-party docs watch video ids are on the thumbnail allowlist, so an unlisted film still gets a poster when it is missing from the public playlist Atom feed. Embeds (one player) Links (no player) Package apps does not embed the shades demo. That video does not teach hosted package apps, and the page already has the pipeline player. Package lifecycle, package subscriptions, and agent inbox stay link-only. Those pages are a decision guide or a dense reference, and the matched videos are one path or a case study rather than the whole page. Motion explainers Published titles below. None of these became a second player. Referenced issues and PRs None. Testing node-unit: doc watch parser, markdown renderer (first-party player vs untrusted quote), catalog one-embed guard, YouTube allowlist (docs watch ids included), and the full node suite on push (3623 tests). Workers unit suite on push (405 tests). Worker typecheck. Docs temporal-language check. Local origin SSR: one player on embed pages, zero on link pages. SSR has exactly one player for , the game link, and the two exchange links. No iframe before click. Browser: that page shows one Integration Game poster, the caption, and the integration-game.kody.codes link. The poster allowlist is on the branch (). First-party docs watch ids, including unlisted , are allowed for . Local thumb for that id returned the 1280×720 poster. System changes See the system recap below. System recap — composes existing primitives (low risk) Mode: recap · Base: @ · Head: Classification: composes — no primitives added or changed. Docs pages reuse the existing lite YouTube player. Docs watch ids are added to the existing thumbnail allowlist. Primitives touched Change flow A docs reader opens a guide, and a first-party watch block becomes the lite player already used by the homepage.    Summary by CodeRabbit New Features** Guides now include video walkthroughs for agent setup, integrations, packages, triggers, and other workflows. Supported documentation displays YouTube videos as click-to-play embeds with captions linking to the video. Video embeds appear above interactive walkthroughs when included in a document. Video controls include descriptive screen-reader labels and a visible keyboard-focus outline. Guides link to related videos and written resources for additional context.

kentcdodds · 16h ago
kentcdodds
Replace package source history on confirmed destructive overwriteMergedPR

Intent Make confirmed / force-publish destructive overwrite a true history replace so prior package source is unreachable from advertised refs (same / ), without weakening the confirm + restorable-backup gate. Why Fixes #2703. Today force-publishes an additive commit on prior history, so canary blobs and leftover refs stay reachable via upload-pack. Product lock: true history replace (not docs-only additive overwrite). Platform feedback: Summary On confirmed package force-publish that promotes , create an orphan root commit () and force-push it to the source default branch. After successful promote, list and delete every advertised session branch (covers the current source-sync session and stale leftovers). (locked fleet codemods) stays additive so the locked tip is not orphaned. Confirm gate + restorable backup verification unchanged. Capability / confirmation description documents history replace and that restorable backups retain prior content (secret scrub of backups still needs or an explicit purge). Referenced issues and PRs Fixes #2703 Platform feedback: https://kody.codes/account/feedback (id ) Testing Unit: / / — orphan root + session-ref deletes + additive + policy text + confirm threading Preview (): create + confirm-gate rejection verified; confirmed overwrite blocked by Artifacts mock ( on restorable-backup verify). Contract coverage is unit tests. Rebased onto latest after mergeability went dirty. Residual scrub limitation Restorable KV published-source backups taken before overwrite retain prior content by design for recovery. Live git graph + current published snapshot are scrubbed; backup scrub still requires or an explicit purge. System recap — extends repo-sessions (medium risk) Mode: recap · Base: @ · Head: Classification: extends — confirmed destructive overwrite on promoting package publishes now orphans prior advertised history and clears session refs. Primitives touched Change flow Confirmed promoting destructive overwrite replaces advertised package history and drops leftover session refs. Before / after Invariants Per-user isolation unchanged. Confirm + restorable-backup gate not weakened.    Summary by CodeRabbit New Features Confirmed destructive force-publishes replace published history with a fresh starting point when published content is promoted, even if the workspace has no new changes. Leftover publishing-session branches are removed when possible. When published content is not promoted, publishing remains additive. Important Backup snapshots retain prior content. Removing backup content still requires package deletion or an explicit purge. Verify that a backup can be restored before publishing.

kentcdodds · 19h ago
kentcdodds
packageSave confirm_destructive_overwrite leaves prior source reachable in git historyClosedIssue

Summary with succeeds but does not make prior source objects unreachable. Flag + capability docs describe destructive overwrite of existing package source history; callers (and secret-scrub use cases) reasonably expect old blobs to leave the reachable graph. Platform feedback: https://kody.codes/admin/platform-feedback?feedbackId=efd875a9-6635-49c5-a5c6-829629ee9be6 Reporter: Noah (), bug, 2026-09-28. Discord (already advanced): channel message . Repro (throwaway private package, since deleted) 1. new package with containing a canary string (e.g. ) 2. same with clean files → rejected without 3. with → succeeds, same 4. (read) + ls-refs/fetch all refs Actual: is a “Publish repo session source-sync-…” commit parented on “Bootstrap source repo …”; the canary blob remains reachable from . Leftover also remains after publish. Expected: true history replace so prior objects are unreachable from advertised refs; OR (rejected for this issue) document additive overwrite + ship a supported purge/history-reset. Pre-overwrite restorable backup snapshot also retains the secret and must be addressed for scrub use cases. Suspected path Gate: in (confirm + restorable backup) Write: → session / / in and Docs: = “destructive overwrite of existing package source history” Fix direction (locked: A) Implement true history replace on confirmed destructive overwrite (orphan/root commit or equivalent force so old objects are not reachable from default branch or leftover session refs). Clean up leftover after publish. Document that restorable backup snapshots retain pre-overwrite content, and purge or isolate those backups when the confirmed goal is secret scrub (or document / rename+rebuild as the only scrub path if backup retention is intentional). Do not weaken the confirm gate. Escalate to Kent only if A is infeasible on Artifacts storage and we must fall back to docs + explicit purge API. Workaround today Rename+rebuild (loses ) or . Acceptance After + with a clean file set, a canary from the prior commit is not reachable via fetch of advertised refs. Leftover source-sync session refs are not left advertising prior history. Capability/docs accurately describe history replace + backup retention for scrub. Tests cover the canary-unreachable case. PR uses GitHub closing keywords and a “Referenced issues and PRs” section. When shipped, tell Pam so she can resolve the platform-feedback card with a to Noah.

kentcdodds · 19h ago
Structured data for AI agents

Repository: kentcdodds/kody. Description: 🐨 Your assistant's home — the memory, keys, code, and automations your AI agent keeps, portable across every MCP host. Built on Cloudflare Workers. Stars: 686, Forks: 66. Primary language: TypeScript. Languages: TypeScript (99.3%), JavaScript (0.4%), CSS (0.4%), Shell (0%). Homepage: https://kody.codes Topics: agents, ai-assistant, cloudflare-workers, code-mode, mcp, personal-assistant. Latest release: v2026.09.28 (1d ago). Open PRs: 4, open issues: 67. Last activity: 5h ago. Community health: 85%. Top contributors: kentcdodds, cursor[bot], devin-ai-integration[bot], kody-bot, cursoragent, sentry[bot], vojtaholik, gravitinos, github-actions[bot].

·@ofershap

Replace github.com with gitshow.dev