Fetch, search, and retrieve GitHub issues — exported as LLM-friendly markdown, JSON, or compact agent format.
- Search issues by keyword using GitHub's Search API with full query syntax support
- Fetch single issues by number with all comments included
- Bulk fetch issues from any repo with date, state, and label filters
- Watch mode — daemon that polls for new issues and comments on an interval
- Three output formats — markdown, JSON, and a compact agent format optimised for LLM context windows
- Flexible output — stdout, file, or custom path; pipe-friendly with
--quiet - Auth-aware — works unauthenticated (60 req/hr) or with a token (5,000 req/hr)
git clone https://github.com/owenob1/IssueMonitor-Python.git
cd IssueMonitor-Python
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
# Search for issues matching a keyword
python -m issue_monitor --search "ECONNRESET timeout" --repo anthropics/claude-code
# Fetch a specific issue by number
python -m issue_monitor --issue 12345 --repo anthropics/claude-code
# Bulk fetch last 7 days (default)
python -m issue_monitorOptionally copy .env.example to .env and add your GitHub token for higher rate limits (5,000 vs 60 requests/hour).
- Python 3.10+
- Dependencies: PyGithub, rich, python-dateutil, python-dotenv
git clone https://github.com/owenob1/IssueMonitor-Python.git
cd IssueMonitor-Python
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt| Method | Rate Limit |
|---|---|
| Unauthenticated | 60 requests/hour |
With GITHUB_TOKEN |
5,000 requests/hour |
Token resolution order: --token flag > GITHUB_TOKEN env var > .env file > unauthenticated.
To set up a token:
- Go to GitHub Settings > Personal Access Tokens
- Generate a token with
public_reposcope (orrepofor private repos) - Provide it via one of:
# .env file (recommended)
cp .env.example .env
# Edit .env and set GITHUB_TOKEN=ghp_xxx
# Environment variable
export GITHUB_TOKEN=ghp_xxx
# CLI flag
python -m issue_monitor --token ghp_xxxSearch issues by keyword using the GitHub Search API. Results are ranked by relevance. Defaults to --format agent --stdout.
# Basic search
python -m issue_monitor --search "rate limit" --repo anthropics/claude-code
# Limit results
python -m issue_monitor --search "crash" --repo vercel/next.js --limit 10
# Filter by state
python -m issue_monitor --search "memory leak" --repo facebook/react --state open
# Filter by label
python -m issue_monitor --search "timeout" --repo anthropics/claude-code --label bug
# Output as markdown instead
python -m issue_monitor --search "auth error" --repo anthropics/claude-code --format markdownThe query is passed directly to the GitHub Search API. You can use any GitHub search qualifiers:
# Exact phrase
python -m issue_monitor --search '"connection reset"' --repo anthropics/claude-code
# Author filter
python -m issue_monitor --search "author:username bug" --repo anthropics/claude-code
# Date range (via GitHub syntax)
python -m issue_monitor --search "created:>2026-01-01 crash" --repo anthropics/claude-codeFetch a single issue by number with all comments. Defaults to --format agent --stdout. Returns an error if the number refers to a pull request.
python -m issue_monitor --issue 12345 --repo anthropics/claude-code
# Output as markdown
python -m issue_monitor --issue 12345 --repo anthropics/claude-code --format markdownFetch all issues from a time range. This is the default mode when neither --search nor --issue is specified. Defaults to --format markdown with file output.
# Target a repository
python -m issue_monitor --repo vercel/next.js
python -m issue_monitor --repo facebook/react
# Private repos require a token
python -m issue_monitor --repo myorg/private-repo --token ghp_xxx
# Date filtering
python -m issue_monitor --days 14
python -m issue_monitor --since 2026-01-01
# State and label filters
python -m issue_monitor --state open
python -m issue_monitor --label bug
python -m issue_monitor --label "bug,critical"Poll continuously for new issues and comments:
# Poll every 15 minutes (default)
python -m issue_monitor --watch
# Custom interval (30 minutes)
python -m issue_monitor --watch --interval 1800
# Run in background
nohup python -m issue_monitor --watch --quiet > monitor.log 2>&1 &Behaviour:
- First run fetches the last
--daysof issues - Subsequent polls fetch only issues updated since the last poll
- State is persisted to
output/.state.json(survives restarts) - Each poll writes to
output/issues-latest.{md,json} - Daily snapshots are saved as
output/issues-YYYY-MM-DD.{md,json} - Handles rate limits automatically (waits for reset)
- Shuts down cleanly on SIGINT/SIGTERM
| Format | Description | Best for |
|---|---|---|
agent |
Compact markdown with truncated bodies (~500 chars) and latest comment preview (~200 chars) | LLM context windows, AI agents |
json |
Full structured data with all fields | Programmatic processing, piping to jq |
markdown |
Full readable markdown with complete bodies and all comments | Human reading, reports, file output |
Auto-defaults by mode:
| Mode | Default format | Default output |
|---|---|---|
--search |
agent |
stdout |
--issue |
agent |
stdout |
| Bulk fetch | markdown |
file |
Override any default with --format and --stdout/--output.
# stdout (default for search/issue modes)
python -m issue_monitor --search "error" --repo owner/repo
# File output (default for bulk fetch)
python -m issue_monitor
# Custom output path
python -m issue_monitor --output /path/to/issues.md
# Force stdout for bulk fetch
python -m issue_monitor --stdout
# Pipe JSON through jq
python -m issue_monitor --format json --stdout | jq '.issues | length'
# Suppress Rich progress output (logs still go to stderr)
python -m issue_monitor --quiet --stdout| Flag | Default | Description |
|---|---|---|
--repo |
anthropics/claude-code |
Target GitHub repository (owner/repo) |
--search |
-- | Search issues by keyword (GitHub Search API) |
--issue |
-- | Fetch a single issue by number |
--limit |
25 |
Max search results (1-100) |
--days |
7 |
Fetch issues from last N days (positive integer) |
--since |
-- | ISO 8601 date (alternative to --days) |
--state |
all |
Filter: open, closed, all |
--label |
-- | Comma-separated label filter |
--output |
output/issues-YYYY-MM-DD.md |
Output file path |
--stdout |
false |
Print to stdout instead of file |
--format |
markdown |
Output format: markdown, json, agent |
--token |
$GITHUB_TOKEN |
GitHub personal access token |
--quiet, -q |
false |
Suppress Rich progress output |
--watch |
false |
Daemon mode: poll for updates |
--interval |
900 |
Poll interval in seconds (positive integer) |
Mutual exclusivity:
--searchand--issuecannot be combined--searchand--watchcannot be combined--issueand--watchcannot be combined--issueand--days/--sincecannot be combined
Auto-defaults: --search and --issue default to --format agent --stdout unless explicitly overridden.
# Search for relevant issues, parse JSON output
result=$(python -m issue_monitor --search "connection timeout" --repo anthropics/claude-code --format json --quiet)
echo "$result" | jq '.issues[0].title'
# Get a specific issue for context
python -m issue_monitor --issue 456 --repo anthropics/claude-code --quiet# Daily at 6am
0 6 * * * cd /path/to/IssueMonitor-Python && .venv/bin/python -m issue_monitor --days 7 --quiet- name: Fetch recent issues
run: python -m issue_monitor --days 7 --format json --output issues.json
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}# Pipe markdown to an LLM tool
python -m issue_monitor --stdout | your-llm-tool process
# Filter JSON to bugs only
python -m issue_monitor --format json --stdout \
| jq '.issues[] | select(.labels | contains(["bug"]))'issue_monitor/
__init__.py # Package marker
__main__.py # python -m entry point
models.py # Dataclasses, constants
github.py # API interaction, search, concurrent comment fetching
formatting.py # Markdown/JSON output, file writing
watcher.py # Daemon mode, state persistence
cli.py # Argument parsing, main()
scripts/
fetch_issues.py # Backwards-compatible shim
output/ # Generated files (gitignored, created on demand)
403: rate limit exceeded
Add a GitHub token — see Authentication.
404 Not Found or 403 Forbidden
Ensure your token has repo scope and you have access to the repository.
ModuleNotFoundError: No module named 'github'
Activate the virtual environment and install dependencies:
source .venv/bin/activate
pip install -r requirements.txtMIT