diff --git a/.reflection-state.json b/.reflection-state.json index 5858405..c77dfe3 100644 --- a/.reflection-state.json +++ b/.reflection-state.json @@ -1,9 +1,11 @@ { "version": 1, - "last_run": "2026-03-15T09:25:01Z", + "last_run": "2026-03-16T22:19:21Z", "processed": { "log/2026-03-12.233744.md": "ca482f03914a3b4dec89c2dbf6e0f2e5", "log/2026-03-13.100758.md": "65c5b65fdd5984c036f1de53f8c82f2a", - "log/2026-03-13.115251.md": "56a27d18deeb89c8ce8b112b099ac7cf" + "log/2026-03-13.115251.md": "56a27d18deeb89c8ce8b112b099ac7cf", + "log/2026-03-15.225345.md": "ae9366aed0b4c87ecbbe535e00cb2cb2", + "log/2026-03-17.103204.md": "56c04b01459f80134e680150c338e9eb" } } diff --git a/memory/decisions.md b/memory/decisions.md index a8c62f2..a2a0162 100644 --- a/memory/decisions.md +++ b/memory/decisions.md @@ -32,6 +32,14 @@ Fast (~1ms), no commits or stash needed, orphan blobs auto-GC'd. Falls back to ` Projects opt in by having a `formatters/` directory with symlinks back to canonical scripts. Zero-config, visible in `ls`, no parsing needed. The hook walks up the directory tree to find `formatters/`. +## Skills: Use CLAUDE_PROJECT_ROOT for cross-project path resolution + +Skills that reference files outside their own project (e.g., `/distill-best-practices` reading settings.yaml) use `CLAUDE_PROJECT_ROOT` env var instead of hardcoded `~/dev/claude/` or relative `../` paths. Makes skills portable across users. Env var exported in `~/.bashrc`, with runtime fallback (walk up directory tree to find highest CLAUDE.md). + +## Skills: settings.yaml paths relative to project root + +`settings.yaml` uses relative paths (`projects_dir: projects`) rather than absolute paths. Combined with `CLAUDE_PROJECT_ROOT`, this keeps config portable. The `extra_projects` section handles projects outside the standard `projects_dir` (e.g., `small-scripts` at root level). + ## CLAUDE.md: Remove technology-specific sections from root Ansible and Helm sections removed from root CLAUDE.md — already covered with more detail in `best-practices/ansible.md` and `best-practices/helm.md`. Technology-specific practices belong in best-practices, not root guidelines. diff --git a/memory/gotchas-skills.md b/memory/gotchas-skills.md index fcbf0fb..3b63371 100644 --- a/memory/gotchas-skills.md +++ b/memory/gotchas-skills.md @@ -6,6 +6,23 @@ **Cause:** `readlink -f` on a broken symlink returns an empty string, causing comparison failure under `set -e`. **Fix:** Remove stale symlinks before re-running install. When skills move directories (e.g., from `~/dev/claude/custom-claude-skills/` to `~/dev/claude/projects/custom-claude-skills/`), old symlinks break. +## `$VAR` and `${VAR}` in bang-command paths rejected by permission checker + +**Symptom:** Skill fails with "Shell expansion syntax in paths requires manual approval" on `cat $HOME/dev/claude/...` or `cat ${HOME}/...`. +**Cause:** Claude Code's Bash permission checker rejects any `$VAR` or `${VAR}` expansion in file path arguments, even if the outer command matches an `allowed-tools` pattern. +**Fix:** Replace bang-commands that need dynamic paths with plain-text instructions telling Claude to use the Read tool at runtime. The Read tool bypasses the shell permission checker entirely. + +## `$()` command substitution in bang-commands is rejected + +**Symptom:** Bang-command like `git log --since="$(git log ...)"` fails even though `Bash(git *)` is in allowed-tools. +**Cause:** The permission checker rejects any command containing `$()` subshells regardless of the outer pattern match. +**Fix:** Keep bang-commands simple. If complex logic is needed, have the skill instructions tell Claude to run it via tool calls instead. + +## Relative paths in bang-commands resolve differently based on CWD + +**Symptom:** `cat ../claude-foundations/settings.yaml` resolves to the wrong path (outside sandbox) when skill is invoked from an unexpected CWD. +**Fix:** Use `CLAUDE_PROJECT_ROOT` env var instead of relative paths. Env var expansion (without `$`) isn't rejected by the permission checker when used in the SKILL.md body instructions rather than bang-commands. + ## Skills created mid-session are not available as slash commands **Symptom:** A newly created skill doesn't appear when you type `/skillname`. diff --git a/memory/process-lessons.md b/memory/process-lessons.md index 7b22da0..2b8bb40 100644 --- a/memory/process-lessons.md +++ b/memory/process-lessons.md @@ -24,6 +24,10 @@ Multiple hooks registered for the same matcher execute concurrently, not sequent Needs ssh-agent loaded before git push to Gitea. If push hangs, check that the key is added to the agent. +## Research full failure history before building validators + +When building a tool that detects known problems (like `validate-skill`), first research all historical failures across session logs and git commits. This reveals non-obvious patterns — e.g., `$HOME` (not just `${HOME}`) being rejected by permission checkers, which wouldn't be found from docs alone. The upfront research investment pays off in comprehensive coverage. + ## Batch parallel file creation for efficiency Creating many independent files in a single Write batch (e.g., 11 best-practices files at once) is significantly faster than sequential creation.