Skip to content
/ cli Public

A modern, secure, and timezone-aware GitHub PR/issue analytics CLI toolπŸ™πŸ“Š

Notifications You must be signed in to change notification settings

octoreport/cli

Repository files navigation

@octoreport/cli

octoreport

A modern, secure, and timezone-aware GitHub PR/issue analytics CLI tool. It provides a clean, interactive command-line interface for retrieving, filtering, and analyzing pull request activity with flexible filtering and accurate participation tracking.

Features

πŸ”’ Secure Authentication: OAuth device flow for secure GitHub login without storing plaintext tokens

πŸ“Š Interactive CLI: User-friendly interface with prompts and rich output formatting

⏰ Participation Tracking: Accurately tracks user PR participation (reviews, comments, authored PRs)

🌏 Timezone-Aware: Built with Luxon for reliable date handling across timezones

⚑ Fast & Modern: TypeScript-based, modular, and designed for performance

πŸ§ͺ Test Coverage: Comprehensive test suites with Vitest

πŸ› οΈ Modular Design: Structured commands and features for maintainability and extensibility

πŸ” Token Management: Secure token storage via system keychain (keytar)

πŸ“‹ Multiple Output Formats: Supports table, JSON, and plain text formats

πŸ”“ Private Repository Support: Optional access to private repositories with --repo-scope private option

πŸ“– Read-Only Operations: Only reads repository data, never modifies or creates content

πŸ”„ Scope Consistency: Login and command execution must use matching repository scopes

Installation

npm install -g @octoreport/cli

Prerequisites

  • Node.js >= 18
  • npm or yarn
  • GitHub account
  • detect-secrets installed (required for contributors)

Quick Start

# Login to GitHub for public repositories (first time only)
octoreport login

# Or login with private repository access
octoreport login --repo-scope private

# Get comprehensive PR activity report (public repositories)
octoreport all

# Get report in JSON format
octoreport all --format json

# Access private repositories (must login with --repo-scope private first)
octoreport all --repo-scope private

⚠️ Important: The --repo-scope option used in commands must match the scope used during login. If you get a "Repository scope mismatch" error, log out and log in again with the desired scope.

Authentication

The CLI uses GitHub's OAuth device flow for secure authentication:

# Login for public repositories (default)
octoreport login

# Login for private repositories
octoreport login --repo-scope private

This will:

  1. Open a browser window for GitHub authentication
  2. Securely store your token in the system keychain
  3. Automatically handle token refresh and management

Repository Scope Management

⚠️ Critical: The repository scope used during login determines which repositories you can access. You must use the same scope when running commands.

# Example: Login with private scope
octoreport login --repo-scope private

# Then use the same scope in commands
octoreport all --repo-scope private

# If scopes don't match, you'll get an error:
# "Repository scope mismatch. Please log in again."

To switch scopes:

# 1. Logout
octoreport logout

# 2. Login with desired scope
octoreport login --repo-scope public  # or private

Required Scopes

The OAuth app requests different scopes based on your needs:

Default (--repo-scope public):

  • public_repo - Full access to public repositories (read/write)
  • read:user - Read user profile information

With --repo-scope private:

  • repo - Full repository access (public and private)
  • read:user - Read user profile information

⚠ Security Note: Both scopes grant read/write access to repositories, not just read-only access.

Commands

octoreport all

Get comprehensive PR activity report with both created and participated PRs.

# Basic usage (public repositories only)
octoreport all

# alias
octoreport a

# With custom format
octoreport all --format json
octoreport all --format table

# Access private repositories (requires login with --repo-scope private)
octoreport all --repo-scope private

# Combine options
octoreport all --repo-scope private --format json

Options:

  • --format <format> - Output format (table, json, general) [default: table]
  • --repo-scope <scope> - Repository access scope (public, private) [default: public]
    • Must match the scope used during login
    • Use public for public repositories only
    • Use private for both public and private repositories

Interactive Prompts:

  • Username (optional - uses authenticated user if skipped)
  • Repository (e.g., octoreport/cli)
  • Start date (YYYY-MM-DD)
  • End date (YYYY-MM-DD)
  • Target branch (optional - all branches if skipped)

Output:

  • User created PRs with detailed information
  • User participated PRs (reviews, comments)
  • Search criteria summary
  • Formatted tables or JSON data

Output Formats

Table Format (Default)

Displays data in beautifully formatted ASCII tables:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Number β”‚ Title              β”‚ Author     β”‚ Branch     β”‚ URL                                         β”‚ State  β”‚ Created At   β”‚ Merged At   β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ 123    β”‚ Add new feature    β”‚ octocat    β”‚ main       β”‚ https://github.com/.../pull/123             β”‚ MERGED β”‚ 2025-01-15   β”‚ 2025-01-16   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

JSON Format

Returns structured JSON data for programmatic use:

{
  "created": [
    {
      "number": 123,
      "title": "Add new feature",
      "url": "https://github.com/octoreport/core/pull/123",
      "author": "octocat",
      "targetBranch": "main",
      "state": "MERGED",
      "createdAt": "2025-01-15T10:30:00Z",
      "mergedAt": "2025-01-16T14:20:00Z"
    }
  ],
  "participated": [
    {
      "number": 125,
      "title": "Update documentation",
      "url": "https://github.com/octoreport/core/pull/125",
      "author": "other-user",
      "targetBranch": "main",
      "state": "OPEN",
      "reviewers": ["octocat"],
      "commenters": ["octocat"]
    }
  ]
}

General Format

Simple text output for quick viewing:

πŸ™πŸ“Š User Created PRs:
[
  {
    number: 123,
    title: "Add new feature",
    url: "https://github.com/octoreport/core/pull/123",
    ...
  }
]

πŸ™πŸ“Š User Participated PRs:
[
  {
    number: 125,
    title: "Update documentation",
    url: "https://github.com/octoreport/core/pull/125",
    ...
  }
]

Data Structure

The CLI returns the same data structure as the core library:

// @octoreport/core

interface PR {
  // Basic PR information (always available)
  number: number;
  title: string;
  url: string;
  createdAt: string;
  user: string | null;

  // Detailed information (may be null if API access is limited)
  targetBranch?: string;
  assignees?: string[];
  state?: 'OPEN' | 'CLOSED' | 'MERGED';
  merged?: boolean;
  isDraft?: boolean;
  mergeable?: 'MERGEABLE' | 'CONFLICTING' | 'UNKNOWN';
  labels?: string[] | null;
  author?: string | null;
  reviewers?: string[] | null;
  commenters?: string[] | null;
  reviewDecision?: 'CHANGES_REQUESTED' | 'APPROVED' | 'REVIEW_REQUIRED' | null;
  mergedAt?: string | null;
  requestedReviewers?: string[] | null;

  // Participation data
  reviews?: (ReviewsRaw | null)[] | null;
  comments?: CommentsRaw[] | null;
}

Architecture

The CLI is organized into modular components for better maintainability:

src/
β”œβ”€β”€ commands/           # Command definitions and handlers
β”‚   β”œβ”€β”€ all/           # All command implementation
β”‚   β”œβ”€β”€ index.ts       # Command registration
β”‚   └── withCommandContext.ts # Command context wrapper
β”œβ”€β”€ config/            # Configuration and setup
β”‚   β”œβ”€β”€ commander.ts   # Commander.js setup
β”‚   └── packageInfo.ts # Package information
β”œβ”€β”€ features/          # Feature modules
β”‚   β”œβ”€β”€ auth/          # Authentication and token management
β”‚   β”œβ”€β”€ prompts/       # Interactive prompts
β”‚   └── ui/            # UI components and formatting
└── index.ts           # Main entry point

Security

Repository Access Control

The CLI implements a security-first approach to repository access:

Default Behavior (Recommended):

  • Requests public_repo scope by default
  • Provides read/write access to public repositories only
  • Includes access to public repository settings and webhooks
  • Minimizes security exposure for most use cases

Private Repository Access:

  • Use --repo-scope private to enable private repository access
  • Requests repo scope which provides full repository access
  • Includes access to organization resources and team memberships
  • Requires re-authentication when switching between public/private access
  • Clearly indicates access level in the output

Scope Consistency Requirement:

  • ⚠️ The --repo-scope used in commands must match the scope used during login
  • Different scopes are stored separately in the system keychain
  • Switching scopes requires logout and re-login
  • Attempting to use mismatched scopes will result in: Repository scope mismatch. Please log in again.

Security Notice: Both scopes grant read/write access, not just read-only access.

What this tool actually does:

  • Reads PR activity data from repositories
  • Generates reports and analytics
  • Does NOT create, modify, or delete any repository content
  • Does NOT make any changes to your repositories
  • Token is securely stored in your OS keychain

Token Storage

  • Tokens are securely stored using the system keychain (keytar)
  • No tokens are stored in plain text or configuration files
  • Automatic token refresh and validation
  • Different tokens for different access levels

OAuth Flow

  • Uses GitHub's OAuth device flow for secure authentication
  • No need to manually create or manage personal access tokens
  • Automatic scope management and validation
  • Clear indication of requested permissions during authentication

Development

Setup

# Clone the repository
git clone https://github.com/octoreport/cli.git
cd cli

# Install dependencies
npm install

# Run tests
npm test

# Build the CLI
npm run build

# Link for local development
npm link

Available Scripts

npm run build         # Build the CLI
npm test              # Run tests
npm run dev:test      # Run tests in watch mode
npm run lint          # Run ESLint
npm run lint:fix      # Fix ESLint issues
npm run format        # Format code with Prettier
npm run format:check  # Check code formatting

Testing

# Run all tests
npm test

# Run tests in watch mode
npm run dev:test

# Run specific test file
npm test -- tests/index.test.ts

Contributing

We welcome contributions! πŸ‘πŸ»

Please read our Contributing Guidelines before submitting any changes. The guidelines include:

  • Security Setup: Required detect-secrets configuration to prevent token leaks
  • Development Workflow: Branching, testing, and PR process
  • Code Style: TypeScript guidelines and quality standards

Quick Start for Contributors

# Clone the repository
git clone https://github.com/octoreport/cli.git
cd cli

# Install dependencies
npm install

# Install detect-secrets (via pipx recommended)
brew install pipx
pipx install detect-secrets

# Ensure baseline file exists
ls .secrets.baseline

# Run an initial scan (if baseline needs update)
detect-secrets scan \
  --exclude-files 'node_modules/.*' \
  --exclude-files '.*package-lock\.json' \
  --exclude-files '.*yarn\.lock' \
  > .secrets.baseline
git add .secrets.baseline
git commit -m "chore(security): update detect-secrets baseline"

⚠️ Important: This project handles GitHub API tokens, so detect-secrets setup is mandatory. The pre-commit hook will block commits containing new secrets. The CI pipeline will re-scan on every PR and push to main.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Acknowledgements

About

A modern, secure, and timezone-aware GitHub PR/issue analytics CLI toolπŸ™πŸ“Š

Topics

Resources

Contributing

Stars

Watchers

Forks

Packages

No packages published