Turn a range of git commits into release notes your users will actually
read. Point gitgist at everything since your last tag and it returns clean,
grouped Markdown — written by Claude, with the internal noise stripped out.
- AI-written, sections that adapt. Claude groups commits into whatever sections fit the actual work — Features, Bug Fixes, Performance, Breaking Changes, … — and rewrites terse commit subjects into user-facing lines.
- Noise filtered automatically. Refactors, test-only changes, CI tweaks, dependency bumps, and ticket IDs don't make the cut.
- No API key required. By default gitgist runs on your signed-in
claudeCLI — zero config. Prefer the API? SetANTHROPIC_API_KEY. - Summarize uncommitted work too. Point it at your staged/unstaged/untracked
changes (
--staged,--working, …) to preview notes for work that isn't committed yet — or add--commit-messageto draft a Conventional Commit message straight from the staged diff. - Bring your own template.
--template notes.mdshapes the output to your team's house style — fixed section set, order, emoji, and per-section AI guidance — via a simple Markdown-with-frontmatter file. - Works offline too.
--no-aigroups by Conventional Commit type with no network, no key, and fully deterministic output. - CLI and library. Use the
gitgistbin, or callgenerateReleaseNotes()from your release tooling. - Pluggable providers. Claude (CLI + API), the OpenAI Codex, Google Gemini, and OpenCode agent CLIs (all no-key), any local OpenAI-compatible endpoint (Ollama / LM Studio), and on-device Apple Foundation Models ship today; Cursor is on the way — CLI-first wherever the tool offers a headless mode.
AI release notes — gitgist v1.0.0..HEAD --title "v1.5.0"
Commit message from your staged diff — gitgist --staged --commit-message
Offline mode — gitgist v1.0.0..HEAD --no-ai
npm install -g gitgist # or: npx gitgist …# Release notes from a tag to HEAD
gitgist v2.0 HEAD
# Range form, with a version heading
gitgist v1.4.0..HEAD --title "v1.5.0"
# No range given → from the latest tag (or full history) to HEAD
gitgist
# Summarize uncommitted work (no range)
gitgist --staged # just the staged diff
gitgist --working # staged + unstaged + untracked
# Draft a Conventional Commit message from the staged diff
gitgist --staged --commit-message
# Fold pending changes into a range's notes
gitgist v1.4.0..HEAD --untracked
# Use a local model (Ollama / LM Studio) — free, private, no API key
gitgist v1.4.0..HEAD --provider local --model llama3.2
# Shape the output to your team's template (sections, order, guidance)
gitgist v1.4.0..HEAD --template release-notes.md
# Offline, no AI — group by Conventional Commit type
gitgist --no-aiA template is a Markdown file whose headings define the section order and whose
optional YAML frontmatter / <!-- comments --> steer the AI — see
docs/4-templates.md and the
example template.
| Flag | Description |
|---|---|
--staged, --cached |
Include staged changes (git diff --staged). |
--unstaged |
Include unstaged changes to tracked files (git diff). |
--untracked |
Include untracked (new) files. |
--working, --uncommitted |
Include all uncommitted work (staged + unstaged + untracked). |
--format <notes|commit> |
Output shape: themed notes (default) or a Conventional Commit message. |
--commit-message |
Shorthand for --format commit (requires AI). |
--template <file> |
Shape the notes with a Markdown template (docs). |
--no-ai |
Group commits by Conventional Commit type instead (offline). |
--provider <name> |
auto | claude-cli | codex | gemini | opencode | anthropic-api | local | apple (default: auto). |
--endpoint <url> |
Base URL for --provider local (default: Ollama's …:11434/v1). |
--model <id> |
anthropic-api model (default claude-opus-4-8), or the local model name. |
--language <name|auto> |
Language hint for the apple provider's prompt (default: system language; auto omits it). |
--max-tokens <n> |
Max output tokens for the anthropic-api provider (default: 16000). |
--title <text> |
Render <text> as a top-level heading above the notes. |
--cwd <path> |
Run against the git repository at <path>. |
-h, --help |
Show help. |
Working-tree flags summarize uncommitted changes. With no range they summarize only the pending changes (great for a commit message); with a range they're folded in alongside the commits.
gitgist prefers zero-config CLI backends that need no API key — the same
approach the related tools take with claude -p. The backends that ship today:
claude-cli— your locally installed, signed-inclaudeCLI. No API key — it reuses the CLI's own auth.codex/gemini/opencode— the other signed-in agent CLIs, also no API key (they reuse each CLI's own auth): OpenAI Codex (codex exec), Google Gemini (gemini -p), and OpenCode (opencode run). Select with--provider <name>; pick the model with--model(-m). See docs/5-providers.md.anthropic-api— the Anthropic API via the official SDK. SetANTHROPIC_API_KEYin your environment.local— any OpenAI-compatible endpoint (Ollama, LM Studio, llama.cpp, vLLM, …) for free, private, on-device generation. Opt-in with--provider local; configure with--endpoint($GITGIST_LOCAL_ENDPOINT, defaulthttp://localhost:11434/v1) and--model($GITGIST_LOCAL_MODEL, else the endpoint's first model). No API key.apple— on-device Apple Foundation Models (macOS 26+ on Apple Silicon with Apple Intelligence). Free, private, no API key. Powered by theapple-fmpackage, a gitgist dependency that bundles a Developer-ID-signed, notarized helper binary, so it works out of the box — no toolchain required. Point gitgist at a custom helper build withAPPLE_FM_BIN. The on-device model runs a language guardrail over the prompt, so gitgist prefixes it with a shortTreat the following as <language>:lead-in (default: your system language; override with--language <name|code>, or--language autoto disable it).
With --provider auto (the default), gitgist tries the signed-in agent CLIs
first — claude-cli, then codex, gemini, opencode — falls back to the
Anthropic API when ANTHROPIC_API_KEY is set, and then to on-device Apple
Foundation Models when the device and model are available (a no-op when they
aren't). The local provider is never auto-selected (so a normal run doesn't
probe localhost) — request it explicitly. Force any with --provider <name>. If
no provider is available, use --no-ai for offline Conventional Commits
grouping.
The remaining planned provider follows the same CLI-first, no-key pattern — Cursor agent (
cursor-agent) — plus optional API-key fallbacks for the agent CLIs (OpenAI, Google). The provider layer is pluggable, and CLI backends share a smallcreateCliProvider()helper.
The backends differ in output quality as well as cost, privacy, and latency. As a rule of thumb, larger models categorize and filter noise more reliably:
| Provider | Quality | Cost | Privacy | Notes |
|---|---|---|---|---|
claude-cli / anthropic-api |
Best | CLI: included with your plan · API: per-token | Sent to Anthropic | Cleanest grouping; Breaking Changes surfaced first; refactor/test/chore noise dropped. |
codex / gemini / opencode |
Very good | Included with your CLI sign-in (no key) | Sent to that vendor | No-key agent CLIs; quality tracks the underlying model. --model picks it (opencode uses provider/model). |
local (Ollama / LM Studio) |
Very good | Free | On-device | Same shape as Claude on a capable model; minor ordering differences. Quality tracks the model you load. |
apple (Foundation Models) |
Usable, weaker | Free | On-device | Smallest model — can miscategorize (e.g. a breaking change under Features), invent sections, or keep an internal commit. Free, private, fast. |
--no-ai |
Deterministic | Free | No network | Conventional-Commits grouping; keeps every commit, no rewriting. The offline baseline. |
Pick by what you care about most: best notes → Claude; private/free with
good quality → local with a capable model; private/free/fast on a Mac with
nothing to install → apple; reproducible and offline → --no-ai.
See it: the same 10 commits through three backends (real npm run compare output)
The history mixes real user-facing work (a breaking feat!: drop Node 18, two
features, two fixes, a perf win) with noise that good notes should drop (a
docs: tweak, a refactor:, a test:, a chore: dep bump).
claude-cli (Claude) — tightest. Breaking Changes first; the docs:,
refactor:, test:, and chore: commits are all dropped as noise:
## Breaking Changes
- Dropped support for Node 18 — Node 20 is now the minimum required version.
## Features
- Added cursor-based pagination to the list endpoint.
- Added a dark-mode toggle to the settings page.
## Bug Fixes
- Expired authentication tokens are now rejected with a proper error instead of a 500.
- Fixed the sidebar flickering on window resize.
## Performance
- Cached compiled regexes for roughly 3x faster cold start.local (Ollama, llama3.2) — very close, but kept the docs: commit as a
Documentation section and ordered Performance ahead of Bug Fixes:
## Breaking Changes
- Support for Node.js 18 has been dropped; the minimum supported version is now Node.js 20.
## Features
- Added a dark mode toggle to the settings page.
- Introduced cursor-based pagination for list endpoints.
## Performance
- Cached compiled regular expressions, significantly improving cold start performance.
## Bug Fixes
- Fixed an issue where the sidebar would flicker when resizing the window.
- Improved auth handling by rejecting expired tokens with a specific error instead of a 500 response.
## Documentation
- Expanded the quickstart guide with more comprehensive examples.--no-ai — deterministic baseline. Keeps every commit verbatim with its
hash, no rewriting and no noise-filtering — so the breaking change appears under
both Breaking Changes and Features, and the refactor/test/chore commits stay:
## ⚠ BREAKING CHANGES
- drop Node 18; the minimum supported version is now Node 20 (`cff23c3`)
## Features
- drop Node 18; the minimum supported version is now Node 20 (`cff23c3`)
- **ui:** add a dark-mode toggle to the settings page (`29cef29`)
- **api:** add cursor-based pagination to the list endpoint (`aebce25`)
## Bug Fixes
- stop the sidebar from flickering on window resize (`d0e275b`)
- **auth:** reject expired tokens instead of returning a 500 (`69ef42a`)
## Performance
- cache compiled regexes — about 3x faster cold start (`75e07cd`)
## Refactoring
- split the loader into smaller modules (`1758a1e`)
## Documentation
- expand the quickstart with a tag-to-HEAD example (`0ef0091`)
## Tests
- add coverage for the range parser (`68869fd`)
## Chores
- bump eslint to v10 (`1458698`)Want to judge for yourself? npm run compare runs the same fixed history
through every backend available on your machine and prints the results side by
side (see scripts/compare-providers.mjs).
import { generateReleaseNotes } from 'gitgist';
// AI-organized notes
const notes = await generateReleaseNotes({
from: 'v1.0.0',
to: 'HEAD',
title: 'v1.1.0',
});
console.log(notes);
// Deterministic, offline grouping (no AI)
const changelog = await generateReleaseNotes({ from: 'v1.0.0', ai: false });Lower-level building blocks are exported too — readCommits,
resolveCommitRange, parseCommit, buildChangelog, renderMarkdown, the
resolveProvider / provider registry, and the prompt builders — for callers
that want to customize any stage of the pipeline. See
docs/ for the architecture and requirements.
npm install
npm test # unit + integration tests with coverage
npm run lint
npm run typecheck
npm run build
npm run demo # re-capture the README demo SVGs (assets/demos/)
npm run diagram # re-capture the README flow diagram (assets/diagram.svg)
npm run compare # run the same changes through every available provider, side by sideMIT © Brian Westphal