PostToolUse hook auto-formats files after Edit/Write/MultiEdit with git-blob checkpoints for safe revert. Pre-commit hook for staged files. Canonical formatter scripts for py, sh, ts, sql, json (+ symlinks for js, yaml, md). Install and setup scripts for project opt-in. Includes best-practices/linting.md, HOOKS.md docs, README.md, and session log. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
75 lines
2.2 KiB
Bash
Executable File
75 lines
2.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Set up formatters for a project by symlinking selected formatters from claude-foundations.
|
|
#
|
|
# Usage: setup-formatters.sh <project-dir> <ext> [<ext> ...]
|
|
# Example: setup-formatters.sh ~/dev/claude/projects/my-project py sh
|
|
#
|
|
# This creates a formatters/ directory in the target project and symlinks
|
|
# the requested formatter scripts from claude-foundations/formatters/.
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
FOUNDATIONS_FORMATTERS="$(cd "$SCRIPT_DIR/../formatters" && pwd)"
|
|
|
|
if [ $# -lt 2 ]; then
|
|
echo "Usage: $(basename "$0") <project-dir> <ext> [<ext> ...]"
|
|
echo ""
|
|
echo "Available formatters:"
|
|
for f in "$FOUNDATIONS_FORMATTERS"/*; do
|
|
[ -e "$f" ] || continue
|
|
NAME="$(basename "$f")"
|
|
if [ -L "$f" ]; then
|
|
TARGET="$(readlink "$f")"
|
|
echo " $NAME → $TARGET"
|
|
else
|
|
echo " $NAME"
|
|
fi
|
|
done
|
|
exit 1
|
|
fi
|
|
|
|
PROJECT_DIR="$1"
|
|
shift
|
|
|
|
if [ ! -d "$PROJECT_DIR" ]; then
|
|
echo "Error: $PROJECT_DIR is not a directory" >&2
|
|
exit 1
|
|
fi
|
|
|
|
DEST="$PROJECT_DIR/formatters"
|
|
mkdir -p "$DEST"
|
|
|
|
# Compute relative path from project formatters/ to foundations formatters/
|
|
REL_PATH="$(python3 -c "import os.path; print(os.path.relpath('$FOUNDATIONS_FORMATTERS', '$DEST'))")"
|
|
|
|
echo "Setting up formatters in $DEST"
|
|
echo ""
|
|
|
|
for EXT in "$@"; do
|
|
SRC="$FOUNDATIONS_FORMATTERS/$EXT"
|
|
if [ ! -e "$SRC" ]; then
|
|
echo " ✗ $EXT — not found in $FOUNDATIONS_FORMATTERS" >&2
|
|
continue
|
|
fi
|
|
ln -sf "$REL_PATH/$EXT" "$DEST/$EXT"
|
|
echo " ✓ $EXT"
|
|
done
|
|
|
|
echo ""
|
|
echo "Done. Add formatters/ to your .gitignore or commit the symlinks."
|
|
|
|
# Also set up pre-commit hook if git repo
|
|
if git -C "$PROJECT_DIR" rev-parse --git-dir >/dev/null 2>&1; then
|
|
GIT_DIR="$(git -C "$PROJECT_DIR" rev-parse --git-dir)"
|
|
PRECOMMIT="$GIT_DIR/hooks/pre-commit"
|
|
PRECOMMIT_SRC="$SCRIPT_DIR/../hooks/pre-commit-lint.sh"
|
|
|
|
if [ ! -e "$PRECOMMIT" ]; then
|
|
ln -sf "$(cd "$(dirname "$PRECOMMIT_SRC")" && pwd)/$(basename "$PRECOMMIT_SRC")" "$PRECOMMIT"
|
|
echo "Git pre-commit hook installed: $PRECOMMIT → pre-commit-lint.sh"
|
|
else
|
|
echo "Git pre-commit hook already exists at $PRECOMMIT (not overwritten)."
|
|
fi
|
|
fi
|