Automatic work logging for Claude Code sessions
Track what you built, how long it took, and what it cost — automatically.
- Why worklog-for-claude?
- Features
- Quick Start
- How It Works
- Usage
- Configuration
- Storage Modes
- Notion Integration
- MCP Server
- Architecture
- FAQ
- Contributing
- License
When you're deep in a Claude Code session, it's easy to lose track of what you've done. worklog-for-claude captures everything automatically — so you can focus on building, not bookkeeping.
| Without worklog-for-claude | With worklog-for-claude |
|---|---|
| Manually write what you did | AI-generated commit summaries |
| Guess how long tasks took | Precise Claude processing time |
| No idea what it cost | Token usage and cost per session |
| Forget to log entirely | Triggered on every commit — zero effort |
- Zero-friction logging — Git post-commit hook writes entries automatically. Just commit and it's done.
- AI-powered summaries — Uses
claude -pto generate human-readable work descriptions from diffs. - Token & cost tracking — Parses Claude Code JSONL logs to calculate per-session deltas.
- Duration tracking — Measures actual Claude work time, not wall-clock time.
- Notion sync — Real-time sync to a Notion database with auto-created schema.
- Flexible storage — Local markdown, Notion, or both. Choose per project.
- Git-tracked worklogs — Optionally commit
.worklogs/alongside your code.
- Non-destructive install — Preserves existing git hooks via chaining.
- Bilingual — Full Korean and English support (
WORKLOG_LANG). - Self-updating — Automatic version check on
SessionStart, or manual with/worklog-update. - Global or local — Install once for all projects, or per-repo.
- Bulk migration — Move existing markdown worklogs to Notion with
/worklog-migrate. - MCP server — Cross-client support (Claude Code, Cursor, Claude Desktop).
| Tool | Purpose |
|---|---|
| Claude Code | AI coding assistant (CLI) |
python3 |
Token/cost calculation |
curl |
Notion API, update checks |
jq (optional) |
JSON processing (session cleanup) |
uv (optional) |
MCP server support |
bash <(curl -fsSL https://raw.githubusercontent.com/kangraemin/worklog-for-claude/main/install.sh)For local install (specific project only), run the same command from your project directory and select scope: Local (2).
The interactive wizard walks you through:
- Language — Korean (
ko) or English (en) - Scope — Global (
~/.claude/) or project-local (.claude/) - Storage — Notion + local files, Notion only, or local files only
- Notion setup — Token input, database auto-creation (if Notion mode selected)
- Git tracking — Track
.worklogs/in git or add to.gitignore - Timing — Auto on commit or manual only
- MCP setup — Client selection (if
uvinstalled)
That's it. Start committing and worklogs appear automatically.
Tip: Run the installer again with
--reconfigureto change settings after initial install.
./uninstall.shRemoves hooks, scripts, commands, and config from settings.json. Preserves .worklogs/ data and .env credentials.
git commit
└─ post-commit hook fires
└─ claude -p generates AI summary from diff
└─ worklog-write.sh
├─ token-cost.py → cost delta from Claude JSONL
├─ duration.py → work time from Claude JSONL
├─ .worklogs/YYYY-MM-DD.md (append locally)
└─ notion-worklog.sh (sync to Notion)
git commit (inside Claude Code)
└─ post-commit hook detects CLAUDECODE env
└─ writes pending marker → exits immediately (never blocks)
└─ on-commit.sh (PostToolUse) detects the commit
└─ blocks and requests /worklog
└─ worklog-write.sh (same pipeline as above)
Works with any commit method:
- Direct
git commitin terminal - Claude Code
/commitskill git commitinside a Claude Code session (viaon-commit.sh)
The post-commit hook always exits 0 — worklog failures never block your commits.
Every git commit triggers a worklog entry. No action required.
/worklog
Writes a worklog entry from the current conversation context. Works regardless of the WORKLOG_TIMING setting.
/worklog-migrate # dry-run preview
/worklog-migrate --all # migrate all .md files
/worklog-migrate --date 2026-03-01 # specific date only
/worklog-migrate --all --delete-after # migrate and delete source files
/worklog-update
Checks GitHub for updates and re-installs if a new version is available.
All settings live in settings.json under env:
| Variable | Values | Default | Description |
|---|---|---|---|
WORKLOG_TIMING |
stop | manual |
stop |
When to write worklogs |
WORKLOG_DEST |
git | notion | notion-only |
git |
Where to store worklogs |
WORKLOG_GIT_TRACK |
true | false |
true |
Track .worklogs/ in git |
WORKLOG_LANG |
ko | en |
ko |
Entry language |
NOTION_DB_ID |
UUID | — | Notion database ID |
AI_WORKLOG_DIR |
path | ~/.claude |
Installation directory (set by installer) |
| Mode | WORKLOG_DEST |
WORKLOG_GIT_TRACK |
Local file | Notion | Git-tracked |
|---|---|---|---|---|---|
| git | git |
true |
Yes | No | Yes |
| git-ignore | git |
false |
Yes | No | No |
| both | notion |
true |
Yes | Yes | Yes |
| notion-only | notion-only |
false |
No | Yes | No |
## 14:30
### Request
- Add duplicate prevention to migration script
### Summary
- Added .migrated fingerprint file to skip already-sent entries
- Updated skipped count in output summary
### Changed Files
- `scripts/notion-migrate-worklogs.sh`: duplicate prevention logic
### Token Usage
- Model: claude-sonnet-4-6
- This session: 52,340 tokens · $1.089Section headers follow
WORKLOG_LANG— Korean or English.
- Create an integration at notion.so/my-integrations
- Run the installer and select a Notion storage mode — the wizard prompts for your token (
ntn_...orsecret_...) and auto-creates the database - Share the created database with your integration (Share → Add connections)
You can also add
NOTION_TOKEN=ntn_...to~/.claude/.envbefore running the installer — it will be auto-detected.
| Column | Type | Description |
|---|---|---|
| Title | title | One-line work summary |
| DateTime | date | Work timestamp |
| Project | select | Repository name |
| Tokens | number | Token delta |
| Cost | number | Cost delta ($) |
| Duration | number | Claude work time (minutes) |
| Model | select | Claude model used |
Content body is auto-converted from markdown to Notion blocks (### → heading_3, - → bulleted_list_item).
The mcp/ directory contains a Python MCP server that extends worklog-for-claude to any MCP-compatible client — Claude Code, Cursor, and Claude Desktop.
- Worklog — write and read worklogs via MCP tools
Requires uv. The installer sets this up automatically, or configure manually:
cd worklog-for-claude/mcp
uv syncAdd to your MCP client config:
{
"mcpServers": {
"worklog-for-claude": {
"command": "uvx",
"args": ["worklog-for-claude"],
"env": {}
}
}
}See mcp/README.md for client-specific configuration examples.
worklog-for-claude/
├── install.sh # Interactive installer (supports curl pipe)
├── uninstall.sh # Clean removal
├── hooks/
│ ├── post-commit.sh # Git post-commit → worklog generation
│ ├── worklog.sh # PostToolUse → tool usage collection
│ ├── on-commit.sh # PostToolUse (Bash) → git commit detection
│ ├── session-end.sh # SessionEnd → cleanup
│ └── stop.sh # Stop → prompt /worklog (legacy, removed by installer)
├── git-hooks/
│ └── post-commit # Git hook wrapper
├── scripts/
│ ├── worklog-write.sh # Core: file + Notion + snapshot
│ ├── token-cost.py # Token/cost delta from JSONL
│ ├── duration.py # Work duration from JSONL
│ ├── notion-worklog.sh # Notion API page creation
│ ├── notion-create-db.sh # Notion database auto-creation
│ ├── notion-migrate-worklogs.sh # Bulk .md → Notion
│ └── worklog-update-check.sh # Version check against remote
├── commands/ # Claude Code skill definitions
│ ├── worklog.md # /worklog
│ ├── worklog-migrate.md # /worklog-migrate
│ └── worklog-update.md # /worklog-update
├── rules/ # Workspace rules
├── mcp/ # MCP server (Python, FastMCP)
│ ├── src/worklog_mcp/ # Server + tools
│ └── tests/ # MCP test suite
├── tests/ # End-to-end test suite
└── docs/ # Documentation assets
| Event | File | Description |
|---|---|---|
Git post-commit |
hooks/post-commit.sh |
Generates worklog entry on each commit |
PostToolUse |
hooks/worklog.sh |
Collects tool usage into per-session JSONL |
PostToolUse (Bash) |
hooks/on-commit.sh |
Detects git commit and requests /worklog |
SessionStart |
scripts/worklog-update-check.sh |
Version check against GitHub (24h throttle) |
SessionEnd |
hooks/session-end.sh |
Cleans up session collection file |
The installer removes any existing Stop hooks for worklog —
PostToolUse(on-commit.sh) handles commit detection instead.
Token and cost deltas are calculated by parsing Claude Code's official JSONL logs:
- Read snapshot timestamp from
~/.claude/worklogs/.snapshot - Filter JSONL entries after that timestamp for the current project
- Sum
input_tokens,output_tokens,cache_read_input_tokens,cache_creation_input_tokens - Apply model-specific pricing (claude-opus-4-6, claude-sonnet-4-6, claude-haiku-4-5)
- Update snapshot after writing the entry
Does it slow down my commits?
Inside a Claude Code session, the hook writes a pending marker and exits immediately — your commit is never blocked. Outside Claude Code, it runs claude -p synchronously but completes in seconds. If AI summary generation fails, it falls back to an auto-generated format using the commit message.
Can I use it on multiple projects?
Yes. Install globally (~/.claude/) and it works across all git repos. Each project gets its own .worklogs/ directory and token calculations are scoped per project.
What if I don't use Notion?
Notion is completely optional. Choose git or git-ignore mode during install to use local markdown files only.
Will it break my existing git hooks?
No. The installer preserves existing hooks by chaining — your original post-commit is saved as post-commit.local and called before the worklog hook.
How accurate is the cost tracking?
It parses Claude Code's actual JSONL logs using official token counts and model-specific pricing. Cost is calculated as a delta since the last worklog entry.
Can I migrate from local files to Notion later?
Yes. Run /worklog-migrate --all to bulk-import existing .worklogs/*.md files into Notion. Use --date to migrate specific dates.
What if I regenerate my Notion token?
Regenerating your Notion integration token invalidates the old one. Update in two steps:
- Replace
NOTION_TOKENin~/.claude/.env(or<project>/.claude/.envfor local installs) - Re-share the database with the new integration in Notion (Share → Add connections)
Without step 2, API calls will fail with a permission error even though the token itself is valid.
Notion API says "not a database" error?
Your NOTION_DB_ID might contain a page ID instead of the actual database ID. To fix:
- Open your worklog database in Notion
- Copy the ID from the URL:
notion.so/<workspace>/<DB_ID>?v=... - Update
NOTION_DB_IDin~/.claude/settings.json(or<project>/.claude/settings.json)
The ID is the 32-character hex string before ?v=.
Contributions are welcome! Here's how to get started:
- Fork the repository
- Create a feature branch
git checkout -b feature/amazing-feature
- Make your changes
- Test — run the e2e tests in
tests/python3 -m pytest tests/
- Commit and push
- Open a Pull Request
- New storage backends (GitHub Issues, Linear, etc.)
- Additional language support
- Improved token pricing for new models
- CI/CD pipeline improvements
- Documentation and examples
Distributed under the MIT License. See LICENSE for details.
Built for Claude Code by @kangraemin
If this project helped you, consider giving it a star!
