Repo Deck scans every repo you own across five quality axes — tests, CI, security, code quality, docs — surfaces what's missing, and opens pull requests that fix it. Self-hosted. Your tokens. Your code never leaves your server.
OAuth (one click) or drop a PAT into .env
for headless deploys. Repo Deck reads your repo list, branches and commits
via the GitHub API — never touches anything else.
Tests, CI/CD, security, code quality, docs — each scored 0–100, then weighted into an overall health number. Batched in groups of 10, streaming results back over NDJSON so you watch the portfolio update live.
For everything auto-fixable — missing workflows, dependabot, SECURITY.md, CODEOWNERS — Repo Deck generates the file, opens a branch, and ships a PR against your default. One item or all of them, your call.
Test directory present, pytest / vitest configured, a coverage report published from CI. Score scales with reported coverage and the breadth of test discovery.
Workflow files on push and PR, required status checks on default branch, dependency caching, pinned action versions. Green builds count more than the presence of YAML.
Dependabot enabled, no stale alerts, secret scanning on, SECURITY.md disclosure policy, no high-severity advisories outstanding for more than 14 days.
Linter and formatter configured, complexity under threshold, consistent style across the tree, pre-commit hooks present. Looks at config + reported violations, not vibes.
README beyond a one-liner, Quickstart and Configuration sections, LICENSE file, CONTRIBUTING when relevant, screenshots or a usage example. Real onboarding, not table-stakes.
Weighted average. Two failed checks or a score under 40 marks the repo critical; one fail or two warnings is needs work; otherwise ready.
The audit is the easy part. The hard part is doing 12 things across 22 repos on a Tuesday. Repo Deck generates the files, opens a single PR per repo, and waits for your review.
Repo Deck is a small Flask app — single Gunicorn worker, Jinja2 templates,
vanilla JS. It runs on Railway in minutes, or anywhere Python runs in seconds.
No third-party services. No analytics. No data sent anywhere but
api.github.com.
GITHUB_PAT on the server for headless / shared use.github_manager/qa_analyzer.py.No. Reads are read-only against the GitHub API. Writes only happen when you click Fix or Fix all, and they go out as pull requests against your default branch — never direct commits. You review every change before it merges.
Yes. With OAuth, Repo Deck inherits whatever access your user has. With a PAT, scope it to repo for full access or public_repo for public-only. Org repos require either an org-installed GitHub App or a member with org access.
Weighted average of the five sub-scores (each 0–100, currently equal-weighted at 0.20). Two failed checks or an overall under 40 marks the repo critical; one fail or two warnings is needs work; everything else is ready. All thresholds live in github_manager/qa_analyzer.py and are one-line changes.
Yes. Subclass QAAnalyzer or drop a function into the checks registry — Repo Deck calls each check with the scanned repo dict and expects a (score, status, recommendations) tuple back. Same shape, same dashboard, same auto-fix hooks.
Built in. The dashboard surfaces your remaining budget in the top bar; scans run batched (default 10 repos per batch) and back off automatically when you cross 30%. Caching is enabled by default with a per-endpoint TTL — clear it from the UI with Refresh.
No outbound calls except api.github.com. No analytics. The only data Repo Deck stores is a small SQLite cache for scan results — and it sits on your server, mounted on your volume.
Free. MIT-licensed. Built originally to QA Berta's own 130+ repo portfolio; we kept it tidy enough to ship. The only cost is the box you run it on — Railway's free tier handles a portfolio of a few hundred repos comfortably.
Five minutes to install. Three minutes to scan. Pull requests waiting by the time the coffee's ready.