`go run build` cannot work — Go resolves a bare argument as an import
path, so it looks for a package named "build" in std. Wrap the existing
commands in make targets instead, which gives the `make build` /
`make check` ergonomics without changing the Go interface underneath.
The wrapper earns its keep beyond the aliasing: `make serve` builds and
previews dist/ in one step, `make test` runs exactly what CI runs, and
`make update` fails with a pointer to LOCAL_DEV.md when GITHUB_TOKEN is
unset rather than erroring out mid-run.
Cloudflare keeps calling `go run . -build` directly. Locally make is
convenience; in the build image it would be a dependency relied on for
no benefit.
The CI failure on the merge commit was the one-time bootstrap ordering
problem: `go run . -build` ran before any data/metadata.json existed. The
nightly updater has since committed one, so the tree builds — but that
commit was pushed with GITHUB_TOKEN, which by design does not re-trigger
workflows, so CI never re-ran and main's status stayed red.
That exposes a standing gap rather than a one-off: every nightly refresh
commits the exact data the build consumes, and none of those commits run
CI. A refresh that broke the build would first be noticed by Cloudflare
at deploy time.
Run `go run . -build` in the update workflow between the fetch and the
commit, so data that does not build is never committed. Add
workflow_dispatch to CI so a bot-pushed commit can still be verified on
demand.
The updater fetched GitHub metadata and rendered the dashboard payload in
a single step, so anything that published the site needed a GITHUB_TOKEN.
Cloudflare Pages builds from a Git webhook and has no business holding
one.
Split the tool into three modes. The default update step still fetches
GitHub and now records every API-sourced field in data/metadata.json,
which is committed alongside README.md and data/history.jsonl. The new
-build mode joins that snapshot with data/agents.yml and
data/history.jsonl to render dist/ with no network access and no token;
-check is unchanged.
Supporting changes:
- computeDeltaAt anchors the delta windows to when the data was fetched
rather than the wall clock, so a redeploy days later reproduces the
same Δ7d instead of sliding the window past its slack allowance.
- writeSiteData takes updatedAt explicitly for the same reason: the
timestamp labels data freshness, not build time.
- sortStats is extracted from fetchStats so the build step re-ranks
identically from committed metadata.
- An agents.yml entry with no metadata yet is omitted with a warning
instead of failing the build, which would otherwise block every deploy
between merging a new entry and the next nightly run.
- update.yml drops the GitHub Pages deploy steps and commits
data/metadata.json; ci.yml runs `go run . -build` so a build that would
break on deploy breaks in CI first.
- site/_headers stops the edge serving a stale data.json after a refresh.
- docs/DEPLOY.md covers the Cloudflare setup, including the one-time
bootstrap of data/metadata.json that the build depends on.
Also carries the in-progress curation work already in the tree: the
module rename to awesome-ai-dev-tools, retagged entries, and removal of
the archived Roo-Code, void, continue and suna entries.
"awesome-coding-agents" no longer described the contents once the scope
widened past coding agents to AI-powered developer tools generally. Renaming
now was near-free: 3 stars, 4 forks, 135 unique visitors, four months old.
Name selection avoided the crowded awesome-* namespace, where the obvious
candidates are held by established lists (awesome-ai-devtools 3.9k,
awesome-ai-tools 6.2k, awesome-ai-coding-tools 2.1k). "ai-dev-tools" has no
incumbent at the exact name.
- Repo renamed; GitHub description and homepage updated.
- Module path, User-Agent, .gitignore, H1, site <title>/og:title and every
GitHub Pages URL updated across README.md, templates/readme.tmpl,
docs/LOCAL_DEV.md and site/index.html.
- plans/reports/ left untouched: it is a dated historical record.
go build: ok. go run . -check: 43 agents valid. go test ./...: ok.
The list was already drifting past "coding agents" — ADEs were admitted in
the previous commit. Rather than keep widening criterion 1 one category at a
time, it now describes the actual subject: developer tools built around AI.
The dividing line becomes tools you use vs. building blocks you import, which
keeps libraries, SDKs, model weights and skill collections out.
The star floor drops from a soft "roughly 10,000+" to a hard 1,000:
- enforceStarFloor drops any below-floor entry from the ranking and emits an
::error:: annotation, so the published list can never violate the rule.
Dropping rather than failing keeps one bad entry from blocking the refresh
of every other repo.
- -check cannot catch this (star counts need the API, -check runs offline);
docs/CONTRIBUTING.md says so explicitly.
Side effect: Orkas (1,998 stars) now clears the floor it previously missed.
go run . -check: 43 agents valid. go test ./...: ok.
Criterion 1 previously excluded "workspaces for agents", which ruled out
the ADE category entirely. ADEs are the surface a developer actually works
in, the same way a coding agent is, so they now qualify on their own terms.
Libraries, SDKs, skill collections and observability-only layers stay out.
- Widen inclusion criterion 1 in templates/readme.tmpl and document the
two admitted kinds in docs/CONTRIBUTING.md.
- Add `orchestration` to the Workflow facet in validate.go so ADEs are
filterable as a distinct class on the dashboard.
- Add stablyai/orca (70.0k) and getpaseo/paseo (17.5k).
README.md is regenerated from the template by the daily run; its
Contributing section is updated here so it is not stale in the meantime.
go run . -check: 43 agents valid. go test ./...: ok.
The emphasis and the bolded row came from Chart.js index-mode
interaction, which only recomputes when the x index changes. Moving
straight up and down inside one date therefore kept whichever series was
picked on entry, so the highlight did not match the line under the
cursor.
Track the pointer on the canvas instead and derive both the date and the
nearest series from pixel distance, so vertical movement re-picks. The
built-in tooltip and interaction config are gone; a small plugin draws
the vertical guide at the hovered date and a dot where the emphasized
series crosses it, replacing the caret and hover point that came with
them. Reads are throttled to one per animation frame, and the card now
follows the cursor's height instead of the average of forty series.
Hovering a date now lists all plotted repos ordered by stars at that
point, with exact counts, so the chart answers "who was ahead when"
instead of only showing one value at a time. The series under the cursor
is bold in the list, stays solid and thickens, and every other line goes
thin and dashed — readable with forty lines on screen.
Chart.js paints its tooltip on the canvas and cannot weight one row
differently, so the readout is an HTML card positioned beside the caret
(flipped and clamped to stay inside the chart) and the built-in tooltip
is off. Forty rows fit as three columns; names truncate on a shared grid
so the counts align. Hidden series are excluded, so the ranking always
matches what is drawn.
The chart hid every series past rank 12 while the legend still listed
all of them, so the card claimed to show everything and drew a third of
it. Plot all series on load; the legend stays the way to hide the ones
you do not want, and hidden state still survives re-renders.
A single category could not describe tools that ship as a CLI, an editor
plugin and a desktop app at once, and 7 of the 40 entries were filed
under a surface they only partly match — cline is "an SDK, IDE extension
or CLI assistant" in one `extension` slot, Reasonix ships CLI, desktop
and VS Code under `cli`, warp is a terminal filed as `ide`.
Tags cover five facets: surface (at least one), model access, workflow,
integration, and origin (at most one). tagVocabulary in validate.go is
the single source of truth — the validator, its error messages, and the
dashboard's filter chips all derive from it, the last via a new facets
field in site/data.json.
The dashboard now filters on tags with multi-select chips grouped by
facet: OR within a facet, AND across facets, plus a clear-filters
control, and search matches tags as well as name and description. Only
tags some row actually carries get a chip, so chips and rows cannot
disagree. Tag pills are tinted per facet, replacing the category badge.
All 40 entries are tagged from each repo's own README, topics and docs;
CONTRIBUTING documents every tag and the evidence rule for applying one.
A leftover `category:` key now fails validation with a message naming
its replacement, rather than being silently ignored.
README.md and data/history.jsonl are the regenerated updater output.
The maintenance criterion was unfalsifiable, so entries went years
without a push before anyone noticed by hand. The updater already
fetches pushedAt; warn when it is older than 90 days, alongside the
existing rename and archival annotations. Archived repos keep their own
warning rather than getting two.
Quantify the criterion in the README and CONTRIBUTING: dropped after 6
months idle, flagged past 3, with removal still a human decision.
Also correct two CONTRIBUTING claims the code contradicts — duplicates
are rejected by CI rather than ignored at run time, and renames do carry
history over once canonicalKeyMigrations has the old key.
README.md and site/data.json were written with os.Create/os.WriteFile,
so a write that failed midway left the repo front page truncated, while
history.jsonl already used a temp-file-plus-rename. Extract that pattern
into atomicWriteFile and route all three writers through it.
Also sort snapshots by date when reading history.jsonl: delta windows
pick the newest snapshot inside the window by scan order, which silently
produces wrong deltas if a hand edit or a merge of two concurrent runs
interleaves lines.
Cover the README renderer, which had no test beyond sanitizeCell, and
name the generated paths as constants instead of repeating literals.
Coverage 65.1% -> 75.7%.
Adds deepseek-harness (top of the list by stars), grok-build,
openinterpreter, Codewhale, DeepSeek-Reasonix, openclaude, oh-my-pi,
open-code-review, prime-agent, jcode, DeepCode, freebuff, kimi-cli and
claurst, all meeting the inclusion criteria.
Drops bolt.new, plandex and trae-agent: no upstream push in 21, 11 and 7
months respectively.
Also points avante.nvim at its current canonical slug and maps the old
history key so its star history stays attached.
Live GitHub audit of all 29 tracked repos plus ~380 candidate slugs:
14 repos meeting the inclusion criteria are untracked (deepseek-harness
at 219.6k stars would rank first), 7 tracked repos have no push in over
three months, and data/agents.yml still carries the pre-rename
yetone/avante.nvim slug.
- notes for gpt-engineer, void, Roo-Code (archived upstream) — shown
as badges + italics on the dashboard; kept for historical value
- README Contributing now states inclusion criteria: must BE a coding
agent (not tooling for agents), ~10k+ stars, open source + maintained
- resolves ambiguity for community PRs proposing sub-bar repos
* chore: project hardening — dep swap, CI gates, dependabot, action bumps
- swap gopkg.in/yaml.v3 (upstream archived Apr 2025) for maintained
github.com/goccy/go-yaml; same Unmarshal API, tags unchanged
- add CI workflow: go vet/test/build + golangci-lint + govulncheck
on PRs and main pushes
- add dependabot for gomod + github-actions (weekly)
- bump actions to latest majors in update.yml (clears Node 20
deprecation annotations); workflow logic untouched
- README/history refreshed by E2E verification run (29 agents)
* fix: check Close/Remove error returns (errcheck)
Write paths (writeSnapshots, renderReadme) now propagate close errors —
a failed close there can hide lost data. Read/cleanup paths ignore
explicitly with _ =.
- Add pi, OpenHands, warp, gpt-pilot, qwen-code, kilocode, onlook,
dyad, trae-agent, copilot-cli (19 -> 29 tracked repos)
- Update renamed slugs to canonical owners (anomalyco/opencode,
aaif-goose/goose, AntonOsika/gpt-engineer) with history key
migrations so star deltas survive the rename
- Generate site/data.json each run and deploy site/ (interactive
table + star-history chart) to GitHub Pages from the daily
workflow, since GITHUB_TOKEN bot pushes cannot trigger a separate
Pages workflow
Two new short docs unblock new contributors who currently have to read
the Go source to figure out the GITHUB_TOKEN requirement and the
agents.yml schema:
- docs/LOCAL_DEV.md walks through the PAT setup, the local run command,
what files the run modifies, and how to revert before opening a PR.
- docs/CONTRIBUTING.md documents the agents.yml fields, enumerates the
six valid category values, and explains the rename and deprecation
policy now that history is keyed canonically.
Also add a one-sentence caption under the table in readme.tmpl so the
Delta7d column has a definition in the rendered README.
The blanket git pull --rebase -X theirs in the push-retry loop silently
discarded conflicting changes in any file, so a maintainer push to
data/agents.yml racing with the daily run could be dropped without
warning. Replace it with a selective resolver: plain rebase first, then
inspect git diff --name-only --diff-filter=U; if every conflicting path
is data/history.jsonl or README.md (both bot-generated), resolve those
with --theirs and continue; otherwise abort the rebase and fail the run
loudly so the human edit is preserved and visible.
Also leave a comment at the permissions block warning future maintainers
not to swap GITHUB_TOKEN for a PAT, since the no-recursion invariant is
what currently prevents the auto-commit from triggering its own workflow.
GitHub fetcher (github.go):
- add 30s HTTP client timeout (was http.DefaultClient with no bound)
- chunk GraphQL alias requests at 50 repos to stay clear of abuse detection
- abort the run on any partial GraphQL error or missing repo rather than
silently shrinking the README and poisoning the next delta
- retry transient failures (network, 5xx, 429) with 2s/4s/8s backoff
History layer (history.go):
- key snapshots by canonical owner/repo from agents.yml instead of the
rename-resolved NameWithOwner returned by the API; carry a lazy
migration map so existing aaif-goose/goose entries fold into block/goose
on next read with no manual data edit
- tighten the 7d delta window to (cutoff-3d, cutoff] so a missed cron week
no longer mislabels a 90d-old comparison as Delta7d
- replace the snapshots[:0] aliased filter loop with slices.DeleteFunc
- log malformed JSONL lines to stderr with line numbers instead of
silently skipping them
- write history.jsonl atomically via tmp file + rename so a crash
mid-write can no longer truncate accumulated history
Plus collapse a few redundant fmt.Errorf wraps, drop a named Config type
that was used once, inline the single-call sortByStars helper with a
deterministic tiebreaker on canonical key, and use filepath.Base instead
of hand-rolling a basename.
Includes unit tests covering the 7d window edges, canonical-key
migration, atomic write path, malformed-line tolerance, YAML validation,
and markdown cell escaping.
Go updater that fetches AI agent coding tool repo stats via GitHub GraphQL
(batched, one query), sorts by star count, appends a daily snapshot to
data/history.jsonl, and regenerates README.md from templates/readme.tmpl.
Daily workflow at .github/workflows/update.yml refreshes rankings and
commits changes. Seed list in data/agents.yml covers 19 tracked repos.