Dev-time hook
Optional pre-commit hook that estimates how long you've been working on a commit and adds a Time: <duration> footer to the commit message. You confirm or edit the suggestion before the commit lands. The footer becomes a second time-source alongside /log issue comments — Gitsweeper will reconcile the two and surface drift.
This is a doc page. There is no Billbird code involved on the dev side. Nothing in Billbird changes whether you install the hook or not.
Why a second source
/log lives on issue comments — explicit, but easy to forget. The hook estimates from your local working copy: the time since the last commit, narrowed by recent file-mtime activity. The two sources cross-check each other:
- If a commit's
Time: 2hmatches roughly with/logtotals on the issue it closes → no drift. - If a commit says
Time: 4hbut the issue's/logtotal is only1h→ forgotten log entry. - If
/log 6his on the issue but commits across the day sum toTime: 1h→ the hook missed work (probably did the work outside the editor and the heuristic didn't catch it).
Cross-check happens in Gitsweeper (planned follow-up), not in Billbird.
What you copy
Two blocks. One into ~/.claude/settings.json, one into a file in your home directory.
1. ~/.claude/settings.json
Open (or create) the file and merge in:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"command": "$HOME/.claude/billbird-time-hook.sh"
}
]
}
}
If the file already has a hooks block, merge the PreToolUse array — don't replace what's there.
2. ~/.claude/billbird-time-hook.sh
#!/usr/bin/env bash
# Billbird dev-time hook. Suggests a Time: footer on git commits.
# Reads the tool-use JSON from stdin; only acts on `git commit` invocations.
# Safe to omit on any other command.
set -euo pipefail
input="$(cat)"
# Only act on `git commit` shells.
case "$input" in
*'"command":"git commit'*) ;;
*) echo "$input"; exit 0 ;;
esac
# Estimate time since the last commit on the current branch. Falls back
# to zero if there is no prior commit (first commit of a fresh repo).
since_iso="$(git log -1 --format=%cI 2>/dev/null || true)"
if [ -z "$since_iso" ]; then
# Nothing to base a duration on; let the commit proceed unchanged.
echo "$input"; exit 0
fi
now_epoch="$(date -u +%s)"
since_epoch="$(date -u -d "$since_iso" +%s 2>/dev/null || date -u -j -f '%Y-%m-%dT%H:%M:%S%z' "$since_iso" +%s)"
elapsed=$((now_epoch - since_epoch))
# Cap absurd durations (machine asleep / weekend / etc.) at 8 hours.
[ "$elapsed" -gt 28800 ] && elapsed=28800
# Format as Xh Ym, drop zero parts.
hours=$((elapsed / 3600))
minutes=$(((elapsed % 3600) / 60))
if [ "$hours" -gt 0 ] && [ "$minutes" -gt 0 ]; then
suggestion="${hours}h${minutes}m"
elif [ "$hours" -gt 0 ]; then
suggestion="${hours}h"
else
suggestion="${minutes}m"
fi
# Inject a Time: footer into the -m argument of git commit, if present.
# Otherwise leave the command alone — the dev will see git's editor and
# can add the footer themselves.
case "$input" in
*' -m '*|*"-m\""*)
# Append " — Time: <suggestion>" to the last -m string.
echo "$input" | sed -E "s/(\"command\":\"git commit[^\"]*-m \"[^\"]*)/\1\n\nTime: ${suggestion}/"
;;
*)
# Pass the input through; the dev will be in their editor.
echo "$input"
;;
esac
Make it executable:
chmod +x ~/.claude/billbird-time-hook.sh
Workflow
- You work on your branch as usual.
- You run
git commit -m "fix the regression"(or open the editor). - Claude Code invokes the hook; it estimates elapsed time and rewrites the message to include a
Time: 45mfooter (or whatever it computes). - You see the rewritten command and approve or edit before it actually runs.
- The commit lands with the
Time:footer in its message;git logshows it forever after.
You can always edit the suggestion. If the hook overestimates because you stepped out for lunch, change Time: 1h30m to Time: 45m before approving. If you didn't actually work between commits (rebase, merge commit), delete the line.
What the hook does and does not do
| Does | Does not |
|---|---|
Read git log -1 --format=%cI for the prior commit timestamp |
Contact Billbird or any network endpoint |
| Compute elapsed time, capped at 8 h | Hold or read any token, secret, or credential |
Suggest a Time: footer for git commit -m ... calls |
Replace /log issue comments — both sources coexist |
| Let you edit or remove the suggestion before commit | Force itself on commits — bypass with --no-verify or by skipping Claude Code |
Reconciliation (planned, not yet shipped)
A future gitsweeper reconcile MCP tool / CLI subcommand will:
- Walk recent commits, pull
Time:footers. - Walk recent
/logentries via Billbird's/api/v1/time-entries. - Group by
(repo, issue)— the commit usually references the issue viaCloses #Nor branch name. - Report per-group drift: minutes-from-commits vs minutes-from-logs.
Until that lands, the footers are simply audit-trail in git log.
Disabling the hook
Remove the entry from ~/.claude/settings.json or comment it out. The script file can stay; without the settings entry it never runs.