Taylor Eernisse 8fb890c528 feat(cli): Implement complete command-line interface
Provides a user-friendly CLI for all GitLab Inbox operations.

src/cli/mod.rs - Clap command definitions:
- Global --config flag for alternate config path
- Subcommands: init, auth-test, doctor, version, backup, reset,
  migrate, sync-status, ingest, list, count, show
- Ingest supports --type (issues/merge_requests), --project filter,
  --force lock override, --full resync
- List supports rich filtering: --state, --author, --assignee,
  --label, --milestone, --since, --due-before, --has-due-date
- List supports --sort (updated/created/iid), --order (asc/desc)
- List supports --open to launch browser, --json for scripting

src/cli/commands/ - Command implementations:

init.rs: Interactive configuration wizard
- Prompts for GitLab URL, token env var, projects to track
- Creates config file and initializes database
- Supports --force overwrite and --non-interactive mode

auth_test.rs: Verify GitLab authentication
- Calls /api/v4/user to validate token
- Displays username and GitLab instance URL

doctor.rs: Environment health check
- Validates config file exists and parses correctly
- Checks database connectivity and migration state
- Verifies GitLab authentication
- Reports token environment variable status
- Supports --json output for CI integration

ingest.rs: Data synchronization from GitLab
- Acquires sync lock with stale detection
- Shows progress bars for issues and discussions
- Reports sync statistics on completion
- Supports --full flag to reset cursors and refetch all data

list.rs: Query local database
- Formatted table output with comfy-table
- Filters build dynamic SQL with parameterized queries
- Username filters normalize @ prefix automatically
- --open flag uses 'open' crate for cross-platform browser launch
- --json outputs array of issue objects

show.rs: Detailed entity view
- Displays issue metadata in structured format
- Shows full description with markdown
- Lists labels, assignees, milestone
- Shows discussion threads with notes

count.rs: Entity statistics
- Counts issues, discussions, or notes
- Supports --type filter for discussions/notes

sync_status.rs: Display sync watermarks
- Shows last sync time per project
- Displays cursor positions for debugging

src/main.rs - Application entry point:
- Initializes tracing subscriber with env-filter
- Parses CLI arguments via clap
- Dispatches to appropriate command handler
- Consistent error formatting for all failure modes

src/lib.rs - Library entry point:
- Exports cli, core, gitlab, ingestion modules
- Re-exports Config, GiError, Result for convenience

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-26 11:28:52 -05:00
2026-01-20 13:11:40 -05:00
2026-01-21 15:56:11 -05:00
2026-01-21 15:56:11 -05:00
2026-01-21 15:56:11 -05:00

gi - GitLab Inbox

A command-line tool for managing GitLab issues locally. Syncs issues, discussions, and notes from GitLab to a local SQLite database for fast, offline-capable querying and filtering.

Features

  • Local-first: All data stored in SQLite for instant queries
  • Incremental sync: Cursor-based sync only fetches changes since last sync
  • Multi-project: Track issues across multiple GitLab projects
  • Rich filtering: Filter by state, author, assignee, labels, milestone, due date
  • Raw payload storage: Preserves original GitLab API responses for debugging

Installation

cargo install --path .

Or build from source:

cargo build --release
./target/release/gi --help

Quick Start

# Initialize configuration (interactive)
gi init

# Verify authentication
gi auth-test

# Sync issues from GitLab
gi ingest --type issues

# List recent issues
gi list issues --limit 10

# Show issue details
gi show issue 123 --project group/repo

Configuration

Configuration is stored in ~/.config/gi/config.json (or $XDG_CONFIG_HOME/gi/config.json).

Example Configuration

{
  "gitlab": {
    "baseUrl": "https://gitlab.com",
    "tokenEnvVar": "GITLAB_TOKEN"
  },
  "projects": [
    { "path": "group/project" },
    { "path": "other-group/other-project" }
  ],
  "sync": {
    "backfillDays": 14,
    "staleLockMinutes": 10
  },
  "storage": {
    "compressRawPayloads": true
  }
}

Configuration Options

Section Field Default Description
gitlab baseUrl GitLab instance URL (required)
gitlab tokenEnvVar GITLAB_TOKEN Environment variable containing API token
projects path Project path (e.g., group/project)
sync backfillDays 14 Days to backfill on initial sync
sync staleLockMinutes 10 Minutes before sync lock considered stale
sync cursorRewindSeconds 2 Seconds to rewind cursor for overlap safety
storage dbPath ~/.local/share/gi/gi.db Database file path
storage compressRawPayloads true Compress stored API responses

GitLab Token

Create a personal access token with read_api scope:

  1. Go to GitLab → Settings → Access Tokens
  2. Create token with read_api scope
  3. Export it: export GITLAB_TOKEN=glpat-xxxxxxxxxxxx

Commands

gi init

Initialize configuration and database interactively.

gi init                    # Interactive setup
gi init --force            # Overwrite existing config
gi init --non-interactive  # Fail if prompts needed

gi auth-test

Verify GitLab authentication is working.

gi auth-test
# Authenticated as @username (Full Name)
# GitLab: https://gitlab.com

gi doctor

Check environment health and configuration.

gi doctor          # Human-readable output
gi doctor --json   # JSON output for scripting

gi ingest

Sync data from GitLab to local database.

gi ingest --type issues                    # Sync all projects
gi ingest --type issues --project group/repo  # Single project
gi ingest --type issues --force            # Override stale lock

gi list issues

Query issues from local database.

gi list issues                              # Recent issues (default 50)
gi list issues --limit 100                  # More results
gi list issues --state opened               # Only open issues
gi list issues --state closed               # Only closed issues
gi list issues --author username            # By author
gi list issues --assignee username          # By assignee
gi list issues --label bug                  # By label (AND logic)
gi list issues --label bug --label urgent   # Multiple labels
gi list issues --milestone "v1.0"           # By milestone title
gi list issues --since 7d                   # Updated in last 7 days
gi list issues --since 2w                   # Updated in last 2 weeks
gi list issues --since 2024-01-01           # Updated since date
gi list issues --due-before 2024-12-31      # Due before date
gi list issues --has-due-date               # Only issues with due dates
gi list issues --project group/repo         # Filter by project
gi list issues --sort created --order asc   # Sort options
gi list issues --open                       # Open first result in browser
gi list issues --json                       # JSON output

gi show issue

Display detailed issue information.

gi show issue 123                      # Show issue #123
gi show issue 123 --project group/repo # Disambiguate if needed

gi count

Count entities in local database.

gi count issues                    # Total issues
gi count discussions               # Total discussions
gi count discussions --type issue  # Issue discussions only
gi count notes                     # Total notes

gi sync-status

Show current sync state and watermarks.

gi sync-status

gi migrate

Run pending database migrations.

gi migrate

gi version

Show version information.

gi version

Database Schema

Data is stored in SQLite with the following main tables:

  • projects: Tracked GitLab projects
  • issues: Issue metadata (title, state, author, assignee info, due date, milestone)
  • milestones: Project milestones with state and due dates
  • issue_assignees: Many-to-many issue-assignee relationships
  • labels: Project labels with colors
  • issue_labels: Many-to-many issue-label relationships
  • discussions: Issue/MR discussions
  • notes: Individual notes within discussions
  • raw_payloads: Compressed original API responses

The database is stored at ~/.local/share/gi/gi.db by default.

Global Options

gi --config /path/to/config.json <command>  # Use alternate config

Development

# Run tests
cargo test

# Run with debug logging
RUST_LOG=gi=debug gi list issues

# Check formatting
cargo fmt --check

# Lint
cargo clippy

Tech Stack

  • Rust (2024 edition)
  • SQLite via rusqlite (bundled)
  • clap for CLI parsing
  • reqwest for HTTP
  • tokio for async runtime
  • serde for serialization
  • tracing for logging

License

MIT

Description
No description provided
Readme 42 MiB
Languages
Rust 100%