Skip to main content

Terminal UI for triaging open Renovate pull requests across multiple repositories

Project description

lsrenovate

Test suites REUSE status The latest version can be found on PyPI. Information on what versions of Python are supported can be found on PyPI.

lsrenovate is a terminal UI for triaging open Renovate pull requests across many GitHub, GitLab, and Gitea repositories at once. It reads a simple YAML project registry, fetches matching PRs/MRs concurrently, and lets you review, merge, and jump into repos without leaving the terminal.

Columns

The table shows two independent signals per PR/MR, color-coded where the forge can tell reliably:

  • Mergeable — whether the forge sees a merge conflict or unmet approval rule (e.g. MERGEABLE/CONFLICTING). This does not reflect CI outcome.
  • Pipeline — the CI/pipeline outcome for the PR's head commit (e.g. success/failed/running, or N/A if the repo has no CI). For GitLab and Gitea this requires a follow-up API call per PR to fetch, since the list endpoints don't expose it directly.

A PR is only color-coded ready when both are favorable; see the Gitea note below for where this can't be determined with full confidence.

Features

  • Cross-repo overview — one table showing every open Renovate (or custom-labeled) PR/MR across all your repos, with age, mergeable state, and pipeline status color-coded at a glance (where the forge can tell reliably — see the Gitea note below).
  • Multi-forge, multi-instance — mix GitHub, GitLab, and Gitea repos in one registry, including multiple self-hosted GitLab or Gitea instances at once, each with its own credentials.
  • Multi-select merge — tick PRs with space and merge them all with m; failures don't block the rest, and you get a summary afterward.
  • Jump to context — open a PR in your browser (o) or drop into a shell at its local checkout (s), with your GitHub token already exported into the shell environment.
  • Configurable — merge method, detection labels, sort order, and the project registry path are all overridable via a TOML config file.
  • Concurrent fetching — all repos are queried in parallel via a thread pool, so refreshing dozens of repos takes seconds, not minutes.

Requirements

  • Python 3.11+
  • One CLI per forge you actually use:
    • GitHub CLI (gh), authenticated or provided a token via config/env (see below)
    • GitLab CLI (glab), no pre-login required — lsrenovate injects the token per call (see below)
    • Gitea CLI (tea), must be pre-authenticated yourself via tea login add (see the Gitea note below)

Installation

Requires at least Python 3.11.

With pipx:

pipx install lsrenovate

With uv:

uv tool install lsrenovate

With pip:

pip install lsrenovate

From source

git clone https://github.com/mxmehl/lsrenovate.git
cd lsrenovate
uv sync --no-dev

Quick start

  1. Create a project registry — a YAML file listing the repos to monitor:

    myprojects:
      github:
        my-tool:
          forge: github
          url: https://github.com/myuser/my-tool
      work:
        internal-service:
          forge: gitlab
          url: https://gitlab.example.com/team/internal-service
      personal:
        my-blog:
          forge: gitea
          url: https://gitea.example.com/myuser/my-blog
    

    Repos are grouped by an arbitrary top-level key (e.g. github, work); this key also determines the local checkout path convention ~/Git/<group>/<project>, used by the "open shell" action. forge must be github, gitlab, or gitea.

  2. Provide a GitHub token, in order of precedence:

    • GITHUB_TOKEN environment variable, or
    • [github].token_command in the config file — a command that prints the token to stdout, e.g. a password manager CLI, or
    • [github].token in the config file (plaintext), or
    • fall back to gh's own stored authentication.
  3. Run it:

    lsrenovate
    

Configuration

lsrenovate reads an optional TOML config file at your platform's user config directory (e.g. ~/Library/Application Support/lsrenovate/config.toml on macOS, ~/.config/lsrenovate/config.toml on Linux):

merge_method = "squash"                # "squash" (default), "merge", or "rebase"
labels = ["Renovate"]                  # default PR label(s) to filter on; all must match
sort_by = "repo"                       # "repo" (default), "age", or "title"
myprojects_path = "~/path/to/myprojects.yaml"  # defaults to a file next to this config

[github]
token = "ghp_..."                      # optional; env var GITHUB_TOKEN takes precedence
token_command = ["kpxc_get_password", "cli://token-gh-cli"]  # optional; takes precedence over token
# labels = ["Renovate"]                # optional; overrides the global `labels` for GitHub only

# One [gitlab."<host>"] table per self-hosted GitLab instance you use.
# <host> must match the hostname in the repo's url in myprojects.yaml.
[gitlab."gitlab.example.com"]
token = "glpat-..."                    # optional; or use token_command like above
# token_command = ["kpxc_get_password", "cli://token-gitlab-example"]
# api_host = "ssh.gitlab.example.com"   # optional; only needed if `glab auth status`
                                        # shows your token stored under a different
                                        # hostname than the one in your repo URLs
                                        # (e.g. glab auth login ran against an SSH host)
# labels = ["dependencies"]            # optional; overrides the global `labels` for this instance only

# One [gitea."<host>"] table per Gitea instance you use. lsrenovate never
# handles Gitea tokens itself — see the note below.
[gitea."gitea.example.com"]
login = "gitea.example.com"            # optional; defaults to the host itself
# labels = ["dependencies"]            # optional; overrides the global `labels` for this instance only

token_command (under [github] or any [gitlab."<host>"] table) is run directly via subprocess (no shell involved, so it works the same regardless of your login shell), and its stdout (trimmed) is used as the token. This avoids storing a plaintext token in the config file. If it fails, lsrenovate falls back to the plaintext token (or, for GitHub, gh's own auth) and shows a warning on startup.

Renovate (and similar bots) don't always use the same label across every forge — for example, GitHub/GitLab repos might use Renovate while Gitea repos use dependencies. Set labels at the top level for the default used everywhere, and override it per forge ([github]) or per instance ([gitlab."<host>"], [gitea."<host>"]) wherever it differs. Multiple labels are always matched with AND semantics — a PR must carry every configured label, not just one.

Gitea limitation: no token management

The tea CLI has no way to pass a token or host per invocation — it only works against named logins that are registered ahead of time. lsrenovate does not manage Gitea credentials at all: before using a Gitea instance, register it yourself with:

tea login add --name gitea.example.com --url https://gitea.example.com --token <your-token>

The login field in [gitea."<host>"] just tells lsrenovate which registered login name to pass to tea --login; it defaults to the host itself, which matches the convention of naming logins after their host.

Gitea's own mergeable field is documented as sometimes wrong upstream — it can report false for a PR that's actually mergeable. lsrenovate still color-codes it, though: attempting to merge a PR that turns out to have a real conflict fails cleanly with an error rather than silently doing anything harmful, so a wrong "mergeable" signal only costs you one failed merge attempt, not a bad merge. Pipeline/CI status is fetched separately via the Gitea API's combined commit status endpoint (one follow-up call per PR) and factors into the same color, alongside mergeable.

Keybindings

Key Action
space Toggle selection of the row under the cursor
m Merge selected PRs (or the focused one if none selected)
o Open selected PRs (or the focused one) in the browser
s Check out the focused PR's branch (force-resetting any stale branch) and open a shell there
t Cycle sort order (repo → age → title)
r Refresh the PR list
q Quit

Copyright and Licensing

This project is licensed under the Apache License 2.0, copyrighted by Max Mehl. As the project follows the REUSE best practices, you can find licensing information for each individual file in the LICENSES directory or corresponding file headers.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

lsrenovate-0.2.0.tar.gz (23.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

lsrenovate-0.2.0-py3-none-any.whl (30.2 kB view details)

Uploaded Python 3

File details

Details for the file lsrenovate-0.2.0.tar.gz.

File metadata

  • Download URL: lsrenovate-0.2.0.tar.gz
  • Upload date:
  • Size: 23.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for lsrenovate-0.2.0.tar.gz
Algorithm Hash digest
SHA256 c411adccaeacd3ae0e5b698304d2f435a22c9496eac14e97991d2f74d5d34cf1
MD5 88fa82a6bedb6f37a8874cb7625016b0
BLAKE2b-256 b16d44ca27fde8c951fe717bf9fef9c68aebc030b78f6994ca08861069b14789

See more details on using hashes here.

Provenance

The following attestation bundles were made for lsrenovate-0.2.0.tar.gz:

Publisher: publish.yaml on mxmehl/lsrenovate

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file lsrenovate-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: lsrenovate-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 30.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for lsrenovate-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 dac14cb55d2fd79f161e07ba694385d5a20eb9cd2d302602571d569cc702ae36
MD5 fb21004baa833cb480d5269c325a3c3d
BLAKE2b-256 92f3b06e02eff5cc2eec6d405ca00e8afb788d0b8dcad0034178c2cfc6ec2209

See more details on using hashes here.

Provenance

The following attestation bundles were made for lsrenovate-0.2.0-py3-none-any.whl:

Publisher: publish.yaml on mxmehl/lsrenovate

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page