agentleFS
waynesuttonwaynesutton/markdown-site/.cursor/skills/convex-doctor/SKILL.md

convex-doctor

Skill628 starsChanged 7 months agoMITView on GitHub

Run convex-doctor static analysis, interpret findings, and fix issues across security, performance, correctness, schema, and architecture categories. Use when running convex-doctor, fixing convex-doctor warnings or errors, improving the convex-doctor score, or when asked about Convex code quality, static analysis, or linting Convex functions.

The file

Show its rules and text

We split this skill into the rules it gives an agent

23 rules. About 0 are common, 12 are distinctive, and 11 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈12

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 11

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    When convex-doctor reports findings, fix them in this order:

    line 45
  2. Distinctive:

    Add auth to HTTP actions and public endpoints

    line 48
  3. Very specific:

    Remove Date.now() from queries (breaks caching and reactivity)

    line 53
  4. Distinctive:

    Add missing indexes for foreign keys where query patterns exist

    line 63
  5. Distinctive:

    Remove redundant indexes (prefixes of compound indexes)

    line 65
  6. Distinctive:

    Instead of calling a public action from the browser, create a job table and mutation-scheduled internal action:

    line 76
  7. Very specific:

    Add a job table to convex/schema.ts with status, result, and error fields

    line 78
  8. Distinctive:

    Create a public mutation that inserts a pending job and schedules the internal action

    line 79
  9. Distinctive:

    Create a public query that returns job status for the UI

    line 80
  10. Distinctive:

    Update the frontend to call the mutation and poll the query

    line 82
  11. Distinctive:

    When a Convex function calls another Convex function on the server side:

    line 88
  12. Very specific:

    Create an internal* version if only a public version exists

    line 90
  13. Distinctive:

    If the function needs both public and internal access, keep both and have the public version call the internal one

    line 92
  14. Very specific:

    When an action makes multiple ctx.runQuery calls for independent data:

    line 96
  15. Distinctive:

    Create a single internal query that returns all needed data in one object

    line 98
  16. Very specific:

    Add a now: v.number() argument to the query

    line 106
  17. Very specific:

    When components.auth.public.* triggers direct-function-ref warnings:

    line 112
  18. Very specific:

    Create helper functions in convex/authComponent.ts that call the component API

    line 114
  19. Very specific:

    Import helpers directly instead of using ctx.runQuery(internal.authComponent.*)

    line 115
  20. Very specific:

    Add convex/authComponent.ts to the [ignore] section of convex-doctor.toml

    line 116
  21. Distinctive:

    After every fix pass:

    line 120
  22. Very specific:

    Always document suppressions with rationale in convex-doctor.toml.

    line 154
  23. Very specific:

    All remediation PRDs are in prds/convex-doctor/:

    line 158

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Convex doctor workflow

This skill codifies the full convex-doctor remediation workflow used in this codebase (score 42 to 100 across 17 passes). Follow it whenever running convex-doctor or fixing its findings.

What is convex-doctor

convex-doctor is a static analysis tool for Convex backends. It scores your codebase 0 to 100 across five categories: security, correctness, performance, schema, and architecture.

Run it with:

npx convex-doctor@latest

Configuration

This project has a convex-doctor.toml at the repo root with intentional suppressions. Always check it before working on findings.

Current suppressions and rationale

RuleLevelRationale
correctness/generated-code-modifiedoffWorking tree is always dirty after codegen
schema/optional-field-no-default-handlingoff94 optional fields by design for markdown frontmatter
correctness/missing-uniqueoffRemaining .first() calls are intentional ordered picks
schema/deep-nestingoff4-level validators needed for chat attachments
schema/array-relationshipsoffFlagged on function args, not table columns
perf/missing-index-on-foreign-keyoffRemaining FK is inside nested array (not indexable)
arch/duplicated-authoffAuth awareness is intentional per public handler
arch/monolithic-fileoffFiles organized by domain
arch/large-handleroffEmail templates, sync, and search are inherently multi-step

Ignored files

  • convex/_generated/** (generated code)
  • convex/authComponent.ts (thin auth component forwarders)

Fix priority order

When convex-doctor reports findings, fix them in this order:

  1. Security errors (highest priority)
    • Add auth to HTTP actions and public endpoints
    • Convert api.* server-to-server calls to internal.*
    • Move public actions to mutation-scheduled internal actions
  2. Correctness errors
    • Remove Date.now() from queries (breaks caching and reactivity)
    • Convert .first() to .unique() only where the index enforces uniqueness
    • Fix collect then filter patterns with indexed queries
  3. Performance warnings
    • Replace unbounded .collect() with .take(n) or pagination
    • Batch sequential ctx.run* calls into single internal queries
    • Eliminate N+1 patterns in HTTP and RSS endpoints
  4. Schema warnings
    • Add missing indexes for foreign keys where query patterns exist
    • Rename indexes to by_field snake_case convention
    • Remove redundant indexes (prefixes of compound indexes)
  5. Architecture warnings
    • Extract helper functions from large handlers
    • Split provider modules from orchestration logic
    • Replace throw new Error(...) with ConvexError in user-facing handlers

Common fix patterns

Convert public action to queued job

Instead of calling a public action from the browser, create a job table and mutation-scheduled internal action:

  1. Add a job table to convex/schema.ts with status, result, and error fields
  2. Create a public mutation that inserts a pending job and schedules the internal action
  3. Create a public query that returns job status for the UI
  4. Convert the action to internalAction that updates the job record on completion or failure
  5. Update the frontend to call the mutation and poll the query

This pattern was used for: AI image generation, AI chat responses, URL imports.

Convert api.* to internal.*

When a Convex function calls another Convex function on the server side:

  1. Create an internal* version if only a public version exists
  2. Replace api.module.fn with internal.module.fn in the caller
  3. If the function needs both public and internal access, keep both and have the public version call the internal one

Batch sequential ctx.run* calls

When an action makes multiple ctx.runQuery calls for independent data:

  1. Create a single internal query that returns all needed data in one object
  2. Replace the sequential calls with one ctx.runQuery to the batched query
  3. This reduces transaction overhead and eliminates the sequential-run-calls warning

Remove Date.now() from queries

Queries must be deterministic. Replace Date.now() with a timestamp argument:

  1. Add a now: v.number() argument to the query
  2. Pass Date.now() from the frontend or from the action/mutation that calls the query
  3. For reactive subscriptions, round the timestamp (e.g., 60-second intervals) to keep reactivity stable

Auth component helper conversion

When components.auth.public.* triggers direct-function-ref warnings:

  1. Create helper functions in convex/authComponent.ts that call the component API
  2. Import helpers directly instead of using ctx.runQuery(internal.authComponent.*)
  3. Add convex/authComponent.ts to the [ignore] section of convex-doctor.toml

Verification checklist

After every fix pass:

  • npx convex codegen passes
  • npx tsc --noEmit passes (or npx convex codegen covers this)
  • npm run build succeeds
  • npx convex-doctor@latest shows improved score or fewer findings
  • Existing functionality still works (AI chat, search, dashboard, RSS, stats)

Score history

PassScoreErrorsWarningsKey changes
Initial42/10073243Baseline
1 (remediation)~55~50~221Security: auth on HTTP, api to internal
2~60~40~200AI action flow, HTTP hardening
368/100--collect-then-filter, auth signals
1080/100168Import URL queued job, unique lookups
1591/100043Newsletter batching, auth forwarders, toml config
1692/100039Semantic search batching, auth helpers
17100/10000Stats helpers, contact helpers, final toml tuning

When to suppress vs fix

Fix it when:

  • The finding points to a real bug or security gap
  • The fix is low risk and improves code quality
  • The pattern can be changed without affecting product behavior

Suppress it when:

  • The finding is a tool false positive (e.g., component function refs)
  • The pattern is intentional by design (e.g., per-handler auth checks)
  • The fix would add more complexity than the warning is worth
  • Generated code triggers the finding

Always document suppressions with rationale in convex-doctor.toml.

Related PRDs

All remediation PRDs are in prds/convex-doctor/:

  • convex-doctor-remediation.md (initial plan, 5 phases)
  • convex-doctor-second-pass.md through convex-doctor-seventeenth-pass.md

Related files

  • convex-doctor.toml (suppression config)
  • convex/schema.ts (indexes and table definitions)
  • convex/authComponent.ts (auth component forwarders)
  • convex/importJobs.ts (queued job pattern example)
  • convex/aiImageJobs.ts (queued job pattern example)
  • convex/semanticSearchJobs.ts (queued job pattern example)

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.