Monitor GitHub issues, pull requests, and their comments through polling with GitHub's GraphQL API, and publish events to NATS JetStream for automated processing.
This tool's intent is to help manage and automate workflows around GitHub issues and PRs by integrating with Claude CLI for AI-driven automation.
You define a set of markdown templates that act as prompts for Claude CLI when specific events occur (e.g., new issue, updated PR, new comment). You can then either have Claude automatically respond to issues/PRs or use it to generate summaries, labels, or other metadata.
This tool provides a single command with three subcommands:
github-monitor monitor: Polls GitHub repositories for issues, PRs, and comments, publishing events to NATS JetStreamgithub-monitor event-handler: Consumes events from NATS and handles them (creates directories, invokes Claude CLI with templates, etc.)github-monitor pr-comment: Submit comments on GitHub Pull Requests (both general and line-specific review comments)
- Monitor multiple GitHub repositories for issues and pull requests
- Track comments on issues and PRs
- Publish events to NATS JetStream with retention policies
- Durable consumer support for reliable event processing
- Template-based event handling with Claude CLI integration
- Flexible monitoring modes (continuous or one-time)
- Dry-run mode for testing
- Filter issues/PRs by update timestamp
- Python 3.13+
- GitHub Personal Access Token (set via
GITHUB_TOKENenvironment variable) - NATS server with JetStream enabled
- Claude CLI (optional, for event handling)
# Using uv (recommended)
uv sync
# Install the package
uv pip install -e .Create a .env file in the project root with your GitHub token:
GITHUB_TOKEN=your_github_personal_access_token_hereAlternatively, export the token as an environment variable:
export GITHUB_TOKEN=your_github_personal_access_token_hereTo create a GitHub Personal Access Token:
- Go to GitHub Settings > Developer settings > Personal access tokens > Tokens (classic)
- Click "Generate new token"
- Select scopes:
repo(for private repositories) orpublic_repo(for public repositories only) - Copy the generated token
You can now use YAML configuration files to store your settings instead of passing command-line arguments each time. See CONFIG.md for detailed documentation.
Example configuration files are provided in the examples/ directory:
examples/config-monitor.yaml- For the monitor commandexamples/config-event-handler.yaml- For the event-handler commandexamples/config-pr-comment.yaml- For the pr-comment command
Usage:
# Use a configuration file
github-monitor monitor --config examples/config-monitor.yaml
# Override specific values from config
github-monitor monitor --config examples/config-monitor.yaml --dry-run --interval 10mCLI arguments always take precedence over configuration file values.
nats-server -js# Monitor specific repositories (runs once)
github-monitor monitor /path/to/data --repositories owner/repo1 owner/repo2
# Monitor with continuous polling every 5 minutes
github-monitor monitor /path/to/data --repositories owner/repo --interval 5m
# Monitor only issues/PRs updated since a specific time
github-monitor monitor /path/to/data --repositories owner/repo --updated-since 2024-01-01T00:00:00Z
# Dry run to see what would happen
github-monitor monitor /path/to/data --repositories owner/repo --dry-run# Start the event handler
github-monitor event-handler /path/to/data
# With custom templates directory
github-monitor event-handler /path/to/data --templates-dir /path/to/templates
# Skip events from users matching regex pattern
github-monitor event-handler /path/to/data --skip-users "^(dependabot|renovate)"
# Adjust AckWait timeout for very long Claude operations (default is 300 seconds)
github-monitor event-handler /path/to/data --ack-wait 600Monitor GitHub repositories and publish events to NATS.
Usage:
github-monitor monitor PATH [OPTIONS]Options:
--repositories: List of repositories to track (format:owner/repo). If not provided, uses existing directories--nats-server: NATS server URL (default:nats://localhost:4222)--dry-run: Show what would be done without making changes--updated-since: Filter issues/PRs updated since ISO8601 timestamp--monitor-issues: Monitor and publish events for issues and PRs (default: true)--monitor-issue-comments: Monitor comments on issues (default: true)--monitor-pr-comments: Monitor comments on PRs (default: true)--active-only: Only monitor issues/PRs with.activeflag (default: true)--interval: Run monitoring at this interval (format:5m,1h30m,2d). If not specified, runs once
Examples:
# Monitor two repositories every 10 minutes
github-monitor monitor ./data --repositories anthropics/claude anthropics/anthropic-sdk-python --interval 10m
# Monitor only new issues, not comments
github-monitor monitor ./data --repositories owner/repo --no-monitor-issue-comments --no-monitor-pr-comments
# Monitor all issues, not just active ones
github-monitor monitor ./data --repositories owner/repo --no-active-onlyHandle GitHub issue and PR events from NATS JetStream.
Usage:
github-monitor event-handler PATH [OPTIONS]Options:
--templates-dir: Templates directory containing markdown files for event handlers--nats-server: NATS server URL (default:nats://localhost:4222)--stream: JetStream stream name (default:GITHUB_EVENTS)--consumer: Durable consumer name (default:github-event-handler)--batch-size: Number of messages to fetch per batch (default: 10)--fetch-timeout: Timeout in seconds for fetching messages (default: 5.0)--ack-wait: AckWait timeout in seconds for message processing (default: 300)--skip-users: Regex pattern to match usernames to skip event handling for--recreate-consumer: Delete and recreate the consumer (useful for reprocessing all messages)--claude-verbose: Print raw Claude CLI output directly to stdout--auto-confirm: Automatically process events without confirmation (default: false)
Examples:
# Run with templates and auto-confirm
github-monitor event-handler ./data --templates-dir ./templates --auto-confirm
# Skip events from users matching regex pattern (e.g., bots)
github-monitor event-handler ./data --skip-users "^(dependabot|renovate)"
# Reprocess all events from the beginning
github-monitor event-handler ./data --recreate-consumerSubmit comments on GitHub Pull Requests.
Usage:
github-monitor pr-comment REPO PR_NUMBER [OPTIONS]Options:
--comment: Comment body text--file: File path for line comment (relative to repository root)--line: Line number for line comment--submit: Submit a review with event:approve,request_changes, orcomment(requires--fileand--line)--token: GitHub token (or use GITHUB_TOKEN env var)
Examples:
# Create a line comment on a specific file (creates pending review)
github-monitor pr-comment owner/repo 123 --file src/main.py --line 42 --comment "This needs refactoring"
# Create a general PR comment
github-monitor pr-comment owner/repo 123 --comment "Looks good to me!"
# Submit a review with approval on a specific line
github-monitor pr-comment owner/repo 123 --file src/main.py --line 42 --comment "LGTM" --submit approve
# Submit a review requesting changes on a specific line
github-monitor pr-comment owner/repo 123 --file src/main.py --line 42 --comment "Please fix" --submit request_changesNote: Make sure GITHUB_TOKEN is set in your environment or .env file, or pass via --token.
The tool organizes data in the following structure:
{base_path}/
└── {owner}/
└── {repo}/
└── {issue_or_pr_number}/
├── .active # Marks issue/PR as actively tracked
├── .type # "issue" or "pr"
├── .last_checked # Last monitoring timestamp
└── .last_comment_check # Last comment check (for both issues and PRs)
The system publishes the following event types to NATS:
github.issue.new: New open issue discoveredgithub.issue.updated: Active issue has been updatedgithub.issue.closed: Active issue has been closedgithub.pr.new: New open PR discoveredgithub.pr.updated: Active PR has been updatedgithub.pr.closed: Active PR has been closedgithub.issue.comment.new: New comment on an issuegithub.pr.comment.new: New comment on a PR
Templates allow you to define custom behavior when events are received. The event handler looks for templates in the following hierarchy:
{owner}/{repo}/{event_name}.md{owner}/.default/{event_name}.md.default/{event_name}.md
Template Variables:
Templates have access to the following variables:
REPOSITORY: Repository inowner/repoformatNUMBER: Issue or PR numberBASE_DIR: Base directory path
Example Template (templates/.default/github.issue.new.md):
A new issue has been created in repository {{REPOSITORY}}.
Issue number: {{NUMBER}}
Base directory: {{BASE_DIR}}
Please review the issue and create a .active file if you want to track it.Skipping Events:
To ignore specific events, create an empty template file. For example, to ignore new PR events for a specific repository:
touch templates/owner/repo/github.pr.new.md# Install with dev dependencies
uv sync# Run tests
uv run pytest
# Run with coverage
uv run pytest --cov=src/github_monitor# Format code
uv run ruff format
# Lint code
uv run ruff check
# Fix linting issues
uv run ruff check --fixThe system automatically creates a JetStream stream with the following configuration:
- Stream Name:
GITHUB_EVENTS - Subjects:
github.* - Retention: Limits-based (keeps messages for 7 days or up to 10k messages/100MB)
- Consumer: Durable consumer with explicit acknowledgment
See LICENSE for details.
Contributions are welcome! Please ensure you:
- Run tests before committing
- Run linter/formatter before committing
- Use type hints
- Create "green path" tests that cover main functionality