Every new Claude Code session starts cold. It doesn't know which branch you're on, what's uncommitted, or that CI went red an hour ago, so the first few turns get spent rediscovering it.

A SessionStart hook fixes that. It runs when a session starts (or resumes), and whatever the command prints to stdout is added to the session context.

The script

Save as .claude/hooks/session-brief.sh and chmod +x it:

#!/usr/bin/env bash # session-brief.sh: short repo briefing for a new Claude Code session set -uo pipefail echo "[repo briefing]" echo "branch: $(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo 'not a git repo')" echo "uncommitted files: $(git status --porcelain 2>/dev/null | wc -l | tr -d ' ')" echo "last 3 commits:" git log --oneline -3 2>/dev/null | sed 's/^/ /' if [ -f TODO.md ]; then echo "open TODOs (first 5):" grep -m5 '^- \[ \]' TODO.md | sed 's/^/ /' fi 

Register it

In .claude/settings.json:

{ "hooks": { "SessionStart": [ { "hooks": [ { "type": "command", "command": ".claude/hooks/session-brief.sh" } ] } ] } } 

Check the hooks page for your installed Claude Code version; matcher options (startup, resume, clear) and exact fields can change between releases.

Keep it small

  • Ten lines of briefing beats a hundred. The goal is orientation, not a dump of git diff.
  • Don't print secrets or .env values. Anything on stdout goes into the model's context.
  • Pair it with a short CLAUDE.md for standing house rules and deny/ask rules in settings.json, so each piece does one job.

I keep the session hook, the settings file, and the short house-rules file together in Vildanden Agent Config. The free sample has enough to try the pattern today.