Install
Docker Compose (recommended)
Section titled “Docker Compose (recommended)”You need Docker with Compose v2, a GitHub account, and a Claude Pro, Max, Team or Enterprise plan for anyone who will run reviews.
git clone https://github.com/Wimukti/reviewstage && cd reviewstagecp .env.example .envdocker compose up -dOpen http://localhost:8899. The first visit is the login page.
Before you sign in, run the doctor. It checks Docker, the .env, that the reviewstage service is healthy, and that the container can reach GitHub:
bin/doctor.shWhat to put in .env
Section titled “What to put in .env”Only two values are required to start:
| Key | What |
|---|---|
REPO | owner/name of the repository to review. |
GITHUB_PAT | A service token used for reads only: listing review requests and cloning the base repo. A fine-grained PAT with Contents: read, Pull requests: read, Metadata: read on that repository is enough. It never posts or approves. |
Everything else has a sensible default. DRY_RUN=1 ships on by default: the dashboard works end to end but refuses to write to GitHub until you flip it. See Configuration for every knob.
Profiles
Section titled “Profiles”docker compose --profile team up -d # adds the review-request poller + Slack cardsdocker compose up -d demo # seeds sample runs so you can explore the UIteam is what you want for a shared server; see Team mode. demo is for looking around before wiring anything.
The first sign-in
Section titled “The first sign-in”- Open http://localhost:8899. With GitHub sign-in configured the page shows Continue with GitHub; without it, a token form. For a solo install the token form is fine: Create a fine-grained token opens GitHub’s fine-grained token page — pick the repositories you review and grant Pull requests: Read and write, Contents: Read and Metadata: Read (a classic token with the
reposcope also works). Pick an expiry (90 days is a good default). This token acts as you; it is what makes every comment attributable to a person. - Paste the token. It is verified against GitHub, stored encrypted, and used only for the posts and approvals you click.
- On the welcome checklist, Connect Claude: a link opens Claude in a new tab, you authorise with your own account and paste the code back. This runs the genuine
claude setup-tokenflow inside the container, so your reviews bill to your plan.
You are ready for your first review.
GitHub sign-in
Section titled “GitHub sign-in”Optional for a solo Docker install; recommended for a team. With it, nobody creates or pastes a token: the login page’s one visible action is Continue with GitHub, and the token GitHub issues is stored encrypted and used exactly like a pasted PAT — for the comments and approvals that person clicks, under their own name. Teammates can still open Use a personal access token instead.
-
On github.com go to Settings → Developer settings → OAuth Apps → New OAuth App (or under your organisation’s settings if the app should belong to the org).
-
Fill in:
Field Value Application name ReviewStage(or your team’s name for it)Homepage URL your PUBLIC_URL, e.g.https://reviews.example.comAuthorization callback URL <PUBLIC_URL>/oauth/callback— exactEnable Device Flow off -
Register, then Generate a new client secret and copy both the Client ID and the secret (the secret is shown once).
-
Optional but recommended: in the app’s Optional features, turn on Expire user access tokens. Tokens then last eight hours and ReviewStage refreshes them itself.
-
In
.env:Terminal window GH_CLIENT_ID=<client id>GH_CLIENT_SECRET=<client secret>GH_OAUTH_SCOPES=reporepois the smallest classic scope that can comment on and approve a pull request in a private repository; OAuth Apps cannot request fine-grained permissions (see Security). Public repositories only?public_repois enough. -
Restart (
docker compose up -dagain, orsystemctl restart reviewstage). The login page now shows Continue with GitHub.
A GitHub App works with the same two .env keys (leave GH_OAUTH_SCOPES empty) and gives narrower, per-repository permissions in exchange for an org owner installing it. It is the roadmap default; see Configuration.
Install as an app
Section titled “Install as an app”The dashboard is a progressive web app. Once it is reachable over HTTPS (or on localhost), install it from the browser and it opens standalone, in the app’s own colours, from your home screen or dock:
- iPhone / iPad (Safari): Share → Add to Home Screen.
- Android (Chrome): the Install app prompt, or ⋮ → Add to Home screen.
- Desktop (Chrome / Edge): the install icon in the address bar.
It is the same app as the tab; the sign-in and Claude connection carry over. Offline, it shows a “needs a connection to your server” page rather than stale data, because everything lives on your server. Native store apps and push notifications are the next phase; see Mobile.
From source on a Linux server
Section titled “From source on a Linux server”Use this when you cannot run Docker, or want the dashboard behind your own web server. The pieces are a Python 3 server, a few bash scripts, the Claude Code CLI and the GitHub CLI. There is no build step for the backend; the dashboard UI is a prebuilt bundle.
Summary of what bin/bootstrap.sh does, so you know what to expect:
- Installs
ghandclaudeif missing. - Copies the scripts to
~/.reviewstage/bin/and creates~/.reviewstage/.env(chmod 600), adding only missing keys so re-running never overwrites your values. - Makes a blobless base clone of
REPOfor worktrees. - Installs the built-in review skill and seeds the editable team default.
- Writes and starts a systemd unit,
reviewstage.service, that binds the dashboard to127.0.0.1:8899. - Installs the cron entry for the poller (every 3 minutes).
Then:
sudo -iu <service-user> # the user the unit runs asclaude # sign Claude Code in as that user, interactively~/reviewstage/bin/bootstrap.sh # prompts for REPO and your GitHub login# paste GITHUB_PAT (and SLACK_WEBHOOK if wanted) into ~/.reviewstage/.env~/reviewstage/bin/bootstrap.sh # re-run to finish; safe at any pointcurl -s localhost:8899/health # -> okPut a TLS-terminating reverse proxy in front (Caddy is two lines) and read Security before turning DRY_RUN off. The server reads .env once at startup: restart it after any edit.
MIT licensed · Built on Claude Code