1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
#!/usr/bin/env bash
# SessionStart(clear) hook: after /clear, point the fresh context at the
# session-context anchor so a "flush" resumes the same logical session
# instead of starting cold.
#
# Pairs with the /flush skill (rulesets flush/SKILL.md): the skill's
# pre-clear half refreshes .ai/session-context.org in place; this hook is the
# post-clear half that /clear's blank session can't run itself.
#
# General by design — not flush-specific:
# - anchor present -> resume (read it, say "flushed.", continue)
# - anchor absent -> run the startup workflow (covers a stray /clear)
#
# SessionStart hooks reach the model ONLY through
# hookSpecificOutput.additionalContext — plain stdout goes to the debug log.
# After /clear the injected context loads but the model still waits for the
# user's next message before it acts; that one keystroke is expected.
#
# Wire in ~/.claude/settings.json:
#
# {
# "hooks": {
# "SessionStart": [
# {
# "matcher": "clear",
# "hooks": [
# { "type": "command",
# "command": "~/.claude/hooks/session-clear-resume.sh" }
# ]
# }
# ]
# }
# }
set -euo pipefail
# Resolve the AI_AGENT_ID-aware anchor path — mirror of
# .ai/scripts/session-context-path, evaluated against the project cwd the
# hook inherits. Fall back to the singleton path when the id is unset.
id="${AI_AGENT_ID:-}"
if [ -n "$id" ]; then
safe=$(printf '%s' "$id" | tr -c 'A-Za-z0-9._-' '_')
sc=".ai/session-context.d/${safe}.org"
else
sc=".ai/session-context.org"
fi
if [ -f "$sc" ]; then
# On resume, read notes.org standing knowledge (code-repo paths,
# conventions, key contacts) BEFORE the anchor — the anchor carries
# session state, notes.org carries the project context a resumed session
# needs to act correctly. Same "key sections" scope startup uses. Only
# when notes.org is present; otherwise resume from the anchor alone.
if [ -f ".ai/notes.org" ]; then
read_order="First read .ai/notes.org key sections (Project-Specific Context, Active Reminders, Pending Decisions; skip About This File) for the project's standing knowledge — code-repo paths, conventions, key contacts. Then read the session-context anchor at ${sc}"
else
read_order="Read the session-context anchor at ${sc}"
fi
ctx="A context flush just happened (/clear). ${read_order} — the * Summary (Active Goal, Next Steps) plus the most recent * Session Log entries. Then reply with 'flushed.' on its own line, followed by one line restating the Active Goal and the immediate Next Step, and resume that work. This is a mid-session resume, NOT a fresh start: do not run the startup workflow, do not re-pull rulesets or re-sync templates."
else
ctx="Session started with no session-context anchor present (.ai/session-context.org absent). Run the startup workflow at .ai/workflows/startup.org."
fi
# Build the whole object in python3 so the additionalContext string is
# JSON-escaped correctly regardless of its content.
python3 -c 'import json,sys; print(json.dumps({"hookSpecificOutput":{"hookEventName":"SessionStart","additionalContext":sys.argv[1]}}))' "$ctx"
|