diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..8ee9eaf --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,13 @@ +version: 2 +updates: + - package-ecosystem: "gomod" + directory: "/" + schedule: + interval: "weekly" + open-pull-requests-limit: 5 + + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + open-pull-requests-limit: 5 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..7febc51 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,53 @@ +name: CI + +on: + pull_request: + push: + branches: [main] + paths: + - '**.go' + - 'go.mod' + - 'go.sum' + - '.github/workflows/ci.yml' + +permissions: + contents: read + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + + - uses: actions/setup-go@v7 + with: + go-version: 'stable' + cache: true + + - run: go vet ./... + - run: go test ./... + - run: go build ./... + + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + + - uses: actions/setup-go@v7 + with: + go-version: 'stable' + cache: true + + - uses: golangci/golangci-lint-action@v9 + + vulncheck: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + + - uses: actions/setup-go@v7 + with: + go-version: 'stable' + cache: true + + - uses: golang/govulncheck-action@v1 diff --git a/.github/workflows/update.yml b/.github/workflows/update.yml index 04865ce..85b97a6 100644 --- a/.github/workflows/update.yml +++ b/.github/workflows/update.yml @@ -35,9 +35,9 @@ jobs: name: github-pages url: ${{ steps.deploy.outputs.page_url }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v7 - - uses: actions/setup-go@v5 + - uses: actions/setup-go@v7 with: go-version: 'stable' cache: true @@ -88,15 +88,15 @@ jobs: # site/data.json was generated by the updater run above; deploy the # static dashboard (site/) to GitHub Pages every run. - name: Configure Pages - uses: actions/configure-pages@v5 + uses: actions/configure-pages@v6 with: enablement: true - name: Upload Pages artifact - uses: actions/upload-pages-artifact@v3 + uses: actions/upload-pages-artifact@v5 with: path: site - name: Deploy to GitHub Pages id: deploy - uses: actions/deploy-pages@v4 + uses: actions/deploy-pages@v5 diff --git a/README.md b/README.md index 62b6ba2..040e412 100644 --- a/README.md +++ b/README.md @@ -5,34 +5,34 @@ ๐Ÿ“Š **[Interactive dashboard with star-history charts โ†’](https://tiennm99.github.io/awesome-coding-agents/)** -**Last updated:** 2026-08-08 18:17 UTC ยท **Tracked:** 29 repos +**Last updated:** 2026-08-08 19:43 UTC ยท **Tracked:** 29 repos | # | Repo | Stars | ฮ”7d | Language | Last push | Description | |---|------|------:|----:|----------|-----------|-------------| -| 1 | [anomalyco/opencode](https://github.com/anomalyco/opencode) | 195.0k | +3341 | TypeScript | 2026-08-08 | The open source coding agent. | -| 2 | [anthropics/claude-code](https://github.com/anthropics/claude-code) | 140.7k | +873 | Python | 2026-08-08 | Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows - all through natural language commands. | +| 1 | [anomalyco/opencode](https://github.com/anomalyco/opencode) | 195.1k | +3356 | TypeScript | 2026-08-08 | The open source coding agent. | +| 2 | [anthropics/claude-code](https://github.com/anthropics/claude-code) | 140.7k | +882 | Python | 2026-08-08 | Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows - all through natural language commands. | | 3 | [google-gemini/gemini-cli](https://github.com/google-gemini/gemini-cli) | 106.4k | +136 | TypeScript | 2026-08-08 | An open-source AI agent that brings the power of Gemini directly into your terminal. | -| 4 | [openai/codex](https://github.com/openai/codex) | 104.8k | +1836 | Rust | 2026-08-08 | Lightweight coding agent that runs in your terminal | -| 5 | [zed-industries/zed](https://github.com/zed-industries/zed) | 88.3k | +431 | Rust | 2026-08-08 | Code at the speed of thought โ€“ Zed is a high-performance, multiplayer code editor from the creators of Atom and Tree-sitter. | +| 4 | [openai/codex](https://github.com/openai/codex) | 104.8k | +1842 | Rust | 2026-08-08 | Lightweight coding agent that runs in your terminal | +| 5 | [zed-industries/zed](https://github.com/zed-industries/zed) | 88.3k | +433 | Rust | 2026-08-08 | Code at the speed of thought โ€“ Zed is a high-performance, multiplayer code editor from the creators of Atom and Tree-sitter. | | 6 | [earendil-works/pi](https://github.com/earendil-works/pi) | 85.6k | โ€” | TypeScript | 2026-08-08 | AI agent toolkit: unified LLM API, agent loop, TUI, coding agent CLI | | 7 | [OpenHands/OpenHands](https://github.com/OpenHands/OpenHands) | 83.5k | โ€” | TypeScript | 2026-08-08 | ๐Ÿ™Œ OpenHands: AI-Driven Development | -| 8 | [cline/cline](https://github.com/cline/cline) | 65.9k | +540 | TypeScript | 2026-08-08 | Autonomous coding agent as an SDK, IDE extension, or CLI assistant. | +| 8 | [cline/cline](https://github.com/cline/cline) | 65.9k | +543 | TypeScript | 2026-08-08 | Autonomous coding agent as an SDK, IDE extension, or CLI assistant. | | 9 | [warpdotdev/warp](https://github.com/warpdotdev/warp) | 64.1k | โ€” | Rust | 2026-08-08 | Warp is an agentic development environment, born out of the terminal. | | 10 | [AntonOsika/gpt-engineer](https://github.com/AntonOsika/gpt-engineer) | 55.2k | -17 | Python | 2025-05-14 | CLI platform to experiment with codegen. Precursor to: https://lovable.dev | -| 11 | [aaif-goose/goose](https://github.com/aaif-goose/goose) | 52.6k | +519 | Rust | 2026-08-08 | an open source, extensible AI agent that goes beyond code suggestions - install, execute, edit, and test with any LLM | -| 12 | [Aider-AI/aider](https://github.com/Aider-AI/aider) | 48.1k | +205 | Python | 2026-05-22 | aider is AI pair programming in your terminal | -| 13 | [continuedev/continue](https://github.com/continuedev/continue) | 35.4k | +140 | TypeScript | 2026-08-08 | open-source coding agent | +| 11 | [aaif-goose/goose](https://github.com/aaif-goose/goose) | 52.6k | +520 | Rust | 2026-08-08 | an open source, extensible AI agent that goes beyond code suggestions - install, execute, edit, and test with any LLM | +| 12 | [Aider-AI/aider](https://github.com/Aider-AI/aider) | 48.1k | +210 | Python | 2026-05-22 | aider is AI pair programming in your terminal | +| 13 | [continuedev/continue](https://github.com/continuedev/continue) | 35.4k | +143 | TypeScript | 2026-08-08 | open-source coding agent | | 14 | [TabbyML/tabby](https://github.com/TabbyML/tabby) | 33.8k | +18 | Rust | 2026-06-30 | Self-hosted AI coding assistant | | 15 | [Pythagora-io/gpt-pilot](https://github.com/Pythagora-io/gpt-pilot) | 33.7k | โ€” | Python | 2026-06-18 | The first real AI developer | | 16 | [voideditor/void](https://github.com/voideditor/void) | 28.9k | -6 | TypeScript | 2026-06-02 | | -| 17 | [charmbracelet/crush](https://github.com/charmbracelet/crush) | 27.2k | +192 | Go | 2026-08-08 | Glamourous agentic coding for all ๐Ÿ’˜ | +| 17 | [charmbracelet/crush](https://github.com/charmbracelet/crush) | 27.2k | +194 | Go | 2026-08-08 | Glamourous agentic coding for all ๐Ÿ’˜ | | 18 | [QwenLM/qwen-code](https://github.com/QwenLM/qwen-code) | 26.9k | โ€” | TypeScript | 2026-08-08 | An open-source AI coding agent that lives in your terminal. | | 19 | [Kilo-Org/kilocode](https://github.com/Kilo-Org/kilocode) | 26.8k | โ€” | TypeScript | 2026-08-08 | Kilo is the all-in-one agentic engineering platform. Build, ship, and iterate faster with the most popular open source coding agent. | | 20 | [onlook-dev/onlook](https://github.com/onlook-dev/onlook) | 26.4k | โ€” | TypeScript | 2026-07-22 | The Cursor for Designers โ€ข An Open-Source AI-First Design tool โ€ข Visually build, style, and edit your React App with AI | -| 21 | [RooCodeInc/Roo-Code](https://github.com/RooCodeInc/Roo-Code) | 24.4k | -12 | TypeScript | 2026-05-15 | Roo Code gives you a whole dev team of AI agents in your code editor. | +| 21 | [RooCodeInc/Roo-Code](https://github.com/RooCodeInc/Roo-Code) | 24.4k | -11 | TypeScript | 2026-05-15 | Roo Code gives you a whole dev team of AI agents in your code editor. | | 22 | [dyad-sh/dyad](https://github.com/dyad-sh/dyad) | 21.1k | โ€” | TypeScript | 2026-08-07 | Local, open-source AI app builder for power users โœจ v0 / Lovable / Replit / Bolt alternative ๐ŸŒŸ Star if you like it! | | 23 | [kortix-ai/suna](https://github.com/kortix-ai/suna) | 20.1k | +35 | TypeScript | 2026-08-08 | The open-source AI Management System | -| 24 | [SWE-agent/SWE-agent](https://github.com/SWE-agent/SWE-agent) | 20.0k | +53 | Python | 2026-08-03 | SWE-agent takes a GitHub issue and tries to automatically fix it, using your LM of choice. It can also be employed for offensive cybersecurity or competitive coding challenges. [NeurIPS 2024] | +| 24 | [SWE-agent/SWE-agent](https://github.com/SWE-agent/SWE-agent) | 20.0k | +54 | Python | 2026-08-03 | SWE-agent takes a GitHub issue and tries to automatically fix it, using your LM of choice. It can also be employed for offensive cybersecurity or competitive coding challenges. [NeurIPS 2024] | | 25 | [yetone/avante.nvim](https://github.com/yetone/avante.nvim) | 18.1k | +29 | Lua | 2026-07-28 | Use your Neovim like using Cursor AI IDE! | | 26 | [stackblitz/bolt.new](https://github.com/stackblitz/bolt.new) | 16.5k | +19 | TypeScript | 2024-12-17 | Prompt, run, edit, and deploy full-stack web applications. -- bolt.new -- Help Center: https://support.bolt.new/ -- Community Support: https://discord.com/invite/stackblitz | | 27 | [plandex-ai/plandex](https://github.com/plandex-ai/plandex) | 15.6k | +21 | Go | 2025-10-03 | Open source AI coding agent. Designed for large projects and real world tasks. | diff --git a/agents.go b/agents.go index 57e88ba..ee22938 100644 --- a/agents.go +++ b/agents.go @@ -4,7 +4,7 @@ import ( "fmt" "os" - "gopkg.in/yaml.v3" + "github.com/goccy/go-yaml" ) type Agent struct { diff --git a/data/history.jsonl b/data/history.jsonl index d93c0ef..528ad5d 100644 --- a/data/history.jsonl +++ b/data/history.jsonl @@ -82,4 +82,4 @@ {"date":"2026-08-05","stars":{"Aider-AI/aider":47944,"AntonOsika/gpt-engineer":55160,"RooCodeInc/Roo-Code":24359,"SWE-agent/SWE-agent":19995,"TabbyML/tabby":33816,"aaif-goose/goose":52264,"anomalyco/opencode":193387,"anthropics/claude-code":140256,"charmbracelet/crush":27074,"cline/cline":65646,"continuedev/continue":35320,"google-gemini/gemini-cli":106364,"kortix-ai/suna":20067,"openai/codex":103966,"plandex-ai/plandex":15568,"stackblitz/bolt.new":16491,"voideditor/void":28862,"yetone/avante.nvim":18098,"zed-industries/zed":88043}} {"date":"2026-08-06","stars":{"Aider-AI/aider":47974,"AntonOsika/gpt-engineer":55158,"RooCodeInc/Roo-Code":24354,"SWE-agent/SWE-agent":20004,"TabbyML/tabby":33821,"aaif-goose/goose":52423,"anomalyco/opencode":193870,"anthropics/claude-code":140402,"charmbracelet/crush":27105,"cline/cline":65718,"continuedev/continue":35339,"google-gemini/gemini-cli":106382,"kortix-ai/suna":20073,"openai/codex":104209,"plandex-ai/plandex":15571,"stackblitz/bolt.new":16496,"voideditor/void":28862,"yetone/avante.nvim":18102,"zed-industries/zed":88094}} {"date":"2026-08-07","stars":{"Aider-AI/aider":48001,"AntonOsika/gpt-engineer":55157,"RooCodeInc/Roo-Code":24355,"SWE-agent/SWE-agent":20015,"TabbyML/tabby":33821,"aaif-goose/goose":52477,"anomalyco/opencode":194361,"anthropics/claude-code":140514,"charmbracelet/crush":27134,"cline/cline":65789,"continuedev/continue":35363,"google-gemini/gemini-cli":106400,"kortix-ai/suna":20079,"openai/codex":104447,"plandex-ai/plandex":15573,"stackblitz/bolt.new":16500,"voideditor/void":28861,"yetone/avante.nvim":18108,"zed-industries/zed":88160}} -{"date":"2026-08-08","stars":{"Aider-AI/aider":48053,"AntonOsika/gpt-engineer":55156,"Kilo-Org/kilocode":26776,"OpenHands/OpenHands":83477,"Pythagora-io/gpt-pilot":33713,"QwenLM/qwen-code":26853,"RooCodeInc/Roo-Code":24352,"SWE-agent/SWE-agent":20024,"TabbyML/tabby":33822,"aaif-goose/goose":52558,"anomalyco/opencode":195048,"anthropics/claude-code":140707,"bytedance/trae-agent":11993,"charmbracelet/crush":27184,"cline/cline":65881,"continuedev/continue":35387,"dyad-sh/dyad":21139,"earendil-works/pi":85566,"github/copilot-cli":11070,"google-gemini/gemini-cli":106423,"kortix-ai/suna":20087,"onlook-dev/onlook":26439,"openai/codex":104783,"plandex-ai/plandex":15577,"stackblitz/bolt.new":16503,"voideditor/void":28860,"warpdotdev/warp":64070,"yetone/avante.nvim":18110,"zed-industries/zed":88274}} +{"date":"2026-08-08","stars":{"Aider-AI/aider":48058,"AntonOsika/gpt-engineer":55156,"Kilo-Org/kilocode":26777,"OpenHands/OpenHands":83480,"Pythagora-io/gpt-pilot":33713,"QwenLM/qwen-code":26857,"RooCodeInc/Roo-Code":24353,"SWE-agent/SWE-agent":20025,"TabbyML/tabby":33822,"aaif-goose/goose":52559,"anomalyco/opencode":195063,"anthropics/claude-code":140716,"bytedance/trae-agent":11993,"charmbracelet/crush":27186,"cline/cline":65884,"continuedev/continue":35390,"dyad-sh/dyad":21141,"earendil-works/pi":85577,"github/copilot-cli":11070,"google-gemini/gemini-cli":106423,"kortix-ai/suna":20087,"onlook-dev/onlook":26439,"openai/codex":104789,"plandex-ai/plandex":15577,"stackblitz/bolt.new":16503,"voideditor/void":28860,"warpdotdev/warp":64073,"yetone/avante.nvim":18110,"zed-industries/zed":88276}} diff --git a/github.go b/github.go index 70f749e..faf1a81 100644 --- a/github.go +++ b/github.go @@ -194,7 +194,7 @@ func doWithRetry(token string, body []byte) ([]byte, int, error) { } raw, err := io.ReadAll(resp.Body) - resp.Body.Close() + _ = resp.Body.Close() // body fully read (or read failed); close error is not actionable if err != nil { lastErr = fmt.Errorf("read body: %w", err) continue diff --git a/go.mod b/go.mod index 3a69af3..7d02bfe 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,4 @@ module github.com/tiennm99/awesome-coding-agents go 1.23 -require gopkg.in/yaml.v3 v3.0.1 +require github.com/goccy/go-yaml v1.19.2 diff --git a/go.sum b/go.sum index a62c313..bd88ba6 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,2 @@ -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM= +github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= diff --git a/history.go b/history.go index ad9a5fb..a344475 100644 --- a/history.go +++ b/history.go @@ -63,7 +63,7 @@ func readSnapshots(path string) ([]Snapshot, error) { } return nil, err } - defer f.Close() + defer func() { _ = f.Close() }() // read-only; close error is not actionable var out []Snapshot scanner := bufio.NewScanner(f) @@ -125,10 +125,13 @@ func writeSnapshots(path string, snapshots []Snapshot) error { if syncErr := f.Sync(); syncErr != nil && writeErr == nil { writeErr = syncErr } - f.Close() + // A failed close on a write path can hide lost data โ€” surface it. + if closeErr := f.Close(); closeErr != nil && writeErr == nil { + writeErr = closeErr + } if writeErr != nil { - os.Remove(tmp) + _ = os.Remove(tmp) // best-effort cleanup; the write error is what matters return writeErr } diff --git a/readme.go b/readme.go index a09cf1f..81b95ea 100644 --- a/readme.go +++ b/readme.go @@ -75,13 +75,17 @@ func renderReadme(tmplPath, outPath string, stats []Stat, deltas map[string]int) if err != nil { return err } - defer f.Close() - return tmpl.ExecuteTemplate(f, filepath.Base(tmplPath), map[string]any{ + execErr := tmpl.ExecuteTemplate(f, filepath.Base(tmplPath), map[string]any{ "Rows": rows, "UpdatedAt": time.Now().UTC().Format("2006-01-02 15:04 UTC"), "Total": len(rows), }) + // A failed close on a write path can hide lost data โ€” surface it. + if closeErr := f.Close(); closeErr != nil && execErr == nil { + execErr = closeErr + } + return execErr } // sanitizeCell escapes pipe and newline characters so descriptions stay in one table cell.