计划执行与检查节点
executing-plans
按既定实施计划完成工作,保持过程检查和反馈。
read-continue-here【效率与协作】Read a CONTINUE_HERE.md continuation file at session start and resume from where the prior session left off. Covers detecting the file, assessing freshness, parsing the structured handoff, confirming the resumption plan with the user, and cleaning up after consumption. Optionally configures a SessionStart hook and CLAUDE.md instruction for automatic …
独立 GitHub 快照 · 自动分类 · 以原作者文档为准
讀續檔、承前任也。
查根 CONTINUE_HERE.md:
ROOT=$(git rev-parse --show-toplevel 2>/dev/null) || ROOT=$PWD
CONTINUE_FILE=
for candidate in CONTINUE_HERE.md docs/CONTINUE_HERE.md .claude/CONTINUE_HERE.md; do
if [ -f "$ROOT/$candidate" ]; then CONTINUE_FILE="$ROOT/$candidate"; break; fi
done
if [ -n "$CONTINUE_FILE" ]; then
echo "handoff: $CONTINUE_FILE"
else
ELSEWHERE=$(find "$ROOT" -maxdepth 3 -name 'CONTINUE_HERE.md' \
-not -path '*/.git/*' -not -path '*/node_modules/*' 2>/dev/null | head -5)
if [ -n "$ELSEWHERE" ]; then
echo "no handoff at a resolved path, but one exists elsewhere:"
echo "$ELSEWHERE"
else
echo "no handoff"
fi
fi
無→雅退。
存→讀容。析五段:Objective、Completed、In Progress、Next Steps、Context。取首行時、枝。
得:檔讀、段析、前會態明。
敗:存而殘(缺段、空)→視為部分號,取所存、告用何缺。
時與今較:
: "${CONTINUE_FILE:?resolve it with the Step 1 block in this shell first}"
# File modification time
stat -c '%Y' "$CONTINUE_FILE" 2>/dev/null || stat -f '%m' "$CONTINUE_FILE"
# Current time
date +%s
分鮮:
察枝合:
: "${CONTINUE_FILE:?resolve it with the Step 1 block in this shell first}"
git branch --show-current
git log --oneline --since="$(stat -c '%Y' "$CONTINUE_FILE" | xargs -I{} date -d @{} --iso-8601=seconds)" 2>/dev/null
得:鮮分(鮮、舊、越)有據。
敗:非庫→略枝、提交察。獨憑檔頭時。
簡示續態於用:
舊或越→示據、問續否抑新起。
Next Steps 標 **[USER]**→明揭,需用決方行。
得:用確續計(或調)。代有明命。
敗:用云「新起」「忽彼檔」→應、不顧續脈。問刪檔以免後混。
由 Next Steps 一始(或用所指):
得:代行正務、有續檔導引。
敗:Next Steps 含糊、In Progress 不明→問用,勿猜。
交用畢、工已起→刪 CONTINUE_HERE.md:
: "${CONTINUE_FILE:?resolve it with the Step 1 block in this shell first}"
# A handoff that carries `coordinate-peer-sessions` Step 3's scope declaration is about to lose
# its only durable copy — this is the one point in the lifecycle where anyone could still act on
# it. A shell loop, not `grep`/`rg`: a session may run this in an environment that has neither on
# PATH, or that blocks a bare `grep` outright (this repository's own Bash hook does exactly that,
# which would otherwise make this warning never fire where it matters most). Anchored on the
# LINE START, not `*Nobody runs:*`: a handoff can quote or discuss the mechanism in prose (as this
# skill's own commit history has), and an unanchored match warns on that too — a real declaration
# always starts the line, by construction of the fence that emits it.
SCOPE_LINE=$(while IFS= read -r l; do
case "$l" in "Nobody runs:"*) printf '%s' "$l"; break ;; esac
done < "$CONTINUE_FILE")
if [ -n "$SCOPE_LINE" ]; then
echo "WARNING: $CONTINUE_FILE carries a peer-session scope declaration about to be lost:" >&2
echo " $SCOPE_LINE" >&2
echo "Copy it somewhere durable (an issue comment, a message to the peer) before it is gone." >&2
fi
if git ls-files --error-unmatch "$CONTINUE_FILE" >/dev/null 2>&1; then
# Tracked: the deletion is recoverable, which is what makes it safe.
# The pathspec is load-bearing: `git commit -m` with none commits the WHOLE
# index, so a peer session's staged work is swept into a commit titled for the
# handoff. This runs at session start, which is exactly when that is likely.
git rm -q "$CONTINUE_FILE" &&
git commit -qm 'chore: consume the session handoff' -- "$CONTINUE_FILE"
else
# Untracked, ignored, or no repository at all — all three land here, and for
# all three an ordinary delete is the right and only option.
rm -- "$CONTINUE_FILE"
fi
舊續檔致後會混。
得:檔除、根淨。
敗:用欲留(如會中參)→留之,告會末必刪以免次會復用。
未設→立自讀於會啟。
建鉤本:
mkdir -p ~/.claude/hooks/continue-here
cat > ~/.claude/hooks/continue-here/read-continuation.sh << 'SCRIPT'
#!/usr/bin/env bash
# SessionStart hook: inject the resolved CONTINUE_HERE.md into session context.
# OS-aware: works on native Linux, WSL, macOS, and Windows (Git Bash/MSYS).
set -uo pipefail
ROOT=$(git rev-parse --show-toplevel 2>/dev/null) || ROOT=$PWD
CONTINUE_FILE=
for candidate in CONTINUE_HERE.md docs/CONTINUE_HERE.md .claude/CONTINUE_HERE.md; do
if [ -f "$ROOT/$candidate" ]; then CONTINUE_FILE="$ROOT/$candidate"; break; fi
done
emit() {
# additionalContext sits DIRECTLY under hookSpecificOutput. Nesting it inside a
# "sessionStartContext" object — the shape this hook shipped until 2.0 — names a
# key Claude Code does not know, so the whole object is discarded and the failure
# is reported nowhere the user will look (#844). stdout carries the JSON and
# nothing else.
if command -v jq >/dev/null 2>&1; then
ESCAPED=$(printf '%s' "$1" | jq -Rsa .)
else
ESCAPED=$(printf '%s' "$1" | awk '
BEGIN {
ORS = ""
# JSON forbids every raw byte below 0x20 inside a string, not only the
# three with short escapes. Handling \\ " and tab alone left CR, ESC and
# the rest to pass through raw, which made the object unparseable — and
# an unparseable object is discarded in exactly the silent way #844 was.
# A handoff quoting terminal output carries ESC; one written on NTFS
# carries CR. Both are ordinary here.
for (i = 1; i < 32; i++) esc[sprintf("%c", i)] = sprintf("\\u%04x", i)
esc["\t"] = "\\t"
print "\""
}
{
line = $0
gsub(/\\/, "\\\\", line)
gsub(/"/, "\\\"", line)
if (line ~ /[\001-\037]/) {
out = ""
n = length(line)
for (i = 1; i <= n; i++) {
ch = substr(line, i, 1)
out = out (ch in esc ? esc[ch] : ch)
}
line = out
}
if (NR > 1) print "\\n"
print line
}
END { print "\"" }
')
fi
printf '{"hookSpecificOutput":{"hookEventName":"SessionStart","additionalContext":%s}}' "$ESCAPED"
}
if [ -n "$CONTINUE_FILE" ]; then
# Strip CRLF (files on NTFS often have Windows line endings)
emit "$(sed 's/\r$//' "$CONTINUE_FILE")"
exit 0
fi
# No handoff at a resolved path. Exiting silently here is what made a misplaced
# handoff indistinguishable from a project that has none, so look once more, cheaply,
# and say what was found.
ELSEWHERE=$(find "$ROOT" -maxdepth 3 -name 'CONTINUE_HERE.md' \
-not -path '*/.git/*' -not -path '*/node_modules/*' 2>/dev/null | head -5)
if [ -n "$ELSEWHERE" ]; then
emit "A CONTINUE_HERE.md exists in this project but not where the continuation hook resolves it. The hook looks for CONTINUE_HERE.md, docs/CONTINUE_HERE.md and .claude/CONTINUE_HERE.md, relative to the repository root. Found instead:
$ELSEWHERE
Read it if it is a handoff for this session, or move it to one of the resolved paths."
fi
exit 0
SCRIPT
chmod +x ~/.claude/hooks/continue-here/read-continuation.sh
入 ~/.claude/settings.json SessionStart 鉤陣:
{
"type": "command",
"command": "~/.claude/hooks/continue-here/read-continuation.sh",
"timeout": 5
}
得:鉤本存、可執、注於 settings.json。次會啟、若 CONTINUE_HERE.md 存→容入會脈。
敗:察 settings.json 編後仍合 JSON。手測鉤:cd /your/project && ~/.claude/hooks/continue-here/read-continuation.sh。本退用 awk 若無 jq,故 jq 宜而非必。
於項 CLAUDE.md 增簡命使 Claude 解檔旨:
## Session Continuity
If `CONTINUE_HERE.md` exists in the project root, read it at session start. It contains a structured handoff from a prior session: objective, completed work, in-progress state, next steps, and context. Act on it — acknowledge the continuation, summarize prior state, and propose resuming from the Next Steps section. If the file is older than 24 hours, flag this to the user before proceeding. After the handoff is consumed, the file can be deleted.
得:CLAUDE.md 含命。後會雖無鉤亦讀行 CONTINUE_HERE.md。
敗:CLAUDE.md 不存→建之,唯此段。檔過長→置近頂以免截斷。
write-continue-here — 補:會末書續檔bootstrap-agent-identity — 全身重構,含續察為一啟發manage-memory — 跨會持知(補此瞬交)write-claude-md — 項命,可選續導所居