skills/clerk-hono/SKILL.md
Use Clerk auth in Hono apps via @hono/clerk-auth. Use when adding or changing Clerk authentication, protecting routes, or reading userId/orgId in Hono.
npx skillsauth add morgs32/skills clerk-honoInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Source: honojs/middleware - packages/clerk-auth
pnpm add @hono/clerk-auth (or npm). No custom auth middleware - use the package directly.CLERK_SECRET_KEY, CLERK_PUBLISHABLE_KEY (e.g. in wrangler or .dev.vars).Apply middleware to the routes that need auth, then use getAuth(c) in handlers:
import { clerkMiddleware, getAuth } from '@hono/clerk-auth';
import { Hono } from 'hono';
const app = new Hono();
app.use('/push/*', clerkMiddleware());
app.use('/orgs/*', clerkMiddleware());
app.route('/', sessionRouter);
In route handlers:
app.get('/', (c) => {
const { userId, orgId } = getAuth(c);
if (!userId) {
return c.json({ message: 'You are not logged in.' }, 401);
}
if (!orgId) {
return c.json({ message: 'No active organization selected.' }, 400);
}
return c.json({ userId, orgId });
});
const clerkClient = c.get('clerk') then e.g. clerkClient.users.getUser(...).Use when the route is a resource server or machine-to-machine and should accept Clerk-issued API keys instead of (or in addition to) session tokens.
Once you have an API key, use it to authenticate requests to your application's API. Send the API key as a Bearer token in the Authorization header:
await fetch('https://your-api.com/users', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${apiKey}`,
},
});
On your backend, verify the API key using Clerk's SDK (e.g. @hono/clerk-auth with getAuth(c, { acceptsToken: 'api_key' })). See the verifying API keys guide for framework-specific examples.
By default getAuth(c) only accepts session tokens; API keys are rejected unless you pass acceptsToken.
const { userId } = getAuth(c, { acceptsToken: 'api_key' });
if (!userId) {
return c.json({ error: 'Unauthorized' }, 401);
}
const { userId, tokenType, scopes } = getAuth(c, {
acceptsToken: ['session_token', 'oauth_token', 'api_key'],
});
if (!userId) {
return c.json({ error: 'Unauthorized' }, 401);
}
// Optional: enforce scopes for api_key
if (tokenType === 'api_key' && !scopes?.includes('write:users')) {
return c.json({ error: 'API key missing required scope' }, 403);
}
Clerk API keys are in beta; behavior may change. Full details: Verify API keys (Clerk).
Do not add a custom clerkAuthMiddleware or re-export from a local auth.ts; import clerkMiddleware and getAuth from @hono/clerk-auth in app and routers.
development
Create and map ZerospinError instances for Effect-based code in zerospin. Use when defining error codes/messages, wrapping causes, mapping/catching errors in Effects, or returning structured errors from Effect.gen/Effect.fn or promise boundaries.
data-ai
Update agent skills in this repo or another.
development
TypeScript type-safety rules and guidance.
devops
Fix and update Turborepo (Turbo) configuration and task setup. Use for turbo.json errors, schema updates (pipeline -> tasks), and package-level config issues like missing extends.