Skip to main content

OpenPullRequest

logo

CLI tool that generates PR titles, descriptions, and post-review change summaries using a local or cloud LLM. Supports Ollama, OpenAI, Anthropic, Google Gemini, OpenRouter, DeepSeek, llama.cpp, and MLX.

CI License


Built primarily for local-first use — pair it with Ollama and a Gemma model (Google's Gemma family is currently the best fit for this kind of task at a size you can run locally) for a free, fully offline workflow. On Apple Silicon Macs, prefer the -mlx tagged variant of your chosen model (e.g. gemma4:26b-mlx) — it runs on Apple's MLX framework instead of plain GGUF and is noticeably faster on that hardware. Don't want to run anything locally? Google's Gemini API has a generous free tier and is a great low-friction cloud option.

Installation

Recommended

uv tool install openpurr

Or

pipx install openpurr

On first run, the setup wizard creates ~/.openpurr automatically. You can also run it any time:

opo setup

Requirements

  • Python 3.11+
  • git on PATH
  • One of: Ollama running locally, or an API key for a cloud provider

Usage

# Generate a PR title + description from the diff against main
opo

# Diff against a different base branch
opo --base develop

# Summarise changes made since the last N commits (for reviewers)
opo review
opo review --commits 3

Configuration

Settings are stored in ~/.openpurr as flat OPO_KEY=value lines — no sections, no quoting:

OPO_PROVIDER=ollama
OPO_MODEL=gemma4:26b
OPO_API_KEY=
OPO_HOST=http://localhost:11434
OPO_TEMPERATURE=0.0
OPO_KEEP_ALIVE=5m
OPO_BASE=main

Use the config subcommand to inspect and update values without editing the file directly.

# Show all keys with descriptions and current values
opo config describe

# Read a single value
opo config get model

# Update a value
opo config set provider ollama
opo config set model gemma4:26b
opo config set api_key sk-...
opo config set keep_alive 0s

Custom system prompts

The prompts opo sends to the LLM aren't fixed — everything after a lone --- line in ~/.openpurr is free text, not OPO_KEY=value config, so it can hold Markdown, headers, = signs, anything. Add an INIT PROMPT: section to override the prompt behind opo (title + description) and/or a REVIEW PROMPT: section to override the one behind opo review. Either section is optional; whichever is missing keeps the built-in default.

OPO_PROVIDER=ollama
OPO_MODEL=gemma4:26b
OPO_API_KEY=
OPO_HOST=http://localhost:11434
OPO_TEMPERATURE=0.0
OPO_KEEP_ALIVE=5m
OPO_BASE=main

---
INIT PROMPT:
You are a Senior Principal Engineer. Write a terse PR title and description in
Conventional Commits style. No emoji, no checklists.

REVIEW PROMPT:
Summarize what changed since the last review in one short paragraph.

opo config set/opo config describe only ever touch the OPO_KEY=value part above the --- line — the prompt section is left exactly as you wrote it, and opo config describe tells you which of init/review are currently overridden.

Configuration keys

Key Env var Default Description
provider OPO_PROVIDER ollama ollama · openai · anthropic · gemini · openrouter · deepseek · llamacpp · mlx
model OPO_MODEL (empty) Model name — set via opo setup or opo config set model <name>
api_key OPO_API_KEY (empty) API key for cloud providers
host OPO_HOST http://localhost:11434 Base URL — Ollama default; set to a custom endpoint when needed
temperature OPO_TEMPERATURE 0.0 Sampling temperature (0.0 = deterministic)
keep_alive OPO_KEEP_ALIVE 5m Ollama VRAM keep-alive (0s = unload immediately, 5m = keep warm)
base OPO_BASE main Default base branch to diff against

There's no hardcoded default model: opo setup always has you pick one (from a live-fetched list, or typed manually), and opo/opo review will error out with a pointer back to opo setup if model is ever left blank (e.g. after hand-editing the file).

Example: switch to Google Gemini (free tier)

opo config set provider gemini
opo config set model <your-chosen-model>
opo config set api_key <your-gemini-api-key>

Model names aren't hardcoded anywhere in this README on purpose — providers retire and rename models constantly. Run opo setup or opo models --provider gemini to pick from what's actually available right now.

Example: unload Ollama from VRAM after each request

opo config set keep_alive 0s

Models

List available models for the current or a specified provider:

opo models
opo models --provider anthropic

Model lists are always fetched live from the provider — Ollama's /api/tags, OpenAI/Anthropic/Gemini/OpenRouter/DeepSeek/llama.cpp/MLX's models.list() (or public models endpoint) — never a hardcoded/curated list baked into the tool. If the fetch fails (offline, bad key, local server not running) the command prints an empty result instead of erroring; check connectivity/credentials, or pull a model directly with ollama pull <model>.

Download files

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

Source Distribution

openpurr-0.8.5.tar.gz (538.6 kB view details)

Uploaded Source

Built Distribution

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

openpurr-0.8.5-py3-none-any.whl (19.6 kB view details)

Uploaded Python 3

File details

Details for the file openpurr-0.8.5.tar.gz.

File metadata

  • Download URL: openpurr-0.8.5.tar.gz
  • Upload date:
  • Size: 538.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for openpurr-0.8.5.tar.gz
Algorithm Hash digest
SHA256 1cfc79c1edf87ef0ec755553ace69d0d88fa57c22df5eb1a7747c1315f474b21
MD5 3d4e2e7aac1942c134ff2da94d9454b5
BLAKE2b-256 685179f8cbf9477dd21d2ccf622cc12e6d860eeffd6219da7bab25cf97d7e03a

See more details on using hashes here.

Provenance

The following attestation bundles were made for openpurr-0.8.5.tar.gz:

Publisher: publish.yml on ilypopv/openpurr

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

File details

Details for the file openpurr-0.8.5-py3-none-any.whl.

File metadata

  • Download URL: openpurr-0.8.5-py3-none-any.whl
  • Upload date:
  • Size: 19.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for openpurr-0.8.5-py3-none-any.whl
Algorithm Hash digest
SHA256 7916b06d3a90d0f8f5c1b2401c56af4f7def52f7cc39ceafb2a0d32c288f78c9
MD5 f1f0bd44a5639c5c950caac2d458c737
BLAKE2b-256 b3565a09a702f9532096784c7a017eb67506ddce2a531be8d3a2e65c2d82df8d

See more details on using hashes here.

Provenance

The following attestation bundles were made for openpurr-0.8.5-py3-none-any.whl:

Publisher: publish.yml on ilypopv/openpurr

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

Release history Release notifications | RSS feed

0.8.9

2 files

0.8.8

2 files

0.8.7

2 files

0.8.6

2 files

This release

0.8.5 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page