Claude Code's Bash permission checker rejects \${VAR} parameter
substitution in skill ! commands. Replace all occurrences with \$VAR
(identical shell expansion) across log, reflect-logs, and
distill-best-practices skills. Rewrite \${VAR:-default} to use
test -n / || pattern instead.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
5.1 KiB
name, description, allowed-tools
| name | description | allowed-tools |
|---|---|---|
| reflect-logs | Process session logs into structured memory. Reads unprocessed logs from memory/log/, extracts lessons into topic memory files (gotchas, process-lessons, decisions, etc.), updates MEMORY.md index, and flags stale entries. Run periodically or after several sessions. | Read, Edit, Write, Glob, Grep, Bash(md5sum *), Bash(ls *), Bash(cat *), Bash(date *), Bash(find *), Bash(git log *), Bash(git diff *), Bash(head *) |
Reflect Logs Skill
You are processing session logs into structured, topic-based memory files.
Pre-gathered context
Reflection state
!cat .reflection-state.json 2>/dev/null || echo "{}"
Available log files
!ls -1t memory/log/ 2>/dev/null || echo "No logs found"
Current MEMORY.md index
!cat MEMORY.md 2>/dev/null || echo "No MEMORY.md found"
Existing memory topic files
!ls -1 memory/ 2>/dev/null || echo "No memory directory"
Settings
!cat settings.yaml 2>/dev/null || cat $CLAUDE_PROJECT_ROOT/projects/claude-foundations/settings.yaml 2>/dev/null || echo "No settings file found — using defaults: max_logs_per_run=10, retention_days=7, warn_unreflected_days=14"
Recent git log (for staleness detection)
!git log --oneline -30 2>/dev/null || echo "Not a git repo"
Instructions
Step 1: Identify unprocessed logs
Compare memory/log/ contents against .reflection-state.json:
- A log is new if its filename is not in the
processedmap - A log is changed if its filename exists but the md5sum differs from the stored hash
- Respect
max_logs_per_runfrom settings (default: 10) — process oldest first
To compute hashes, run md5sum memory/log/<filename> for each file and compare against the stored values.
If there are no unprocessed logs, say so and stop.
Step 2: Read and categorise
Read each unprocessed log file. Group the extracted content by destination:
Routing rules:
- Gotchas tagged
[topic]→memory/gotchas-<topic>.md(e.g.,[k8s]→memory/gotchas-k8s.md) - Decisions →
memory/decisions.md - Process Notes →
memory/process-lessons.md - Key Context that represents a stable pattern →
memory/process-lessons.mdor a new topic file - Open Questions that were resolved across sessions → note the resolution, don't carry forward
If a [topic] tag doesn't match any existing gotchas file, create a new memory/gotchas-<topic>.md file following the format of existing ones (title heading, individual gotcha subheadings with 2-4 line explanations).
Step 3: Update memory files
For each destination file:
- Read the existing content using the Read tool
- Deduplicate: Do NOT add entries that already exist in substance, even if worded differently. Check for semantic overlap, not just string matching.
- Append new entries in the same style as existing content:
- Gotcha files:
## Headingwith 2-4 lines of explanation including symptom and fix - Process lessons: Imperative rule format ("Always X before Y", "Never assume Z")
- Decisions:
## Headingwith rationale paragraph
- Gotcha files:
- If creating a new topic file, include a top-level
# <Topic> Gotchasheading and make it self-contained
Step 4: Staleness detection
Scan existing entries in the memory topic files you touched (not all files — only the ones relevant to this run):
- Version-based: If an entry mentions a specific version (e.g., "Cilium 1.19.1", "chart v39.x"), check
git logfor version bumps past that number. If found, add<!-- STALE? Project has upgraded past <version> -->as a comment after the entry. - Fix-based: If an entry describes a workaround for a bug, grep recent log files and git commits for keywords suggesting the bug was fixed upstream. If found, flag it.
- Automation-based: If a process lesson describes a manual sequence, check if a script in
scripts/now handles it. If so, flag or update the entry.
Print all flagged items in the summary so the user can confirm removal.
Step 5: Update MEMORY.md index
If any new topic files were created:
- Add a one-line entry to the appropriate section of MEMORY.md
- Follow the existing format:
- [Title](memory/filename.md) -- Description - Make the description specific and searchable — it's used to decide what to read
Step 6: Update reflection state
Write .reflection-state.json with updated hashes:
{
"version": 1,
"last_run": "<ISO-8601 timestamp>",
"processed": {
"log/YYYY-MM-DD.HHMMSS.md": "<md5hash>",
...existing entries...
}
}
Preserve existing entries. Add new ones for the logs just processed. Use date -u +%Y-%m-%dT%H:%M:%SZ for the timestamp.
Step 7: Summary
Print:
- Number of logs processed
- New entries added (listed by destination file)
- Stale entries flagged (with the reason)
- Any new topic files created
- Any open questions resolved
Quality checks
- Every new entry must be actionable or informative — no filler
- Gotchas include symptom AND fix, not just "X was tricky"
- Process lessons are phrased as rules ("Always X before Y")
- New entries match the formatting style of existing entries in the target file
- Deduplication is by substance, not exact string match