# Daily Releases

> Create GitHub Releases with AI-analyzed changelogs for every calendar day with commits on origin/main. Uses the same analyze → AI-categorize → format pipeline as /create-merge-request-changelog for rich, structured output. Idempotent: skips days that are already up to date, updates releases where new commits have been added. Automatically invoked when command is run; accepts optional --start-date, --end-date, --branch, --dry-run arguments.

- Skill: `tools-only/daily-releases-2` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add tools-only/daily-releases-2`
- Raw SKILL.md: https://api.skillmd.com/api/skills/tools-only/daily-releases-2/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- Author: tools-only (https://skillmd.com/u/tools-only)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/tools-only/daily-releases-2

---

# Daily Releases

Create GitHub Releases with AI-categorized changelogs for every day that had commits. Uses the same pipeline as `/create-merge-request-changelog` — real AI analysis, not template substitution.

## Automatic Invocation

When this skill is activated, immediately begin processing without asking the user. Parse any arguments from `$ARGUMENTS`:

```text
--start-date YYYY-MM-DD   Only process days on or after this date
--end-date YYYY-MM-DD     Only process days on or before this date (default: today)
--branch BRANCH           Git branch (default: origin/main)
--dry-run                 Preview without creating releases
```

## Process

Requires `GITHUB_TOKEN` for release status checks (list) and publishing.

**Working directory:** Run all commands from the repository root. Paths below assume cwd is the repo root.

### Step 1: List days to process

```bash
uv run .claude/skills/daily-releases/scripts/list_daily_ranges.py [--branch BRANCH] [--start-date ...] [--end-date ...] [-R OWNER/REPO]
```

This outputs a JSON array. Each entry has:

```json
{
  "date": "2026-02-21",
  "tag": "v2026.02.21",
  "base_ref": "<parent-commit-hash>",
  "head_ref": "<last-commit-hash-of-day>",
  "commit_count": 12,
  "release_exists": true,
  "needs_update": false
}
```

Skip entries where `release_exists: true` and `needs_update: false` — those are up to date.

For `--dry-run`, print the list and stop.

### Step 2: For each day that needs a release

Work through days chronologically. For each day:

#### 2a. Extract git data

```bash
uv run .claude/skills/create-merge-request-changelog/scripts/analyze_git_changes.py \
  <base_ref> <head_ref> ./daily-releases/<date>/
```

This writes to `./daily-releases/<date>/`:

- `commits_oneline.txt` — one-line commit list
- `commits_detailed.txt` — full commit messages with metadata
- `changes.diff` — unified diff
- `changes_stat.txt` — diffstat summary
- `changed_files.txt` — file list with A/M/D status
- `changes_numstat.txt` — per-file line counts
- `summary.json` — machine-readable stats

#### 2b. AI analysis (delegate to subagent — do NOT read git data files yourself)

Delegate analysis to a Haiku subagent via Task():

```python
Task(
  subagent_type="general-purpose",
  model="claude-haiku-4-5-20251001",
  prompt="""
Read these files:
- ./daily-releases/<date>/commits_detailed.txt
- ./daily-releases/<date>/changes.diff  (if file exceeds 4000 chars, use changes_stat.txt instead)
- ./daily-releases/<date>/changed_files.txt
- ./daily-releases/<date>/summary.json

Apply the Primary Analysis Prompt from:
  .claude/skills/create-merge-request-changelog/references/analysis_prompts.md

Substitute the file contents into the prompt template variables:
- {commit_details} <- commits_detailed.txt
- {changes_diff} <- changes.diff (or changes_stat.txt)
- {changed_files} <- changed_files.txt
- stats fields <- summary.json

Write the complete structured JSON output to: ./daily-releases/<date>/analysis.json

Report "analysis.json written" when done.
"""
)
```

Replace `<date>` with the actual date value for that iteration before emitting the Task() call.

After the Task() returns, verify `./daily-releases/<date>/analysis.json` exists before proceeding to Step 2c. If missing, report the error and stop.

#### 2c. Format into release notes

```bash
uv run .claude/skills/create-merge-request-changelog/scripts/format_mr_description.py \
  ./daily-releases/<date>/analysis.json \
  --no-preview \
  --output ./daily-releases/<date>/description.md
```

#### 2d. Publish the release

```bash
uv run .claude/skills/daily-releases/scripts/publish_daily_release.py \
  --date <date> \
  --tag <tag> \
  --head-ref <head_ref> \
  --notes-file ./daily-releases/<date>/description.md
```

Add `--keep-existing-tag=false` if updating a release that already has the correct tag commit.

### Step 3: Report

After processing all days, print a summary:

```text
Processed N days:
  - Created: X new releases
  - Updated: Y existing releases
  - Skipped: Z already up to date
```

## Reference files

- [./scripts/list_daily_ranges.py](./scripts/list_daily_ranges.py) — list days + commit ranges
- [./scripts/publish_daily_release.py](./scripts/publish_daily_release.py) — create/update git tag + GitHub release
- [../create-merge-request-changelog/scripts/analyze_git_changes.py](../create-merge-request-changelog/scripts/analyze_git_changes.py) — extract git data per day
- [../create-merge-request-changelog/references/analysis_prompts.md](../create-merge-request-changelog/references/analysis_prompts.md) — AI analysis prompts
- [../create-merge-request-changelog/scripts/format_mr_description.py](../create-merge-request-changelog/scripts/format_mr_description.py) — render AI analysis to markdown

Reference paths above are relative to this skill directory; CLI commands use repo-root paths.

