From worklog-notion
Log today's git commits to the Notion Work Log database. Pulls commits authored by the current user today, groups them by ticket/branch, infers impact/category/wins/skills from commit messages and branch names, then writes structured rows to Notion. Run once at end of work day.
How this skill is triggered — by the user, by Claude, or both
Slash command
/worklog-notion:worklogThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Log today's git commits to the Notion Work Log database. Do this step by step, in order.
Log today's git commits to the Notion Work Log database. Do this step by step, in order.
Run the following to verify the environment:
git rev-parse --git-dir 2>/dev/null && echo "IS_GIT_REPO=yes" || echo "IS_GIT_REPO=no"
echo "TODAY=$(date '+%Y-%m-%d')"
echo "GIT_AUTHOR=$(git config user.name 2>/dev/null)"
NOTION_PAGE_ID=$(jq -r '.pluginOptions["worklog-notion@local-plugins"].notion_page_id // empty' "$HOME/.claude/settings.json" 2>/dev/null)
echo "NOTION_PAGE_ID=${NOTION_PAGE_ID}"
IS_GIT_REPO=no: stop and tell the user to run /worklog from inside a git repository.NOTION_PAGE_ID is empty: stop and tell the user to add notion_page_id under pluginOptions["worklog-notion@local-plugins"] in ~/.claude/settings.json.GIT_AUTHOR is empty: stop and ask the user to run git config user.name "Your Name".Use git config user.name for the author. Store the resolved NOTION_PAGE_ID value — it will be used in Step 5.
AUTHOR="${CLAUDE_PLUGIN_OPTION_GIT_AUTHOR:-$(git config user.name)}"
TODAY=$(date '+%Y-%m-%d')
git log \
--since="${TODAY} 00:00:00" \
--author="$AUTHOR" \
--format="<<<COMMIT>>>%n%H%n%s%n%b<<<REFS>>>%D%n<<<END>>>" \
--all
If there is no output: respond "No commits found today for . Nothing to log." and stop.
The output contains commit blocks delimited by <<<COMMIT>>> and <<<END>>>. Each block has this structure:
<<<COMMIT>>>
<hash>
<subject>
<body — may be empty or span multiple lines>
<<<REFS>>>
<refs>
<<<END>>>
Parse each block: extract hash, subject, body (all lines between the subject line and <<<REFS>>>), and refs. Use the subject and body when inferring descriptions and impact in Step 4.
From the <refs> field, extract branch names. From branch names, commit subjects, and commit bodies, extract ticket IDs matching the pattern [A-Z]+-\d+ (e.g. SOFTDEV-19381, JIRA-42).
Group all commits that share the same ticket ID. Commits with no detectable ticket → group under the branch name itself (or "OTHER" if on main/develop).
For each ticket group, reason carefully about the commits and produce a JSON object with these exact fields:
{
"ticket": "SOFTDEV-19381",
"description": "...",
"impact": "...",
"category": "Migration",
"wins": false,
"skills": ["React", "Saga", "API Design"]
}
ticket: The extracted ticket ID (e.g. SOFTDEV-19381). If no ticket pattern found, use the branch name.
description: 1–2 sentences summarizing what was done. Be specific — name the component, file, or system affected. Draw from the commit messages and branch name.
Examples:
- "Adapted NavProcessPage saga, utils, and components to new backend contract. Created frontend migration specs (510+ lines)."
- "Fixed parseFloat footer summatory logic in InvestorsTable column cell views."
impact: 1 sentence describing the business or technical value of this work.
Examples:
- "Establishes the frontend contract for backend API migration, unblocking future integration across the Reporting domain."
- "Corrects numeric calculation accuracy in the investors table footer, fixing incorrect aggregated totals."
category — choose exactly one:
| Value | When to use |
|---|---|
Feature | New functionality added |
Bug Fix | Fixes broken behavior (fix, bug, broken, strange-behavior in branch/commit) |
Migration | Adapting to new API/contract (adapt, contract, endpoint, naming, migr) |
Architecture | Structural changes, refactoring (refactor, restructure, move, arch) |
Docs | Documentation or specs (spec, readme, doc, guide) |
Review | PR review / requested changes (pr-change, requested, review) |
Chore | Maintenance, config, tooling (default if nothing else fits) |
wins (boolean): true if you'd mention this work in a performance review:
skills — pick 1–4 most relevant from this exact list:
React, Redux, RTK Query, Architecture, API Design, Saga, Docs, Data Formatting, Testing, Styling,
Django, DRF, FastAPI, Celery, Pytest, Ruff, MyPy, SQLAlchemy, Migrations,
UV, ClickHouse, AWS Lambda, AI Agents, OpenAPI, Docker
First, check if the database ID is already cached locally:
cat "$HOME/.claude/plugins/data/worklog-notion/database-id.txt" 2>/dev/null
If the output is a non-empty string, use that value as the Work Log database ID directly and skip the page fetch below.
If no cached ID, the user's Notion page ID was resolved in Step 1 from ~/.claude/settings.json (pluginOptions["worklog-notion@local-plugins"].notion_page_id). Use the available Notion MCP tools to fetch the page and look for a child database named "Work Log" inside it.
After finding or creating the database, save its ID for future runs:
mkdir -p "$HOME/.claude/plugins/data/worklog-notion"
printf '%s\n' "<DATABASE_ID>" > "$HOME/.claude/plugins/data/worklog-notion/database-id.txt"
If Work Log does not exist, create it with this exact schema using the Notion MCP:
Ticket — TITLEDate — DATEDescription — RICH_TEXTImpact — RICH_TEXTCategory — SELECT with options: Feature/blue, Bug Fix/red, Migration/orange, Architecture/purple, Docs/gray, Review/yellow, Chore/defaultWins — CHECKBOXSkills — MULTI_SELECT with options: React/blue, Redux/purple, RTK Query/green, Architecture/pink, API Design/orange, Saga/yellow, Docs/gray, Data Formatting/brown, Testing/red, Styling/default, Django/green, DRF/blue, FastAPI/orange, Celery/yellow, Pytest/red, Ruff/gray, MyPy/purple, SQLAlchemy/brown, Migrations/pink, UV/default, ClickHouse/blue, AWS Lambda/orange, AI Agents/green, OpenAPI/yellow, Docker/grayQuery the Work Log database once for all rows where Date = today. Collect the resulting set of Ticket values into a list.
For each ticket group in your inferred data, check if its ticket ID is already in that list. If it is, skip that group and note it as "already logged". Do not make per-ticket queries — one batch query is sufficient.
For each ticket group that isn't already logged, create a row in the Work Log database using the Notion MCP with:
Ticket → the ticket IDDate → today in YYYY-MM-DD formatDescription → inferred descriptionImpact → inferred impactCategory → inferred categoryWins → true or falseSkills → array of skill namesOnly run this step if all rows from Step 7 were written successfully. If any Notion write failed, report the failure and do not update the tracker (so the session-end hook will still remind the user).
REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
REPO_ID=$(printf '%s' "$REPO_ROOT" | cksum | awk '{print $1}')
mkdir -p "$HOME/.claude/plugins/data/worklog-notion"
date '+%Y-%m-%d' > "$HOME/.claude/plugins/data/worklog-notion/last-logged-${REPO_ID}.txt"
Report the results clearly:
TICKET1, TICKET2"TICKET3"Guides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.
npx claudepluginhub vanhaaggen/worklog-plugin --plugin worklog-notion