From 47b97d1037edf13c2f4fc645a719fe5b0ed16f88 Mon Sep 17 00:00:00 2001 From: dhanya elizabath jose Date: Sun, 26 Apr 2026 19:20:22 +0100 Subject: [PATCH] feat(hooks): add SessionEnd progress logger and local progress tracker (#87) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(hooks): add SessionEnd progress logger and local progress tracker Adds a SessionEnd hook that prompts for modules studied at session end and appends a record to ~/.claude-howto-progress.json — outside the repo so progress survives git pull without being overwritten. Also adds local-progress/index.html: a self-contained visual tracker with checkboxes for all 10 modules, per-module notes, an overall progress bar, and Export/Import to sync with a local JSON backup file. Key patterns demonstrated: - SessionEnd vs Stop (fires once on exit, not after every response) - /dev/tty for interactive input in hooks (stdin carries the JSON payload) - $CLAUDE_PROJECT_DIR for portable paths (never hardcode /Users/...) - Guard clause to prevent global hook running in unrelated projects Co-Authored-By: Claude Sonnet 4.6 (1M context) * fix(hooks): address PR review — bash 3.2 compat, JSON escaping, textarea XSS - Replace pipeline+while with IFS for-loop (bash 3.2 compatible) - Pass NOTES as Python arg to avoid broken JSON on quotes/backslashes - Set textarea.value instead of innerHTML to prevent XSS from imported JSON Co-Authored-By: Claude Sonnet 4.6 (1M context) --------- Co-authored-by: Claude Sonnet 4.6 (1M context) --- .gitignore | 3 + 06-hooks/README.md | 135 ++++++++ 06-hooks/session-end.sh | 94 +++++ local-progress/index.html | 697 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 929 insertions(+) create mode 100755 06-hooks/session-end.sh create mode 100644 local-progress/index.html diff --git a/.gitignore b/.gitignore index fd5335b..054fbe0 100644 --- a/.gitignore +++ b/.gitignore @@ -51,6 +51,9 @@ yarn-error.log* !.claude/skills/lesson-quiz/ blog-posts/ +# Local progress tracker — HTML ships in repo, but exported JSON data files stay local +local-progress/*.json + # EPUB files in root directory /*.epub diff --git a/06-hooks/README.md b/06-hooks/README.md index 68b7db7..31837b2 100644 --- a/06-hooks/README.md +++ b/06-hooks/README.md @@ -965,6 +965,141 @@ python3 09-advanced-features/setup-auto-mode-permissions.py - `DROP TABLE`, `kubectl delete`, `terraform destroy` - `npm publish`, `curl | bash`, production deploys +### Example 8: Learning Progress Logger (SessionEnd) + +Log which modules you studied at the end of each Claude Code session. Progress is stored +in `~/.claude-howto-progress.json` — outside the repo, so it survives `git pull` without +being overwritten. + +**Why `SessionEnd` and not `Stop`?** +`Stop` fires after *every* Claude response. `SessionEnd` fires once when the session +terminates — exactly what you want for an end-of-session diary entry. + +**Why `/dev/tty` for input?** +Hook scripts receive the hook JSON payload via `stdin`, so interactive `read` must use +`/dev/tty` directly to reach the terminal. + +**File:** `06-hooks/session-end.sh` + +```bash +#!/usr/bin/env bash +# SessionEnd hook: prompts for modules worked on, then appends a session record +# to ~/.claude-howto-progress.json for persistent learning progress tracking. + +PROGRESS_FILE="$HOME/.claude-howto-progress.json" + +# Guard: only run inside this repo +if [[ "$CLAUDE_PROJECT_DIR" != *"claude-howto"* ]] && [[ "$PWD" != *"claude-howto"* ]]; then + exit 0 +fi + +if [ ! -f "$PROGRESS_FILE" ]; then + echo '{"sessions":[]}' > "$PROGRESS_FILE" +fi + +DATE=$(date +"%Y-%m-%d") +TIME=$(date +"%H:%M") + +echo "" +echo " Which modules did you work on? (e.g. 06,07 or press Enter to skip)" +echo " 01=Slash 02=Memory 03=Skills 04=Subagents 05=MCP" +echo " 06=Hooks 07=Plugins 08=Checkpoints 09=Advanced 10=CLI" +printf " > " +read -r INPUT "$PROGRESS_FILE" +fi + +DATE=$(date +"%Y-%m-%d") +TIME=$(date +"%H:%M") + +echo "" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo " Claude Code — Learning Session End" +echo " $DATE $TIME" +echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" +echo "" +echo " Which modules did you work on? (e.g. 06,07 or press Enter to skip)" +echo " 01=Slash 02=Memory 03=Skills 04=Subagents 05=MCP" +echo " 06=Hooks 07=Plugins 08=Checkpoints 09=Advanced 10=CLI" +echo "" +printf " > " +read -r INPUT + + + + + Claude Code — Learning Progress + + + + +
+

Claude Code — Learning Progress

+

10 modules · Progress stored in browser localStorage · Export to back up

+
+ + + + + +
+
+ +
+
+ Overall progress + 0% +
+
+
+ +
+ +
+ + + +