Taylor Eernisse 7aaa51f645 feat(core): Implement infrastructure layer for CLI operations
Establishes foundational modules that all other components depend on.

src/core/config.rs - Configuration management:
- JSON-based config file with Zod-like validation via serde
- GitLab settings: base URL, token environment variable
- Project list with paths to track
- Sync settings: backfill days, stale lock timeout, cursor rewind
- Storage settings: database path, payload compression toggle
- XDG-compliant config path resolution via dirs crate
- Loads GITLAB_TOKEN from configured environment variable

src/core/db.rs - Database connection and migrations:
- Opens or creates SQLite database with WAL mode for concurrency
- Embeds migration SQL as const strings (001-005)
- Runs migrations idempotently with checksum verification
- Provides thread-safe connection management

src/core/error.rs - Unified error handling:
- GiError enum with variants for all failure modes
- Config, Database, GitLab, Ingestion, Lock, IO, Parse errors
- thiserror derive for automatic Display/Error impls
- Result type alias for ergonomic error propagation

src/core/lock.rs - Distributed sync locking:
- File-based locks to prevent concurrent syncs
- Stale lock detection with configurable timeout
- Force override for recovery scenarios
- Lock file contains PID and timestamp for debugging

src/core/paths.rs - Path resolution:
- XDG Base Directory Specification compliance
- Config: ~/.config/gi/config.json
- Data: ~/.local/share/gi/gi.db
- Creates parent directories on first access

src/core/payloads.rs - Raw payload storage:
- Optional gzip compression for storage efficiency
- SHA-256 content addressing for deduplication
- Type-prefixed keys (issue:, discussion:, note:)
- Batch insert with UPSERT for idempotent ingestion

src/core/time.rs - Timestamp utilities:
- Relative time parsing (7d, 2w, 1m) for --since flag
- ISO 8601 date parsing for absolute dates
- Human-friendly relative time formatting

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-26 11:28:07 -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%