Self-hosted autonomous agent that turns your commit history into clean, grouped, human-readable release notes — durably, so a release-notes job is never lost.
Overview
This pack provides an autonomous agent that turns a list of commit messages
into a structured changelog (Keep a Changelog style): commits are
classified according to the Conventional Commits convention (feat, fix, perf,
refactor, docs…), grouped by section, breaking changes are highlighted,
and the result is rendered as Markdown ready to paste into a CHANGELOG.md
or a GitHub/GitLab release.
The core of the product is a durable SQLite job queue. Each release generation is a task: a success is archived, a transient failure is rescheduled with backoff, a terminal failure goes to the dead-letter queue for inspection or replay. An idempotency key prevents generating the notes for the same version twice.
This pack targets operators who ship regular releases (libs, SaaS, CLIs, agent packs) and want clean release notes without manual writing. It does not replace a full CI/CD tool and does not execute any arbitrary git command supplied in the payload: it consumes a list of commits that you pass to it.
The pack is designed to be self-hosted (BYO-LLM): no API key is included. The LLM adapter detects a local CLI (Claude Code / Kimi Code / Codex) and uses it only to rewrite the wording of entries into clear prose. The deterministic parser remains the source of truth: the LLM can neither invent nor remove a change.
Architecture
┌─────────────────────────────────────────────────────────────────────┐
│ Commit list (payload / log) │
└──────────────────────────────────┬──────────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────────────────┐
│ IDLE → COLLECTING → CATEGORIZING → DRAFTING → REVIEWING → PUBLISHING │
│ OODA State Machine │
└──────────────────────────────────┬──────────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────────────────┐
│ Conventional-commit parser (deterministic) → BYO-LLM Editor │
│ load_prompt("Editor") → wording rewrite only │
└──────────────────────────────────┬──────────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────────────────┐
│ SQLite queue → retry / dead-letter → rendered Markdown changelog │
└─────────────────────────────────────────────────────────────────────┘
Pack contents
| File | Role |
|---|---|
README.md |
This file — overview and quick-start |
SOUL.md |
Mission, values and changelog-specific OODA states |
PROMPTS.md |
5 named, versioned system prompts |
CHECKLIST.md |
28 operational steps with commands |
SPEC.md |
Technical spec, configurable parameters, interfaces |
CUSTOMIZE.md |
Where to plug in your own commit sources |
OPERATING_COST_ESTIMATE.md |
LLM cost estimate (provider-agnostic) |
CHANGELOG.md |
Pack version history |
agent.py |
Runnable agent (queue + parser + renderer + BYO-LLM) |
llm_adapter.py |
BYO-LLM adapter (claude / kimi / codex, no API key) |
agent-changelog-v1.json |
Pack manifest with stats and files |
install.sh |
One-shot installer (venv, deps, systemd service) |
test_agent.py / smoke_test.sh |
Offline test suite (deterministic) |
scripts/* |
Helpers: config, install, run, prompt test |
templates/*.yaml |
Configuration templates and log examples |
Quick installation
cd /opt/agent-changelog-v1
sudo bash install.sh
The installer checks for Python 3.10+, creates a venv, installs the dependencies, detects a local LLM CLI and configures a systemd unit.
Immediate test
# Offline test suite (deterministic, no API key)
python3 test_agent.py
# Generate a changelog from commits, without an LLM
python3 agent.py enqueue --type render_changelog \
--payload '{"version":"1.2.0","commits":["feat(api): add CSV export","fix: crash on empty input","feat!: drop py38"]}'
python3 agent.py run --once --deterministic
Job types
categorize_commits: classifies a list of commits into ordered sections.draft_release: produces a structured release object (version + date + sections).render_changelog: renders the final Markdown changelog.
python3 agent.py enqueue --type render_changelog \
--payload '{"version":"2.0.0","date":"2026-06-23","commits":["feat: ...","fix: ..."]}'
python3 agent.py run --once
python3 agent.py status
python3 agent.py replay --task t-ab12cd34
Deterministic mode covers all parsing and rendering without an LLM. The
BYO-LLM mode is limited to improving the wording of entries: its output is
a JSON object {"markdown": "..."} and any error falls back to the
deterministic rendering.
Determinism vs LLM
| Step | Deterministic (no LLM) | With a connected LLM |
|---|---|---|
| Commit classification | ✅ always | identical (never delegated) |
| Breaking change detection | ✅ always | identical |
| Grouping by section | ✅ always | identical |
| Entry wording | ✅ raw commit message | ✍️ rewritten, clearer prose |
| "Zero invention" guarantee | ✅ | ✅ (the LLM can neither add nor remove) |
Customization
- Copy
scripts/config.yamltoconfig.local.yaml. - Adapt
templates/changelog_config.yaml(sections, order, type mapping). - Plug in your commit source — see
CUSTOMIZE.md.
Costs and limits
This pack favors deterministic logic: everything works without an LLM. The LLM
is only used to polish the text. See OPERATING_COST_ESTIMATE.md
for the operating cost estimate.
License
Personal use per purchase. Resale prohibited.