
Git Weekly Report
- 35 installs
- 16 repo stars
- Updated July 13, 2026
- yangsonhung/awesome-agent-skills
Helps with ai & agent building tasks.
About
git-weekly-report is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.
- git-weekly-report
- AI & Agent Building
- AI-coding skill
Git Weekly Report by the numbers
- 35 all-time installs (skills.sh)
- +2 installs in the week ending Jul 27, 2026 (Skillselion tracking)
- Ranked #8,740 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 1, 2026 (Skillselion catalog sync)
npx skills add https://github.com/yangsonhung/awesome-agent-skills --skill git-weekly-reportAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 35 |
|---|---|
| repo stars | ★ 16 |
| Last updated | July 13, 2026 |
| Repository | yangsonhung/awesome-agent-skills ↗ |
What it does
Helps with ai & agent building tasks.
Files
Git Weekly Report
Overview
Extract git commit logs and generate a structured daily or weekly report. The output groups recent work into completed items, in-progress work, highlights, plans, and risks so commit history can be reused for standups, daily reports, weekly reports, or project summaries.
When to Use
Use this skill when the user asks for:
- Generating a weekly report or daily report from git commits
- Summarizing yesterday's or today's git activity
- Summarizing recent git activity across one or more repositories
- Reviewing what work was done over a date range
- Compiling commit history into a categorized report
- Preparing a daily standup summary from commits
Do not use
Do not use this skill for:
- Code review of specific changes (use code-reviewer instead)
- Inspecting a single commit in detail
- Git operations other than log extraction (branching, merging, etc.)
- Non-git-related report generation
Instructions
1. Determine the date range and report type:
- Daily report: if user says "yesterday", "today", or "daily report", default
--sinceto yesterday and--untilto today. - Weekly report: if user says "this week" or "weekly report", default
--sinceto last Monday and--untilto today. - Otherwise: default to last 7 days. Accept user overrides.
2. Determine the author filter if the user specifies one. Default: all authors. 3. Determine repository path(s). Default: current working directory. If the user mentions multiple projects, collect all paths. 4. Run the script:
python3 scripts/git_weekly_report.py --since <YYYY-MM-DD> --until <YYYY-MM-DD> [--author <name>] [--repo <path1> <path2> ...]5. Read the JSON output. The script provides structured commit data grouped by repository. 6. Use weekly-report-format.md as the categorization guide to classify commits by type. 7. Use weekly-report-template.md as the output structure when generating the final report. 8. For "next-week plans" and "risks" sections: ask the user if they have items to add, since these are not derivable from git logs. For daily reports, omit these sections unless the user requests them. 9. Present the final Markdown report. Save to a file if the user requests it.
Script Usage
# Default: last 7 days, current directory
python3 scripts/git_weekly_report.py
# Specific date range
python3 scripts/git_weekly_report.py --since 2026-04-21 --until 2026-04-28
# With author filter
python3 scripts/git_weekly_report.py --since 2026-04-21 --author "Yang"
# Multiple repositories
python3 scripts/git_weekly_report.py --since 2026-04-21 --repo /path/to/project-a /path/to/project-b
# Save output to file
python3 scripts/git_weekly_report.py --since 2026-04-21 --output /tmp/weekly.json
# Include merge commits
python3 scripts/git_weekly_report.py --since 2026-04-21 --mergesJSON Output Structure
The script outputs JSON with this structure:
date_range:{ since, until }— the queried date rangeauthor_filter: string or null — applied author filterrepositories: array of{ path, name, commit_count, commits }total_commits: total across all repositories
Each commit has: hash, short_hash, author, date, subject, body, refs.
Report Generation
When commits exceed 50 per repository, summarize by category rather than listing every commit individually. Always preserve short hashes for traceability.
For the "In Progress" section, look for signals like: WIP, TODO, partial implementations, or incomplete feature branches.
For the "Highlights" section, identify: breaking changes, security fixes, major features, or commits touching critical paths.
Weekly Report
Period: {since} - {until} Author: {author}
---
Completed Work
{Project Name}
New Features
- {commit subject} ({short_hash})
Bug Fixes
- {commit subject} ({short_hash})
Refactoring
- {commit subject} ({short_hash})
Documentation
- {commit subject} ({short_hash})
Maintenance
- {commit subject} ({short_hash})
---
In Progress
- {description of ongoing work}
---
Highlights
- {notable achievements or important changes}
---
Next Week Plan
- {planned tasks — ask the user to provide}
---
Risks & Blockers
- {risks or blockers — ask the user to provide}
Weekly Report Categorization Guide
Conventional Commit Mapping
Map commit prefixes to report categories:
| Prefix | Category |
|---|---|
feat: | New Features |
fix: | Bug Fixes |
refactor: | Refactoring |
docs: | Documentation |
chore: | Maintenance |
test: | Testing |
perf: | Performance |
style: | Code Style |
ci: | CI/CD |
build: | Build System |
Non-Conventional Commits
When commits lack conventional prefixes, infer category from keywords:
- New Features: add, implement, create, introduce, support, enable
- Bug Fixes: fix, resolve, repair, patch, workaround, hotfix
- Refactoring: refactor, restructure, reorganize, simplify, clean up, migrate
- Documentation: docs, readme, guide, comment, document
- Maintenance: update, upgrade, bump, deps, dependency, config, chore
- Testing: test, spec, coverage, verify, assert
- Performance: optimize, speed, fast, slow, latency, memory
Grouping Strategy
1. Group by project first (repository name) 2. Within each project, group by category 3. Within each category, list commits chronologically (newest first) 4. Merge similar commits (e.g., multiple "docs(readme)" commits → one entry with count)
In-Progress Detection Signals
Identify work that may still be in progress:
- Subject contains: WIP, TODO, draft, partial, temp, workaround
- Body contains: "still need to", "remaining", "follow-up", "next step"
- Feature branches not yet merged to main
Highlight Detection Signals
Identify commits worth highlighting:
- Subject contains: breaking, BREAKING, security, critical, important, milestone
- Body contains: "breaking change", "security fix", "migration required"
- Large scope changes (files changed > 10 in a single commit)
- First commit implementing a major feature
#!/usr/bin/env python3
"""Extract git commit logs as structured JSON for weekly report generation."""
import argparse
import json
import os
import subprocess
import sys
from datetime import date, timedelta
MAX_BODY_LENGTH = 500
def run_git_log(repo_path, since, until, author=None, no_merges=True):
"""Run git log in a repo and return parsed commit entries."""
cmd = ["git", "-C", repo_path, "log", "--all"]
if no_merges:
cmd.append("--no-merges")
cmd.append(f"--since={since}")
cmd.append(f"--until={until} 23:59:59")
if author:
cmd.append(f"--author={author}")
# %x00 = NUL (record separator), %x01 = SOH (field separator)
cmd.append("--format=%H%x01%h%x01%an%x01%aI%x01%s%x01%b%x01%D%x00")
try:
result = subprocess.run(
cmd, capture_output=True, text=True, encoding="utf-8", errors="replace"
)
except FileNotFoundError:
print("Error: git not found on PATH", file=sys.stderr)
sys.exit(1)
if result.returncode != 0:
print(f"Warning: git log failed for {repo_path}: {result.stderr.strip()}", file=sys.stderr)
return []
commits = []
for record in result.stdout.split("\x00"):
record = record.strip()
if not record:
continue
parts = record.split("\x01")
if len(parts) < 7:
print(f"Warning: skipping malformed record: {record[:80]}", file=sys.stderr)
continue
body = parts[5].strip()
if len(body) > MAX_BODY_LENGTH:
body = body[:MAX_BODY_LENGTH] + "..."
commits.append({
"hash": parts[0],
"short_hash": parts[1],
"author": parts[2],
"date": parts[3],
"subject": parts[4],
"body": body,
"refs": parts[6],
})
return commits
def is_git_repo(path):
"""Check if a path is a git repository."""
try:
result = subprocess.run(
["git", "-C", path, "rev-parse", "--git-dir"],
capture_output=True, text=True, encoding="utf-8", errors="replace"
)
return result.returncode == 0
except FileNotFoundError:
return False
def main():
parser = argparse.ArgumentParser(
description="Extract git commit logs as structured JSON for weekly reports"
)
parser.add_argument(
"--since",
default=None,
help="Start date (YYYY-MM-DD), default: 7 days ago",
)
parser.add_argument(
"--until",
default=None,
help="End date (YYYY-MM-DD), default: today",
)
parser.add_argument(
"--author",
default=None,
help="Filter commits by author (substring match)",
)
parser.add_argument(
"--repo",
nargs="+",
default=None,
help="One or more git repository paths (default: current directory)",
)
parser.add_argument(
"--output",
default=None,
help="Output file path (default: stdout)",
)
parser.add_argument(
"--no-merges",
action="store_true",
default=True,
help="Exclude merge commits (default: True)",
)
parser.add_argument(
"--merges",
action="store_true",
default=False,
help="Include merge commits",
)
args = parser.parse_args()
today = date.today()
since = args.since or (today - timedelta(days=7)).isoformat()
until = args.until or today.isoformat()
no_merges = not args.merges
repos = args.repo or [os.getcwd()]
output = {
"date_range": {"since": since, "until": until},
"author_filter": args.author,
"repositories": [],
"total_commits": 0,
}
for repo_path in repos:
repo_path = os.path.abspath(repo_path)
if not is_git_repo(repo_path):
print(f"Warning: {repo_path} is not a git repository, skipping", file=sys.stderr)
continue
repo_name = os.path.basename(repo_path)
commits = run_git_log(repo_path, since, until, args.author, no_merges)
output["repositories"].append({
"path": repo_path,
"name": repo_name,
"commit_count": len(commits),
"commits": commits,
})
output["total_commits"] += len(commits)
json_str = json.dumps(output, ensure_ascii=False, indent=2)
if args.output:
with open(args.output, "w", encoding="utf-8") as f:
f.write(json_str)
else:
print(json_str)
if __name__ == "__main__":
main()