Eslam HelmyEslam Helmy
9 min readEslam

Build Your Own Dev Agent — Lesson 6: Building Skills

This lesson introduces a pattern you will reuse: signal, query, prioritize, report. You build three skills that follow it -- a PR reviewer, a git reviewer, and a standup generator. The standup generator adds a second pattern: skill composition, where one skill's output becomes another skill's input through shared state files.


Where You Are

your-project/
  CLAUDE.md
  .claude/
    preferences.md
    tasks-active.md
    tasks-completed.md
    progress.txt
    error-log.md
    learnings.md
    priority-map.md
    cron-jobs.json                   # 1 job: daily-planner
    settings.json
    hooks/
      stop-telegram.sh
      permission-gate.sh
    skills/
      daily-planner/
        SKILL.md

See It: What the PR Reviewer Checks

The skill evaluates each open PR on five dimensions:

  • Size -- Lines changed > 500
  • Security -- Changes to auth, env, secrets, config
  • Tests -- No test files modified
  • Staleness -- Open for more than 3 days
  • Conflicts -- Merge conflict status

Each flag gets a severity: high (blocks merge), medium (needs attention), low (informational).


Build It: PR Reviewer Skill

Prerequisites:

  • The GitHub CLI (gh) must be installed and authenticated. Install it from https://cli.github.com/ and run gh auth login to authenticate before using this skill.
  • Create the .claude/reports/ directory for skill output files: mkdir -p .claude/reports

Intent: Create a skill that monitors GitHub repos for open PRs and produces a risk-flagged digest.

Prompt for Claude Code:

Create the directory .claude/skills/pr-reviewer/ and then create
.claude/skills/pr-reviewer/SKILL.md with this content:

# PR Review Agent Skill

Schedule: Configurable (default: every 4 hours during work hours)

## Input

Read before processing:
- .claude/preferences.md -- repos to monitor (look for GitHub repos list)
- .claude/priority-map.md -- priority rules for flagging

Configuration (add to preferences.md if not present):
- github_repos: list of owner/repo to monitor

## Process

1. **Query Open PRs**
   For each configured repo:
   - Use GitHub CLI (gh) to list open pull requests
   - Command: gh pr list --repo {owner/repo} --state open --json number,title,author,createdAt,additions,deletions,changedFiles,headRefName,baseRefName,mergeable,reviewDecision,labels
   - If gh is not available, note it and skip

2. **Analyze Each PR**
   For each open PR, evaluate:

   a. Size Check:
      - additions + deletions > 500 --> flag HIGH: "Large PR ({lines} lines)"
      - additions + deletions > 200 --> flag LOW: "Medium-sized PR"

   b. Security Check:
      - Get changed files: gh pr view {number} --repo {owner/repo} --json files
      - Flag HIGH if any file matches: .env, auth, secret, credential,
        security, permission, token, password, config/prod, middleware/auth
      - Flag: "Security-sensitive files modified: {file list}"

   c. Test Check:
      - Look for test/spec files in changed files
      - If code files changed but no test files --> flag MEDIUM:
        "No tests modified"

   d. Staleness Check:
      - Calculate days since creation
      - Open > stale_days threshold --> flag MEDIUM:
        "Stale PR (open {N} days)"
      - Open > stale_days * 2 --> flag HIGH:
        "Very stale PR (open {N} days)"

   e. Conflict Check:
      - If mergeable == "CONFLICTING" --> flag HIGH: "Merge conflicts"

   f. Review Status:
      - APPROVED --> note as ready to merge
      - CHANGES_REQUESTED --> note as needs work
      - No reviews --> flag LOW: "No reviews yet"

3. **Prioritize**
   Sort PRs by:
   - Number of HIGH flags (descending)
   - Number of MEDIUM flags (descending)
   - Days open (descending)

4. **Generate Report**
   Format as a digest:

   ## PR Review Digest -- [date]

   ### Needs Attention (HIGH flags)
   For each PR with HIGH flags:
   - PR #{number}: {title} by {author}
   - Flags: [list of HIGH and MEDIUM flags]
   - Link: {url}

   ### Monitor (MEDIUM flags only)
   For each PR with only MEDIUM flags:
   - PR #{number}: {title} by {author}
   - Flags: [list]

   ### On Track (no flags or LOW only)
   - PR #{number}: {title} -- {status}

   ### Summary
   - Total open PRs: {count}
   - Needs attention: {count}
   - Ready to merge: {count}
   - Average age: {days} days

## Output

Write the digest to .claude/reports/pr-review-[date].md

## State Update

- Append to progress.txt: "[timestamp] -- PR review: {total} open PRs,
  {high_count} need attention, {ready_count} ready to merge"
- If any PR has been flagged HIGH for 3+ consecutive runs, add a P1 task
  to tasks-active.md: "Review PR #{number} in {repo} -- consistently flagged"

Expected output: A complete PR reviewer skill file.


Build It: Add Repos to Preferences

Intent: Add GitHub repos to monitor in your preferences file.

Prompt for Claude Code:

Append the following section to .claude/preferences.md:

## GitHub Monitoring

Repos to monitor for PR reviews:
- owner/repo-name (replace with your actual repos)

Expected output: Updated preferences with repo configuration.


Build It: Add PR Reviewer Cron Entry

Intent: Schedule the PR reviewer.

Prompt for Claude Code:

Add a cron entry for the pr-reviewer skill to .claude/cron-jobs.json.
Schedule it 3x daily on weekdays (9 AM, 1 PM, 5 PM). Set expires to 7d.
Keep the existing daily-planner entry.

Expected output: cron-jobs.json with two entries.


Build It: Test the PR Reviewer

Intent: Run the skill manually to verify it works.

Prompt for Claude Code:

Run the pr-reviewer skill. Read .claude/skills/pr-reviewer/SKILL.md
and follow its instructions. Use one of my actual repos if configured
in preferences.md, or use a well-known public repo like cli/cli as a test.

Expected output: A PR review digest file and a progress.txt entry.


Skill 2: Git Reviewer

The git reviewer follows the same signal-query-prioritize-report pattern with a different data source. It monitors commits across your configured repos. For each commit, it explains three things: WHAT changed, WHY it changed, and the IMPACT on the system.

Intent: Create a skill that reviews recent commits and produces a categorized digest.

Prompt for Claude Code:

Create the directory .claude/skills/git-reviewer/ and then create
.claude/skills/git-reviewer/SKILL.md with this content:

# Git Reviewer Skill

Schedule: 12:00 PM daily (weekdays)

## Input

Read before processing:
- .claude/preferences.md -- repos to monitor
- .claude/priority-map.md -- priority rules

## Process

1. **Query Recent Commits**
   For each repo configured in preferences.md:
   - Use: gh api repos/{owner}/{repo}/commits --jq '.[0:20]'
   - Or use: git log --since="24 hours ago" --oneline for local repos
   - Collect: hash, author, message, date, files changed

2. **Analyze Each Commit**
   For each commit, determine:
   - WHAT: One-line summary of what changed
   - WHY: Reason from commit message body or linked issue
   - IMPACT: Categorize changed files (API, database, UI,
     infrastructure, tests, docs). Flag HIGH impact: migrations,
     auth changes, API breaking changes, dependency updates.

3. **Categorize**
   Group commits into: Features, Fixes, Refactors, Chores, Unknown

4. **Generate Digest**
   Format:

   ## Git Review -- [date]
   ### High Impact
   - {hash} by {author}: {WHAT} | WHY: {reason} | IMPACT: {areas}
   ### Features
   - {hash}: {summary}
   ### Fixes
   - {hash}: {summary}
   ### Summary
   - Total commits: {count} | Contributors: {list} | High impact: {count}

## Output

Write digest to progress.txt (appended)

## State Update

- Append summary to progress.txt
- If any commit touches database migrations with no tests, add a
  task to tasks-active.md

Rules:
- Do not overwrite existing files
- Only create what is missing
- List created files when done

Expected output: Git reviewer skill file created at .claude/skills/git-reviewer/SKILL.md.


Skill 3: Standup Generator

The standup generator demonstrates skill composition -- it reads data the agent already has (git commits from yesterday's reviewer, completed tasks, active tasks, and progress log) and composes a ready-to-paste standup. No skill calls another skill directly. They communicate through shared state files.

Intent: Create a skill that generates your daily standup by combining existing agent data.

Prompt for Claude Code:

Create the directory .claude/skills/standup-generator/ and then create
.claude/skills/standup-generator/SKILL.md with this content:

# Standup Generator Skill

Schedule: 8:30 AM daily (weekdays)

## Purpose

Generate a ready-to-paste daily standup message by combining data
the agent already has. No external API calls needed.

## Input

Read these files (all internal to the agent):
- .claude/tasks-completed.md -- what was done yesterday
- .claude/tasks-active.md -- what is planned today
- .claude/progress.txt -- recent action log entries (last 24h)
- Latest git review entry in progress.txt (from git-reviewer skill)

## Process

1. **Extract Yesterday's Work**
   From tasks-completed.md, find entries dated yesterday.
   From progress.txt, find entries from yesterday.
   Combine into a deduplicated list of accomplishments.

2. **Extract Today's Plan**
   From tasks-active.md, find tasks due today or marked as
   current priority. Group by priority level.

3. **Identify Blockers**
   Scan tasks-active.md for items tagged with [blocked] or
   past deadline. Scan progress.txt for entries containing
   "blocked", "waiting", "failed", or "stuck".

4. **Include Code Activity**
   If a git review ran yesterday, summarize:
   - Number of commits authored by the user
   - Key PRs merged or reviewed

5. **Generate Standup**
   Format (ready to paste into Slack/Teams):

   **Yesterday:**
   - {accomplishment 1}
   - {accomplishment 2}
   - {accomplishment 3}

   **Today:**
   - {planned task 1}
   - {planned task 2}

   **Blockers:**
   - {blocker or "None"}

   Keep it concise -- 3-5 bullets per section max.
   Use plain language, not internal file references.
   Write "Merged PR #{number}: {title}" not "completed task from
   tasks-completed.md"

## Output

Display the standup message in the terminal for copy-paste.
Optionally send via Telegram if configured.

## State Update

- Append to progress.txt: "[timestamp] -- Standup generated:
  {yesterday_count} done, {today_count} planned, {blocker_count}
  blockers"

## Why This Skill Matters

This demonstrates SKILL COMPOSITION:
- Git reviewer runs at noon --> writes to progress.txt
- Daily planner runs at 5:33 PM --> updates tasks
- Standup generator runs at 8:30 AM --> reads both outputs
- No skill calls another skill directly. They communicate
  through shared state files. This is the agent pattern.

Rules:
- Do not overwrite existing files
- Only create what is missing
- List created files when done

Expected output: Standup generator skill file created at .claude/skills/standup-generator/SKILL.md.


Build It: Add Cron Entries for All Three Skills

Intent: Schedule all three new skills.

Prompt for Claude Code:

Add three new entries to .claude/cron-jobs.json (keep the existing
daily-planner entry):

1. pr-reviewer: 3x daily weekdays (9 AM, 1 PM, 5 PM), expires 7d
2. git-reviewer: noon weekdays, expires 7d
3. standup-generator: 8:30 AM weekdays, expires 7d

The file should now have 4 jobs total.

Expected output: cron-jobs.json with four entries.


Checkpoint

Your .claude/ directory should now contain: skills/pr-reviewer/SKILL.md, skills/git-reviewer/SKILL.md, skills/standup-generator/SKILL.md, updated preferences.md with GitHub repos, and cron-jobs.json with 4 jobs (daily-planner, pr-reviewer, git-reviewer, standup-generator).


This is part of the Build Your Own Dev Agent course. ← Previous Lesson | Next Lesson →

Share this post