[TERMINAL · SKILLS]
> mounting /skills...
> indexing 295 manifests...
> linking agents: claude · codex · gemini · cursor
> ready.
[░░░░░░░░░░░░░░░░░░░░░░░░░░░░] 0%
Terminal.skills
Use Cases/Build an AI Code Review Bot for Pull Requests

Build an AI Code Review Bot for Pull Requests

Automate first-pass code reviews with an AI bot that catches bugs, security issues, and style violations — reducing review turnaround from 2 days to 15 minutes and letting senior engineers focus on architecture, not nitpicks.

#github-actions#cicd#automation#testing#deployment
Works with:claude-codeopenai-codexgemini-clicursor

Skills stack · 6 skills

Avg quality 95/100·All SAFE
>

typescript

v

Not yet scored
View skill
>

vercel-ai-sdk

v

Not yet scored
View skill
>

github-actions

v1.0.0

Build CI/CD pipelines with GitHub Actions — workflows, jobs, steps, triggers, caching, artifacts, matrix builds, secrets, environments, reusable workflows, and custom actions. Use when tasks involve automating tests, builds, deployments, code quality checks, or any GitHub-triggered automation.

93/100 quality
1.02× impact
SAFE
View skill
>

zod

v1.0.0

You are an expert in Zod, the TypeScript-first schema declaration and validation library. You help developers define schemas that validate data at runtime AND infer TypeScript types at compile time — eliminating the need to write types and validators separately. Used for API input validation, form validation, environment variables, config files, and any data boundary.

100/100 quality
1.21× impact
SAFE
View skill
>

hono

v1.0.0

You are an expert in Hono, the ultrafast web framework for the edge. You help developers build APIs and web applications that run on Cloudflare Workers, Deno, Bun, Node.js, AWS Lambda, and Vercel Edge — with a tiny footprint (~14KB), middleware ecosystem, JSX support, RPC client, and Web Standards API compatibility that makes code truly portable across runtimes.

93/100 quality
3.00× impact
SAFE
View skill
>

redis

v1.0.0

Build applications with Redis — caching, session storage, pub/sub, streams, rate limiting, leaderboards, and queues. Use when tasks involve in-memory data storage, real-time messaging, distributed locking, or performance optimization with caching layers.

93/100 quality
1.81× impact
SAFE
View skill
$

The Problem

A 30-person engineering team has a PR review bottleneck. Average review turnaround is 2 days — 3 senior engineers review 15-20 PRs each per week. 60% of review comments are mechanical: missing error handling, inconsistent naming, missing types, obvious security issues. Senior engineers are frustrated — they spend 10 hours/week on reviews instead of architecture work. Junior developers are blocked waiting. The team tried linting rules but they only catch formatting, not logic issues.

Step 1: Diff Parser and Context Builder

typescript
// src/review/diff-parser.ts
import { z } from 'zod';

const FileDiff = z.object({
  filename: z.string(),
  status: z.enum(['added', 'modified', 'removed', 'renamed']),
  additions: z.number().int(),
  deletions: z.number().int(),
  patch: z.string(),
  language: z.string(),
});

export function parsePRDiff(files: any[]): z.infer<typeof FileDiff>[] {
  return files
    .filter(f => f.patch) // skip binary files
    .map(f => ({
      filename: f.filename,
      status: f.status,
      additions: f.additions,
      deletions: f.deletions,
      patch: f.patch,
      language: detectLanguage(f.filename),
    }));
}

function detectLanguage(filename: string): string {
  const ext = filename.split('.').pop()?.toLowerCase();
  const langMap: Record<string, string> = {
    ts: 'typescript', tsx: 'typescript', js: 'javascript', jsx: 'javascript',
    py: 'python', go: 'go', rs: 'rust', java: 'java', rb: 'ruby',
    sql: 'sql', yml: 'yaml', yaml: 'yaml', json: 'json', md: 'markdown',
  };
  return langMap[ext ?? ''] ?? 'unknown';
}

// Build context for AI: surrounding code, not just the diff
export async function buildReviewContext(
  owner: string, repo: string, pr: number, token: string
): Promise<{ files: z.infer<typeof FileDiff>[]; prDescription: string; commitMessages: string[] }> {
  const headers = { Authorization: `token ${token}`, Accept: 'application/vnd.github.v3+json' };

  // Fetch PR details
  const prRes = await fetch(`https://api.github.com/repos/${owner}/${repo}/pulls/${pr}`, { headers });
  const prData = await prRes.json() as any;

  // Fetch files
  const filesRes = await fetch(`https://api.github.com/repos/${owner}/${repo}/pulls/${pr}/files?per_page=100`, { headers });
  const filesData = await filesRes.json() as any[];

  // Fetch commits
  const commitsRes = await fetch(`https://api.github.com/repos/${owner}/${repo}/pulls/${pr}/commits`, { headers });
  const commitsData = await commitsRes.json() as any[];

  return {
    files: parsePRDiff(filesData),
    prDescription: prData.body ?? '',
    commitMessages: commitsData.map((c: any) => c.commit.message),
  };
}

Step 2: AI Review Engine

typescript
// src/review/ai-reviewer.ts
import { generateObject } from 'ai';
import { openai } from '@ai-sdk/openai';
import { z } from 'zod';

const ReviewComment = z.object({
  file: z.string(),
  line: z.number().int().optional(),
  severity: z.enum(['critical', 'warning', 'suggestion', 'praise']),
  category: z.enum([
    'bug', 'security', 'performance', 'error-handling',
    'naming', 'types', 'testing', 'documentation', 'style', 'architecture',
  ]),
  comment: z.string(),
  suggestedFix: z.string().optional(),
});

const ReviewResult = z.object({
  summary: z.string(),
  overallRisk: z.enum(['low', 'medium', 'high']),
  comments: z.array(ReviewComment),
  approvalRecommendation: z.enum(['approve', 'request_changes', 'needs_discussion']),
});

export async function reviewCode(context: {
  files: Array<{ filename: string; patch: string; language: string }>;
  prDescription: string;
}): Promise<z.infer<typeof ReviewResult>> {
  const fileSummaries = context.files.map(f =>
    `### ${f.filename} (${f.language})\n\`\`\`diff\n${f.patch}\n\`\`\``
  ).join('\n\n');

  const { object } = await generateObject({
    model: openai('gpt-4o'),
    schema: ReviewResult,
    prompt: `You are a senior code reviewer. Review this pull request thoroughly.

PR Description: ${context.prDescription}

## Changed Files:
${fileSummaries}

Focus on:
1. **Bugs**: Logic errors, off-by-one, null/undefined issues, race conditions
2. **Security**: SQL injection, XSS, auth bypass, secret exposure, path traversal
3. **Error handling**: Missing try/catch, unhandled promises, silent failures
4. **Performance**: N+1 queries, unnecessary loops, missing indexes
5. **Types**: Missing or incorrect TypeScript types, unsafe casts
6. **Architecture**: SOLID violations, coupling issues, missing abstractions

Do NOT comment on:
- Formatting (handled by linters)
- Import order
- Trailing whitespace
- Minor style preferences

Be specific. Reference exact line numbers. Suggest fixes when possible.
For good code, add a "praise" comment — reinforce good practices.`,
  });

  return object;
}

Step 3: GitHub Integration

typescript
// src/github/post-review.ts
export async function postReview(
  owner: string,
  repo: string,
  pr: number,
  review: { summary: string; comments: any[]; approvalRecommendation: string },
  token: string
): Promise<void> {
  const headers = {
    Authorization: `token ${token}`,
    Accept: 'application/vnd.github.v3+json',
    'Content-Type': 'application/json',
  };

  // Map severity to emoji
  const emoji: Record<string, string> = {
    critical: '🚨', warning: '⚠️', suggestion: '💡', praise: '✨',
  };

  // Create review with inline comments
  const githubComments = review.comments
    .filter(c => c.line) // only comments with line numbers
    .map(c => ({
      path: c.file,
      line: c.line,
      body: `${emoji[c.severity]} **${c.category}** (${c.severity})\n\n${c.comment}${
        c.suggestedFix ? `\n\n**Suggested fix:**\n\`\`\`suggestion\n${c.suggestedFix}\n\`\`\`` : ''
      }`,
    }));

  const event = review.approvalRecommendation === 'approve' ? 'APPROVE'
    : review.approvalRecommendation === 'request_changes' ? 'REQUEST_CHANGES'
    : 'COMMENT';

  // Post the review
  await fetch(`https://api.github.com/repos/${owner}/${repo}/pulls/${pr}/reviews`, {
    method: 'POST',
    headers,
    body: JSON.stringify({
      body: `## 🤖 AI Code Review\n\n${review.summary}\n\n---\n*Risk level: ${review.approvalRecommendation}*`,
      event,
      comments: githubComments,
    }),
  });
}

Step 4: GitHub Actions Workflow

yaml
# .github/workflows/ai-review.yml
name: AI Code Review
on:
  pull_request:
    types: [opened, synchronize]

jobs:
  review:
    runs-on: ubuntu-latest
    permissions:
      pull-requests: write
      contents: read
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: 22 }
      - run: npm ci && npm run build
      - name: Run AI Review
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
        run: |
          node dist/cli.js review \
            --owner ${{ github.repository_owner }} \
            --repo ${{ github.event.repository.name }} \
            --pr ${{ github.event.pull_request.number }}

Results

  • Review turnaround: 15 minutes average (was 2 days)
  • Senior engineer time: 3 hours/week on reviews (was 10 hours) — freed 7 hours for architecture
  • Bugs caught pre-merge: 40% more issues caught vs human-only review
  • Security findings: 6 critical vulnerabilities caught in first month (SQL injection, exposed secrets)
  • False positive rate: 8% — tuned prompts to reduce noise
  • Developer satisfaction: 92% approval in team survey — juniors unblocked, seniors less fatigued
  • AI cost: ~$200/month for 300 PRs — 100x cheaper than the engineer time saved