{"id":51224444,"url":"https://github.com/tibtof/lgtm-buzzer","last_synced_at":"2026-06-28T10:01:25.681Z","repository":{"id":359512947,"uuid":"1245899148","full_name":"tibtof/lgtm-buzzer","owner":"tibtof","description":"Browser extension that quizzes you on the diff before letting you approve a PR. Powered by your local LLM CLI.","archived":false,"fork":false,"pushed_at":"2026-06-04T21:35:18.000Z","size":1102,"stargazers_count":0,"open_issues_count":3,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-04T22:17:54.804Z","etag":null,"topics":["azure-devops","browser-extension","chrome-extension","claude","code-review","developer-tools","github","llm","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tibtof.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-21T17:05:50.000Z","updated_at":"2026-06-04T21:35:21.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/tibtof/lgtm-buzzer","commit_stats":null,"previous_names":["tibtof/lgtm-buzzer"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/tibtof/lgtm-buzzer","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tibtof%2Flgtm-buzzer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tibtof%2Flgtm-buzzer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tibtof%2Flgtm-buzzer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tibtof%2Flgtm-buzzer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tibtof","download_url":"https://codeload.github.com/tibtof/lgtm-buzzer/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tibtof%2Flgtm-buzzer/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34884278,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-28T02:00:05.809Z","response_time":54,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["azure-devops","browser-extension","chrome-extension","claude","code-review","developer-tools","github","llm","typescript"],"created_at":"2026-06-28T10:01:24.764Z","updated_at":"2026-06-28T10:01:25.657Z","avatar_url":"https://github.com/tibtof.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# LGTM-Buzzer\n\n**Gate your PR approvals behind a quiz on the actual diff.**\n\n[![CI](https://github.com/tibtof/lgtm-buzzer/actions/workflows/ci.yml/badge.svg)](https://github.com/tibtof/lgtm-buzzer/actions/workflows/ci.yml)\n[![Release](https://img.shields.io/github/v/release/tibtof/lgtm-buzzer)](https://github.com/tibtof/lgtm-buzzer/releases)\n[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE)\n\n---\n\n## What this is\n\nLGTM-Buzzer is a Chrome extension that intercepts the Approve button on GitHub\npull requests and gates it behind a short quiz generated from the actual diff.\nIf you can answer the quiz, the approval goes through. If you can't, you didn't\nread the PR.\n\n**The quiz is always generated from the raw diff bytes — never from the PR\ntitle, description, commit messages, labels, or comments.** A teammate writing\na great PR description cannot short-circuit the gate. This is the core\ninvariant of the project, enforced at six layers from the VCS adapter through\nthe wire protocol to the LLM prompt.\n\n**All LLM calls stay local.** The extension never contacts an LLM directly.\nThe native messaging host shells out to whichever CLI or API you already have\nconfigured on your machine. No credentials live in the extension, no diff bytes\nleave your machine through a third-party proxy, no telemetry of any kind.\n\nFour LLM adapters are available: Claude Code CLI, Codex CLI, `gh copilot`, and\nthe Anthropic API (host-held key). Two VCS adapters are available: GitHub\n(fully functional) and Azure DevOps (UI interception works; the multi-call diff\nadapter is deferred to the next milestone — see the status table below).\n\n---\n\n## Status: v0.1.0 — M3 release\n\n| Area | Status | Notes |\n|---|---|---|\n| Chrome MV3 extension | Working | Approve-button interception on `github.com` PR pages |\n| Quiz modal | Working | Questions, answers, pass/fail, error states, retry, WCAG AA |\n| `claude-cli` adapter | Working | Shells out to the `claude` binary |\n| `codex-cli` adapter | Working | Shells out to the `codex` binary |\n| `copilot-cli` adapter | Working | Shells out to `gh copilot` |\n| `claude-api` adapter | Working | Anthropic REST API with prompt caching |\n| GitHub VCS adapter | Working | PAT-authenticated diff fetch from the GitHub API |\n| ADO VCS adapter | Stubbed | Approve button intercepted on `dev.azure.com`; the diff-fetching adapter (multi-call ADO API) is deferred to v0.2 |\n| Options page | Working | Runtime LLM + VCS adapter selection, credential storage |\n| Native messaging host | Working | macOS and Linux; Windows deferred |\n| GitHub Actions CI | Working | `npm run check` on every push and PR |\n| Release packaging | Working | Extension zip + host tarball with checksums |\n| Playwright e2e | Working | Happy-path quiz gate in CI (xvfb-run on Linux) |\n| promptfoo evals | Working | Quiz-quality eval suite across all four adapters |\n| Safari port | Deferred | Post-v1.0 via Xcode MV3 converter |\n| Firefox MV3 | Deferred | Future milestone |\n| OS keychain integration | Deferred | Credentials currently stored as plaintext |\n\n---\n\n## Screenshots\n\nScreenshots TBD — no screenshots have been captured yet for v0.1.0. A short\nscreen recording of the quiz gate in action will be added before the v0.1.0\ntag is published.\n\n---\n\n## Quick start\n\n### Prerequisites\n\n| Requirement | Minimum | Notes |\n|---|---|---|\n| Node.js | 22 LTS | `node --version` to check |\n| Chrome | any recent stable | Developer mode required |\n| At least one LLM | — | See table below |\n| GitHub PAT | — | `Contents: read` scope (or `repo` scope for classic tokens) |\n\n**LLM prerequisites — pick at least one:**\n\n| Adapter | What you need |\n|---|---|\n| `claude-cli` | `claude` CLI installed and authenticated |\n| `codex-cli` | `codex` CLI installed and authenticated |\n| `copilot-cli` | `gh` CLI with `gh copilot` extension, authenticated via `gh auth login` |\n| `claude-api` | `ANTHROPIC_API_KEY` environment variable set |\n\n### Install steps\n\n```bash\n# 1. Clone and install\ngit clone https://github.com/tibtof/lgtm-buzzer.git\ncd lgtm-buzzer\nnpm install\n\n# 2. Build everything\nnpm run build\n\n# 3. Install the native-messaging manifest (macOS / Linux)\nnode packages/host/dist/install-manifest.js\n# Re-run with your extension ID after Step 5:\n# LGTM_BUZZER_EXTENSION_ID=\u003cid\u003e node packages/host/dist/install-manifest.js\n\n# 4. Load the extension in Chrome\n#    chrome://extensions → Developer mode → Load unpacked\n#    → packages/extension/.output/chrome-mv3/\n\n# 5. Open the extension options page, pick your LLM + VCS adapter,\n#    and enter credentials (GitHub PAT, or Anthropic API key if using claude-api).\n```\n\nSee **[docs/getting-started.md](docs/getting-started.md)** for the full\nstep-by-step walkthrough, including the extension ID lookup, troubleshooting,\nand a detailed description of each step.\n\n### Downloading a pre-built release\n\nPre-built artifacts are on the\n[GitHub Releases page](https://github.com/tibtof/lgtm-buzzer/releases):\n\n- `lgtm-buzzer-extension-v\u003cversion\u003e.zip` — Chrome MV3 extension (load unpacked or submit to the Web Store).\n- `lgtm-buzzer-host-v\u003cversion\u003e.tar.gz` — Native messaging host with installer; no `npm install` needed.\n\nSee **[docs/release.md](docs/release.md)** for the maintainer release guide.\n\n---\n\n## How to use\n\nOnce installed and configured:\n\n1. Navigate to a GitHub pull request.\n2. Click the **Approve** button (or go through **Review changes → Approve →\n   Submit review**).\n3. A quiz modal appears in place of the usual confirmation.\n4. Read the questions — they are generated from the PR diff, not the description.\n5. Type your answers and click **Submit**.\n6. **Pass**: your approval is submitted. **Fail**: close the modal and re-read the diff.\n\nThe quiz is generated fresh for each approval attempt. There is no \"skip\" path.\n\n---\n\n## Configuration\n\nOpen the extension options page by clicking the LGTM-Buzzer icon in Chrome's\ntoolbar and selecting **Options** (or navigating to\n`chrome-extension://\u003cid\u003e/options.html`).\n\nOn the options page you can:\n\n- Select your preferred LLM adapter (Claude CLI, Codex CLI, Copilot CLI, or Claude API).\n- Select your VCS adapter (GitHub or ADO — ADO diff fetch is stubbed in v0.1.0).\n- Enter adapter credentials (GitHub PAT, Anthropic API key).\n\nSettings are saved immediately to `chrome.storage.local`. The storage schema\nis validated with Zod on every read; corrupt storage falls back to defaults\nwith a visible warning.\n\n---\n\n## Security\n\n### Credential storage\n\nCredentials (GitHub PAT, Anthropic API key) are stored in **`chrome.storage.local` as plaintext**. This is a v1 limitation. We do not yet integrate with OS keychains (macOS Keychain, Linux SecretService). A future ADR will track this upgrade — the `StorageArea` port in the extension is the designed injection point.\n\n### Diff-only invariant\n\nPRs are quizzed on the diff bytes only — never on the PR title, description,\ncommit messages, labels, or comments. This is enforced at six layers:\n\n1. The VCS port (`VCSProvider`) accepts only a PR identifier and returns a raw diff string. No other PR metadata is in the type.\n2. The GitHub adapter fetches only the `application/vnd.github.diff` media type from the GitHub API.\n3. The wire-format `quiz-request` message schema (ADR-7, ADR-11) carries only `prId` and `diff` — no title or description fields exist in the schema.\n4. The `QuizSession` aggregate (ADR-14) receives only the diff from the wire message; it never sees PR metadata.\n5. Each LLM adapter prompt template is diff-in / structured-JSON-out with no slot for PR metadata.\n6. The promptfoo eval suite includes a negative-control fixture (`docs-readme-update`) that asserts adapters return an error rather than a quiz when fed a docs-only change with no code symbols.\n\nAny change that adds non-diff PR text to any of these layers is treated as a security boundary violation and requires a new ADR.\n\n### LLM calls\n\n- **CLI adapters** (`claude-cli`, `codex-cli`, `copilot-cli`): the host spawns a subprocess. The diff bytes go in on stdin. No network egress from the extension or the host beyond the subprocess's own network activity.\n- **API adapter** (`claude-api`): the host calls the Anthropic REST API directly with the API key you configured. No third-party proxy, no telemetry.\n- The extension itself makes no LLM calls and holds no LLM credentials.\n\n---\n\n## Architecture\n\nLGTM-Buzzer uses hexagonal architecture enforced by npm workspace boundaries.\n\n### System diagram\n\nThe extension lives in the browser; everything that touches an LLM or a VCS\nAPI lives in a Node host process on the user's machine. The two sides only\never talk over Chrome's native-messaging stdio bridge, and every frame is\nvalidated by a Zod schema from `packages/protocol`.\n\n```mermaid\nflowchart TB\n    subgraph Browser[\"Browser (Chrome MV3) — packages/extension\"]\n        direction TB\n        CS[\"Content Script\u003cbr/\u003eintercepts Approve click\u003cbr/\u003emounts Quiz Modal\"]\n        SW[\"Service Worker\u003cbr/\u003eowns native-messaging port\u003cbr/\u003ezod-validates host replies\"]\n        CS \u003c--\u003e SW\n    end\n\n    subgraph Machine[\"User's machine — Node host process\"]\n        direction TB\n        Host[\"Native Host (packages/host)\u003cbr/\u003estdin read-loop · zod-validate · dispatch\"]\n\n        subgraph Core[\"Core domain (packages/core) — pure, zero I/O\"]\n            direction TB\n            Domain[\"QuizSession · ReviewGate\"]\n            Ports[\"Ports\u003cbr/\u003eLLMProvider · VCSProvider · QuizPolicy\"]\n            Domain --- Ports\n        end\n\n        subgraph Adapters[\"Adapters (packages/adapters)\"]\n            direction LR\n            subgraph VCSGroup[\"VCS\"]\n                direction TB\n                GH[\"github\"]\n                ADO[\"ado\"]\n            end\n            subgraph LLMGroup[\"LLM\"]\n                direction TB\n                CLAUDE[\"claude-cli\"]\n                CODEX[\"codex-cli\"]\n                COPILOT[\"copilot-cli\"]\n                API[\"claude-api\"]\n            end\n        end\n\n        Host --\u003e|\"drives\"| Core\n        Ports -.-\u003e|\"implemented by\"| Adapters\n    end\n\n    subgraph External[\"External services and processes\"]\n        direction TB\n        GHAPI[\"GitHub REST API\"]\n        ADOAPI[\"Azure DevOps API\"]\n        LocalLLMs[\"Local LLM CLIs\u003cbr/\u003eclaude · codex · gh copilot\"]\n        Anthropic[\"Anthropic API\"]\n    end\n\n    SW \u003c==\u003e|\"Native Messaging stdio\u003cbr/\u003euint32 length-prefixed JSON · schemas in packages/protocol\"| Host\n\n    GH --\u003e GHAPI\n    ADO --\u003e ADOAPI\n    CLAUDE --\u003e LocalLLMs\n    CODEX --\u003e LocalLLMs\n    COPILOT --\u003e LocalLLMs\n    API --\u003e Anthropic\n```\n\n**In one breath:** the content script and service worker are the only pieces\nthat run in the browser. The service worker speaks a length-prefixed JSON\nprotocol over stdio to the native host. Inside the host, the core domain is\npure and exposes ports (`LLMProvider`, `VCSProvider`, `QuizPolicy`); adapters\nimplement those ports and are the only place that touches the network, a\nsubprocess, or any other external service. The extension cannot reach an\nLLM directly — there is no arrow from the browser box to any external\nservice. Adapter availability is tracked in the\n[LLM + VCS adapter matrix](#llm--vcs-adapter-matrix) below; this diagram\nshows architectural structure, not per-adapter shipping status.\n\n### Request flow — one approval attempt\n\nThis sequence walks one Approve click from the moment the content script\nintercepts it through quiz generation, scoring, and the eventual pass-or-\nkeep-the-modal decision. Wire-frame names (`quiz-request`, `quiz-response`,\n`quiz-submit`, `quiz-result`) match the schemas in `packages/protocol` per\nADR-13.\n\n```mermaid\nsequenceDiagram\n    autonumber\n    actor User\n    participant CS as Content Script\n    participant SW as Service Worker\n    participant Host as Native Host\n    participant Core as Core (QuizSession / ReviewGate)\n    participant VCS as VCS Adapter\n    participant LLM as LLM Adapter\n    participant Ext as External (Git provider / LLM)\n\n    User-\u003e\u003eCS: clicks Approve\n    CS-\u003e\u003eSW: quiz-request { pr, questionCount }\n    SW-\u003e\u003eHost: stdio frame\n    Note over Host: zod-validates every\u003cbr/\u003eincoming frame\n    Host-\u003e\u003eCore: QuizSession.start\n    Core-\u003e\u003eVCS: getDiff(pr)\n    VCS-\u003e\u003eExt: HTTPS diff fetch (provider-specific)\n    Ext--\u003e\u003eVCS: raw diff bytes\n    VCS--\u003e\u003eCore: diff\n    Note over VCS,LLM: Only the raw diff crosses this boundary.\u003cbr/\u003eNo PR title, description, or comments.\n    Core-\u003e\u003eLLM: generateQuiz(diff)\n    Note right of LLM: CLI adapters: spawnIO,\u003cbr/\u003estdin = diff.\u003cbr/\u003eAPI adapter: HTTPS.\n    LLM-\u003e\u003eExt: spawn CLI or HTTPS\n    Ext--\u003e\u003eLLM: questions JSON\n    LLM--\u003e\u003eCore: Quiz\n    Core--\u003e\u003eHost: Quiz\n    Host--\u003e\u003eSW: quiz-response { quiz }\n    SW--\u003e\u003eCS: Quiz\n    CS-\u003e\u003eUser: render Quiz Modal\n    User-\u003e\u003eCS: submit answers\n    CS-\u003e\u003eSW: quiz-submit { quizId, answers }\n    SW-\u003e\u003eHost: stdio frame\n    Host-\u003e\u003eCore: ReviewGate.grade(answers)\n    Core--\u003e\u003eHost: pass / fail\n    Host--\u003e\u003eSW: quiz-result { passed, perQuestion? }\n    SW--\u003e\u003eCS: result\n    alt pass\n        CS-\u003e\u003eCS: re-fire original Approve click\n    else fail\n        CS-\u003e\u003eUser: modal stays, Approve remains gated\n    end\n```\n\n**In one breath:** Approve clicks never go straight through. The extension\nasks the host for a quiz over a `quiz-request` frame; the host's core asks\nthe VCS adapter for the diff, hands that diff (and only the diff) to the\nLLM adapter, and returns the questions as `quiz-response`. The user\nanswers in the modal; the extension forwards a `quiz-submit` frame; the\nhost's `ReviewGate` scores it and replies with `quiz-result`. On pass, the\ncontent script re-fires the original Approve click; on fail, the modal\nstays put and the gate holds.\n\n### Workspaces\n\n```\npackages/\n  protocol/    Wire-format schemas (zod) and domain DTOs. Zero runtime deps except zod.\n  core/        Pure domain logic: ports, QuizSession, ReviewGate. No Node, no DOM, no I/O.\n  adapters/    Concrete port implementations (claude-cli, codex-cli, copilot-cli,\n               claude-api, github, ado). One subfolder per adapter.\n  host/        Native messaging host. Node-only wiring of adapters into core.\n  extension/   Chrome MV3 service worker, content scripts, options page, quiz modal.\n  evals/       promptfoo eval suite for quiz quality.\n```\n\nDependency direction is strict and enforced by ESLint:\n\n```\nprotocol  \u003c- core  \u003c- adapters  \u003c- host\nprotocol  \u003c- core  \u003c- extension\n```\n\nSee [`CLAUDE.md`](./CLAUDE.md) for the full project constitution (architecture\nprinciples, dependency rules, FP idioms, code style) and\n[`decisions.md`](./decisions.md) for the full architecture decision log (28 ADRs\ncovering every significant design choice from the FP foundation through the\nrelease pipeline).\n\n---\n\n## LLM + VCS adapter matrix\n\n| Adapter | Type | Status | Credentials | Notes |\n|---|---|---|---|---|\n| `claude-cli` | LLM | Working | none (CLI login) | requires `claude` binary on PATH |\n| `codex-cli` | LLM | Working | none (CLI login) | requires `codex` binary on PATH |\n| `copilot-cli` | LLM | Working | none (`gh auth login`) | requires `gh` + `gh-copilot` extension |\n| `claude-api` | LLM | Working | `ANTHROPIC_API_KEY` | prompt caching enabled |\n| `github` | VCS | Working | GitHub PAT (`Contents: read`) | fetches raw diff via GitHub API |\n| `ado` | VCS | Stubbed | ADO PAT (when impl lands) | UI interception works; multi-call diff adapter deferred to v0.2 |\n\n---\n\n## Development\n\n### Setup\n\n```bash\ngit clone https://github.com/tibtof/lgtm-buzzer.git\ncd lgtm-buzzer\nnpm install\nnpm run build\n```\n\n### Common commands\n\n```bash\nnpm run build          # tsc -b for all lib packages + wxt build for the extension\nnpm run build:libs     # tsc -b only (skip the extension)\nnpm test               # vitest run across all packages\nnpm run lint           # eslint with flat config (enforces dependency direction)\nnpm run format         # prettier --write\nnpm run typecheck:tests  # type-check all *.test.ts files (excluded from tsc -b)\nnpm run check          # full CI gate: build + test + lint + typecheck:tests\n```\n\n### Running e2e tests\n\nThe Playwright suite requires a display. On Linux without a desktop:\n\n```bash\nxvfb-run --auto-servernum npm test\n```\n\nOn macOS, run `npm test` directly.\n\n### Running evals\n\nEvals make real LLM calls and are excluded from `npm run check`. They require\nthe adapter tools and credentials described in the prerequisites section.\n\n```bash\nnpm run evals          # full suite — all adapters x all fixtures\nnpm run evals:quick    # fast fixtures only (ts-add-validator, dep-bump-only)\n```\n\nSee [`packages/evals/README.md`](packages/evals/README.md) for the full eval\nguide including the negative-control fixture and how to update the baseline.\n\n### Workspace READMEs\n\n- [`packages/extension/README.md`](packages/extension/README.md) — options page, quiz modal, monadyssey usage, WCAG commitments.\n- [`packages/evals/README.md`](packages/evals/README.md) — promptfoo eval suite, fixtures, how to run and interpret results.\n\n---\n\n## Contributing\n\nThe canonical contribution flow uses the four-agent pipeline (PM → Architect →\nDev → Reviewer) described in [`CLAUDE.md`](./CLAUDE.md). See\n[`CONTRIBUTING.md`](./CONTRIBUTING.md) for a short orientation.\n\nFor bug reports and feature requests, open a GitHub issue. The PM agent will\ntriage and file the structured spec; the architect will write an ADR; the dev\nagent will implement; the reviewer agent will gate the PR before human review.\n\n---\n\n## Roadmap\n\nItems planned after v0.1.0:\n\n- **ADO multi-call diff adapter** — complete Azure DevOps support (the Approve button interception is already in; the diff adapter needs the multi-call ADO API).\n- **Quiz cancel wire frame** (#96) — `quiz-cancel-request` message so the host can abort the in-flight LLM fiber and stop billing tokens when the user closes the modal.\n- **OS keychain integration** — macOS Keychain and Linux SecretService for encrypted credential storage.\n- **Firefox MV3 port** — Firefox MV3 compatibility (the codebase is designed for it; no architectural changes needed).\n- **Dark mode** — extension UI currently follows the host page's color scheme; a first-class dark-mode pass is planned.\n- **i18n** — all user-facing strings are currently English-only.\n- **Chrome Web Store listing** — public listing once the extension reaches a stable UX.\n- **Safari port** — wrap the MV3 extension via the Xcode converter (locked decision: post-v1.0).\n\n---\n\n## License\n\nMIT — see [`LICENSE`](./LICENSE).\n\n---\n\n## Acknowledgments\n\n- [monadyssey](https://github.com/lean-mind/monodyssey) — the FP foundation (`IO`, `Either`, `Option`, `Schedule`) used across every non-extension workspace.\n- [WXT](https://wxt.dev) — the extension framework that handles the MV3 build, HMR, and cross-browser plumbing.\n- [promptfoo](https://promptfoo.dev) — the eval framework used to measure quiz quality across LLM adapters.\n- [httptape](https://github.com/tibtof/httptape) — HTTP fixture recording and replay used in adapter contract tests.\n- [Anthropic Claude](https://anthropic.com) — the LLM behind the Claude CLI and API adapters, and the agent pipeline that built this project.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftibtof%2Flgtm-buzzer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftibtof%2Flgtm-buzzer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftibtof%2Flgtm-buzzer/lists"}