Skip to content

aryen1101/PRHawk

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

44 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ¦… PRHawk

AI-powered GitHub Pull Request reviewer. Sign in, paste a PR URL, and get inline code comments, a quality score, and a merge recommendation β€” posted directly back to GitHub.

PRHawk also learns your team's coding conventions from merged PR history and applies them as additional review rules on every future review.

πŸ”— Live: frontend on Vercel (pr-hawk.vercel.app) Β· backend API on Render.


✨ Features

  • Account-based access β€” email/password sign-up & login (powered by better-auth, sessions stored in MongoDB). The dashboard is gated behind authentication.
  • Automated inline comments β€” bugs, security issues, performance regressions, style violations, and suggestions, pinned to the exact line.
  • Risk summary β€” overall quality score (0–100), highest-risk changes, and an approve / request_changes / comment merge decision.
  • Convention learning β€” analyses your repo's last 10 merged PRs and extracts team-specific rules that are applied on all future reviews.
  • Bring your own keys β€” users can supply their own GitHub token and OpenRouter key in the UI (Settings), so reviews run under their own identity and quota instead of the server's.
  • Graceful posting β€” if the GitHub token can't post the review (e.g. insufficient scope), the analysis is still returned to the UI with a clear warning instead of failing.
  • CLI mode β€” run reviews and convention learning from the terminal without the web server or auth.

🧱 Tech Stack

Layer Stack
Frontend React 19, Vite, React Router v7, better-auth React client, lucide-react
Backend Node + Express 5, TypeScript (run directly via tsx), Octokit, OpenAI SDK (Groq / OpenRouter), Zod
Auth & data better-auth (email/password) + MongoDB
Hosting Vercel (frontend) Β· Render (backend) Β· MongoDB Atlas

πŸ—‚οΈ Project Structure

PRHawk/
β”œβ”€β”€ backend/          # Express REST API + CLI (TypeScript)
β”‚   β”œβ”€β”€ src/
β”‚   β”‚   β”œβ”€β”€ index.ts           # Entry point: server or CLI; CORS + routes
β”‚   β”‚   β”œβ”€β”€ config.ts          # Environment-variable configuration
β”‚   β”‚   β”œβ”€β”€ types.ts           # Shared TypeScript types
β”‚   β”‚   β”œβ”€β”€ lib/
β”‚   β”‚   β”‚   └── auth.ts        # better-auth instance (email/password, cookies)
β”‚   β”‚   β”œβ”€β”€ db/
β”‚   β”‚   β”‚   └── index.ts       # MongoClient (used by better-auth)
β”‚   β”‚   β”œβ”€β”€ github/            # GitHub API integration (Octokit)
β”‚   β”‚   β”‚   β”œβ”€β”€ client.ts      # Octokit client factory (central or custom token)
β”‚   β”‚   β”‚   β”œβ”€β”€ diffParser.ts  # Parses unified diffs β†’ added line numbers
β”‚   β”‚   β”‚   β”œβ”€β”€ prService.ts   # Fetches PR metadata & file contents
β”‚   β”‚   β”‚   └── reviewPublishers.ts  # Posts reviews & comments to GitHub
β”‚   β”‚   β”œβ”€β”€ llm/
β”‚   β”‚   β”‚   └── groq.ts        # OpenAI-compatible client (Groq / OpenRouter)
β”‚   β”‚   β”œβ”€β”€ review/
β”‚   β”‚   β”‚   β”œβ”€β”€ prompts.ts     # System & user prompt builders
β”‚   β”‚   β”‚   β”œβ”€β”€ schema.ts      # Zod schemas for structured LLM output
β”‚   β”‚   β”‚   └── reviewer.ts    # Orchestrates the review pipeline
β”‚   β”‚   └── conventions/
β”‚   β”‚       β”œβ”€β”€ learner.ts     # Extracts team conventions from merged PRs
β”‚   β”‚       └── store.ts       # Reads/writes conventions/rules.json
β”‚   └── .env.example           # ← copy to backend/.env and fill in
└── frontend/         # React + Vite web UI
    └── src/
        β”œβ”€β”€ main.jsx           # Mounts <App/> inside <BrowserRouter>
        β”œβ”€β”€ App.jsx            # Routes: /login, /signup, protected dashboard
        β”œβ”€β”€ lib/
        β”‚   β”œβ”€β”€ api.js         # Wrappers around the backend REST API
        β”‚   β”œβ”€β”€ auth.js        # better-auth React client (authClient)
        β”‚   └── storageKeys.js # localStorage keys + per-session cleanup
        β”œβ”€β”€ hooks/
        β”‚   └── usePersistentState.js  # localStorage-backed React state
        β”œβ”€β”€ pages/
        β”‚   β”œβ”€β”€ LoginPage.jsx
        β”‚   └── SignupPage.jsx
        └── components/
            β”œβ”€β”€ AuthGuard.jsx  # Redirects to /login when no session
            β”œβ”€β”€ Header.jsx Β· ToastContainer.jsx
            β”œβ”€β”€ ReviewTab.jsx  + review/   # input, loader, summary, findings
            β”œβ”€β”€ RulesTab.jsx   + rules/    # toolbar, add/edit, learn panel
            └── OnboardingOverlay.jsx + onboarding/  # settings / custom keys

βš™οΈ Environment Setup

Backend β€” backend/.env

cp backend/.env.example backend/.env
Variable Required Description
OPENROUTER_API_KEY One of these two API key for OpenRouter. When set, OpenRouter is the LLM provider.
GROQ_API_KEY One of these two API key for Groq. Used when OPENROUTER_API_KEY is not set.
GITHUB_TOKEN βœ… Yes GitHub PAT used to fetch PRs and post reviews. Classic token with repo (private) or public_repo (public).
MONGODB_URL βœ… Yes MongoDB connection string for better-auth (users/sessions). The server fails to start if unset. e.g. mongodb+srv://…
BETTER_AUTH_SECRET βœ… Yes Secret used to sign sessions. Generate with openssl rand -base64 32.
BETTER_AUTH_URL βœ… Yes Public base URL of this backend (e.g. http://localhost:3000 locally, the Render URL in prod).
MODEL No Override the LLM model. Defaults to google/gemini-2.5-flash (OpenRouter) or llama-3.3-70b-versatile (Groq).
PORT No Port the Express server listens on. Defaults to 3000. (Render injects this β€” don't hardcode it there.)
APP_SECRET No Legacy x-access-key gate, predates better-auth. Leave empty.

Frontend β€” frontend/.env

cp frontend/.env.example frontend/.env   # optional for local dev
Variable Description
VITE_API_BASE_URL Base URL of the backend API. Leave empty for local dev (requests stay relative and use the Vite proxy β†’ localhost:3000). Set to the backend's public URL for production builds.

πŸš€ Running Locally

You'll need a MongoDB instance (local or Atlas free tier) for auth.

Backend

cd backend
npm install
npm start          # Express server at http://localhost:3000

Frontend (development)

cd frontend
npm install
npm run dev        # Vite dev server, proxies /api/* to :3000

Open http://localhost:5173, create an account, and you're in.

Production build

cd frontend && npm run build   # Outputs to frontend/dist/
cd ../backend && npm start     # Also serves frontend/dist as static files

A single backend process can serve both the API and the built frontend when they're co-located.


☁️ Deployment (Vercel + Render)

PRHawk is deployed as two services on different domains, so a few things are wired specifically for that:

Backend (Render)

  • Root Directory: backend Β· Build: npm install Β· Start: npm start (no compile step β€” tsx runs TypeScript directly).
  • Env vars: all the backend vars above, including MONGODB_URL, BETTER_AUTH_SECRET, and BETTER_AUTH_URL (= the Render URL). Don't set PORT.
  • In MongoDB Atlas, allow Render's network access (0.0.0.0/0 or Render's IPs).

Frontend (Vercel)

  • Root Directory: frontend Β· Build: npm run build Β· Output: dist.
  • Set VITE_API_BASE_URL to the Render backend URL (or commit it in frontend/.env.production).

Cross-domain auth β€” because the two run on different domains:

  • The backend's CORS allows the frontend origin and sends Access-Control-Allow-Credentials: true (allowed origins are listed in backend/src/index.ts; trusted origins in backend/src/lib/auth.ts).
  • Session cookies are issued with SameSite=None; Secure so the browser sends them cross-site. Browsers that block third-party cookies may still reject them β€” the most robust alternative is to put both behind one domain (a Vercel rewrite of /api/*, or sub-domains with crossSubDomainCookies).

πŸ–₯️ CLI Usage

Reviews and convention learning can run from the terminal without the web server or authentication.

cd backend

# Review a pull request
npm run review https://github.com/owner/repo/pull/123

# Learn conventions from a repository's merged PR history
npm run learn owner/repo
# or
npm run learn https://github.com/owner/repo

πŸ”„ How It Works

Authentication

  • The React app renders /login and /signup; every other route is wrapped in AuthGuard, which checks the better-auth session and redirects to /login when there isn't one.
  • Sign-up/sign-in call the backend's /api/auth/* routes (handled by better-auth), which store users and sessions in MongoDB and set a session cookie.
  • Per-user dashboard state (last review, active tab) lives in localStorage and is cleared on login/logout so it never leaks between accounts on a shared browser.

PR Review

  1. You paste a GitHub PR URL into the UI (or pass it to the CLI).
  2. The backend fetches the PR metadata and changed files via the GitHub API.
  3. Each file's unified diff is parsed to identify the exact added/modified line numbers.
  4. The full file content at the PR's head commit is fetched for context.
  5. Saved team conventions are loaded from conventions/rules.json.
  6. A structured prompt (diff, numbered file content, addable lines, conventions) is sent to the LLM.
  7. The LLM returns JSON (validated against a Zod schema) with inline comments and a risk summary.
  8. Comments referencing lines outside the "addable" set are discarded to prevent ghost comments.
  9. The review is posted to the PR as inline comments + a summary. If posting fails (token permissions), the analysis is still returned to the UI with a postWarning.

Convention Learning

  1. You provide a repository (owner/repo) in the UI or CLI.
  2. The backend fetches recent closed PRs and keeps the 10 most recently merged.
  3. Their diff patches are sent to the LLM.
  4. The LLM extracts recurring patterns β€” naming, error handling, testing expectations, etc. β€” as concrete rules with severity tags.
  5. Rules are saved to backend/conventions/rules.json and applied to all future reviews.

πŸ”‘ GitHub Token Notes

Use case Token
Review public repos Classic token with public_repo scope
Review private repos Classic token with repo scope (and access to the repo)
Review another account's repo That account's token; for private repos you must be a collaborator

⚠️ Fine-grained tokens are bound to a single resource owner and can only write to repos that owner controls β€” they cannot post reviews to a repo owned by a different account, even a public one. Use a classic token with public_repo/repo for cross-account reviews. Reviews are posted with event: "COMMENT", so reviewing your own PR works (GitHub only blocks self-approval).

About

πŸ¦… AI-powered GitHub PR reviewer β€” paste a pull request URL to get inline comments, a quality score, and a merge recommendation posted β–Ž back to GitHub. Learns each team's coding conventions from merged PR history. React + Express + better-auth.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors