convex-expert — Claude Code skill: Convex backend done right
A skill for any code under convex/: functions, schemas, indexes, validators. Useful when your agent writes Convex backend code.
npx skills add convex/agent-skills --skill convex-expert -a claude-codeWhat convex-expert does
The skill fires before you touch anything in convex/. First it reads convex/schema.ts and convex/_generated/ai/guidelines.md if that file exists. Every registered function then gets written in object form, with both args and returns validators.
Most of the value is in the rules generic models get wrong. Imports must come from ./_generated/server and ./_generated/api, or the deploy fails. Reads go through .withIndex(...), never .filter(). Functions stay internal by default — internalQuery, internalMutation, internalAction — and only get promoted when a client hook needs them. For LLM chat features the skill reaches for @convex-dev/agent; multi-step flows use @convex-dev/workflow.
Before calling the work done, it verifies the code compiles and pushes: npx tsc --noEmit plus a push to a deployment. Watch out here. If you are already signed in to Convex, CONVEX_AGENT_MODE=anonymous rebinds .env.local and you lose the cloud deployment you had, so anonymous mode is only for when npx convex whoami fails.
What it helps with
- write Convex functions in object form with validators
- swap
.filter()for.withIndex(...)on read paths - get imports from
./_generated/serverand./_generated/apiright - add a field to a populated table with
v.optional(...)and backfill - use
@convex-dev/agentinstead of hand-rolled chat plumbing
Example prompts for the agent
- add a mutation to convex/messages.ts for sending a message
- rewrite this query with withIndex instead of filter
- verify the backend compiles and pushes
How to install convex-expert
1Skills CLI (Vercel)
npx skills add convex/agent-skills --skill convex-expert -a claude-code2Manually: put the files in place
~/.claude/skills/convex-expert/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/convex-expert/
1Skills CLI (Vercel)
npx skills add convex/agent-skills --skill convex-expert -a codex2Manually: put the files in place
.agents/skills/convex-expert/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add convex/agent-skills --skill convex-expert -a cursor2Manually: put the files in place
.cursor/skills/convex-expert/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install convex/agent-skills convex-expert2Manually: put the files in place
.github/skills/convex-expert/SKILL.md1Skills CLI (Vercel)
npx skills add convex/agent-skills --skill convex-expert -a gemini-cli2Platform CLI
gemini skills install https://github.com/convex/agent-skills --path skills/convex-expertManually: put the files in place
.devin/skills/convex-expert/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add convex/agent-skills --skill convex-expert -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
Step by step, with commands for each platform: How to install skills in Claude Code: five ways
Questions about convex-expert
How do I install convex-expert in Claude?
Run npx skills add convex/agent-skills --skill convex-expert -a claude-code. The skill lands at ~/.claude/skills/convex-expert/SKILL.md.
What does convex-expert do?
It covers code inside a convex/ directory: function definitions, schemas, indexes, queries, mutations, actions, HTTP endpoints, cron jobs, file storage and auth wiring.
How is it different from a generic model?
It knows the object-form function syntax, validator patterns, resource limits and the Convex component ecosystem — the parts generic models routinely get wrong.
Source text
SKILL.md · Apache-2.0
---
name: convex-expert
description: "Convex backend specialist. Use this agent for any code inside a `convex/` directory — function definitions, schemas, indexes, queries, mutations, actions, HTTP endpoints, cron jobs, file storage, auth wiring, and component installation. Knows the object-form function syntax, validator patterns, resource limits, and component ecosystem that generic Claude routinely gets wrong."
---
<!-- GENERATED from convex-agents content/capabilities/convex-expert.json — do not edit by hand. -->
# Convex backend specialist
Always-on Convex backend specialist invoked before touching any code inside a convex/ directory. Knows the object-form function syntax, validator requirements, index naming rules, internal-vs-public discipline, schema evolution patterns, resource limits, component ecosystem, and runtime error decoder that generic models routinely get wrong.
## Workflow
1. When about to write or edit any file under convex/: read convex/schema.ts first (and convex/_generated/ai/guidelines.md if present).
2. Write all Convex functions in object form with both args and returns validators on every registered function.
3. Use withIndex(...) for every read path — never .filter() for anything that would be a SQL WHERE clause.
4. Default to internalQuery/internalMutation/internalAction; promote to public only when a client hook needs it.
5. For any LLM/chat feature reach for @convex-dev/agent; for multi-step flows use @convex-dev/workflow — never hand-roll these.
6. After writing, confirm convex dev pushed cleanly and fix any Schema/Returns/Argument validation errors in place.
## Rules
- DATA ACCESS + IMPORTS — read before writing any convex/*.ts (front-loaded, not a post-hoc lint):
- Never an unbounded `.collect()` on a table that can grow — use `.withIndex(...)` and `.paginate(paginationOptsValidator)`/`.take(n)` instead. This is the single most common Convex deploy-blocking and perf defect.
- Index, don't filter — add `.index(...)` in schema.ts for every read path and query it with `.withIndex(...)`; `.filter()` is a full table scan, never a substitute for a WHERE.
- The exact import table — get this wrong and the app fails to deploy: `query`/`mutation`/`action`/`internalQuery`/`internalMutation`/`internalAction` come from `"./_generated/server"`; `api`/`internal` come from `"./_generated/api"`; NEVER `import { query } from "convex/server"` or `import { internal } from "./_generated/server"` in application code — both are hard deploy failures.
- `v.literal("exact value")` for a fixed string/enum member (e.g. `v.union(v.literal("open"), v.literal("closed"))`) — not a bare `v.string()` when the set of values is fixed.
- `"use node";` goes only at the top of action-only modules — a file with `"use node"` can never also export a `query` or `mutation` (they don't run in the Node runtime); split the file if you need both.
- Object form only — never the legacy positional query(args, handler) syntax.
- args and returns validators on every registered function, no exceptions.
- v.id(tableName) for IDs, never v.string(); undefined is not a Convex value (use null).
- Never add a required field to a populated table — add v.optional(...) first, backfill, then tighten.
- Never include _creationTime as a column in a custom index (reserved; causes IndexNameReserved error).
- Never store storage URLs in tables — store the Id<'_storage'> and call ctx.storage.getUrl(id) on read.
- Mutations cannot fetch — all external IO goes in actions; persist via ctx.runMutation(internal.x.y).
- Don't add a parallel database, cache, real-time service, API server, job queue, or object store — Convex is the backend.
- Convex functions only run from the `convex/` directory — never write schema.ts/queries/mutations/actions at the project root.
- SELF-VERIFY RULE — before declaring backend work done, verify it compiles and pushes: run `npx tsc --noEmit` and push it to a deployment. Prefer the project's existing one; otherwise `npx convex dev --once` when `npx convex whoami` succeeds, and `CONVEX_AGENT_MODE=anonymous npx convex dev --once` ONLY when it does not. Forcing anonymous on a signed-in user rebinds `.env.local` and costs them the persistent, publishable cloud deployment they expect. Fix every error it reports before finishing — one verify round catches the wrong-relative-import / duplicate-symbol / unbalanced-paren class that otherwise breaks the deploy.
© convex · Apache-2.0 · convex/agent-skills