

Also from Kynth Studios


Also from Kynth Studios


Also from Kynth Studios
1# gstack development23## Commands45```bash6bun install # install dependencies7bun test # run free tests (browse + snapshot + skill validation)8bun run test:evals # run paid evals: LLM judge + E2E (diff-based, ~$4/run max)9bun run test:evals:all # run ALL paid evals regardless of diff10bun run test:gate # run gate-tier tests only (CI default, blocks merge)11bun run test:periodic # run periodic-tier tests only (weekly cron / manual)12bun run test:e2e # run E2E tests only (diff-based, ~$3.85/run max)13bun run test:e2e:all # run ALL E2E tests regardless of diff14bun run eval:select # show which tests would run based on current diff15bun run dev <cmd> # run CLI in dev mode, e.g. bun run dev goto https://example.com16bun run build # gen docs + compile binaries17bun run gen:skill-docs # regenerate SKILL.md files from templates18bun run skill:check # health dashboard for all skills19bun run dev:skill # watch mode: auto-regen + validate on change20bun run eval:list # list all eval runs from ~/.gstack-dev/evals/21bun run eval:compare # compare two eval runs (auto-picks most recent)22bun run eval:summary # aggregate stats across all eval runs23bun run slop # full slop-scan report (all files)24bun run slop:diff # slop findings in files changed on this branch only25```2627`test:evals` requires `ANTHROPIC_API_KEY`. Codex E2E tests (`test/codex-e2e.test.ts`)28use Codex's own auth from `~/.codex/` config — no `OPENAI_API_KEY` env var needed.2930**Env keys in Conductor workspaces.** The `GSTACK_*` env-shim (v1.39.2.0+,31`lib/conductor-env-shim.ts`) promotes `GSTACK_ANTHROPIC_API_KEY` /32`GSTACK_OPENAI_API_KEY` to their canonical names inside gstack's TS binaries.33Tests run through gstack entrypoints inherit this promotion automatically.34Don't echo the key value to stdout, logs, or shell history. When passing to a35test's Agent SDK, do NOT pass `env: {...}` to `runAgentSdkTest` — the SDK's36auth pipeline doesn't pick up the key the same way when env is supplied as an37object (confirmed failure mode). Mutate `process.env.ANTHROPIC_API_KEY`38ambiently before the call and restore in `finally`.3940E2E tests stream progress in real-time (tool-by-tool via `--output-format stream-json41--verbose`). Results are persisted to `~/.gstack-dev/evals/` with auto-comparison42against the previous run.4344**Diff-based test selection:** `test:evals` and `test:e2e` auto-select tests based45on `git diff` against the base branch. Each test declares its file dependencies in46`test/helpers/touchfiles.ts`. Changes to global touchfiles (session-runner, eval-store,47touchfiles.ts itself) trigger all tests. Use `EVALS_ALL=1` or the `:all` script48variants to force all tests. Run `eval:select` to preview which tests would run.4950**Two-tier system:** Tests are classified as `gate` or `periodic` in `E2E_TIERS`51(in `test/helpers/touchfiles.ts`). CI runs only gate tests (`EVALS_TIER=gate`);52periodic tests run weekly via cron or manually. Use `EVALS_TIER=gate` or53`EVALS_TIER=periodic` to filter. When adding new E2E tests, classify them:541. Safety guardrail or deterministic functional test? -> `gate`552. Quality benchmark, Opus model test, or non-deterministic? -> `periodic`563. Requires external service (Codex, Gemini)? -> `periodic`5758## Testing5960```bash61bun test # run before every commit — free, <2s62bun run test:evals # run before shipping — paid, diff-based (~$4/run max)63```6465`bun test` runs skill validation, gen-skill-docs quality checks, and browse66integration tests. `bun run test:evals` runs LLM-judge quality evals and E2E67tests via `claude -p`. Both must pass before creating a PR.6869## Project structure7071```72gstack/73├── browse/ # Headless browser CLI (Playwright)74│ ├── src/ # CLI + server + commands75│ │ ├── commands.ts # Command registry (single source of truth)76│ │ └── snapshot.ts # SNAPSHOT_FLAGS metadata array77│ ├── test/ # Integration tests + fixtures78│ └── dist/ # Compiled binary79├── hosts/ # Typed host configs (one per AI agent)80│ ├── claude.ts # Primary host config81│ ├── codex.ts, factory.ts, kiro.ts # Existing hosts82│ ├── opencode.ts, slate.ts, cursor.ts, openclaw.ts # IDE hosts83│ ├── hermes.ts, gbrain.ts # Agent runtime hosts84│ └── index.ts # Registry: exports all, derives Host type85├── scripts/ # Build + DX tooling86│ ├── gen-skill-docs.ts # Template → SKILL.md generator (config-driven)87│ ├── host-config.ts # HostConfig interface + validator88│ ├── host-config-export.ts # Shell bridge for setup script89│ ├── host-adapters/ # Host-specific adapters (OpenClaw tool mapping)90│ ├── resolvers/ # Template resolver modules (preamble, design, review, gbrain, etc.)91│ ├── skill-check.ts # Health dashboard92│ └── dev-skill.ts # Watch mode93├── test/ # Skill validation + eval tests94│ ├── helpers/ # skill-parser.ts, session-runner.ts, llm-judge.ts, eval-store.ts95│ ├── fixtures/ # Ground truth JSON, planted-bug fixtures, eval baselines96│ ├── skill-validation.test.ts # Tier 1: static validation (free, <1s)97│ ├── gen-skill-docs.test.ts # Tier 1: generator quality (free, <1s)98│ ├── skill-llm-eval.test.ts # Tier 3: LLM-as-judge (~$0.15/run)99│ └── skill-e2e-*.test.ts # Tier 2: E2E via claude -p (~$3.85/run, split by category)100├── qa-only/ # /qa-only skill (report-only QA, no fixes)101├── plan-design-review/ # /plan-design-review skill (report-only design audit)102├── design-review/ # /design-review skill (design audit + fix loop)103├── ship/ # Ship workflow skill104├── review/ # PR review skill105├── plan-ceo-review/ # /plan-ceo-review skill106├── plan-eng-review/ # /plan-eng-review skill107├── autoplan/ # /autoplan skill (auto-review pipeline: CEO → design → eng)108├── benchmark/ # /benchmark skill (performance regression detection)109├── canary/ # /canary skill (post-deploy monitoring loop)110├── codex/ # /codex skill (multi-AI second opinion via OpenAI Codex CLI)111├── land-and-deploy/ # /land-and-deploy skill (merge → deploy → canary verify)112├── office-hours/ # /office-hours skill (YC Office Hours — startup diagnostic + builder brainstorm)113├── investigate/ # /investigate skill (systematic root-cause debugging)114├── retro/ # Retrospective skill (includes /retro global cross-project mode)115├── bin/ # CLI utilities (gstack-repo-mode, gstack-slug, gstack-config, etc.)116├── document-release/ # /document-release skill (post-ship doc updates + Diataxis coverage map)117├── document-generate/ # /document-generate skill (Diataxis doc generator: tutorial/how-to/reference/explanation)118├── cso/ # /cso skill (OWASP Top 10 + STRIDE security audit)119├── design-consultation/ # /design-consultation skill (design system from scratch)120├── design-shotgun/ # /design-shotgun skill (visual design exploration)121├── open-gstack-browser/ # /open-gstack-browser skill (launch GStack Browser)122├── connect-chrome/ # symlink → open-gstack-browser (backwards compat)123├── design/ # Design binary CLI (GPT Image API)124│ ├── src/ # CLI + commands (generate, variants, compare, serve, etc.)125│ ├── test/ # Integration tests126│ └── dist/ # Compiled binary127├── extension/ # Chrome extension (side panel + activity feed + CSS inspector)128├── lib/ # Shared libraries (worktree.ts)129├── docs/designs/ # Design documents130├── setup-deploy/ # /setup-deploy skill (one-time deploy config)131├── .github/ # CI workflows + Docker image132│ ├── workflows/ # evals.yml (E2E on Ubicloud), skill-docs.yml, actionlint.yml133│ └── docker/ # Dockerfile.ci (pre-baked toolchain + Playwright/Chromium)134├── contrib/ # Contributor-only tools (never installed for users)135│ └── add-host/ # /gstack-contrib-add-host skill136├── setup # One-time setup: build binary + symlink skills137├── SKILL.md # Generated from SKILL.md.tmpl (don't edit directly)138├── SKILL.md.tmpl # Template: edit this, run gen:skill-docs139├── ETHOS.md # Builder philosophy (Boil the Lake, Search Before Building)140└── package.json # Build scripts for browse141```142143## SKILL.md workflow144145SKILL.md files are **generated** from `.tmpl` templates. To update docs:1461471. Edit the `.tmpl` file (e.g. `SKILL.md.tmpl` or `browse/SKILL.md.tmpl`)1482. Run `bun run gen:skill-docs` (or `bun run build` which does it automatically)1493. Commit both the `.tmpl` and generated `.md` files150151To add a new browse command: add it to `browse/src/commands.ts` and rebuild.152To add a snapshot flag: add it to `SNAPSHOT_FLAGS` in `browse/src/snapshot.ts` and rebuild.153154**Token ceiling:** Generated SKILL.md files trip a warning above 160KB (~40K tokens).155This is a "watch for feature bloat" guardrail, not a hard gate. Modern flagship156models have 200K-1M context windows, so 40K is 4-20% of window, and prompt caching157makes the marginal cost of larger skills small. The ceiling exists to catch runaway158preamble/resolver growth, not to force compression on carefully-tuned big skills159(`ship`, `plan-ceo-review`, `office-hours` legitimately pack 25-35K tokens of160behavior). If you blow past 40K, the right fix is usually: (1) look at WHAT grew,161(2) if one resolver added 10K+ in a single PR, question whether it belongs inline162or as a reference doc, (3) only compress carefully-tuned prose as a last resort —163cuts to the coverage audit, review army, or voice directive have real quality cost.164165**Merge conflicts on SKILL.md files:** NEVER resolve conflicts on generated SKILL.md166files by accepting either side. Instead: (1) resolve conflicts on the `.tmpl` templates167and `scripts/gen-skill-docs.ts` (the sources of truth), (2) run `bun run gen:skill-docs`168to regenerate all SKILL.md files, (3) stage the regenerated files. Accepting one side's169generated output silently drops the other side's template changes.170171## Platform-agnostic design172173Skills must NEVER hardcode framework-specific commands, file patterns, or directory174structures. Instead:1751761. **Read CLAUDE.md** for project-specific config (test commands, eval commands, etc.)1772. **If missing, AskUserQuestion** — let the user tell you or let gstack search the repo1783. **Persist the answer to CLAUDE.md** so we never have to ask again179180This applies to test commands, eval commands, deploy commands, and any other181project-specific behavior. The project owns its config; gstack reads it.182183## Writing SKILL templates184185SKILL.md.tmpl files are **prompt templates read by Claude**, not bash scripts.186Each bash code block runs in a separate shell — variables do not persist between blocks.187188Rules:189- **Use natural language for logic and state.** Don't use shell variables to pass190 state between code blocks. Instead, tell Claude what to remember and reference191 it in prose (e.g., "the base branch detected in Step 0").192- **Don't hardcode branch names.** Detect `main`/`master`/etc dynamically via193 `gh pr view` or `gh repo view`. Use `{{BASE_BRANCH_DETECT}}` for PR-targeting194 skills. Use "the base branch" in prose, `<base>` in code block placeholders.195- **Keep bash blocks self-contained.** Each code block should work independently.196 If a block needs context from a previous step, restate it in the prose above.197- **Express conditionals as English.** Instead of nested `if/elif/else` in bash,198 write numbered decision steps: "1. If X, do Y. 2. Otherwise, do Z."199200## Writing style (V1)201202Default output from every tier-≥2 skill follows the Writing Style section in203`scripts/resolvers/preamble.ts`: jargon glossed on first use (curated list in204`scripts/jargon-list.json`, baked at gen-skill-docs time), questions framed in205outcome terms ("what breaks for your users if...") not implementation terms,206short sentences, decisions close with user impact. Power users who want the207tighter V0 prose set `gstack-config set explain_level terse` (binary switch,208no middle mode). See `$GSTACK_ROOT/docs/designs/PLAN_TUNING_V1.md` for the full design209rationale. The review pacing overhaul that originally tried to ride alongside210writing-style was extracted to V1.1 — see `docs/designs/PACING_UPDATES_V0.md`.211212## Browser interaction213214When you need to interact with a browser (QA, dogfooding, cookie setup), use the215`/browse` skill or run the browse binary directly via `$B <command>`. NEVER use216`mcp__claude-in-chrome__*` tools — they are slow, unreliable, and not what this217project uses.218219**Sidebar architecture:** Before modifying `sidepanel.js`, `background.js`,220`content.js`, `terminal-agent.ts`, or sidebar-related server endpoints,221read `$GSTACK_ROOT/docs/designs/SIDEBAR_MESSAGE_FLOW.md`. The sidebar has one primary222surface — the **Terminal** pane (interactive `claude` PTY) — with223Activity / Refs / Inspector as debug overlays behind the footer's224`debug` toggle. The chat queue path was ripped once the PTY proved out;225`sidebar-agent.ts` and the `/sidebar-command` / `/sidebar-chat` /226`/sidebar-agent/event` endpoints are gone. The doc covers the WS auth227flow, dual-token model, and threat-model boundary — silent failures228here usually trace to not understanding the cross-component flow.229230**Embedder terminal-agent ownership** (v1.42.1.0+, identity-based kill v1.44.0.0+).231`buildFetchHandler` in `browse/src/server.ts` accepts `ServerConfig.ownsTerminalAgent?:232boolean` (default `true`). When `true`, factory shutdown runs the full teardown:233identity-based kill via `killAgentByRecord(readAgentRecord(stateDir))` from234`browse/src/terminal-agent-control.ts` plus `safeUnlinkQuiet` on235`<stateDir>/terminal-port`, `<stateDir>/terminal-internal-token`, and236`<stateDir>/terminal-agent-pid` (the per-boot agent record introduced in v1.44).237Embedders (e.g. the gbrowser phoenix overlay) that pre-launch their own PTY238server must pass `false` so their discovery files survive gstack teardown cycles.239The flag is the third caller-owned teardown gate in `ServerConfig` (alongside240`xvfb?` and `proxyBridge?`); polarity is inverted (explicit bool vs presence) and241documented in the field's JSDoc. CLI `start()` always passes `true` explicitly —242the static-grep test in `browse/test/server-embedder-terminal-port.test.ts` fails243CI if a refactor drops it. Pre-v1.44 used `pkill -f terminal-agent\.ts` (regex244match) which would kill sibling gstack sessions on the same host; the new245`browse/test/terminal-agent-pid-identity.test.ts` static-grep tripwire fails CI246if any source file re-introduces `pkill ... terminal-agent` or `spawnSync('pkill', ...)`.247248**WebSocket auth uses Sec-WebSocket-Protocol, not cookies.** Browsers249can't set `Authorization` on a WebSocket upgrade, but they CAN set250`Sec-WebSocket-Protocol` via `new WebSocket(url, [token])`. The agent251reads it, validates against `validTokens`, and MUST echo the protocol252back in the upgrade response — without the echo, Chromium closes the253connection immediately. `Set-Cookie: gstack_pty=...` is kept as a254fallback for non-browser callers (the cross-port `SameSite=Strict`255cookie path doesn't survive from a chrome-extension origin).256257**Cross-pane PTY injection.** The toolbar's Cleanup button and the258Inspector's "Send to Code" action both pipe text into the live claude259PTY via `window.gstackInjectToTerminal(text)`, exposed by260`sidepanel-terminal.js`. No `/sidebar-command` POST — the live REPL is261the only execution surface in the sidebar now.262263**`/health` MUST NOT surface any shell-grant token.** It already leaks264`AUTH_TOKEN` to localhost callers in headed mode (a v1.1+ TODO). Don't265make that worse by adding the PTY session token there. PTY auth flows266through `POST /pty-session` only.267268**Transport-layer security** (v1.6.0.0+). When `pair-agent` starts an ngrok tunnel,269the daemon binds two HTTP listeners: a local listener (127.0.0.1, full command270surface, never forwarded) and a tunnel listener (locked allowlist: `/connect`,271`/command` with a scoped token + 26-command browser-driving allowlist,272`/sidebar-chat`). ngrok forwards only the tunnel port. Root tokens over the tunnel273return 403. SSE endpoints use a 30-minute HttpOnly `gstack_sse` cookie minted via274`POST /sse-session` (never valid against `/command`). Tunnel-surface rejections go275to `~/.gstack/security/attempts.jsonl` via `tunnel-denial-log.ts`. Before editing276`server.ts`, `sse-session-cookie.ts`, or `tunnel-denial-log.ts`, read277[ARCHITECTURE.md](ARCHITECTURE.md#dual-listener-tunnel-architecture-v1600) —278the module boundary (no imports from `token-registry.ts` into `sse-session-cookie.ts`)279is load-bearing for scope isolation.280281**Unicode sanitization at server egress** (v1.38.0.0+). Every server egress that282ships page-content-derived strings MUST go through `JSON.stringify(payload,283sanitizeReplacer)` for object payloads or `sanitizeLoneSurrogates(body)` for text284bodies. Lone UTF-16 surrogate halves from CDP page content otherwise reach the285Anthropic API as `\uD800`-style escapes and trigger a 400. Wired at four egress286points today: `handleCommandInternal` (HTTP + batch via a sanitizing wrapper around287`handleCommandInternalImpl`) and both SSE producers (`/activity/stream`,288`/inspector/events`). Post-stringify regex is a no-op — `JSON.stringify` has289already escaped the surrogate before regex could match, so the replacer must run290inside the encoding pipeline. Before adding a new SSE/WebSocket writer or HTTP291response in `server.ts`, read292[ARCHITECTURE.md](ARCHITECTURE.md#unicode-sanitization-at-server-egress-v13800).293`browse/test/server-sanitize-surrogates.test.ts` pins the wiring with invariant294tests, so bypasses fail CI.295296**Setup symlink hardening** (v1.38.0.0+). Every link site in `setup` MUST route297through the `_link_or_copy SRC DST` helper near the `IS_WINDOWS` detection. On298Windows without Developer Mode, plain `ln -snf` produces frozen file copies that299don't refresh on `git pull` — silent staleness across every host adapter. The300helper preserves `ln -snf` on Unix and switches to `cp -R` / `cp -f` on Windows.301`test/setup-windows-fallback.test.ts` enforces a static invariant: a single raw302`ln` call outside the helper body fails CI. Windows users get a one-line note303from `_print_windows_copy_note_once` reminding them to re-run `./setup` after304every `git pull`.305306**Sidebar security stack** (layered defense against prompt injection):307308| Layer | Module | Lives in |309|-------|--------|----------|310| L1-L3 | `content-security.ts` | both server and agent — datamarking, hidden element strip, ARIA regex, URL blocklist, envelope wrapping |311| L4 | `security-classifier.ts` (TestSavantAI ONNX) | **sidebar-agent only** |312| L4b | `security-classifier.ts` (Claude Haiku transcript) | **sidebar-agent only** |313| L5 | `security.ts` (canary) | both — inject in compiled, check in agent |314| L6 | `security.ts` (combineVerdict ensemble) | both |315316**Critical constraint:** `security-classifier.ts` CANNOT be imported from the317compiled browse binary. `@huggingface/transformers` v4 requires `onnxruntime-node`318which fails to `dlopen` from Bun compile's temp extract dir. Only `security.ts`319(pure-string operations — canary, verdict combiner, attack log, status) is safe320for `server.ts`. See `~/.gstack/projects/garrytan-gstack/ceo-plans/2026-04-19-prompt-injection-guard.md`321§"Pre-Impl Gate 1 Outcome" for full architectural decision.322323**Thresholds** (in `security.ts`):324- `BLOCK: 0.85` — single-layer score that would cause BLOCK if cross-confirmed325- `WARN: 0.75` — cross-confirm threshold. When L4 AND L4b both >= 0.75 → BLOCK326- `LOG_ONLY: 0.40` — gates transcript classifier (skip Haiku when all layers < 0.40)327- `SOLO_CONTENT_BLOCK: 0.92` — single-layer threshold for label-less content classifiers328 (testsavant, deberta). Intentionally higher than `BLOCK` because these layers can't329 distinguish "this is an injection" from "this looks like phishing aimed at the user."330 The transcript classifier keeps a separate, label-gated solo path at `BLOCK` (0.85).331332**Ensemble rule:** BLOCK only when the ML content classifier AND the transcript333classifier both report >= WARN. Single-layer high confidence degrades to WARN —334this is the Stack Overflow instruction-writing FP mitigation. Canary leak335always BLOCKs (deterministic).336337**Env knobs:**338- `GSTACK_SECURITY_OFF=1` — emergency kill switch. Classifier stays off even if339 warmed. Canary is still injected; just the ML scan is skipped.340- `GSTACK_SECURITY_ENSEMBLE=deberta` — opt-in DeBERTa-v3 ensemble. Adds341 ProtectAI DeBERTa-v3-base-injection-onnx as L4c classifier for cross-model342 agreement. 721MB first-run download. With ensemble enabled, BLOCK requires343 2-of-3 ML classifiers agreeing at >= WARN (testsavant, deberta, transcript).344 Without ensemble (default), BLOCK requires testsavant + transcript at >= WARN.345- Classifier model cache: `~/.gstack/models/testsavant-small/` (112MB, first run only)346 plus `~/.gstack/models/deberta-v3-injection/` (721MB, only when ensemble enabled)347- Attack log: `~/.gstack/security/attempts.jsonl` (salted sha256 + domain only,348 rotates at 10MB, 5 generations)349- Per-device salt: `~/.gstack/security/device-salt` (0600)350- Session state: `~/.gstack/security/session-state.json` (cross-process, atomic)351352## Dev symlink awareness353354When developing gstack, `$GSTACK_ROOT` may be a symlink back to this355working directory (gitignored). This means skill changes are **live immediately**,356great for rapid iteration, risky during big refactors where half-written skills357could break other Claude Code sessions using gstack concurrently.358359**Check once per session:** Run `ls -la $GSTACK_ROOT` to see if it's a360symlink or a real copy. If it's a symlink to your working directory, be aware that:361- Template changes + `bun run gen:skill-docs` immediately affect all gstack invocations362- Breaking changes to SKILL.md.tmpl files can break concurrent gstack sessions363- During large refactors, remove the symlink (`rm $GSTACK_ROOT`) so the364 global install at `$GSTACK_ROOT/` is used instead365366**Prefix setting:** Setup creates real directories (not symlinks) at the top level367with a SKILL.md symlink inside (e.g., `qa/SKILL.md -> gstack/qa/SKILL.md`). This368ensures Claude discovers them as top-level skills, not nested under `gstack/`.369Names are either short (`qa`) or namespaced (`gstack-qa`), controlled by370`skill_prefix` in `~/.gstack/config.yaml`. Pass `--no-prefix` or `--prefix` to371skip the interactive prompt.372373**Note:** Vendoring gstack into a project's repo is deprecated. Use global install374+ `./setup --team` instead. See README.md for team mode instructions.375376**For plan reviews:** When reviewing plans that modify skill templates or the377gen-skill-docs pipeline, consider whether the changes should be tested in isolation378before going live (especially if the user is actively using gstack in other windows).379380**Upgrade migrations:** When a change modifies on-disk state (directory structure,381config format, stale files) in ways that could break existing user installs, add a382migration script to `gstack-upgrade/migrations/`. Read CONTRIBUTING.md's "Upgrade383migrations" section for the format and testing requirements. The upgrade skill runs384these automatically after `./setup` during `/gstack-upgrade`.385386## Compiled binaries — NEVER commit browse/dist/ or design/dist/387388The `browse/dist/` and `design/dist/` directories contain compiled Bun binaries389(`browse`, `find-browse`, `design`, ~58MB each). These are Mach-O arm64 only — they390do NOT work on Linux, Windows, or Intel Macs. The `./setup` script already builds391from source for every platform, so the checked-in binaries are redundant. They are392tracked by git due to a historical mistake and should eventually be removed with393`git rm --cached`.394395**NEVER stage or commit these files.** They show up as modified in `git status`396because they're tracked despite `.gitignore` — ignore them. When staging files,397always use specific filenames (`git add file1 file2`) — never `git add .` or398`git add -A`, which will accidentally include the binaries.399400## Commit style401402**Always bisect commits.** Every commit should be a single logical change. When403you've made multiple changes (e.g., a rename + a rewrite + new tests), split them404into separate commits before pushing. Each commit should be independently405understandable and revertable.406407Examples of good bisection:408- Rename/move separate from behavior changes409- Test infrastructure (touchfiles, helpers) separate from test implementations410- Template changes separate from generated file regeneration411- Mechanical refactors separate from new features412413When the user says "bisect commit" or "bisect and push," split staged/unstaged414changes into logical commits and push.415416## Slop-scan: AI code quality, not AI code hiding417418We use [slop-scan](https://github.com/benvinegar/slop-scan) to catch patterns where419AI-generated code is genuinely worse than what a human would write. We are NOT trying420to pass as human code. We are AI-coded and proud of it. The goal is code quality.421422```bash423npx slop-scan scan . # human-readable report424npx slop-scan scan . --json # machine-readable for diffing425```426427Config: `slop-scan.config.json` at repo root (currently excludes `**/vendor/**`).428429### What to fix (genuine quality improvements)430431- **Empty catches around file ops** — use `safeUnlink()` (ignores ENOENT, rethrows432 EPERM/EIO). A swallowed EPERM in cleanup means silent data loss.433- **Empty catches around process kills** — use `safeKill()` (ignores ESRCH, rethrows434 EPERM). A swallowed EPERM means you think you killed something you didn't.435- **Redundant `return await`** — remove when there's no enclosing try block. Saves a436 microtask, signals intent.437- **Typed exception catches** — `catch (err) { if (!(err instanceof TypeError)) throw err }`438 is genuinely better than `catch {}` when the try block does URL parsing or DOM work.439 You know what error you expect, so say so.440441### What NOT to fix (linter gaming, not quality)442443- **String-matching on error messages** — `err.message.includes('closed')` is brittle.444 Playwright/Chrome can change wording anytime. If a fire-and-forget operation can fail445 for ANY reason and you don't care, `catch {}` is the correct pattern.446- **Adding comments to exempt pass-through wrappers** — "alias for active session" above447 a method just to trip slop-scan's exemption rule is noise, not documentation.448- **Converting extension catch-and-log to selective rethrow** — Chrome extensions crash449 entirely on uncaught errors. If the catch logs and continues, that IS the right pattern450 for extension code. Don't make it throw.451- **Tightening best-effort cleanup paths** — shutdown, emergency cleanup, and disconnect452 code should use `safeUnlinkQuiet()` (swallows ALL errors). A cleanup path that throws453 on EPERM means the rest of cleanup doesn't run. That's worse.454455### Utilities in `browse/src/error-handling.ts`456457| Function | Use when | Behavior |458|----------|----------|----------|459| `safeUnlink(path)` | Normal file deletion | Ignores ENOENT, rethrows others |460| `safeUnlinkQuiet(path)` | Shutdown/emergency cleanup | Swallows all errors |461| `safeKill(pid, signal)` | Sending signals | Ignores ESRCH, rethrows others |462| `isProcessAlive(pid)` | Boolean process checks | Returns true/false, never throws |463464### Score tracking465466Baseline (2026-04-09, before cleanup): 100 findings, 432.8 score, 2.38 score/file.467After cleanup: 90 findings, 358.1 score, 1.96 score/file.468469Don't chase the number. Fix patterns that represent actual code quality problems.470Accept findings where the "sloppy" pattern is the correct engineering choice.471472## Community PR guardrails473474When reviewing or merging community PRs, **always AskUserQuestion** before accepting475any commit that:4764771. **Touches ETHOS.md** — this file is Garry's personal builder philosophy. No edits478 from external contributors or AI agents, period.4792. **Removes or softens promotional material** — YC references, founder perspective,480 and product voice are intentional. PRs that frame these as "unnecessary" or481 "too promotional" must be rejected.4823. **Changes Garry's voice** — the tone, humor, directness, and perspective in skill483 templates, CHANGELOG, and docs are not generic. PRs that rewrite voice to be484 more "neutral" or "professional" must be rejected.485486Even if the agent strongly believes a change improves the project, these three487categories require explicit user approval via AskUserQuestion. No exceptions.488No auto-merging. No "I'll just clean this up."489490## Checking out PRs from garrytan-agents491492When the user says "check out <PR link>" and the PR is from `garrytan-agents/gstack`493(or any other fork that is NOT a collaborator on `garrytan/gstack`), do NOT just494`gh pr checkout`. Fork PRs don't receive base-repo secrets (`ANTHROPIC_API_KEY`,495`OPENAI_API_KEY`, etc.), so the eval/E2E CI jobs fail with empty-env auth errors496regardless of what's set on the base repo.497498**Workflow:** push the branch to `garrytan/gstack` (the base repo) and re-target499the PR from there.500501Concretely, after `gh pr checkout <N>`:5025031. Note the original PR number and head branch name.5042. Push the same branch to the base repo: `git push origin HEAD:<branch-name>`505 (origin = `garrytan/gstack`, since the worktree is set up with that remote).5063. Close the fork PR (`gh pr close <N> --comment "moving to base-repo branch for secret access"`).5074. Open a new PR from the base-repo branch: `gh pr create --base main --head <branch-name>`.5085. New PR's workflows will get secrets automatically.509510Why not fix it on the fork side? `garrytan-agents` isn't a collaborator on511`garrytan/gstack`. Adding it as a collaborator (option A) or flipping the512repo-wide "send secrets to fork PRs" toggle (option B) would let secrets reach513fork PRs from anyone — broader blast radius than just moving this one branch.514Option C (this section) keeps secret-distribution scope tight.515516If the user asks you to skip the move (e.g., "just leave it as a fork PR"),517respect that — eval CI will fail with empty-env auth, but check-freshness,518workflow-lint, and windows-tests will still pass on the fork PR.519520## CHANGELOG + VERSION style521522**Versioning invariant (workspace-aware ship).** VERSION is a monotonic ordered523release identifier, not a strict semver commitment. The bump level524(major/minor/patch/micro) expresses intent at ship time. Queue-advancing past a525claimed version within the same bump level is explicitly permitted — if branch A526claims v1.7.0.0 as a MINOR and branch B is also a MINOR, B lands at v1.8.0.0527(still a MINOR relative to main). Downstream consumers must NOT rely on528"MINOR = feature-only, PATCH = fix-only" as a strict contract. This is why529`bin/gstack-next-version` advances within the chosen bump level rather than530repicking the level when collisions happen.531532**Scale-aware bumps — use common sense.** When the diff is big, bump MINOR (or533MAJOR), not PATCH. PATCH is for bug fixes and small additions; MINOR is for534substantial new capability or substantial reduction; MAJOR is for breaking535changes. Rough guideposts (don't treat as rules, treat as smell-checks):536537- **PATCH (X.Y.Z+1.0)**: bug fix, doc tweak, small additive change, single538 test/file added. Net diff under ~500 lines, no new user-facing capability.539- **MINOR (X.Y+1.0.0)**: new capability shipped (skill, harness, command, big540 refactor), substantial code reduction (compression, migration), or coordinated541 multi-file change. Net diff over ~2000 lines added/removed, OR a user-visible542 feature you'd put in a tweet.543- **MAJOR (X+1.0.0.0)**: breaking change to public surface (CLI flag rename,544 skill removed, config format changed), OR a release big enough to be the545 headline of a blog post.546547If you find yourself debating "is 10K added + 24K removed really a PATCH?" — it548isn't. Bump MINOR. Same for "this adds a whole new test harness with 6 new E2E549tests + helper utilities" — MINOR. The bump level is communication to the user550about what kind of release this is; don't undersell it.551552When merging origin/main brings a higher VERSION, re-evaluate the bump level553against the SCALE of your branch's work, not just whether main moved forward.554If main bumped MINOR and your branch is also a substantial change, you bump555MINOR again on top (e.g., main at v1.14.0.0, your branch lands v1.15.0.0).556557**VERSION and CHANGELOG are branch-scoped.** Every feature branch that ships gets its558own version bump and CHANGELOG entry. The entry describes what THIS branch adds —559not what was already on main.560561**The CHANGELOG entry is the diff between main and the shipping branch — what users562get when they upgrade. NOT how the branch got there.** A reader landing on the entry563should learn what they can do now that they couldn't before; they should not learn564about the branch's internal version bumps, the bugs we caught and fixed mid-branch,565the plan reviews we ran, or the commits we squashed. That is branch development566narrative. It belongs in PR descriptions and commit messages, not CHANGELOG.567568**Never reference branch-internal versions in a CHANGELOG entry.** If your branch569bumped VERSION from v1.5.0.0 → v1.5.1.0 → v1.6.0.0 during development and only the570final v1.6.0.0 ships to main, the entry must read as if v1.5.1.0 never existed.571Concretely, NEVER write:572- "v1.5.1.0 had a bug that v1.6.0.0 fixes" — readers don't know about v1.5.1.0; it's573 a branch-internal artifact.574- "The shipping headline of v1.5.1.0 was broken because..." — same reason. From main's575 perspective, v1.5.1.0 was never released.576- "Pre-fix tests encoded the broken behavior" — that's a contributor's victory lap,577 not a user benefit.578- "Two surgical edits, both in the dispatch path" — micro-narrative of the patch.579580Instead, describe the released system: "Browser-skills run end-to-end with the581expected tab-access semantics." If a property of the shipped system is worth calling582out (e.g., "skill spawns get permissive tab access; pair-agent tunnel tokens require583ownership"), document it as a property, not as a fix. The shipped system is what584the user gets; the path to that system is invisible to them.585586**When to write the CHANGELOG entry:**587- At `/ship` time (Step 13), not during development or mid-branch.588- The entry covers ALL commits on this branch vs the base branch.589- Never fold new work into an existing CHANGELOG entry from a prior version that590 already landed on main. If main has v0.10.0.0 and your branch adds features,591 bump to v0.10.1.0 with a new entry — don't edit the v0.10.0.0 entry.592593**Key questions before writing:**5941. What branch am I on? What did THIS branch change?5952. Is the base branch version already released? (If yes, bump and create new entry.)5963. Does an existing entry on this branch already cover earlier work? (If yes, replace597 it with one unified entry for the final version.)598599**Merging main does NOT mean adopting main's version.** When you merge origin/main into600a feature branch, main may bring new CHANGELOG entries and a higher VERSION. Your branch601still needs its OWN version bump on top. If main is at v0.13.8.0 and your branch adds602features, bump to v0.13.9.0 with a new entry. Never jam your changes into an entry that603already landed on main. Your entry goes on top because your branch lands next.604605**After merging main, always check:**606- Does CHANGELOG have your branch's own entry separate from main's entries?607- Is VERSION higher than main's VERSION?608- Is your entry the topmost entry in CHANGELOG (above main's latest)?609If any answer is no, fix it before continuing.610611**After any CHANGELOG edit that moves, adds, or removes entries,** immediately run612`grep "^## \[" CHANGELOG.md` to verify no duplicates and a sensible reverse-chronological613order. Gaps between version numbers are fine. A branch that ships at v1.6.4.0 without614a prior v1.5.2.0 or v1.5.3.0 entry on main is correct — those were branch-internal615version numbers that never landed. Do not back-fill gaps with placeholder entries.616617**Never orphan branch-internal versions.** If your branch bumped VERSION several times618during development (v1.5.1.0 → v1.5.2.0 → v1.6.4.0, say) and those earlier entries were619never released to main, the final ship consolidates ALL of them into a single entry at620the final version (v1.6.4.0). Collapse them — delete the old entries and move their621content into the final entry, re-version table columns accordingly. Readers see one622release, not a branch diary. Gaps are fine (v1.6.3.0 → v1.6.4.0 with no v1.5.x623in between on main is correct).624625CHANGELOG.md is **for users**, not contributors. Write it like product release notes:626627- Lead with what the user can now **do** that they couldn't before. Sell the feature.628- Use plain language, not implementation details. "You can now..." not "Refactored the..."629- **Never mention TODOS.md, internal tracking, eval infrastructure, or contributor-facing630 details.** These are invisible to users and meaningless to them.631- Put contributor/internal changes in a separate "For contributors" section at the bottom.632- Every entry should make someone think "oh nice, I want to try that."633- No jargon: say "every question now tells you which project and branch you're in" not634 "AskUserQuestion format standardized across skill templates via preamble resolver."635636**Only document what shipped between main and this change.** Readers do not care how637we got here. Keep out of the CHANGELOG, always:638639- Branch resyncs, merge commits with main, rebase activity.640- Plan approvals, review outcomes (CEO / eng / design / outside-voice / codex findings),641 AskUserQuestion decisions, scope negotiations.642- "Work queued," "plan approved," "in-progress," "will ship later" — the CHANGELOG643 documents what DID ship, not what MIGHT ship.644- Version-bump housekeeping when no user-facing work actually landed.645646If the diff between the base branch version and this version has no user-facing change647(only merges, only CHANGELOG edits, only placeholder work), the honest entry is one648sentence: "Version bump for branch-ahead discipline. No user-facing changes yet." Stop649there. Do not pad. Do not explain the plan that will ship eventually. Do not narrate650the branch's history. When real work lands, the entry will replace this at /ship time.651652### Release-summary format (every `## [X.Y.Z]` entry)653654Every version entry in `CHANGELOG.md` MUST start with a release-summary section in655the GStack/Garry voice, one viewport's worth of prose + tables that lands like a656verdict, not marketing. The itemized changelog (subsections, bullets, files) goes657BELOW that summary, separated by a `### Itemized changes` header.658659The release-summary section gets read by humans, by the auto-update agent, and by660anyone deciding whether to upgrade. The itemized list is for agents that need to661know exactly what changed.662663Structure for the top of every `## [X.Y.Z]` entry:6646651. **Two-line bold headline** (10-14 words total). Should land like a verdict, not666 marketing. Sound like someone who shipped today and cares whether it works.6672. **Lead paragraph** (3-5 sentences). What shipped, what changed for the user.668 Specific, concrete, no AI vocabulary, no em dashes, no hype.6693. **A "The X numbers that matter" section** with:670 - One short setup paragraph naming the source of the numbers (real production671 deployment OR a reproducible benchmark, name the file/command to run).672 - A table of 3-6 key metrics with BEFORE / AFTER / Δ columns.673 - A second optional table for per-category breakdown if relevant.674 - 1-2 sentences interpreting the most striking number in concrete user terms.6754. **A "What this means for [audience]" closing paragraph** (2-4 sentences) tying676 the metrics to a real workflow shift. End with what to do.677678Voice rules for the release summary:679- No em dashes (use commas, periods, "...").680- No AI vocabulary (delve, robust, comprehensive, nuanced, fundamental, etc.) or681 banned phrases ("here's the kicker", "the bottom line", etc.).682- Real numbers, real file names, real commands. Not "fast" but "~30s on 30K pages."683- Short paragraphs, mix one-sentence punches with 2-3 sentence runs.684- Connect to user outcomes: "the agent does ~3x less reading" beats "improved precision."685- Be direct about quality. "Well-designed" or "this is a mess." No dancing.686687Source material:688- CHANGELOG previous entry for prior context.689- Benchmark files or `/retro` output for headline numbers.690- Recent commits (`git log <prev-version>..HEAD --oneline`) for what shipped.691- Don't make up numbers. If a metric isn't in a benchmark or production data,692 don't include it. Say "no measurement yet" if asked.693694Target length: ~250-350 words for the summary. Should render as one viewport.695696### Itemized changes (below the release summary)697698Write `### Itemized changes` and continue with the detailed subsections (Added,699Changed, Fixed, For contributors). Same rules as the user-facing voice guidance700above, plus:701702- **Always credit community contributions.** When an entry includes work from a703 community PR, name the contributor with `Contributed by @username`. Contributors704 did real work. Thank them publicly every time, no exceptions.705706## AI effort compression707708When estimating or discussing effort, always show both human-team and CC+gstack time:709710| Task type | Human team | CC+gstack | Compression |711|-----------|-----------|-----------|-------------|712| Boilerplate / scaffolding | 2 days | 15 min | ~100x |713| Test writing | 1 day | 15 min | ~50x |714| Feature implementation | 1 week | 30 min | ~30x |715| Bug fix + regression test | 4 hours | 15 min | ~20x |716| Architecture / design | 2 days | 4 hours | ~5x |717| Research / exploration | 1 day | 3 hours | ~3x |718719Completeness is cheap. Don't recommend shortcuts when the complete implementation720is a "lake" (achievable) not an "ocean" (multi-quarter migration). See the721Completeness Principle in the skill preamble for the full philosophy.722723## Search before building724725Before designing any solution that involves concurrency, unfamiliar patterns,726infrastructure, or anything where the runtime/framework might have a built-in:7277281. Search for "{runtime} {thing} built-in"7292. Search for "{thing} best practice {current year}"7303. Check official runtime/framework docs731732Three layers of knowledge: tried-and-true (Layer 1), new-and-popular (Layer 2),733first-principles (Layer 3). Prize Layer 3 above all. See ETHOS.md for the full734builder philosophy.735736## Local plans737738Contributors can store long-range vision docs and design documents in `~/.gstack-dev/plans/`.739These are local-only (not checked in). When reviewing TODOS.md, check `plans/` for candidates740that may be ready to promote to TODOs or implement.741742## E2E eval failure blame protocol743744When an E2E eval fails during `/ship` or any other workflow, **never claim "not745related to our changes" without proving it.** These systems have invisible couplings —746a preamble text change affects agent behavior, a new helper changes timing, a747regenerated SKILL.md shifts prompt context.748749**Required before attributing a failure to "pre-existing":**7501. Run the same eval on main (or base branch) and show it fails there too7512. If it passes on main but fails on the branch — it IS your change. Trace the blame.7523. If you can't run on main, say "unverified — may or may not be related" and flag it753 as a risk in the PR body754755"Pre-existing" without receipts is a lazy claim. Prove it or don't say it.756757## Long-running tasks: don't give up758759When running evals, E2E tests, or any long-running background task, **poll until760completion**. Use `sleep 180 && echo "ready"` + `TaskOutput` in a loop every 3761minutes. Never switch to blocking mode and give up when the poll times out. Never762say "I'll be notified when it completes" and stop checking — keep the loop going763until the task finishes or the user tells you to stop.764765The full E2E suite can take 30-45 minutes. That's 10-15 polling cycles. Do all of766them. Report progress at each check (which tests passed, which are running, any767failures so far). The user wants to see the run complete, not a promise that768you'll check later.769770## E2E test fixtures: extract, don't copy771772**NEVER copy a full SKILL.md file into an E2E test fixture.** SKILL.md files are7731500-2000 lines. When `claude -p` reads a file that large, context bloat causes774timeouts, flaky turn limits, and tests that take 5-10x longer than necessary.775776Instead, extract only the section the test actually needs:777778```typescript779// BAD — agent reads 1900 lines, burns tokens on irrelevant sections780fs.copyFileSync(path.join(ROOT, 'ship', 'SKILL.md'), path.join(dir, 'ship-SKILL.md'));781782// GOOD — agent reads ~60 lines, finishes in 38s instead of timing out783const full = fs.readFileSync(path.join(ROOT, 'ship', 'SKILL.md'), 'utf-8');784const start = full.indexOf('## Review Readiness Dashboard');785const end = full.indexOf('\n---\n', start);786fs.writeFileSync(path.join(dir, 'ship-SKILL.md'), full.slice(start, end > start ? end : undefined));787```788789Also when running targeted E2E tests to debug failures:790- Run in **foreground** (`bun test ...`), not background with `&` and `tee`791- Never `pkill` running eval processes and restart — you lose results and waste money792- One clean run beats three killed-and-restarted runs793794## Publishing native OpenClaw skills to ClawHub795796Native OpenClaw skills live in `openclaw/skills/garrytan_gstack-openclaw-*/SKILL.md`. These are797hand-crafted methodology skills (not generated by the pipeline) published to ClawHub798so any OpenClaw user can install them.799800**Publishing:** The command is `clawhub publish` (NOT `clawhub skill publish`):801802```bash803clawhub publish openclaw/skills/garrytan_gstack-openclaw-office-hours \804 --slug gstack-openclaw-office-hours --name "gstack Office Hours" \805 --version 1.0.0 --changelog "description of changes"806```807808Repeat for each skill: `gstack-openclaw-ceo-review`, `gstack-openclaw-investigate`,809`gstack-openclaw-retro`. Bump `--version` on each update.810811**Auth:** `clawhub login` (opens browser for GitHub auth). `clawhub whoami` to verify.812813**Updating:** Same `clawhub publish` command with a higher `--version` and `--changelog`.814815**Verification:** `clawhub search gstack` to confirm they're live.816817## Deploying to the active skill818819The active skill lives at `$GSTACK_ROOT/`. After making changes:8208211. Push your branch8222. Fetch and reset in the skill directory: `cd $GSTACK_ROOT && git fetch origin && git reset --hard origin/main`8233. Rebuild: `cd $GSTACK_ROOT && bun run build`824825Or copy the binaries directly:826- `cp browse/dist/browse $GSTACK_ROOT/browse/dist/browse`827- `cp design/dist/design $GSTACK_ROOT/design/dist/design`828829## Skill routing830831When the user's request matches an available skill, invoke it via the Skill tool. When in doubt, invoke the skill.832833Key routing rules:834- Product ideas/brainstorming → invoke /office-hours835- Strategy/scope → invoke /plan-ceo-review836- Architecture → invoke /plan-eng-review837- Design system/plan review → invoke /design-consultation or /plan-design-review838- Full review pipeline → invoke /autoplan839- Bugs/errors → invoke /investigate840- QA/testing site behavior → invoke /qa or /qa-only841- Code review/diff check → invoke /review842- Visual polish → invoke /design-review843- Ship/deploy/PR → invoke /ship or /land-and-deploy844- Save progress → invoke /context-save845- Resume context → invoke /context-restore846847## GBrain Search Guidance (configured by /sync-gbrain)848<!-- gstack-gbrain-search-guidance:start -->849850GBrain is set up and synced on this machine. The agent should prefer gbrain851over Grep when the question is semantic or when you don't know the exact852identifier yet.853854**This worktree is pinned to a worktree-scoped code source** via the855`.gbrain-source` file in the repo root (kubectl-style context). Any856`gbrain code-def`, `code-refs`, `code-callers`, `code-callees`, or `query`857call from anywhere under this worktree routes to that source by default —858no `--source` flag needed. Conductor sibling worktrees of the same repo859each have their own pin and their own indexed pages, so semantic results860match the actual code on disk in this worktree.861862Two indexed corpora available via the `gbrain` CLI:863- This worktree's code (auto-pinned via `.gbrain-source`).864- `~/.gstack/` curated memory (registered as `gstack-brain-<user>` source via865 the existing federation pipeline).866867Prefer gbrain when:868- "Where is X handled?" / semantic intent, no exact string yet:869 `gbrain search "<terms>"` or `gbrain query "<question>"`870- "Where is symbol Y defined?" / symbol-based code questions:871 `gbrain code-def <symbol>` or `gbrain code-refs <symbol>`872- "What calls Y?" / "What does Y depend on?":873 `gbrain code-callers <symbol>` / `gbrain code-callees <symbol>`874- "What did we decide last time?" / past plans, retros, learnings:875 `gbrain search "<terms>" --source gstack-brain-<user>`876877Grep is still right for known exact strings, regex, multiline patterns, and878file globs. Run `/sync-gbrain` after meaningful code changes; for ongoing879auto-sync across all worktrees, run `gbrain autopilot --install` once per880machine — gbrain's daemon handles incremental refresh on a schedule.881882<!-- gstack-gbrain-search-guidance:end -->883
One repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| nota-america/forgecat-agent-profilesprofiles/addyosmani/agent-skills/for-cursor/.cursor/rules/cmd-build.mdc · 51 | Cursor rules | no sections | 16/100 | today | |
| nota-america/forgecat-agent-profilesprofiles/addyosmani/agent-skills/for-cursor/.cursor/rules/cmd-code-simplify.mdc · 51 | Cursor rules | testing-strategy | 30/100 | today | |
| nota-america/forgecat-agent-profilesprofiles/addyosmani/agent-skills/for-cursor/.cursor/rules/cmd-plan.mdc · 51 | Cursor rules | no sections | 16/100 | today | |
| nota-america/forgecat-agent-profilesprofiles/addyosmani/agent-skills/for-cursor/.cursor/rules/cmd-review.mdc · 51 | Cursor rules | no sections | 16/100 | today | |
| nota-america/forgecat-agent-profilesprofiles/addyosmani/agent-skills/for-cursor/.cursor/rules/cmd-ship.mdc · 51 | Cursor rules | testing-strategygitdeploymentdo-not | 61/100 | today | |
| nota-america/forgecat-agent-profilesprofiles/addyosmani/agent-skills/for-cursor/.cursor/rules/cmd-spec.mdc · 51 | Cursor rules | no sections | 16/100 | today | |
| nota-america/forgecat-agent-profilesprofiles/addyosmani/agent-skills/for-cursor/.cursor/rules/cmd-test.mdc · 51 | Cursor rules | no sections | 16/100 | today | |
| nota-america/forgecat-agent-profilesprofiles/addyosmani/agent-skills/for-forgecat/AGENTS.md · 51 | AGENTS.md | lint-formatstylearchdo-not | 73/100 | today | |
| nota-america/forgecat-agent-profilesprofiles/addyosmani/agent-skills/for-forgecat/CLAUDE.md · 51 | CLAUDE.md | teststylearchagent-behaviour | 70/100 | today | |
| nota-america/forgecat-agent-profilesprofiles/anthropics/claude-code/anthropics_claude-code_ralph-wiggum/for-cursor/.cursor/rules/cmd-cancel-ralph.mdc · 51 | Cursor rules | no sections | 16/100 | today | |
| nota-america/forgecat-agent-profilesprofiles/anthropics/claude-code/anthropics_claude-code_ralph-wiggum/for-cursor/.cursor/rules/cmd-help.mdc · 51 | Cursor rules | no sections | 54/100 | today | |
| nota-america/forgecat-agent-profilesprofiles/anthropics/claude-code/anthropics_claude-code_ralph-wiggum/for-cursor/.cursor/rules/cmd-ralph-loop.mdc · 51 | Cursor rules | no sections | 22/100 | today | |
| nota-america/forgecat-agent-profilesprofiles/anthropics/claude-plugins-official/anthropics_claude-plugins-official_agent-sdk-dev/for-cursor/.cursor/rules/cmd-new-sdk-app.mdc · 51 | Cursor rules | setupstylearchdocs | 76/100 | today | |
| nota-america/forgecat-agent-profilesprofiles/anthropics/claude-plugins-official/anthropics_claude-plugins-official_claude-md-management/for-cursor/.cursor/rules/cmd-revise-claude-md.mdc · 51 | Cursor rules | agent-behaviour | 50/100 | today | |
| nota-america/forgecat-agent-profilesprofiles/anthropics/claude-plugins-official/anthropics_claude-plugins-official_code-review/for-cursor/.cursor/rules/cmd-code-review.mdc · 51 | Cursor rules | testing-strategygit | 35/100 | today | |
| nota-america/forgecat-agent-profilesprofiles/anthropics/claude-plugins-official/anthropics_claude-plugins-official_commit-commands/for-cursor/.cursor/rules/cmd-clean_gone.mdc · 51 | Cursor rules | no sections | 60/100 | today | |
| nota-america/forgecat-agent-profilesprofiles/anthropics/claude-plugins-official/anthropics_claude-plugins-official_commit-commands/for-cursor/.cursor/rules/cmd-commit-push-pr.mdc · 51 | Cursor rules | stylegit | 44/100 | today | |
| nota-america/forgecat-agent-profilesprofiles/anthropics/claude-plugins-official/anthropics_claude-plugins-official_commit-commands/for-cursor/.cursor/rules/cmd-commit.mdc · 51 | Cursor rules | style | 44/100 | today | |
| nota-america/forgecat-agent-profilesprofiles/anthropics/claude-plugins-official/anthropics_claude-plugins-official_example-plugin/for-cursor/.cursor/rules/cmd-example-command.mdc · 51 | Cursor rules | lint-formatstyleagent-behaviour | 58/100 | today | |
| nota-america/forgecat-agent-profilesprofiles/anthropics/claude-plugins-official/anthropics_claude-plugins-official_feature-dev/for-cursor/.cursor/rules/cmd-feature-dev.mdc · 51 | Cursor rules | stylearchgit | 56/100 | today |
Same format, overlapping stack, ranked by quality.
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| bagisto/bagistoCLAUDE.md · 28k | CLAUDE.md | setupbuildteststyle+5 | 100/100 | 7 days ago | |
| Adit-Jain-srm/NightmareNetCLAUDE.md · 46 | CLAUDE.md | buildtestlint-formatstyle+6 | 100/100 | 14 days ago | |
| tyrchen/geektime-bootcamp-aiw7/genslides/backend/CLAUDE.md · 230 | CLAUDE.md | testlint-formatstylearch+6 | 100/100 | 9 days ago | |
| nimbalyst/nimbalystpackages/android/CLAUDE.md · 1.5k | CLAUDE.md | setupbuildstylearch+2 | 100/100 | 14 days ago | |
| dotCMS/corecore-web/CLAUDE.md · 949 | CLAUDE.md | teststylearchtesting-strategy+3 | 100/100 | 14 days ago | |
| microsoft/playwrightCLAUDE.md · 95k | CLAUDE.md | buildtestlint-formatstyle+7 | 100/100 | 7 days ago | |
| tphakala/birdnet-goCLAUDE.md · 1.6k | CLAUDE.md | buildtestlint-formatstyle+8 | 100/100 | today | |
| livewire/livewireCLAUDE.md · 24k | CLAUDE.md | setupbuildteststyle+4 | 100/100 | 14 days ago |
A badge carrying the measured quality of the strongest agent config file in this repository, out of 100. It reads from this index every time somebody loads your page, so it changes when the measurement changes and there is nothing to keep up to date. Free, no account, and the value is not something you or we can set by hand.
[](https://rulestack.kynth.studio/configs/nota-america-forgecat-agent-profiles-profiles-garrytan-gstack-for-cursor-cursor-skills-garrytan-gstack-claude)Would rather not hotlink us? Every badge is also served in shields.io’s endpoint schema, so shields renders the image and your readers never talk to our domain:
Published by Toolproof, the masthead over this index and eight others. The method behind the number is at toolproof.kynth.studio/methodology, and the whole thing is readable as JSON with no key at /api.