Stats
Actions
Tags
From tl
Captures git commits/status snapshots to markdown files before compaction/SessionEnd; warns on destructive git/bash commands (reset/clean/rm) pre-tool; review checklist post-tool. Runs bash.
6 events · 7 hooks
Safety signals detected in this hook configuration
Where this hook configuration is defined
Defined in hooks/hooks.json
Event handlers and matchers — expand Raw Configuration for the full JSON
mkdir -p .claude/tackline/memory/sessions && { NOW=$(date -u +%Y-%m-%dT%H:%M:%SZ); printf '## Pre-Compact Snapshot\n**Time**: %s\n\n### Recent Commits\n' "$NOW"; git log --oneline -5 2>/dev/null || echo '(no git)'; printf '\n### Working Tree\n'; git status --short 2>/dev/null || echo '(no git)'; printf '\n### Open Questions\n(fill in before context is lost)\n\n### Working Theories\n(fill in before context is lost)\n\n### Key Decisions\n(fill in before context is lost)\n'; } > .claude/tackline/memory/sessions/pre-compact.md 2>/dev/null || trueBashINPUT="$CLAUDE_TOOL_INPUT"; if echo "$INPUT" | grep -qE '"git reset --hard' 2>/dev/null; then echo 'DESTRUCTIVE WARNING: git reset --hard will discard all uncommitted changes. This is irreversible.' >&2; elif echo "$INPUT" | grep -qE '"git checkout \.' 2>/dev/null; then echo 'DESTRUCTIVE WARNING: git checkout . will discard all unstaged changes. This is irreversible.' >&2; elif echo "$INPUT" | grep -qE '"git clean -f' 2>/dev/null; then echo 'DESTRUCTIVE WARNING: git clean -f will permanently delete untracked files.' >&2; elif echo "$INPUT" | grep -qE '"rm -rf [^"]*[^/.]' 2>/dev/null; then echo 'DESTRUCTIVE WARNING: rm -rf detected on a non-trivial path. Verify the target before proceeding.' >&2; fimkdir -p .claude/tackline/memory/sessions && NOW=$(date -u '+%Y-%m-%dT%H-%M-%SZ') && FILE=".claude/tackline/memory/sessions/${NOW}.md" && echo "## Session: $NOW" > "$FILE" && echo '' >> "$FILE" && echo '### Commits' >> "$FILE" && COMMITS=$(git log --oneline -10 2>/dev/null); if [ -n "$COMMITS" ]; then echo "$COMMITS" >> "$FILE"; else echo '(none)' >> "$FILE"; fi && echo '' >> "$FILE" && echo '### Working Tree' >> "$FILE" && TREE=$(git status --short 2>/dev/null); if [ -n "$TREE" ]; then echo "$TREE" >> "$FILE"; else echo 'clean' >> "$FILE"; fi && cp "$FILE" .claude/tackline/memory/sessions/last.md 2>/dev/null || true && ls -t .claude/tackline/memory/sessions/[0-9]*.md 2>/dev/null | tail -n +4 | xargs rm -f 2>/dev/null || trueTaskecho 'REVIEW GATE: Agent completed. Verify deliverable quality before proceeding:' >&2; echo ' [ ] Spike sections present: Firm Tasks Found | Areas Needing Deeper Spikes | Clean Areas | Summary' >&2; echo ' [ ] Findings tagged with confidence: CONFIRMED | LIKELY | POSSIBLE' >&2; echo ' [ ] Evidence includes file paths and line numbers' >&2; echo ' [ ] Gaps captured as new tasks | Downstream connections identified' >&2Skillmkdir -p ~/.claude/telemetry && echo "{\"ts\":\"$(date -Is)\",\"skill\":\"$(echo "$CLAUDE_TOOL_INPUT" | head -c 200)\",\"project\":\"$(pwd)\"}" >> ~/.claude/telemetry/skills.jsonl || trueecho '=== Session Start ==='; git log --oneline -3 2>/dev/null | sed 's/^/Last: /'; git diff --stat --cached 2>/dev/null; echo "Tree: $(git status --short 2>/dev/null | wc -l) uncommitted files"; echo '=== ==='python3 -c "
import os, json, sys, re
domain = '.claude/tackline/memory/project/domain.md'
if not os.path.exists(domain): sys.exit(0)
try:
inp = json.loads(os.environ.get('CLAUDE_TOOL_INPUT', '{}'))
prompt = inp.get('prompt', '')
except Exception: sys.exit(0)
if not prompt: sys.exit(0)
text = open(domain).read()
blocks = re.split(r'(?=^## )', text, flags=re.MULTILINE)
matched = [b for b in blocks if b.startswith('## ') and re.search(r'## (.+)', b) and re.search(re.escape(re.search(r'## (.+)', b).group(1)), prompt, re.IGNORECASE)]
if not matched: sys.exit(0)
print('<!-- domain-context -->')
for b in matched:
print(b.strip())
print()
" 2>/dev/null || truenpx claudepluginhub tyevans/tackline --plugin tackline