Files
claude-foundations/scripts/context-load
Paul O'Reilly f41c22d0ac Add question-reframing guidance to CLAUDE.md; commit accumulated project files
- CLAUDE.md: add "Question the question" and "One clarifying question" rules
  to Tone and Interaction — XY problem detection, false premise checks, and
  explicit reframe pattern before answering
- Add claude/ detail-file directory (topic docs referenced from CLAUDE.md)
- Add ABOUT.md, FUTURE.md
- Update memory/, scripts/, settings.yaml with accumulated session changes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-25 09:37:28 +12:00

162 lines
4.8 KiB
Bash
Executable File

#!/usr/bin/env bash
# context-load — Gather project context for a Claude Code session
#
# Walks from cwd upward collecting key index files.
# Outputs structured context to stdout, suitable for --append-system-prompt.
#
# What it loads:
# - Paths to every CLAUDE.md found walking up from cwd (not contents — Claude Code loads those natively)
# - Paths to every project CLAUDE.md found under each CLAUDE.md directory (for project discovery)
# - Every CONTEXT.md found walking up from cwd (top-down order)
# - Every MEMORY.md found walking up from cwd (top-down order)
# - Every BESTPRACTICES.md found walking up from cwd (top-down order)
set -uo pipefail
# --- Helpers ---
emit_header() {
echo ""
echo "================================================================"
echo "=== $1"
echo "================================================================"
echo ""
}
emit_file() {
local filepath="$1"
emit_header "FILE: $filepath"
cat "$filepath"
echo ""
}
# Extract description from ABOUT.md in the same directory as a CLAUDE.md
get_project_description() {
local claude_path="$1"
local dir
dir="$(dirname "$claude_path")"
local about="$dir/ABOUT.md"
if [[ -f "$about" ]]; then
sed -n 's/^description:[[:space:]]*//p' "$about" | head -1
fi
}
# --- Discovery: walk from cwd upward ---
discover_upward() {
local dir="$PWD"
local dirs=()
while [[ "$dir" != "/" ]]; do
dirs+=("$dir")
dir="$(dirname "$dir")"
done
# Return in top-down order (reverse — highest ancestor first)
for ((i=${#dirs[@]}-1; i>=0; i--)); do
echo "${dirs[$i]}"
done
}
# Collect dirs that have key index files
claude_dirs=()
context_dirs=()
memory_dirs=()
bestpractices_dirs=()
while IFS= read -r dir; do
[[ -f "$dir/CLAUDE.md" ]] && claude_dirs+=("$dir")
[[ -f "$dir/CONTEXT.md" ]] && context_dirs+=("$dir")
[[ -f "$dir/MEMORY.md" ]] && memory_dirs+=("$dir")
[[ -f "$dir/BESTPRACTICES.md" ]] && bestpractices_dirs+=("$dir")
done < <(discover_upward)
if [[ ${#claude_dirs[@]} -eq 0 ]]; then
echo "# No CLAUDE.md found in directory hierarchy" >&2
echo "# Searched from: $PWD" >&2
fi
# --- Output: Claude profile ---
profile_dir="${CLAUDE_CONFIG_DIR:-$HOME/.claude}"
profile_name="$(basename "$profile_dir")"
if [[ "$profile_name" == ".claude" ]]; then
emit_header "CLAUDE PROFILE: default (~/.claude)"
else
emit_header "CLAUDE PROFILE: $profile_name ($profile_dir)"
fi
# --- Output: CLAUDE.md paths (not contents — Claude Code loads those natively) ---
# Also discover project CLAUDE.md files under each directory for project listing
# Track files we've already emitted to avoid duplicates
declare -A emitted_files
emit_header "CLAUDE.md FILES"
for dir in "${claude_dirs[@]}"; do
real_path="$(readlink -f "$dir/CLAUDE.md")"
if [[ -z "${emitted_files[$real_path]:-}" ]]; then
desc="$(get_project_description "$dir/CLAUDE.md")"
if [[ -n "$desc" ]]; then
echo "- $dir/CLAUDE.md — $desc"
else
echo "- $dir/CLAUDE.md"
fi
emitted_files["$real_path"]=1
fi
done
# Discover project CLAUDE.md files (depth 2-4 under each CLAUDE.md dir)
# This replaces the old tree output — gives Claude a fresh project listing
project_claudes=()
for dir in "${claude_dirs[@]}"; do
while IFS= read -r f; do
real_path="$(readlink -f "$f")"
if [[ -z "${emitted_files[$real_path]:-}" ]]; then
project_claudes+=("$f")
emitted_files["$real_path"]=1
fi
done < <(find "$dir" -mindepth 2 -maxdepth 4 -name CLAUDE.md -not -path '*/.git/*' -not -path '*/node_modules/*' -not -path '*/__pycache__/*' 2>/dev/null | sort)
done
if [[ ${#project_claudes[@]} -gt 0 ]]; then
echo ""
echo "Project CLAUDE.md files:"
for f in "${project_claudes[@]}"; do
desc="$(get_project_description "$f")"
if [[ -n "$desc" ]]; then
echo "- $f$desc"
else
echo "- $f"
fi
done
fi
echo ""
# --- Output: CONTEXT.md files (top-down) ---
for dir in "${context_dirs[@]}"; do
real_path="$(readlink -f "$dir/CONTEXT.md")"
if [[ -z "${emitted_files[$real_path]:-}" ]]; then
emit_file "$dir/CONTEXT.md"
emitted_files["$real_path"]=1
fi
done
# --- Output: MEMORY.md files (top-down) ---
for dir in "${memory_dirs[@]}"; do
real_path="$(readlink -f "$dir/MEMORY.md")"
if [[ -z "${emitted_files[$real_path]:-}" ]]; then
emit_file "$dir/MEMORY.md"
emitted_files["$real_path"]=1
fi
done
# --- Output: BESTPRACTICES.md files (top-down) ---
for dir in "${bestpractices_dirs[@]}"; do
real_path="$(readlink -f "$dir/BESTPRACTICES.md")"
if [[ -z "${emitted_files[$real_path]:-}" ]]; then
emit_file "$dir/BESTPRACTICES.md"
emitted_files["$real_path"]=1
fi
done