Generate clean, consistent pull request titles and descriptions from your Git history with AI.
lazypr reads the commits on your current branch, compares them with a target branch, and generates a ready-to-review PR title, description, and labels. It supports several AI providers, existing GitHub PR templates, multiple output languages, and a short lzp command alias.
- Features
- Requirements
- Installation
- Quick start
- How it works
- CLI reference
- Configuration
- AI providers
- PR templates
- Commit filtering
- GitHub CLI integration
- Troubleshooting
- Development
- Groq, Cerebras, Google Gemini, OpenAI, and OpenAI-compatible APIs
- Interactive configuration with masked API-key input
- Smart filtering for merge, dependency-update, and formatting-only commits
- Support for existing GitHub pull request templates
- Output in 13 languages
- Custom context and label guidance
- Optional token-usage details
- Generation of a ready-to-run
gh pr createcommand lazyprandlzpcommand names
- Node.js 22 or newer
- Git
- A repository with at least one commit on the current branch that is not on the target branch
- An API key for the selected hosted AI provider; local OpenAI-compatible endpoints may not require one
The GitHub CLI is only required when using the --gh option.
Install lazypr globally with npm:
npm install -g lazyprThen verify the installation:
lazypr --version
# or use the short alias
lzp --version-
Open the interactive configuration menu:
lazypr config
-
Choose a provider and model, then add the provider's API key. API keys entered through the interactive menu are masked and do not appear in your shell history.
-
From a feature branch, generate a PR against
main:lazypr
To compare against a different branch, pass it as the first argument:
lazypr develop
-
Review the generated content. lazypr can copy the title and description to your clipboard, but AI output should always be checked before publishing.
For a command such as lazypr main, lazypr:
- Finds commits in
main..HEAD. - Removes common noise commits unless filtering is disabled.
- Loads an optional PR template and any configured generation context.
- Sends the commit messages and guidance to the selected AI model.
- Validates and displays the generated title, description, and suggested labels.
- Offers to copy the result, or a
gh pr createcommand when--ghis used.
Only the current branch name, commit messages, configuration guidance, and the contents of a selected PR template are used to generate the prompt. lazypr does not analyze the repository's source files.
lazypr [target] [options]
target is the branch the current branch will be merged into. It defaults to DEFAULT_BRANCH, which is main unless changed.
| Option | Description |
|---|---|
-t, --template [name] |
Use a discovered PR template. Omit the name to select interactively. |
-u, --usage |
Display input, output, and total token usage. |
-l, --locale <language> |
Override the configured output language for this run. |
--no-filter |
Include commits normally removed by smart filtering. |
--gh |
Generate a gh pr create command instead of copying the title and body separately. |
-c, --context <text> |
Add guidance for this run, overriding configured context. |
-h, --help |
Show command help. |
-V, --version |
Show the installed version. |
Examples:
# Compare the current branch with main
lazypr
# Compare with develop and include every commit
lazypr develop --no-filter
# Generate in Italian with extra guidance
lazypr --locale it --context "Focus on the user-facing changes"
# Select a template interactively
lazypr --template
# Use a named template and show token usage
lazypr --template bug_fix --usage
# Generate a GitHub CLI command
lazypr main --ghRun lazypr config for the recommended interactive setup. The menu lets you edit the provider and model together, enter a masked API key, change general settings, and inspect the current configuration.
For scripts and dotfiles, use the configuration subcommands:
lazypr config list
lazypr config get PROVIDER
lazypr config set LOCALE=it
lazypr config remove CONTEXTThe set command requires KEY=VALUE as one argument. Quote the whole argument when the value contains spaces:
lazypr config set "CONTEXT=Keep the description concise and mention breaking changes"API keys passed to
lazypr config setcan remain in shell history. Preferlazypr configfor secret entry.
Configuration is stored in ~/.lazypr (for example, C:\Users\YourName\.lazypr on Windows). The file uses one KEY=value entry per line and is created with owner-only permissions on supported systems.
| Key | Default | Description |
|---|---|---|
PROVIDER |
groq |
groq, cerebras, google, or openai |
MODEL |
openai/gpt-oss-20b |
Model ID sent to the selected provider |
GROQ_API_KEY |
empty | API key used by Groq |
CEREBRAS_API_KEY |
empty | API key used by Cerebras |
GOOGLE_GENERATIVE_AI_API_KEY |
empty | API key used by Google Gemini |
OPENAI_API_KEY |
empty | API key used by OpenAI or a compatible endpoint |
OPENAI_BASE_URL |
empty | Base URL for an OpenAI-compatible API |
DEFAULT_BRANCH |
main |
Target branch used when no target argument is provided |
LOCALE |
en |
Language used for generated PR content |
FILTER_COMMITS |
true |
Whether smart commit filtering is enabled |
CONTEXT |
empty | Persistent generation guidance, up to 200 characters |
CUSTOM_LABELS |
empty | Comma-separated labels the model may suggest |
MAX_RETRIES |
2 |
Number of model request retries; may be 0 |
TIMEOUT |
10000 |
Request timeout in milliseconds |
Supported locale codes are en, es, pt, fr, de, it, ja, ko, zh, ru, nl, pl, and tr.
Custom labels must start with a letter and may contain letters, numbers, hyphens, and underscores. Up to 17 custom labels can be added.
| Provider | PROVIDER |
API-key setting | Get a key |
|---|---|---|---|
| Groq | groq |
GROQ_API_KEY |
Groq Console |
| Cerebras | cerebras |
CEREBRAS_API_KEY |
Cerebras Cloud |
| Google Gemini | google |
GOOGLE_GENERATIVE_AI_API_KEY |
Google AI Studio |
| OpenAI | openai |
OPENAI_API_KEY |
OpenAI API keys |
The interactive menu includes a small curated model list and a custom model option. Model catalogs change, so any non-empty model ID can also be configured directly:
lazypr config set PROVIDER=cerebras
lazypr config set MODEL=gpt-oss-120bServices such as Ollama, LM Studio, and other OpenAI-compatible APIs can be used through the openai provider:
lazypr config set PROVIDER=openai
lazypr config set OPENAI_BASE_URL=http://localhost:11434/v1
lazypr config set MODEL=llama3.2OPENAI_API_KEY is optional for the openai provider so local endpoints that do not authenticate can work. Set it if your endpoint requires authentication.
The selected model must support structured object output. If a custom model repeatedly returns invalid output, try a model with reliable JSON or structured-output support.
lazypr discovers Markdown templates in these locations, using either lowercase or uppercase filenames where shown:
.github/pull_request_template.md
.github/PULL_REQUEST_TEMPLATE.md
.github/pull_request_template/*.md
.github/PULL_REQUEST_TEMPLATE/*.md
docs/pull_request_template.md
docs/PULL_REQUEST_TEMPLATE.md
Use --template without a value to choose from discovered templates, or pass a template name or path:
lazypr --template
lazypr --template feature
lazypr --template .github/PULL_REQUEST_TEMPLATE/bug_fix.mdThe model is instructed to preserve the template's headings, sections, checkboxes, and formatting. YAML frontmatter between --- markers at the top of a template is ignored.
Smart filtering is enabled by default. It excludes commits whose messages look like:
- merge commits, such as
Merge pull request #42 - dependency updates, including common Dependabot and Renovate messages
- formatting- or lint-only changes
Disable filtering for one run:
lazypr --no-filterOr disable it persistently:
lazypr config set FILTER_COMMITS=falseFiltering is based on commit-message patterns. Use --no-filter if meaningful work was excluded because its message matched one of those patterns.
With GitHub CLI installed and authenticated, --gh builds a shell-safe command containing the generated base branch, title, description, and labels:
lazypr main --ghlazypr asks whether to copy the generated command. Review it, then paste it into a POSIX-compatible shell to create the pull request. The command is generated but not executed automatically.
lazypr reads target..HEAD. Make sure you are on the feature branch, the target branch exists locally or as a listed remote branch, and the current branch has commits not present on the target.
If the message says every commit was filtered, retry with:
lazypr --no-filterPass the branch explicitly or update the default:
lazypr develop
lazypr config set DEFAULT_BRANCH=developWhen the configured target is missing or matches the current branch, lazypr offers an interactive branch selector.
Open lazypr config, choose API key, and enter the key for the active provider. You can confirm the active provider and masked configuration with:
lazypr config listIncrease the timeout or retry count, then confirm that the configured provider, model, endpoint, and API key belong together:
lazypr config set TIMEOUT=30000
lazypr config set MAX_RETRIES=4For local endpoints, also confirm that the server is running and that OPENAI_BASE_URL includes the expected /v1 path.
The generated title and description remain visible in the terminal and can be copied manually. Clipboard access may not be available in headless or remote environments.
For bugs and feature requests, open a GitHub issue.
This repository uses Bun for development:
bun install
bun run dev --help
bun test
bun run lint
bun run format
bun run buildThe published CLI targets Node.js 22 or newer.
Issues and pull requests are welcome. Please keep changes focused, add or update tests when behavior changes, and run the development checks before opening a PR. All contributors must follow the Code of Conduct.
MIT Β© Raul Carini
