Cursor plugin for Hono v4 (TypeScript edge web framework) + TypeScript. Pinned to hono ^4.12.19, @hono/zod-validator ^0.8.0, @hono/zod-openapi ^1.4.0 (peer zod ^4.x), @hono/node-server ^2.0.3 (Node 20+). Teaches the v4 APIs that LLMs trained on pre-2024 data do not know (c.json() always typed, validator throws HTTPException, getCookie/setCookie from hono/cookie, c.env as property, streamText from hono/streaming, showRoutes from hono/dev, getRuntimeKey from hono/adapter, fire(app) from hono/service-worker, Workers Static Assets binding instead of deprecated serveStatic, JSR @hono/hono for Deno). Catches 50+ LLM regressions with BAD / CORRECT TypeScript pairs.
No Hono v5 exists. Latest stable is v4.12.19. Any "v5" in generated code is hallucination.
Hono's own maintainers filed Issue #3906 ("llm.txt file") and Issue #4812 ("Official AI Agent Skill for Hono") explicitly because "LLMs have basically no knowledge of how the latest Hono works." Pre-2025 training data is v3-era. LLMs emit:
c.jsonT()instead ofc.json()(always typed since v4.0.0)c.stream()/c.streamText()as Context methods (moved tohono/streamingin v4)c.env()function form (now property; runtime detection viagetRuntimeKey()fromhono/adapter)c.req.cookie()(removed; usegetCookie(c)fromhono/cookie)app.showRoutes(),app.routerName(moved tohono/dev)addEventListener('fetch')+app.handleEvent()(Service Worker syntax; useexport default { fetch: app.fetch })app.head(...)routes (HEAD auto-derived from GET in v4)hono/nextjsimport (usehono/vercel)hono/middlewarebarrel import (use per-middleware subpath)c.req.headers()/c.req.body()/c.req.signal()accessor methods (usec.req.raw.*)FCwith implicit children (usePropsWithChildren<P>)app.fire()(deprecated v4.8.0; usefire(app)fromhono/service-worker)import { Hono } from 'https://deno.land/x/hono/mod.ts'on Deno (stale since v4.4.0; usejsr:@hono/hono)
- Missing
returnonc.json()(resolves to undefined; v4 throws "Context is not finalized") res.json()/res.send()instead ofc.json()(noresin Hono)(req, res, next)middleware signature (use(c, next))(err, req, res, next)error middleware (useapp.onError+HTTPException)app.use(express.json())body parser (Hono parses on demand viac.req.json())import cors from 'cors'from npm (usehono/cors)supertestfor tests (useapp.request()/testClient(app))c.req.bodyas already parsed (it's aReadableStream)c.req.parseBody()for JSON (only form / multipart)c.req.text()thenc.req.json()(body consumed twice)c.userId = ...inline assignment (usec.set('userId', ...)with typed Variables)
new Hono()withoutBindings/Variablesgenerics (c.envis{})- Routes defined as statements (
app.get(...)thenapp.post(...)) - drops RPC types - Sub-app
app.route()calls as statements - same rule - Rails-style controllers passing
Contextaround (loses path-param inference, per Hono Best Practices) app.use('/path', zValidator(...))instead of as route arg (TS error:'json' not assignable to 'never')c.notFound()in RPC-consumed routes (cannot type on client)new Response(JSON.stringify(...))in RPC routes (client seesunknown)hc<AppType>('/')relative URL (throws on$url())- Value-import of server app into client bundle (drags
drizzle-orm,fs, native deps - the #1 RPC bundle-bloat pitfall) - Middleware without
createMiddleware<Env>(Variables types do not propagate)
process.env.Xin Workers code (undefined; usec.env.Xwith typedBindings)fs/pathimports in Workers (no filesystem)compatibility_flags: ["node_compat"]legacy flag (usenodejs_compat)- Deprecated
serveStaticfromhono/cloudflare-workers(since v4.3.0; use asset binding) - Missing
c.executionCtx.waitUntil()for fire-and-forget - Truthy-check
if (c.executionCtx)(getter throws on Bun and Next.js App Router) - Unawaited D1
.run()/.first()/.all()(insert cancelled when worker terminates) - WebSocket upgrade without Durable Object forwarding (state vanishes)
- No
secureHeaders()middleware - No
csrf()on cookie-authenticated mutations cors({ origin: '*', credentials: true })(browsers silently drop; AJAX fails)- Missing
bodyLimit()on POST / PUT routes and pinhono >= 4.9.7for CVE-2025-59139 - Cookies without
httpOnly/secure/sameSite/path sameSite: 'None'withoutsecure: true(silently dropped)- Body-logging middleware without redaction (passwords / tokens / PII leak)
- No
etag()/cache()on static GETs - Hard-coded JWT secret string (leaks via bundle)
- Building large JSON in memory instead of
streamText(Workers 128MB cap)
- Sub-app
notFoundhandler (dead code; only top-level fires) - Trailing-slash inconsistency (
/usersvs/users/are different routes by default) await next()more than once (doubles downstream work)app.use(prefix, mw)+app.route(prefix, subApp)overlap (middleware fires twice)app.basePath('/api')as statement (prefix is thrown away from the type)
serve(app)on@hono/node-server(useserve({ fetch: app.fetch }))export default appon Workers (useexport default { fetch: app.fetch })Bun.serve({ fetch: app })(useapp.fetch)
c.req.query()with no arg when expecting single valuec.req.param('id')in global middleware (undefined where:idisn't in path)- Hand-rolled OpenAPI without
@hono/zod-openapi cors()mounted AFTER routes (never matches)
A handful of Hono rules already live on cursor.directory and in awesome-cursorrules (PR #152): they cover c.json() returns, zValidator + Zod, c.env for Workers, chained routes for RPC, and app.fetch Workers export. They have three structural problems this plugin fixes:
- They do NOT cover the v3 -> v4 removed APIs. LLMs continue to emit
c.jsonT,c.stream,c.env(),c.req.cookie,app.showRoutes, thehono/middlewarebarrel, andapp.handleEvent- all removed in v4.0.0 (2024-02). Existing rules silently allow them. - They omit the Express-leakage class.
(req, res, next),(err, req, res, next), npmcors,app.use(express.json()),supertest, missingreturnonc.json- all happen constantly in LLM-generated Hono code. Existing rules treat them as one-offs. - They miss security defaults and the CVE pin. None enforce
secureHeaders()/csrf(); none mentionbodyLimitCVE-2025-59139 (fix in v4.9.7); none address RPC client pitfalls (relative URL, value-import leakage,c.notFoundtyping).
This plugin ships:
- 10 MDC rules with proper
globsso the routes / RPC checks fire onsrc/routes/**, Workers checks onwrangler.{toml,jsonc}+ Worker entry, security checks on middleware files, etc. - 59 documented anti-patterns with BAD / CORRECT TypeScript pairs
- 5 skills:
/hono-new-route,/hono-rpc-setup,/hono-cloudflare-workers-setup,/hono-migrate-to-v4,/hono-validate - 1 reviewer agent with severity grouping (CRITICAL / ERROR / WARN / NIT) and per-file checks
- 2 fixture projects:
correct-sample(gold-standard Hono 4.12.19 + Workers + D1 + Drizzle + Zod) andanti-pattern-sample(Hono v3 hangover with 25+ tracked violations)
Copy the rules, skills, and agent into your project's Cursor configuration. Back up your existing files first; cp -r will overwrite same-named rules.
git clone https://github.com/RoninForge/roninforge-hono.git
# Use -n to avoid clobbering an existing customised rule of the same name.
cp -rn roninforge-hono/rules/* your-project/.cursor/rules/
cp -rn roninforge-hono/skills/* your-project/.cursor/skills/
cp -rn roninforge-hono/agents/* your-project/.cursor/agents/Or vendor the whole repo as a git submodule under your-project/.cursor/plugins/. Refer to the Cursor plugin docs for the current global-install path on your Cursor version.
| Rule | Scope (globs) | What it does |
|---|---|---|
hono-anti-patterns |
**/*.ts,**/*.js,**/*.tsx,**/*.jsx,wrangler.{toml,jsonc,json} |
59 LLM regressions with BAD / CORRECT pairs, organized A-H by category (Express leakage, v3-era APIs, TypeScript / RPC, CF Workers, security, routing, runtime, smaller issues) |
hono-core |
**/*.ts,**/*.tsx,**/*.js,**/*.jsx (alwaysApply) |
App init with typed Bindings + Variables, Context API, request accessors, middleware signature, built-in middleware list, cookie helpers, runtime detection |
hono-routing-and-rpc |
src/**/*.ts,src/routes/**/*,src/api/**/*,src/server/**/*,src/client/**/*,routes/**/* |
Chained routes, sub-app composition, basePath immutability, double-execution overlap fix, sub-app notFound dead code, hc<AppType> setup, import type rule, typed base URL, $path(), TanStack Query / SWR integration, factory.createHandlers, RPC at 30+ routes mitigation |
hono-validators |
src/**/*.ts,routes/**/*.ts,api/**/*.ts,handlers/**/*.ts |
@hono/zod-validator placement, c.req.valid() accessor, validator-throws-on-failure, @hono/zod-openapi (zod ^4 peer gotcha), @hono/standard-validator, @hono/valibot-validator, built-in hono/validator, decision tree |
hono-cloudflare-workers |
src/**/*.ts,worker/**/*.ts,workers/**/*.ts,wrangler.{toml,jsonc,json},**/cloudflare-env.d.ts,**/worker-configuration.d.ts |
wrangler.jsonc canonical shape, compatibility flag rules, wrangler types, typed Bindings, c.env vs process.env, c.executionCtx.waitUntil + portability, Static Assets binding, D1 awaits, Drizzle + D1 stack, Hyperdrive + Prisma adapter gotcha, Durable Objects for WebSockets, hono/cache custom-domain rule, ES Module Worker export |
hono-security |
src/**/*.ts,src/**/*.tsx,src/middleware/**/*.ts,src/auth/**/*.ts,src/index.ts,src/app.ts |
secureHeaders(), csrf(), CORS allow-list, bodyLimit() + CVE-2025-59139 pin floor 4.9.7, cookie defaults, JWT secret from c.env, logging without PII leaks, etag() + cache(), IP restriction, timeouts, request ID, auth library decision (Lucia deprecated; Better Auth / Clerk recommended), @sentry/hono over @hono/sentry |
hono-error-handling |
src/**/*.ts,routes/**/*.ts,api/**/*.ts,middleware/**/*.ts,src/index.ts,src/app.ts |
HTTPException canonical throw, app.onError global handler, app.notFound top-level only, typed RPC errors via discriminated unions, validator throws, Sentry via @sentry/hono, structured logging with pino redaction, error response shape convention |
hono-jsx |
**/*.tsx,**/*.jsx,**/jsx-runtime.ts,src/components/**/*,src/views/**/*,src/islands/**/*,app/islands/**/* |
hono/jsx server-side, tsconfig setup, FC does NOT include children, jsxRenderer middleware for layouts, hono/jsx/streaming with Suspense, hono/jsx/dom client components, HonoX islands, htmx integration, JSX SSR security pin floor 4.12.18 |
hono-testing |
**/*.test.ts,**/*.test.tsx,**/*.spec.ts,**/*.spec.tsx,vitest.config.{ts,js},**/test/**/*.ts,**/tests/**/*.ts,**/__tests__/**/*.ts |
app.request() universal pattern, testClient(app) typed RPC tests, Vitest + @cloudflare/vitest-pool-workers for real-runtime D1, applyD1Migrations fixture, Bun + bun:test, snapshot testing, middleware / validator / waitUntil testing, NEVER supertest |
hono-deployment |
wrangler.{toml,jsonc,json},deno.json,deno.jsonc,package.json,Dockerfile,fly.toml,vercel.json,netlify.toml,**/serverless.yml,**/template.yaml |
Cloudflare Workers (wrangler.jsonc + compatibility flags), Bun.serve, Deno + JSR, @hono/node-server v2 (Node 20+), AWS Lambda + Lambda@Edge, Vercel Edge, Netlify, build pipelines, pin floors, common deployment mistakes |
| Skill | Command | What it does |
|---|---|---|
| New route | /hono-new-route |
Scaffold a chained sub-app with zValidator as route argument, c.req.valid() typed access, c.json({ ... } as const, status) for typed RPC responses, Bindings + Variables generics, sub-app exported as typeof users, wired into parent with chained .route(). Refuses Rails-style controllers, c.notFound() in RPC routes, raw new Response(). |
| RPC setup | /hono-rpc-setup |
Scaffold the hc<AppType> client with import type (the load-bearing rule), absolute base URL, typed shared api module, TanStack Query / SWR integration via InferRequestType / InferResponseType, parseResponse utility, $path() method, IDE-slowdown mitigations for 30+ routes. |
| Workers setup | /hono-cloudflare-workers-setup |
Scaffold a fresh Hono + Workers project with wrangler.jsonc (NOT .toml), nodejs_compat, typed Bindings generated from wrangler types, D1 + Drizzle middleware pattern, secureHeaders + cors + csrf + bodyLimit stack, Vitest config for @cloudflare/vitest-pool-workers. |
| Migrate to v4 | /hono-migrate-to-v4 |
Stage-by-stage v3 -> v4 migration: bump pins (CVE-2025-59139 floor), replace c.jsonT / c.stream / c.env() / c.req.cookie / app.showRoutes / app.handleEvent, drop hono/middleware barrel, switch Deno to JSR, @hono/node-server v2 + Node 20+, register app.onError for validator throws. |
| Validate | /hono-validate |
Run validate-plugin.sh + tsc --noEmit + tests + grep audit for syntactic anti-patterns the type checker won't catch (c.jsonT, c.req.cookie, process.env, node_compat, serveStatic from hono/cloudflare-workers, hard-coded JWT secret, sameSite:'None' without secure, missing bodyLimit, value-import on hc client). |
| Agent | What it does |
|---|---|
hono-reviewer |
Reviews Hono v4 + TypeScript code by severity. CRITICAL: hono < 4.9.7 (CVE), v5 references (hallucination), cors wildcard + credentials, sameSite:'None' without secure, hard-coded JWT secret, process.env in Workers, missing bodyLimit, no csrf on cookie-auth, deprecated serveStatic, JSX SSR on < 4.12.18. ERROR: missing return on c.json, Express middleware shapes, all v3-era removed APIs, unchained routes / sub-apps, Rails controllers, zValidator placement, c.notFound/raw Response in RPC, relative URL hc(), value-import server app, unawaited D1, runtime export shapes. WARN: cookie defaults, secureHeaders, body-logging without redaction, app.onError, sub-app notFound, c.executionCtx truthy-check, no Bindings generic, cors after routes, middleware overlap, basePath statement, trailing slashes, hono/middleware barrel, wrangler.toml on greenfield, Lucia, @hono/sentry. NIT: missing satisfies ExportedHandler<Env>, hand-rolled OpenAPI, missing observability.enabled. |
tests/fixtures/correct-sample/ is a slim Hono 4.12.19 + Cloudflare Workers + D1 + Drizzle + Zod project demonstrating the gold-standard shape: chained routes, typed RPC, zValidator as route arg, c.json({ ... } as const, status) typed responses, secureHeaders + cors + csrf + bodyLimit stack, app.onError + app.notFound at top-level, export default { fetch: app.fetch } satisfies ExportedHandler<Env>.
tests/fixtures/anti-pattern-sample/ is the inverse. Every file violates a numbered anti-pattern. package.json pins hono ^3.12.0 + cors ^2.8.5 + supertest ^6.3.0 + @hono/sentry ^1.0.0 + lucia ^3.2.0 on purpose - the v3 era is the LLM-training-data baseline for most pre-2025 models, plus deprecated companions that LLMs still recommend. Tracked violations include: missing return on c.json (#1), (req, res) Express handler shape (#2), (req, res, next) middleware (#3), (err, req, res, next) (#4), npm cors (#6), supertest (#12), c.jsonT (#13), addEventListener('fetch') + app.handleEvent (#15), c.req.cookie (#16), c.env() function call (#17), hono/middleware barrel (#20), app.head() (#23), no Bindings/Variables (#24), c.notFound in RPC route (#29), process.env in Workers (#34), node_compat flag (#36), serveStatic from hono/cloudflare-workers (#37), unawaited D1 (#40), cors * + credentials (#43), cookie without httpOnly/secure/sameSite/path (#45), sameSite:'None' without secure:true (#46), hard-coded JWT secret (#48), sub-app notFound (#50), basePath as statement (#53), export default app on Workers (#55), deprecated @hono/sentry + lucia references.
Rules target hono ^4.12.19 with Node 20+ (when on Node), Bun latest, Deno latest, Wrangler ^4.0.0. Most patterns work back to Hono 4.0.0 (Feb 2024) with the deltas called out inline. Pin floors:
hono >= 4.9.7mandatory - CVE-2025-59139 / GHSA-92vj-g62v-jqhhbodyLimitbypass fixhono >= 4.12.18mandatory if rendering JSX SSR - tag-name, attribute-name, CSS-injection hardening@hono/node-server >= 2.0.0requires Node 20+@hono/zod-openapi >= 1.0.0requireszod ^4.0.0(peer is^4.0.0ONLY, not^3.x)compatibility_date >= "2024-09-23"required fornodejs_compatto implynodejs_compat_v2
Where the rule cites a version (c.json() always typed since v4.0.0, c.text() typed since v4.3.0, JSR for Deno since v4.4.0, secureHeaders Permissions-Policy since v4.6.0, Standard Schema validator since v4.7.0, fire(app) since v4.8.0, JSR parseResponse since v4.9.0, typed base URL on hc since v4.11.0, $path() method since v4.12.0), verify against the changelog for the version you have installed before adopting.
MIT - see LICENSE