An open, always-fresh directory of AI coding tools. Every editor, terminal agent, orchestrator, extension and cloud agent, with pricing verified against vendor pages and the graph of what runs what.
The data lives in git, one YAML file per tool in content/tools. The site is a renderer. No affiliate links, no sponsored placement, no benchmarks.
wraps graph records which tools run which, whether they reuse your login, and from which tier./compare/<a>-vs-<b> built from the same data.Nuxt 4 and Nuxt UI, comark-content for the YAML corpus with schema validation, Nuxt SEO for sitemap, robots, JSON-LD and per-tool OG images, nuxt-agent-discovery for the markdown an AI agent reads instead of the page. Deployed on Vercel with ISR: in production the content is read from GitHub at request time, pinned to the latest commit that touched content/tools, so a merged data PR goes live through the push webhook without a redeploy. Builds are skipped for content-only commits (vercel.json).
Environment variables are listed in .env.example. The GitHub webhook points at /api/revalidate with push events and the same secret.
pnpm install
pnpm dev
pnpm validate checks every file in content/tools against shared/schema.ts plus the rules a schema cannot express: slugs match filenames, aliases and successor resolve, the wraps graph has no cycle, pricing.same_as and tier mirrors agree with the tool they point at, SPDX expressions parse, and every price in a tool that has a capture appears verbatim in the vendor text under content/snapshots. In development the same schema is enforced by comark-content and a bad file throws.
/api/v1/tools.json every tool with computed fields (open_source, pricing_model, has_free_tier, entry_price, effective_providers, wrapped_by, freshness)/api/v1/tools/<slug>.json one tool/api/v1/compare.json the canonical pair list, plus the URL pattern for the pairs it does not enumerate/api/v1/finder/parse turns one sentence into finder filters, the only route that calls a model/api/content/list and /api/content/get/<slug> the raw documents served by comark-content, unversioned and outside the policy below/openapi.json describes all of the above and every page, including the versioning policy in info.descriptionEvery GET route is cached with ISR and purged when content changes. POST /api/v1/finder/parse and POST /api/revalidate stay uncached.
The public surface lives under /api/v1 and every response carries API-Version: 1. The unversioned paths it used to live at still answer, with a 301 (308 on the finder, which is a POST). Adding a field is not a new version; removing or renaming one is. A current version carries no deprecation headers, and when one is superseded it gains Deprecation, then Sunset at least 180 days later, and a Link naming the successor. The policy is stated once in shared/api.ts, read from there by the middleware and published in openapi.json under info.description.
For agents, every page has a markdown twin at /raw/<path>.md, and asking a page URL for text/markdown returns it. /llms.txt, /llms-full.txt and /sitemap.md list what is there.
An eve agent in agent/ re-reads every vendor pricing page daily and opens a PR when a price changed. It never merges. It identifies itself and honours robots.txt, see whichcoding.tools/crawler and agent/README.md.
Read CONTRIBUTING.md. Adding a tool is one YAML file and a pull request. Fixing a price is one line and a bumped verified_at.
Without a checkout, the two issue forms do the same job: Add a tool and Report outdated data. Both start an automated first pass that reads the vendor page and opens a pull request for a person to review.
Code is MIT. The tool data in content/tools/ is CC BY 4.0, see LICENSE-DATA: use it anywhere, including commercially, as long as you credit whichcoding.tools and link back. Contributing a tool file puts it under the same terms.
The captures under content/snapshots/ are verbatim excerpts of vendor pages, kept to verify prices. They are not covered by that grant and stay under their original terms.