herald-ai
v2.5.1
Published
<img width="1472" height="704" alt="Gemini_Generated_Image_kca972kca972kca9" src="https://github.com/user-attachments/assets/a6a42f2e-01e1-4f5e-ba7c-c098aa4fec0a" />
Readme
Herald is a CLI tool that generates AI-powered changelogs from your git commit history and announces releases to multiple platforms. It diffs commits between HEAD and a selected tag, sends them to an LLM, and posts the result to your configured providers.
Supports any OpenAI-compatible AI platform (defaults to OpenRouter).
Installation
Install Herald as a dev dependency:
pnpm install -D herald-aiAgent-Assisted Setup
Herald ships with a herald-setup skill that works with any agent supporting the skills spec (Claude Code, Cursor, etc.). It walks you through choosing a config format, selecting providers, and generating the config and env vars for your project.
Add the skill using your package manager of choice:
# npm
npx skills add amirhosseinNouri/herald-ai
# bun
bunx skills add amirhosseinNouri/herald-ai
# pnpm
pnpm dlx skills add amirhosseinNouri/herald-ai
# yarn
yarn dlx skills add amirhosseinNouri/herald-aiThen ask your agent to "set up herald-ai".
Configuration
Create a herald.config.ts (or .js, .mjs, .json) file in your project root:
import { defineConfig } from "herald-ai";
export default defineConfig({
ai: {
model: "openai/gpt-4o-mini",
apiKey: process.env.AI_API_KEY!,
},
providers: [
{ type: "teams", webhookUrl: process.env.TEAMS_WEBHOOK_URL! },
],
});JSON Config
You can also use a herald.config.json file. Environment variable references ($VAR or ${VAR}) are automatically interpolated:
{
"ai": {
"model": "openai/gpt-4o-mini",
"apiKey": "$AI_API_KEY"
},
"providers": [
{ "type": "teams", "webhookUrl": "${TEAMS_WEBHOOK_URL}" }
]
}Environment Variables
Herald uses dotenv-flow to automatically load environment variables from .env files. The following files are loaded in order (variables defined in earlier files take precedence):
.env.env.local.env.[NODE_ENV](e.g..env.development,.env.production).env.[NODE_ENV].local(e.g..env.development.local)
This works for both TS/JS configs (via process.env) and JSON configs (via $VAR / ${VAR} interpolation). Existing environment variables (e.g. from CI) are never overridden.
Tip: Add
.env*.localto your.gitignoreto keep local secrets out of version control.
Full Config Example
import { defineConfig } from "herald-ai";
export default defineConfig({
ai: {
model: "openai/gpt-4o-mini",
apiKey: process.env.AI_API_KEY!,
baseUrl: "https://openrouter.ai/api/v1", // optional, defaults to OpenRouter
},
providers: [
// Microsoft Teams
{
type: "teams",
webhookUrl: process.env.TEAMS_WEBHOOK_URL!,
},
// GitLab Release Page
{
type: "gitlab-release",
baseUrl: "https://gitlab.example.com/api/v4",
token: process.env.GITLAB_TOKEN!,
projectId: "5755",
},
// Telegram
{
type: "telegram",
botToken: process.env.TELEGRAM_BOT_TOKEN!,
chatId: process.env.TELEGRAM_CHAT_ID!,
},
// Element (Matrix)
{
type: "element",
homeserverUrl: "https://matrix.example.com",
accessToken: process.env.ELEMENT_ACCESS_TOKEN!,
roomId: "!roomid:example.com",
},
// Slack
{
type: "slack",
webhookUrl: process.env.SLACK_WEBHOOK_URL!,
},
// Mattermost
{
type: "mattermost",
webhookUrl: process.env.MATTERMOST_WEBHOOK_URL!,
},
],
// Optional: path to a markdown file with extra instructions appended to the
// built-in changelog prompt (e.g. project-specific rules, ignored commit
// patterns, grouping preferences). Path is resolved relative to cwd.
promptFile: "./herald.prompt.md",
// Optional: require an interactive confirmation before publishing outside CI
manualConfirm: true,
// Optional: override project name (defaults to package.json name)
projectName: "My App",
// Optional: override release manager (defaults to git config user.name)
releaseManager: "Jane Doe",
// Optional: debug mode - only prints changelog, no announcements
debug: false,
});Debug-Only Config
To only generate and preview the changelog without sending announcements:
import { defineConfig } from "herald-ai";
export default defineConfig({
ai: {
model: "openai/gpt-4o-mini",
apiKey: process.env.AI_API_KEY!,
},
providers: [
{ type: "teams", webhookUrl: "https://placeholder" },
],
debug: true,
});Usage
# Interactive mode: select a tag from a list
herald-ai
# Specify a tag directly
herald-ai --from v1.2.0
# Debug mode: generate changelog without sending announcements
herald-ai --debug
# Custom config path
herald-ai --config ./config/herald.config.ts
# Inject custom instructions from a markdown file
herald-ai --prompt ./herald.prompt.mdCustom Prompt File
Use promptFile (config) or --prompt / -p (CLI) to point to a markdown file with extra instructions. Contents are appended to Herald's built-in changelog prompt inside a <custom-instructions> block, so the defaults still apply. The CLI flag takes precedence over the config field.
Example herald.prompt.md:
- Skip commits whose messages start with `chore(release)` or look like version bumps (`v1.2.3`).
- Group all dependency bumps under a single "Dependencies" item.
- Prefix breaking-change items with `[BREAKING]`.Add to Scripts
{
"scripts": {
"announce": "herald-ai",
"changelog": "herald-ai --debug"
}
}How It Works
- Herald loads your configuration (
herald.config.ts,.js,.mjs, or.json) - Fetches all semver tags from your local git repository
- You select a tag (interactively, via
--from, or auto-selected in CI environments) - Gets all commits between the selected tag and HEAD
- Sends commits to the configured AI model to generate a changelog
- Posts the changelog to all configured providers (or prints it in debug mode)
Command Line Options
| Flag | Description |
|------|-------------|
| --config <path> | Path to config file (default: auto-discover herald.config.{ts,js,mjs,json}) |
| --from <tag> | Specify a tag to diff against HEAD |
| --prompt <path>, -p | Path to a markdown file with extra instructions appended to the changelog prompt (overrides promptFile in config) |
| --debug | Generate changelog and print it without sending announcements |
Note: Herald automatically detects CI environments (GitHub Actions, GitLab CI) and runs in non-interactive mode, auto-selecting the latest semver tag.
Providers
| Provider | Description | Required Config |
|----------|-------------|-----------------|
| teams | Microsoft Teams webhook | webhookUrl |
| gitlab-release | GitLab Release page | baseUrl, token, projectId |
| telegram | Telegram bot message | botToken, chatId |
| element | Element/Matrix room message | homeserverUrl, accessToken, roomId |
| slack | Slack incoming webhook | webhookUrl |
| mattermost | Mattermost incoming webhook | webhookUrl |
Requirements
- Node.js 18+ or Bun
- AI API key (OpenRouter by default, or any OpenAI-compatible platform)
- Git repository with semver tags (e.g.,
v1.2.3)
