Skip to main content

GitHub Tracker Plugin

The GitHub tracker plugin integrates with GitHub Issues, allowing Agent Orchestrator to manage tasks, track progress, and update issue state as agents work.

Overview

This plugin uses the GitHub CLI (gh) to interact with the GitHub Issues API. It provides full CRUD operations for issues and generates context-aware prompts for agents based on issue content.
The GitHub tracker plugin requires the GitHub CLI (gh) to be installed and authenticated.

Configuration

Configure the GitHub tracker plugin in your agent-orchestrator.yaml:
plugins:
  tracker:
    name: github

projects:
  - id: my-app
    repo: owner/repo-name  # GitHub repository in owner/repo format
    tracker:
      type: github

Configuration Options

The GitHub tracker plugin requires no additional configuration parameters. All settings are derived from the project’s repo field.
repo
string
required
GitHub repository in owner/repo format (e.g., octocat/hello-world).This is used for all GitHub API operations.

Requirements

Prerequisites:
  • GitHub CLI (gh) installed and in PATH
  • Authenticated with gh auth login
  • Read/write access to issues in the target repository

Installing GitHub CLI

# macOS
brew install gh

# Linux (Debian/Ubuntu)
sudo apt install gh

# Login
gh auth login

Verifying Authentication

# Check authentication status
gh auth status

# Test issue access
gh issue list --repo owner/repo-name --limit 5

Features

Issue Operations

Get Issue Fetch a single issue by number:
const issue = await tracker.getIssue("123", project);
// Returns: { id, title, description, url, state, labels, assignee }
List Issues List issues with filters:
const issues = await tracker.listIssues({
  state: "open",           // "open" | "closed" | "all"
  labels: ["bug", "p1"],  // Filter by labels
  assignee: "username",    // Filter by assignee
  limit: 30                // Max results (default: 30)
}, project);
Create Issue Create a new issue:
const issue = await tracker.createIssue({
  title: "Bug: App crashes on startup",
  description: "Steps to reproduce...\n\n## Expected\n...",
  labels: ["bug", "priority-high"],
  assignee: "username"
}, project);
Update Issue Update issue state, labels, or add comments:
await tracker.updateIssue("123", {
  state: "closed",              // "open" | "closed"
  labels: ["fixed"],           // Adds labels (additive)
  assignee: "reviewer",         // Change assignee
  comment: "Fixed in PR #456"  // Add comment
}, project);
State updates: GitHub Issues only supports open and closed states. Setting in_progress is a no-op (GitHub doesn’t have this state).

Issue State Mapping

GitHub Issue State → Tracker State:
GitHub StateState ReasonTracker State
OPEN-open
CLOSEDCOMPLETEDclosed
CLOSEDNOT_PLANNEDcancelled

Prompt Generation

The plugin generates context-aware prompts for agents:
const prompt = await tracker.generatePrompt("123", project);
Example output:
You are working on GitHub issue #123: Fix login redirect bug
Issue URL: https://github.com/owner/repo/issues/123

Labels: bug, authentication

## Description

Users are redirected to the wrong page after login...

Please implement the changes described in this issue. When done, commit and push your changes.

Branch Naming

The plugin generates branch names from issue numbers:
tracker.branchName("123", project);
// Returns: "feat/issue-123"

Issue URLs and Labels

// Generate URL from issue number
tracker.issueUrl("123", project);
// Returns: "https://github.com/owner/repo/issues/123"

// Extract label from URL
tracker.issueLabel("https://github.com/owner/repo/issues/123", project);
// Returns: "#123"

Usage Example

Start Agent on Issue

# agent-orchestrator.yaml
projects:
  - id: my-app
    repo: owner/my-app
    path: ~/repos/my-app
    defaultBranch: main
# Start agent on issue #123
ao start my-app "#123"

# The agent will:
# 1. Fetch issue details from GitHub
# 2. Create branch "feat/issue-123"
# 3. Generate prompt with issue context
# 4. Start coding to fix the issue

Auto-Update on PR Merge

# Configure reactions to close issues when PRs merge
reactions:
  - event: pr_merged
    action: close_issue
When a PR is merged, the orchestrator will automatically close the associated issue.

Troubleshooting

The GitHub CLI is not installed or not in PATH.Solution:
# macOS
brew install gh

# Linux
sudo apt install gh

# Verify
which gh
The GitHub CLI is not authenticated.Solution:
# Login interactively
gh auth login

# Check status
gh auth status
The repo field must be in owner/repo format.Example:
projects:
  - id: my-app
    repo: owner/repo-name  # ✓ Correct
    # repo: github.com/owner/repo  # ✗ Wrong
    # repo: repo-name              # ✗ Wrong
The authenticated GitHub account doesn’t have access to the repository or issues.Solutions:
  • Verify repository access: gh repo view owner/repo-name
  • Check issue permissions (requires write access for updates)
  • Re-authenticate: gh auth login --force
GitHub API requests have a 30-second timeout.Solutions:
  • Check network connectivity
  • Verify GitHub API status: https://www.githubstatus.com/
  • Increase timeout in plugin code if needed (requires source modification)
GitHub uses numeric issue numbers (e.g., 123), not alphanumeric identifiers.The plugin accepts:
  • "123" - Issue number as string
  • "#123" - With hash prefix (stripped automatically)
Invalid:
  • "ABC-123" - Not a GitHub issue format (use Linear for this)

API Reference

Tracker Interface Methods

getIssue(identifier, project)
  • Fetches issue details by number
  • Returns: Issue object with all fields
isCompleted(identifier, project)
  • Checks if issue is closed
  • Returns: boolean
issueUrl(identifier, project)
  • Generates GitHub issue URL
  • Returns: string
issueLabel(url, project)
  • Extracts issue number from URL
  • Returns: string (e.g., "#123")
branchName(identifier, project)
  • Generates branch name from issue number
  • Returns: string (e.g., "feat/issue-123")
generatePrompt(identifier, project)
  • Creates context prompt for agent
  • Returns: string (formatted prompt)
listIssues(filters, project)
  • Lists issues with optional filters
  • Returns: Issue[]
updateIssue(identifier, update, project)
  • Updates issue state/labels/assignee/comments
  • Returns: void
createIssue(input, project)
  • Creates a new issue
  • Returns: Issue (created issue)

Advanced Usage

Issue Filters

// Open bugs assigned to me
const bugs = await tracker.listIssues({
  state: "open",
  labels: ["bug"],
  assignee: "myusername",
  limit: 50
}, project);

// All closed issues (recent 100)
const closed = await tracker.listIssues({
  state: "closed",
  limit: 100
}, project);

// High-priority tasks
const priority = await tracker.listIssues({
  state: "open",
  labels: ["priority-high", "p1"]
}, project);

Label Management

Labels are additive: using updateIssue with labels adds them to existing labels, it doesn’t replace them.
// Add labels to an issue
await tracker.updateIssue("123", {
  labels: ["in-progress", "needs-review"]
}, project);

// Existing labels are preserved, new ones are added

Comment Workflow

// Post status update
await tracker.updateIssue("123", {
  comment: "🚀 Started working on this issue"
}, project);

// Post completion comment
await tracker.updateIssue("123", {
  state: "closed",
  comment: "✅ Fixed in PR #456\n\nTested locally and all checks pass."
}, project);

Integration with Other Plugins

With SCM Plugin

The tracker and SCM plugins work together for full issue-to-PR workflow:
  1. Tracker generates prompt from issue
  2. Agent writes code
  3. SCM creates PR and links it to the issue
  4. Reactions auto-close issue when PR merges
reactions:
  - event: pr_merged
    action: run
    command: |
      gh issue close $ISSUE_NUMBER --repo $REPO --comment "Fixed in PR #$PR_NUMBER"

With Workspace Plugin

The tracker provides the branch name for workspace creation:
const branchName = tracker.branchName(issueId, project);
// Used by workspace plugin to create branch "feat/issue-123"

Security Considerations

  • All GitHub API calls are made through the gh CLI (no direct token handling)
  • Commands are executed with execFile (not exec) to prevent shell injection
  • 30-second timeout prevents hanging on network issues
  • Repository format is validated before use

Source Code

Source: packages/plugins/tracker-github/src/index.ts

Build docs developers (and LLMs) love