Caution
NEVER deliver work, submit a feature, or claim a task is completed without explicitly checking and verifying it beforehand!
- Check existing reference implementations first: Before designing UI or features, search for and inspect reference code in existing projects (e.g., Kandown or past clean implementations) to avoid guessing or inventing broken/flawed designs.
- Visual & Browser Verification:
- For web pages: ALWAYS run
pnpm devinsidewebsite/, open the URL in Chrome (open http://localhost:4328), and visually inspect layout, sidebar, navigation, links, and rendered Markdown styling.
- For web pages: ALWAYS run
- Run Unit Tests & Build:
- Always execute
pnpm testandpnpm --prefix website typecheck(orpnpm build) to confirm zero regressions before marking a task complete.
- Always execute
- Zero AI Slop:
- Never generate generic placeholder chips, artificial summary cards, or fake quote boxes when raw Markdown source content is available. Render real source data cleanly and accurately.
Important
Every single new feature, engine enhancement, bug fix, or catalog change MUST function perfectly across all three user-facing surfaces of the application:
- CLI (TUI): Terminal command line mode.
- Web Dashboard / Docker: Daemon-served web interface on
localhost:19280. - Desktop version (Tauri): System tray utility.
If you add or modify logic in the shared core (src/ or sources.js), you must ensure it does not break any surface, and that it is fully utilized by all three versions. Building a feature that only works on one surface while ignoring or breaking the others is strictly prohibited.
Important
Every time work is performed on the marketing site / documentation (website/ directory):
- Launch the dev server (
pnpm devinsidewebsite/) in a dedicated herdr tab labelledvite 4328orwebsite 4328. - Open
http://localhost:4328in Chrome (or viachrome-devtools new_page/open http://localhost:4328) so vava can view and test the website in real time.
After completing any feature or fix, the agent MUST:
- Run
pnpm testto verify all unit tests pass (62 tests across 11 suites) - If any test fails, fix the issue immediately
- Re-run
pnpm testuntil all tests pass - Run
pnpm startto verify there are no runtime errors - If there are errors, fix them immediately
- Re-run
pnpm startuntil all errors are resolved - Only then consider the task complete
This ensures the codebase remains in a working state at all times.
When releasing a new version, follow this exact process:
- Version Check: Check if version already exists with
git log --oneline | grep "^[a-f0-9]\+ [0-9]" - Version Bump: Update version in
package.json(e.g.,0.1.16→0.1.17) - Commit ALL Changed Files:
git add . && git commit -m "0.1.17"- Always commit with just the version number as the message (e.g., "0.1.17")
- Include ALL modified files in the commit (bin/, src/, test/, README.md, changelog/, etc.)
- Push:
git push origin main— GitHub Actions will auto-publish to npm - **Wait for npm Publish":
for i in $(seq 1 30); do sleep 10; v=$(npm view free-coding-models version 2>/dev/null); echo "Attempt $i: npm version = $v"; if [ "$v" = "0.1.17" ]; then echo "✅ published!"; break; fi; done
- Install and Verify:
npm install -g free-coding-models@0.1.17 - Test Binary:
free-coding-models --help(or any other command to verify it works) - Only when the global npm-installed version works → the release is confirmed
Why: A local npm install -g . can mask issues because it symlinks the repo. The real npm package is a tarball built from the files field — only a real npm install will catch missing files.
Never trust local-only testing. pnpm start runs from the repo and won't catch missing files in the published package. Always run the full npm verification:
- Bump version in
package.json(e.g.0.1.14→0.1.15) - Commit and push to
main— GitHub Actions auto-publishes to npm - Wait for the new version to appear on npm:
# Poll until npm has the new version for i in $(seq 1 30); do sleep 10; v=$(npm view free-coding-models version 2>/dev/null); echo "Attempt $i: npm version = $v"; if [ "$v" = "NEW_VERSION" ]; then echo "✅ published!"; break; fi; done
- Install the published version globally:
npm install -g free-coding-models@NEW_VERSION
- Run the global binary and verify it works:
free-coding-models
- Only if the global npm-installed version works → the fix is confirmed
Why: A local npm install -g . can mask issues because it symlinks the repo. The real npm package is a tarball built from the files field — if something is missing there, only a real npm install will catch it.
- Tests live in
test/test.jsusing Node.js built-innode:test+node:assert(zero deps) - Pure logic functions are in
src/utils.js(extracted from the main CLI for testability) - The main CLI (
bin/free-coding-models.js) imports fromsrc/utils.js - If you add new pure logic (calculations, parsing, filtering), add it to
src/utils.jsand write tests - If you modify existing logic in
src/utils.js, update the corresponding tests
- sources.js data integrity — model structure, valid tiers, no duplicates, count consistency
- Core logic — getAvg, getVerdict, getUptime, filterByTier, sortResults, findBestModel
- CLI arg parsing — all flags (--best, --fiable, --opencode, --openclaw, --tier)
- Package sanity — package.json fields, bin entry exists, shebang, ESM imports
When new PRs are merged, add the contributor's GitHub handle to the footer in bin/free-coding-models.js (the Contributors: line near line 775), separated by spaces. Also update this list:
- @whit3rabbit
- @PhucTruong-ctrl
- @stgreenb
- @MoriDanWork
- @Muhammad95959
- @FaintFlower
- @lehneres
- @ia-S-on
- @bangla24bdrang-lab
The project's TUI is built with raw ANSI escape codes + chalk. To visually test TUI behavior, use tmux — pre-installed on macOS and provides native PTY support.
No setup needed — tmux is already installed. Just spawn sessions and send keys.
| Command | What it does |
|---|---|
tmux new-session -d -s <name> "pnpm start" |
Spawn the TUI in a detached session |
tmux send-keys -t <name> "keys" |
Send keypresses to the session |
tmux send-keys -t <name> C-c |
Send Ctrl+C |
tmux send-keys -t <name> Escape |
Send Escape |
tmux send-keys -t <name> Up |
Send ArrowUp |
tmux send-keys -t <name> Down |
Send ArrowDown |
tmux send-keys -t <name> Enter |
Send Enter |
tmux capture-pane -p -t <name> |
Capture current screen as text |
tmux capture-pane -p -t <name> -S -200 |
Capture with scrollback (200 lines) |
tmux kill-session -t <name> |
Kill the session |
tmux attach -t <name> |
Connect to session (watch live) |
tmux attach -t <name> -r |
Connect read-only |
| Key | Action | Use Case |
|---|---|---|
T |
Cycle tier filter | Test filtering (All → S+ → S → A+ → A → A- → B+ → B → C → All) |
P |
Open Settings screen | Test API key config, enable/disable providers |
Z |
Cycle mode | Test mode switching (OpenCode CLI → Desktop → OpenClaw) |
R |
Sort by rank | Verify rank-based sorting |
Y |
Sort by tier | Verify tier-based sorting |
O |
Sort by origin | Verify origin-based sorting |
M |
Sort by model name | Verify model name sorting |
L |
Sort by latest ping | Verify ping sorting |
A |
Sort by avg ping | Verify average ping sorting |
S |
Sort by SWE score | Verify SWE score sorting |
N |
Sort by context window | Verify context window sorting |
H |
Sort by health/condition | Verify health-based sorting |
V |
Sort by verdict | Verify verdict sorting |
U |
Sort by uptime | Verify uptime sorting |
↑/↓ |
Navigate rows | Move cursor up/down |
Enter |
Select model | Choose model |
Ctrl+C |
Exit | Quit the TUI |
Ctrl+P |
Command Palette | Open cmd palette |
Shift+P |
Probe failed rows only | Re-probe rows showing auth fail / 429 / 404 / timeout (issue #168) |
Ctrl+Shift+P |
Probe all models | 404/410 probe on every configured model (terminals that support the combo) |
Space |
Expand selected row | Toggle a 2-line provider/model detail card under the cursor row; Space again or cursor move collapses |
Esc |
Close modal/dialog | Close palette, settings, help |
# 1. Spawn the TUI in a detached session
tmux new-session -d -s fcm-test "cd /Users/vava/Documents/GitHub/free-coding-models && pnpm start"
# 2. Wait for it to render, then capture
sleep 2
tmux capture-pane -p -t fcm-test
# 3. Test tier filter — press T, wait, verify
tmux send-keys -t fcm-test "T"
sleep 1
tmux capture-pane -p -t fcm-test | tail -20
# 4. Test cmd palette — Ctrl+P
tmux send-keys -t fcm-test C-p
sleep 1
tmux capture-pane -p -t fcm-test | tail -25
# 5. Close with Escape
tmux send-keys -t fcm-test Escape
sleep 1
# 6. Test navigation — scroll down
for i in {1..5}; do
tmux send-keys -t fcm-test Down
sleep 1
tmux capture-pane -p -t fcm-test | tail -15
done
# 7. Connect to watch live
tmux attach -t fcm-test
# 8. Clean up
tmux kill-session -t fcm-test# Terminal 1: spawn and let it run
tmux new-session -d -s fcm-live "cd /path/to/project && pnpm start"
# Terminal 2: watch the live session
tmux attach -t fcm-live
# From anywhere, send keys to test while watching in Terminal 2
tmux send-keys -t fcm-live "T" # cycle tier
tmux send-keys -t fcm-live C-p # open palette- Use
sleep 1aftersend-keysto let the TUI re-render before capturing tmux capture-pane -poutputs ANSI codes — pipe throughcat -vor strip with a tool if you need clean text- Sessions persist — you can detach (
Ctrl+b d) and re-attach later - Use
tmux list-sessionsto see all active sessions - For read-only watching (no accidental input):
tmux attach -t <name> -r
Use tmux when:
- Visual Testing Needed — Changes affect TUI rendering, layout, colors, or formatting
- Interaction Testing — New keypress handlers, filters, or navigation logic
- Regression Detection — Verify existing flows still work after code changes
- User-Facing Features — Settings screen, mode switching, tier filtering
- Live Demo — Let the user watch the TUI run in real-time
Do NOT use tmux testing for:
- Unit test verification (use
pnpm testinstead) - Code-only logic changes (use tests for pure functions)
- Build errors (use
pnpm build:weborpnpm start)
| tmux | agent-tui |
|---|---|
| Pre-installed on macOS | Extra npm dependency |
| Zero config | Needs daemon setup |
tmux send-keys is simple |
Custom CLI wrapper |
tmux capture-pane is direct |
Screenshot API |
| Native PTY, no latency | Additional abstraction layer |
| Sessions persist, can re-attach | Ephemeral sessions |
| Can watch live in another terminal | Must use screenshots |
Per-version changelog files. Every version has its own changelog file in the changelog/ directory, named changelog/vX.Y.Z.md where X.Y.Z is the version number.
- Format: Each file must start with
# Changelog vX.Y.Z - YYYY-MM-DDfollowed by the release notes. - Location: All changelog files live in
changelog/— there is no root-levelCHANGELOG.md. - Structure: List changes under
### Added,### Fixed, or### Changedas appropriate. - Content: Check all commits, code changes, and work done since the last version to ensure the changelog is complete. Add clear, user-facing explanations of why changes were made and how they work.
- Order: Keep the structure clean so it can be reused directly in the GitHub Release notes screen.
- Timing: Create/update the changelog file BEFORE committing and pushing.
# For version 0.3.68 released on 2026-05-20
cat > changelog/v0.3.68.md << 'EOF'
# Changelog v0.3.68 - 2026-05-20
### Added
- ...
### Changed
- ...
### Fixed
- ...
EOFAll past versions (v0.1.1 through the latest) already have their changelog files in changelog/. They were extracted from GitHub Release notes and git commit messages. If a version's notes are missing or sparse, it means no detailed release notes were published for that version.
When user requests /bump, "push commit", or "bump a new version now", execute this comprehensive workflow:
- Check current version in
package.json - Check last published version:
git log --oneline | grep "^[a-f0-9]\+ [0-9]" - If multiple uncommitted version bumps exist, consolidate them into the next sequential version
- Review all work done since the last published version
- Create a new file
changelog/vX.Y.Z.mdwith the release notes for the new version - Include comprehensive details, intentions, and explanations for all changes
- Ensure changelog is user-facing with clear bullet points
- Use the format:
# Changelog vX.Y.Z - YYYY-MM-DDfollowed by### Added,### Changed,### Fixedsections
changelog/vX.Y.Z.md (minus the # Changelog vX.Y.Z - YYYY-MM-DD header line) MUST be used as the GitHub Release body when the release is created. This is the single source of truth — the changelog file IS the release notes. Never publish a GitHub Release with empty or auto-generated notes when a changelog file exists. The CI workflow automates this (it reads changelog/vX.Y.Z.md and uses it as --notes-file), but if you create a release manually, you must copy the changelog content into the release body verbatim.
- Review and update
README.mdif needed for new features/changes - Ensure documentation reflects current functionality
- Run
pnpm test— fix any failures immediately - Run
pnpm start— verify no runtime errors - Only proceed when all tests pass
- Update version in
package.jsonto next sequential version - Identify the most significant change for this release
git add . && git commit -m "VERSION_NUMBER - EMOJI SHORT_TITLE"(version + emoji + main feature)git push origin main— triggers GitHub Actions auto-publish
- Poll npm registry for 5 minutes:
for i in $(seq 1 30); do sleep 10; v=$(npm view free-coding-models version 2>/dev/null); echo "Attempt $i: npm version = $v"; if [ "$v" = "NEW_VERSION" ]; then echo "✅ published!"; break; fi; done
npm install -g free-coding-models@NEW_VERSIONfree-coding-models --help— verify binary works globally- Only confirm release when global npm-installed version functions correctly
Critical: Never skip versions — consolidate all changes into the next sequential version number.
After every successful bump (npm publish verified + free-coding-models --help works), the agent MUST propose a ready-to-post tweet for vava.
Goal: content first, zero fluff. The news starts at line 1. No funny hook, no star count, links at the very bottom.
Structure to propose (copy-paste ready):
free-coding-models vX.Y.Z is live!
what's new ?
- 🛠️ emoji short feature (1 line)
- ⚡ emoji short feature
- 🐛 emoji short fix
- 📦 emoji deps/docs
📦 github: https://github.com/vava-nessa/free-coding-models
📦 npm: https://www.npmjs.com/package/free-coding-models
#AI #Coding #OpenSource #VibeCoding #FreeLLM #freeai #codingmodels #freecodingmodels #pi #codex #claudecode
Rules:
- First line is exactly
free-coding-models vX.Y.Z is live!: no joke, no hook phrase, no star count. - Then
what's new ?followed by 3 to 6 items max, each 1 line, each starts with a distinct emoji, plain language, no jargon. - Links go at the bottom, after the list: repo link then npm link, each prefixed with 📦.
- Hashtag block is fixed:
#AI #Coding #OpenSource #VibeCoding #FreeLLM #freeai #codingmodels #freecodingmodels #pi #codex #claudecode. - Keep total tweet under ~600 chars so it fits in one X post with line breaks. No em dash "—" ever.
- Propose it automatically, don't wait for vava to ask. Show it in a code block ready to copy.
Example for v0.5.84:
free-coding-models v0.5.84 is live!
what's new ?
- 🔍 full audit: 28 dead models removed, 42 fresh ones added (225 total)
- 🚀 Kilo gateway: 2 to 19 free coding models
- 🧠 new Qwen3.8 family + GLM-5.3, all 1M ctx
- 🪦 37 context windows fixed against live APIs
- 🐛 router tests updated after NVIDIA killed gpt-oss-120b
📦 github: https://github.com/vava-nessa/free-coding-models
📦 npm: https://www.npmjs.com/package/free-coding-models
#AI #Coding #OpenSource #VibeCoding #FreeLLM #freeai #codingmodels #freecodingmodels #pi #codex #claudecode
This project uses Kandown. Before task work, run kandown work and follow its output.
This project uses kandown for task management. Always run kandown work when starting a new task — it prints the current rules and board state, kept in sync with the installed CLI version. (Tasks live in ./tasks/*.md.)