Skip to content

Repository files navigation

πŸš€ GitLab MR Tracker

CI Quality Gate Crates.io Version Crates.io Total Downloads License: MIT Built with Rust

GitLab MR Tracker is a fast, asynchronous Terminal User Interface (TUI) dashboard designed for engineering teams. It provides real-time verification of GitLab Merge Requests across target environment branches (main, preproduction, staging, etc.), handling strict SHA verification as well as cherry-picked commit identification.

gitlab-tracker demo

✨ Key Features

  • πŸ” OS Keyring Integration (Zero Plain-Text Secrets): Personal Access Tokens (PAT) can be securely stored directly in your OS secret manager (GNOME Keyring, KWallet, macOS Keychain, or Windows Credential Manager).

  • 🏷️ Dynamic Scoped Labels & Custom Chips:

    • Smart Filtering: Configure specific label prefixes (e.g., deploy::, review::) to display cleanly as colored chips in the main table grid, while keeping all attached tags visible in the side inspector panel.
    • Customizable Palette: Map label names or wildcard patterns (e.g., deploy::*) to custom terminal colors or standard HEX codes (#FF5733) via an XDG-compliant JSON config.
  • ⚑ High Performance & Asynchronous: Powered by tokio and reqwest, utilizing non-blocking event loops and bounded concurrent requests via semaphores to protect GitLab API rate limits.

  • πŸ›‘οΈ Pass-Through Pass Caching: Core MR metadata (author, milestone, assignee, description, labels) is fetched once and cached locally. Fully deployed MRs bypass network re-queries entirely ("Green Pass").

  • πŸ” Dual Match Verification Engine:

    • System 1 (Strict SHA): Validates precise merge/squash commit SHAs on target branches (resistant to git reset --hard).
    • System 2 (Intelligent Fuzzy Matcher): Uses a keyword relevance matrix to verify cherry-picked commits deployed across branches.
  • πŸ–₯️ Responsive Flexbox TUI Grid: Features a dynamic layout engine (Constraint::Fill) that seamlessly scales table columns and side panels from 1080p laptop displays to ultra-wide 4K monitors without empty trailing spaces.

  • πŸ”ƒ Smart Auto-Sorting by Last Update: The dashboard defaults to sorting MRs by updated_at (most recently pushed to remote first), automatically re-applied after each refresh. Cycle through sort columns (S) and toggle direction (Shift+S). The active sort is always visible in the table title bar.

  • 🌐 Browser Integration: Open any selected MR directly in your default browser with a single keypress (O).

  • πŸ”” Smart Desktop Notifications: Receives native OS desktop notifications only when an MR's branch status has changed since the last run β€” no duplicate alerts on restart or redundant refreshes.

  • ✨ Refresh Highlight: After each background refresh, any MR whose updated_at timestamp has changed since the previous cycle is briefly highlighted in the table with a green tint. The highlight fades out automatically after ~10 seconds.

  • πŸ“ XDG-Compliant Persistence: Saves tracked dashboard state, UI configurations, and last-known branch statuses automatically to platform-standard configuration paths using directories.

  • Customizable Refresh Interval: Tailor the background polling rate to your needs (defaults to 15 minutes / 900s) via config.json or the GITLAB_REFRESH_INTERVAL_SECS environment variable.

  • πŸ“Š Activity Badge: Each MR in the Context Inspector displays a color-coded activity badge based on its updated_at timestamp β€” 🟒 Active, 🟑 Slowing, or πŸ”΄ Stale. Thresholds are fully configurable via config.json or environment variables (ACTIVITY_RECENT_DAYS, ACTIVITY_STALE_DAYS).

  • πŸ’¬ Notes Indicator: The total number of comments and discussion threads (user_notes_count) is fetched from the GitLab API at no extra cost and displayed both in the optional Notes table column and in the Context Inspector. A yellow πŸ’¬ N badge signals that comments are awaiting attention; a dimmed βœ” No comments confirms there is nothing to address.

  • πŸ”€ Animated Mergeability Badge: For open MRs, the Status column alternates every second between the base Open badge and a live mergeability indicator sourced directly from the GitLab API:

    Badge Color Meaning
    Mergeable 🟩 Light green MR can be merged cleanly
    Conflict πŸŸ₯ Red Merge conflicts must be resolved
    Rebase 🟨 Yellow Branch is behind target β€” rebase required

    No extra column is added: the animation keeps the layout compact while surfacing critical merge-readiness at a glance.

  • πŸ—‚οΈ Toggleable Table Columns (C): Press C at any time to open an interactive column picker popup. Use ↑/↓ to navigate and Space to toggle each optional column on or off. Your selection is instantly saved to config.json and persisted across restarts β€” no manual file editing required. Available optional columns:

    Column Description
    Activity Color-coded activity badge β€” 🟒 Active, 🟑 Slowing, πŸ”΄ Stale (same thresholds as the Inspector)
    Target The branch the MR is intended to merge into
    Labels Filtered label chips (respects table_label_prefixes)
    Milestone The associated milestone title
    Notes Total number of comments and discussion threads β€” πŸ’¬ N in yellow when non-zero, dimmed βœ” 0 otherwise

    All columns are hidden by default to keep the layout compact. They can also be enabled statically via visible_columns in config.json (see configuration section below).

  • ⭐ MR Flagging & Focused Filter: Manually flag any MR with Space to mark it with a coloured star chevron (β˜…) in the title column. Press F to cycle the active filter between All and Flagged β˜…, instantly narrowing the table to only your flagged MRs. Flagged state is persisted across restarts via tracker_state.json β€” your watchlist survives application restarts and background refreshes.

  • 🏁 Milestone Bulk-Add (Release Manager Workflow): In Insert mode, type @ followed by any part of a milestone name to trigger a live autocomplete dropdown. Active and upcoming milestones are fetched from GitLab on startup and filtered in real time as you type. Selecting a milestone with Enter automatically adds all open MRs attached to that milestone in a single action β€” no need to enter IDs one by one. Ideal for release managers preparing a deployment checklist.

    i             β†’ Enter Insert mode
    @5.2          β†’ filters milestones containing "5.2"
    ↓ / Tab       β†’ navigate suggestions
    Enter         β†’ bulk-add all open MRs from the selected milestone
    Esc           β†’ close dropdown without selecting
    
  • πŸ”¬ Pipeline Inspector (P): Press P on any selected MR to toggle the side panel between MR metadata and its pipeline history. The last 5 pipeline runs are displayed with per-stage job breakdown, status icons, and execution durations:

    #9981  βœ” passed
      β–Έ test
        βœ” lint        (18s)
        βœ” unit-tests  (74s)
      β–Έ build
        βœ” build       (42s)
      β–Έ deploy
        βœ” deploy-staging (31s)
    

    Pipeline data is fetched alongside MR metadata in the same refresh cycle and persisted to disk β€” so it is immediately available on restart without an extra network call. Re-fetching only occurs when GitLab reports a new updated_at timestamp, keeping API usage minimal.


πŸ”‘ Authentication & Configuration

The application requires your GitLab Project configuration and an API Personal Access Token.

Step 1: Set up environment variables (optional)

✨ Zero-config first run: If no .env file or config.json is present, gitlab-tracker will interactively prompt you for the required values on first launch and persist them automatically to config.json. No manual file setup is needed.

 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
 β”‚              FIRST-RUN INTERACTIVE ONBOARDING            β”‚
 β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
 β”‚ 🌐 GitLab URL [https://gitlab.com]: _                    β”‚
 β”‚ πŸ”’ GitLab Project ID: _                                  β”‚
 β”‚ πŸ”‘ GitLab Personal Access Token: _                       β”‚
 β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

For teams and CI pipelines, you can still pre-configure everything via a .env file to skip the prompts entirely:

  1. Copy the provided template to create your local .env file:

    cp .env.example .env
  2. Open .env and specify your project details:

    # Required: Your target GitLab Project ID
    GITLAB_PROJECT_ID=12345678
    
    # Optional: Custom self-hosted GitLab instance (Defaults to https://gitlab.com if omitted)
    GITLAB_URL=https://gitlab.my-company.com
    
    # Optional: Override token via environment variable (Not recommended for disk storage)
    # GITLAB_TOKEN=glpat-xxxxxxxxxxxxxxxxxxxx
    
    # Optional: Override initial tracked branches for new sessions (comma-separated)
    DEFAULT_BRANCHES="main,develop"
    
    # Optional: Filter table column tags by prefix (comma-separated)
    TABLE_LABEL_PREFIXES="deploy::,review::"
    
    # Optional: Activity badge thresholds in the Context Inspector (in days)
    ACTIVITY_RECENT_DAYS=2   # 🟒 Green if updated within N days (default: 2)
    ACTIVITY_STALE_DAYS=7    # πŸ”΄ Red if not updated for N days (default: 7)

πŸ”„ Settings Resolution Order

Settings are resolved in the following order (highest to lowest priority):

  1. System Environment Variables & Local .env (current directory)
  2. Global .env (~/.config/gitlab-tracker/.env)
  3. User Config File (~/.config/gitlab-tracker/config.json)
  4. Built-in Fallback Defaults (https://gitlab.com, ["main"] for default branch)

Step 2: First-Run Interactive Onboarding & Keyring PAT Security Layer

Your GitLab personal access token is never stored in plain text.

On first launch, gitlab-tracker resolves each required value using the following priority order β€” prompting interactively only as a last resort:

 β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
 β”‚                    SETTINGS LOOKUP ORDER                     β”‚
 β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
 β”‚ GITLAB_PROJECT_ID & GITLAB_URL                               β”‚
 β”‚   1. Environment variable / .env file                        β”‚
 β”‚   2. ~/.config/gitlab-tracker/config.json                    β”‚
 β”‚   3. Interactive CLI prompt β†’ saved to config.json           β”‚
 β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
 β”‚ GITLAB_TOKEN                                                 β”‚
 β”‚   1. GITLAB_TOKEN environment variable (if set)              β”‚
 β”‚   2. Native OS Keyring (GNOME Keyring / macOS Keychain)      β”‚
 β”‚   3. Interactive CLI prompt β†’ saved to OS Keyring            β”‚
 β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
  1. First-Run Onboarding: If no GITLAB_TOKEN is found in your .env or environment, the application will prompt you interactively in the terminal on its initial launch:

    🌐 No GitLab URL found in config or environment.
       Leave empty to use the default (https://gitlab.com)
    GitLab URL [https://gitlab.com]: https://gitlab.my-company.com
    πŸ”’ No GitLab Project ID found in config or environment.
    Please enter your GitLab Project ID: 12345678
    βœ… Config saved to config.json!
    
    πŸ”‘ No GITLAB_TOKEN found in environment or system Keyring.
    Please enter your GitLab Personal Access Token: glpat-xxxxxxxxxxxx
    βœ… Token securely saved to OS Keyring!
    
  2. Secure Token Persistence: The token is encrypted and handed off directly to your operating system's native secret manager:

    • Linux: GNOME Keyring / KWallet via Secret Service API
    • macOS: Apple Keychain Service
    • Windows: Windows Credential Manager
  3. Subsequent Launches: You can delete the GITLAB_TOKEN entry from your .env completely. On subsequent runs, gitlab-tracker retrieves the token silently from the OS Keyring without requiring plain-text files or manual re-entry.


Step 3: UI, Default Branches & Label Customization (config.json)

On its first launch, the tool automatically generates a config.json file inside your OS user configuration directory:

  • Linux: ~/.config/gitlab-tracker/config.json
  • macOS: ~/Library/Application Support/gitlab-tracker/config.json
  • Windows: C:\Users\<User>\AppData\Roaming\gitlab-tracker\config.json

You can edit this file to adjust default environment branches, label badge colors, wildcard rules, and activity badge thresholds:

{
  "project_id": "12345678",
  "gitlab_url": "https://gitlab.my-company.com",
  "refresh_interval_secs": 900,
  "default_branches": [
    "main"
  ],
  "table_label_prefixes": [
    "deploy::",
    "review::"
  ],
  "activity_recent_days": 2,
  "activity_stale_days": 7,
  "visible_columns": {
    "target_branch": false,
    "labels": false,
    "milestone": false
  },
  "label_colors": {
    "deploy::*": {
      "bg": "#2E7D32",
      "fg": "white"
    },
    "review::approved": {
      "bg": "magenta",
      "fg": "white"
    },
    "review::*": {
      "bg": "cyan",
      "fg": "black"
    },
    "size::*": {
      "bg": "dark_gray",
      "fg": "white"
    },
    "bug": {
      "bg": "#D32F2F",
      "fg": "white"
    }
  }
}

Optional table columns β€” By default the table only shows the fixed columns (ID, Title, Status) plus your tracked branches, keeping the layout compact. Enable any optional column individually in config.json under visible_columns:

Key Default Column shown
activity false Activity β€” 🟒 Active / 🟑 Slowing / πŸ”΄ Stale badge
target_branch false Target β€” the branch the MR merges into
labels false Labels β€” filtered label chips (respects table_label_prefixes)
milestone false Milestone β€” the associated milestone title
notes false Notes β€” total comment count (πŸ’¬ N in yellow when non-zero)

Example β€” enable Activity and Target only:

"visible_columns": {
  "activity": true,
  "target_branch": true,
  "labels": false,
  "milestone": false,
  "notes": false
}

Activity badge thresholds control the colored indicator displayed next to the Updated field in the Context Inspector:

Badge Meaning Condition
🟒 Active Updated recently elapsed days < activity_recent_days
🟑 Slowing Activity slowing down between the two thresholds
πŸ”΄ Stale No recent activity elapsed days β‰₯ activity_stale_days
⬛ Unknown Timestamp unavailable β€”

πŸ”” How Desktop Notifications Work:

Notifications are powered by notify-rust and rely on your system's native notification daemon (e.g., libnotify on Linux, NSUserNotifications on macOS).

Four events trigger a desktop notification:

Event Trigger condition
🌿 New branch detected An MR's commit SHA was found on a branch not present in the last persisted state
πŸ• MR updated updated_at from GitLab differs from the previously stored value
πŸ”€ Mergeability changed The mergeability status transitioned (e.g. Mergeable β†’ Conflict)
🏁 Milestone changed The milestone attached to the MR changed (e.g. v2.4.0 β†’ v2.5.0)

Anti-spam on startup: change notifications (updated_at, mergeability, milestone) are suppressed during the initial sync β€” the first fetch cycle after launch. This prevents a flood of toasts when the app starts and reconciles its in-memory state with the GitLab API. Only genuine changes detected during subsequent background refreshes (or a manual R refresh) will produce notifications.

  • βœ… No duplicate alerts when restarting the app with an unchanged state.
  • βœ… No spam during the initial sync or redundant refresh cycles.
  • βœ… Reliable detection of real changes across refreshes and restarts.

The last-known branch state per MR is persisted in tracker_state.json under the last_known_branches key.


🌿 How Branch Resolution Works:

  1. Active Session Priority: If tracker_state.json exists from a previous run, the app restores your last active layout (columns added/removed via input).
  2. First Run / Fresh Session: If no state exists, initial branches are loaded from DEFAULT_BRANCHES in .env if provided, falling back to default_branches in config.json (defaults to ["main"]).

πŸ“¦ Installation

Recommended β€” Install from crates.io

The simplest way to install gitlab-tracker if you have Rust (1.80+) available:

cargo install gitlab-tracker

This downloads, compiles, and installs the latest published release directly from crates.io into ~/.cargo/bin/. No cloning required.

Pre-built Binaries

If you prefer not to compile, download the latest pre-compiled binary for your architecture from the Releases Page and place it somewhere on your $PATH.

Building from Source

For development or to test unreleased changes, clone the repository and build manually:

git clone git@github.com:julien-langlois/gitlab-tracker.git
cd gitlab-tracker

# Build optimized release executable (builds all workspace members)
cargo build --release

# Optional: install binary globally to ~/.cargo/bin/
cargo install --path gitlab-tracker

# Build without desktop notifications (headless / CI environments)
cargo install --path gitlab-tracker --no-default-features

Once installed via any of the methods above, launch the dashboard from any terminal folder:

gitlab-tracker

⌨️ Dashboard Navigation & Shortcuts

The dashboard operates in two keyboard modes, inspired by vim:

🟦 Normal Mode (default)

Shortcut keys are active. The input field is passive.

Shortcut Action
i or / Enter Insert mode β€” focus the input field
β–² / β–Ό or k / j Navigate rows in the table
Tab Cycle focus between Dashboard and Inspector panes
P Cycle Inspector view: MR Info β†’ Pipelines β†’ Time Log (redmine) β†’ MR Info
L Log time on the linked Redmine ticket (redmine feature only)
C Open column picker β€” toggle optional columns on/off
O Open selected MR in your default web browser
R Force immediate network refresh for all MRs
s Cycle sort column (Updated β†’ ID β†’ Milestone β†’ Title β†’ …)
S Toggle sort direction (ascending / descending)
Space Toggle flag β˜… on the selected MR β€” persisted across restarts
F Cycle filter (All β†’ Flagged β˜… β†’ All)
Del Delete selected MR row
Esc Quit dashboard

🟩 Column Picker Mode

Opened with C. The table border turns cyan as a visual indicator.

Shortcut Action
β–² / β–Ό or k / j Navigate the column list
Space Toggle the highlighted column on/off
Enter or Esc Close the picker β€” changes are saved immediately to config.json

🟨 Insert Mode

The input field has exclusive focus. All printable keys feed the field β€” shortcuts are suspended. The input bar turns yellow as a visual indicator.

Shortcut Action
142 + Enter Add MR ID !142 to tracking
staging + Enter Add branch staging to target columns
-142 + Enter Remove MR ID !142 from tracking
-staging + Enter Remove branch column staging
@name Filter milestones matching name β€” opens autocomplete dropdown
Enter Submit input, or confirm highlighted milestone suggestion
Esc Close autocomplete dropdown, or cancel and return to Normal mode

🏁 Milestone Autocomplete (Insert Mode)

When the input starts with @, a dropdown appears above the input bar listing all active/upcoming milestones fetched from GitLab. The list is filtered in real time as you type.

Shortcut Action
↑ / ↓ or Shift+Tab / Tab Navigate suggestions
Enter Confirm selection β€” bulk-adds all open MRs from the milestone
Esc Close dropdown without selecting

Why two modes? Branch names starting with s, S, p, P, o, O, r or R would otherwise collide with shortcut keys. Insert mode guarantees the full branch name is captured without interference.


πŸ—οΈ Project Architecture

This project is structured as a Cargo workspace with four crates:

gitlab-tracker/                  # Binary crate β€” TUI orchestrator
└── src/
    β”œβ”€β”€ main.rs          # Event loop orchestrator & async channel setup
    β”œβ”€β”€ app.rs           # State machine, InputMode, row navigation & sort logic
    β”œβ”€β”€ config.rs        # Label filtering, wildcard matching, HEX color parsing & activity badge
    β”œβ”€β”€ models.rs        # Strongly-typed API DTOs & runtime event types
    β”œβ”€β”€ gitlab.rs        # Async network handling & rate-limit semaphores
    β”œβ”€β”€ events.rs        # Keyboard & mouse event dispatch (Normal / Insert mode routing)
    β”œβ”€β”€ storage.rs       # OS Keyring interface & XDG state/config persistence
    β”œβ”€β”€ utils.rs         # Fuzzy matching algorithmic utilities
    β”œβ”€β”€ demo.rs          # Demo mode with pre-populated mock data (screenshots & CI)
    └── ui/
        β”œβ”€β”€ mod.rs       # Root layout renderer & input bar (mode-aware)
        β”œβ”€β”€ table.rs     # Main MR table widget
        └── inspector.rs # Side panel: MR metadata & pipeline history views

gitlab-tracker-core/             # Library crate β€” shared trait contracts (TrackerProvider, LinkedTicket)
gitlab-tracker-notify/           # Library crate β€” optional desktop notification plugin
└── src/
    └── lib.rs           # notify-rust integration (no-op stubs when feature `desktop` is disabled)

gitlab-tracker-redmine/          # Library crate β€” optional Redmine integration plugin
└── src/
    β”œβ”€β”€ lib.rs           # RedmineProvider: implements TrackerProvider
    β”œβ”€β”€ client.rs        # Async Redmine REST API client
    β”œβ”€β”€ config.rs        # RedmineConfig: YAML config load/save & interactive onboarding
    β”œβ”€β”€ detector.rs      # Regex-based ticket ID detector (title & description)
    └── keyring.rs       # Secure token retrieval via OS Keyring

Optional Feature Flags

Feature flag Default Effect
notifications βœ… enabled Desktop notifications via notify-rust
redmine ❌ disabled Redmine ticket integration

πŸ”΄ Redmine Integration (Optional)

The Redmine integration is an opt-in feature. It is not compiled or active by default β€” the application works fully without it.

When enabled, gitlab-tracker detects Redmine ticket IDs in MR titles and descriptions (via configurable regex patterns) and enriches the Context Inspector panel with ticket information and time tracking data.

Features

  • Linked ticket display: subject, status, author, and assignee are shown in the Inspector's MR Info view.
  • Time Log view (P): press P twice to reach the Time Log view. It displays:
    • A progress bar comparing time spent vs. the ticket's estimate.
    • The full list of time entries (date, user, activity, duration, comment) fetched live from Redmine via GET /time_entries.json?issue_id={id}.
    • Navigating between MRs with ↑/↓ while on this view automatically refreshes the entries for the newly selected ticket.
  • Log time (L): press L from any view to open a popup and submit a new time entry directly to Redmine. Select the activity category, enter the duration (e.g. 1h30, 0.5), optionally add a comment, and confirm with Enter.

Enabling Redmine at Build Time

You must explicitly enable the redmine feature flag when building or installing:

# Build from source with Redmine support
cargo build --release --features redmine

# Install from source with Redmine support
cargo install --path gitlab-tracker --features redmine

# Install from crates.io with Redmine support
cargo install gitlab-tracker --features redmine

Note: The redmine feature pulls in gitlab-tracker-redmine and gitlab-tracker-core as additional dependencies (HTTP client, YAML config, OS Keyring). Without the flag, neither crate is compiled and there is zero runtime overhead.

Redmine Configuration

On first launch with the redmine feature enabled, the app interactively prompts for your Redmine URL if none is found:

🌐 No Redmine URL found in config or environment.
   Leave empty to disable Redmine integration.
Redmine URL: https://redmine.my-company.com

Leaving the prompt empty silently disables the integration β€” no error, no impact on the rest of the dashboard.

The configuration is persisted as a YAML file:

  • Linux: ~/.config/gitlab-tracker/gitlab-tracker/redmine.yaml
  • macOS: ~/Library/Application Support/gitlab-tracker/gitlab-tracker/redmine.yaml
  • Windows: C:\Users\<User>\AppData\Roaming\gitlab-tracker\gitlab-tracker\redmine.yaml

You can also set the URL via environment variable to skip the prompt entirely:

REDMINE_URL=https://redmine.my-company.com

The generated redmine.yaml file looks like this (edit it to customise the ticket detection patterns):

redmine_url: "https://redmine.my-company.com"
ticket_patterns:
  - "#(\\d+)"
  - "(?i)(?:refs|fixes|closes|resolves)\\s+#(\\d+)"
  - "/issues/(\\d+)"
Field Description
redmine_url Base URL of your Redmine instance (no trailing slash)
ticket_patterns Regex patterns to detect ticket IDs β€” capture group 1 must match the numeric ID

Redmine API Token

The Redmine personal API token follows the same secure lookup chain as the GitLab token:

1. REDMINE_TOKEN environment variable (if set)
2. Native OS Keyring (GNOME Keyring / macOS Keychain / Windows Credential Manager)
3. Interactive CLI prompt β†’ saved to OS Keyring

The token is never stored in plain text on disk.



πŸ“„ License

Distributed under the MIT License. See LICENSE for details.

About

A fast terminal TUI dashboard for tracking GitLab Merge Requests across branches

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages