Getting Started

Go from zero to release notes in under two minutes.

Installation

Install Cullit globally or use it with npx — no install needed:

# Run without installing
npx cullit generate --from HEAD~10 --provider none

# Or install globally
npm install -g cullit

# Or with pnpm
pnpm add -g cullit
The --provider none flag uses a built-in template engine — no AI key needed. Great for trying Cullit out.

Your First Run

Navigate to any Git repository and run:

# Generate notes from the last 10 commits, no AI key required
cullit generate --from HEAD~10 --provider none

# Generate notes between two tags with AI
cullit generate --from v1.0.0 --to v1.1.0

# Auto-detect: uses the two most recent tags
cullit generate

Cullit collects commits, enriches with ticket context (if configured), runs them through AI, and outputs categorized release notes.

Pricing & Tiers

Cullit uses a CULLIT_API_KEY to unlock Pro features. Without a key, the free tier is fully functional for template-based notes.

FeatureFreePro ($29/mo)
Template engine (--provider none)
Publish to stdout & file
cullit status & cullit tags
AI providers (Anthropic, OpenAI, Gemini, Ollama)
Jira & Linear enrichment
Slack, Discord & GitHub Release publishing
GitHub Action with AI

To activate Pro, set your API key:

# In your shell or .env file
CULLIT_API_KEY=clt_your_key_here

Get your key at sales@cullit.io or visit cullit.io/pricing.

Enterprise plans with team seats, SSO, and SLAs are available. Contact sales@cullit.io.

Configuration

Create a .cullit.yml in your project root. You can generate one interactively:

cullit init

Full config reference:

# .cullit.yml

ai:
  provider: anthropic        # anthropic | openai | gemini | ollama | openclaw | none
  model: claude-sonnet-4-20250514  # optional: override default model
  audience: developer       # developer | end-user | executive
  tone: professional        # professional | casual | terse
  categories:              # customize change categories
    - features
    - fixes
    - breaking
    - improvements
    - chores

source:
  type: local               # local (git) | jira | linear
  enrichment:              # enrich git commits with ticket data
    - jira
    - linear

publish:
  - type: stdout
  - type: file
    path: RELEASE_NOTES.md
  - type: slack
    webhook_url: $SLACK_WEBHOOK_URL
  - type: slack
    webhook_url: $DISCORD_WEBHOOK_URL

jira:
  domain: yourcompany.atlassian.net
  # Set JIRA_EMAIL and JIRA_API_TOKEN in your environment

linear:
  # Set LINEAR_API_KEY in your environment

AI Providers

Cullit supports six providers. Set the relevant API key in your environment:

ProviderEnv VariableDefault ModelNotes
AnthropicANTHROPIC_API_KEYclaude-sonnet-4-20250514Best quality. Recommended.
OpenAIOPENAI_API_KEYgpt-4oGreat alternative.
GeminiGEMINI_API_KEYgemini-2.5-flashGoogle AI.
OllamaOLLAMA_HOST (optional)llama3.1Local inference. Free. Private.
OpenClawOPENCLAW_TOKENroutes to best modelAI gateway / router.
nonebuilt-in templateNo AI key needed. Categorizes by conventional commits.
Override the provider per-run: cullit generate --from v1.0.0 --provider openai --model gpt-4o-mini

Environment Variables

Cullit reads these from your shell or a .env file in the project root:

VariablePurpose
CULLIT_API_KEYCullit Pro license key (enables AI, integrations, advanced publishing)
ANTHROPIC_API_KEYAnthropic API key
OPENAI_API_KEYOpenAI API key
GEMINI_API_KEYGemini API key
OLLAMA_HOSTOllama server URL (default: http://localhost:11434)
OPENCLAW_TOKENOpenClaw gateway auth token
JIRA_EMAILJira account email for API auth
JIRA_API_TOKENJira API token
LINEAR_API_KEYLinear API key
SLACK_WEBHOOK_URLSlack incoming webhook
DISCORD_WEBHOOK_URLDiscord webhook
GITHUB_TOKENGitHub token (auto-set in Actions)

CLI Reference

cullit generate

Generate release notes from git commits, Jira issues, or Linear tickets.

FlagShortDescriptionDefault
--from-fStart ref โ€” tag, branch, SHA, JQL, or Linear filterAuto-detect (2nd latest tag)
--to-tEnd ref โ€” tag, branch, or SHAHEAD
--providerAI provider to useFrom config or anthropic
--modelAI model overrideProvider default
--formatOutput format: markdown, html, jsonmarkdown
--sourceSource type: local, jira, linearFrom config or local
--audienceAudience: developer, end-user, executiveFrom config or developer
--config-cConfig file path.cullit.yml
--dry-runGenerate but don't publish
--verboseShow detailed output
--quietSuppress non-error output
# Between two tags
cullit generate --from v2.3.0 --to v2.4.0

# Last N commits, JSON output
cullit generate --from HEAD~15 --format json

# Executive summary with Gemini
cullit generate --from v1.0.0 --audience executive --provider gemini

# From Jira sprint
cullit generate --source jira --from "project = PROJ AND sprint = 'Sprint 42'"

# From Linear team
cullit generate --source linear --from "team:ENG"

# No AI key, template engine
cullit generate --from HEAD~5 --provider none

# Local Ollama
cullit generate --from v1.0.0 --provider ollama --model llama3.1

cullit status

Release readiness check. Analyzes unreleased commits and recommends whether it's time to release, what semver bump to use, and why.

cullit status

# Output:
  Current version:   v1.2.0
  Suggested next:    v1.3.0 (minor)
  Last release:      12 day(s) ago
  Unreleased commits: 8
  Contributors:      3

  Commit breakdown:
    โœจ Features:  โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ 4
    ๐Ÿ› Fixes:     โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ 2
    ๐Ÿงน Chores:    โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ 1
    ๐Ÿ“ Other:     โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ 1

  Should you release? ๐ŸŸข Yes โ€” time to release

  Why:
    โ†’ 4 new feature(s) โ€” minor bump recommended
    โ†’ 8 commit(s) since v1.2.0 โ€” consider releasing

The advisor also runs automatically after cullit generate and nudges you when thresholds are met (suppressed in --quiet mode).

cullit init

Interactive config setup. Creates a .cullit.yml with your preferences:

cullit init

# Prompts for: provider, source, audience, tone, enrichment
# Creates .cullit.yml in the current directory

cullit tags

Lists recent git tags in the repository โ€” useful for finding the right --from ref:

cullit tags

Recent tags:
  โ†’ v2.4.0
    v2.3.0
    v2.2.1
    v2.2.0

Integrations

GitHub Action

Add Cullit to your CI/CD pipeline with zero configuration:

# .github/workflows/release-notes.yml
name: Release Notes
on:
  push:
    tags: ['v*']

jobs:
  release-notes:
    runs-on: ubuntu-latest
    permissions:
      contents: write  # for GitHub Release
    steps:
      - uses: actions/checkout@v5
        with:
          fetch-depth: 0  # full history for tag comparison

      - uses: mttaylor/cullit@main
        with:
          provider: anthropic
          audience: end-user
          publish-github-release: 'true'
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Action inputs:

InputDescriptionDefault
fromStart ref (auto-detects previous tag if omitted)previous tag
toEnd refHEAD
providerAI provideranthropic
modelAI model overrideprovider default
audienceTarget audiencedeveloper
toneWriting toneprofessional
formatOutput formatmarkdown
publish-github-releaseCreate/update GitHub Releasefalse
publish-slack-webhookSlack webhook URL
publish-discord-webhookDiscord webhook URL
jira-domainJira domain for enrichment

Jira Integration

Cullit can use Jira as a primary source (replace git) or as enrichment (add ticket context to git commits).

As primary source:

# Query completed issues by project
cullit generate --source jira --from PROJ

# By sprint
cullit generate --source jira --from "project = PROJ AND sprint = 'Sprint 42'"

# By fix version
cullit generate --source jira --from PROJ --to v2.0

As enrichment (adds Jira details to git commits):

# .cullit.yml
source:
  type: local
  enrichment: [jira]

jira:
  domain: yourcompany.atlassian.net

Set JIRA_EMAIL and JIRA_API_TOKEN in your environment.

Cullit extracts Jira keys like PROJ-123 from commit messages and enriches them with titles, descriptions, labels, and priority from the Jira API.

Linear Integration

Works the same way — as a primary source or enrichment.

As primary source:

# By team
cullit generate --source linear --from "team:ENG"

# By project
cullit generate --source linear --from "project:Mobile App"

# By label
cullit generate --source linear --from "label:release-v2"

# Current cycle
cullit generate --source linear --from "cycle:current"

As enrichment:

# .cullit.yml
source:
  type: local
  enrichment: [linear]

Set LINEAR_API_KEY in your environment.

Publishing

Cullit publishes to multiple targets simultaneously. Configure in .cullit.yml.

stdout & File

publish:
  - type: stdout           # print to terminal
  - type: file
    path: RELEASE_NOTES.md # write to file

Slack

Create an incoming webhook in your Slack workspace, then:

publish:
  - type: slack
    webhook_url: $SLACK_WEBHOOK_URL

Cullit formats notes with emoji categories and Slack mrkdwn syntax.

Discord

Create a webhook in your Discord channel settings, then:

publish:
  - type: discord
    webhook_url: $DISCORD_WEBHOOK_URL

Posts as a rich embed with the Cullit accent color.

GitHub Release

Automatically creates or updates a GitHub Release. Works in GitHub Actions (uses GITHUB_TOKEN automatically):

publish:
  - type: github-release

Advanced Usage

Library Usage

Use Cullit programmatically in your Node.js / TypeScript projects:

npm install @cullit/core @cullit/config
import { runPipeline, createLogger } from '@cullit/core';
import { loadConfig } from '@cullit/config';

const config = loadConfig();
const logger = createLogger('verbose');

const result = await runPipeline('v1.0.0', 'HEAD', config, {
  format: 'markdown',
  dryRun: true,
  logger,
});

console.log(result.formatted);     // the release notes string
console.log(result.notes.changes); // structured change entries
console.log(result.duration);      // pipeline duration in ms

Packages:

PackagePurpose
cullitCLI tool — npx cullit generate
@cullit/coreCore engine: pipeline, collectors, generators, publishers
@cullit/configConfig loader: YAML parsing, env var resolution, type exports

Release Advisor

The release advisor analyzes your unreleased commits and recommends when to release:

import { analyzeReleaseReadiness } from '@cullit/core';

const advisory = analyzeReleaseReadiness();

console.log(advisory.shouldRelease);   // true | false
console.log(advisory.suggestedBump);   // 'patch' | 'minor' | 'major'
console.log(advisory.nextVersion);     // 'v1.3.0'
console.log(advisory.reasons);         // ['4 new features', '12 days since last release']
console.log(advisory.breakdown);       // { features: 4, fixes: 2, breaking: 0, ... }

Heuristics that trigger a release recommendation:

API Server

Cullit includes a lightweight REST API for programmatic access:

# Start the server
node packages/api/dist/index.js

# Generate release notes
curl -X POST http://localhost:3000/generate \
  -H "Content-Type: application/json" \
  -d '{"from": "v1.0.0", "provider": "none"}'

Endpoints:

MethodPathDescription
GET/healthHealth check — version, uptime
GET/openapi.jsonOpenAPI 3.1 specification
POST/generateGenerate release notes

Configuration:

Env VariablePurposeDefault
PORTServer port3000
CULLIT_API_TOKENBearer token for authdisabled
ALLOWED_ORIGINSCORS allowed origins*
RATE_LIMITRequests per minute per IP30

Real-World Walkthrough

Here's exactly how you'd set up Cullit for a real project from scratch.

Scenario

You maintain a SaaS product called Acme Dashboard. Your team uses GitHub for code, Jira for project management, and Slack for comms. You want release notes auto-generated when you push a tag.

Step 1 — Install & Initialize

cd ~/projects/acme-dashboard
npm install -g cullit
cullit init

# Answer the prompts:
  AI provider: anthropic
  Source type: local
  Audience: end-user
  Tone: professional
  Enrich from: jira
  โœ“ Created .cullit.yml

Step 2 — Configure Integrations

Edit the generated .cullit.yml:

ai:
  provider: anthropic
  audience: end-user     # customer-facing notes
  tone: professional

source:
  type: local
  enrichment: [jira]    # pull ticket context

publish:
  - type: stdout
  - type: file
    path: CHANGELOG.md
  - type: slack
    webhook_url: $SLACK_WEBHOOK_URL

jira:
  domain: acme.atlassian.net

Step 3 — Set Environment Variables

# .env (add to .gitignore!)
ANTHROPIC_API_KEY=sk-ant-...
JIRA_EMAIL=matt@acme.com
JIRA_API_TOKEN=ATATT3x...
SLACK_WEBHOOK_URL=https://hooks.slack.com/services/T.../B.../...

Step 4 — Test Locally

# Preview notes from the last 5 commits (dry run)
cullit generate --from HEAD~5 --dry-run

# Check readiness
cullit status

# Full run between tags
cullit generate --from v2.3.0 --to v2.4.0

Step 5 — Automate with GitHub Actions

Create .github/workflows/release-notes.yml:

name: Release Notes
on:
  push:
    tags: ['v*']

permissions:
  contents: write

jobs:
  notes:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v5
        with:
          fetch-depth: 0

      - uses: mttaylor/cullit@main
        with:
          provider: anthropic
          audience: end-user
          publish-github-release: 'true'
          publish-slack-webhook: ${{ secrets.SLACK_WEBHOOK_URL }}
          jira-domain: acme.atlassian.net
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
          JIRA_EMAIL: ${{ secrets.JIRA_EMAIL }}
          JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }}
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Step 6 — Ship a Release

# Check if it's time to release
cullit status

# Tag and push
git tag v2.4.0
git push origin v2.4.0

# GitHub Actions fires automatically:
#   โ†’ Collects commits v2.3.0..v2.4.0
#   โ†’ Enriches with Jira ticket data
#   โ†’ Generates AI-powered release notes
#   โ†’ Creates GitHub Release
#   โ†’ Posts to #releases in Slack

What You Get

A GitHub Release and Slack message that looks like this:

## Release v2.4.0 โ€” March 13, 2026

This release introduces real-time collaboration, new export
formats, and several performance improvements.

โœจ Features
- Real-time collaboration for shared dashboards (DASH-142)
- Export API now supports CSV and PDF formats (DASH-156)
- Webhook configuration UI with test-send (DASH-161)

๐Ÿ› Bug Fixes
- Fixed timezone rendering in scheduled reports (DASH-149)
- Resolved memory leak in WebSocket pool (DASH-155)

โš ๏ธ Breaking Changes
- /api/v1/export deprecated, use /api/v2/export (DASH-160)
The AI generates human-readable descriptions from raw commit messages and ticket data — not just a commit log dump. Different audience modes produce different output from the same data.

Cullit is open source under the MIT license. View on GitHubnpmHome