terrylica

tether

Tether (install/uninstall) hooks that enforce git-town over raw git commands in Claude Code. Renamed from 'hooks' to avoid.

terrylica 61 9 Updated 4mo ago

Resources

1
GitHub

Install

npx skillscat add terrylica/cc-skills/plugins-git-town-workflow-skills-tether

Install via the SkillsCat registry.

SKILL.md

Git-Town Enforcement Hooks — Installation

This command installs Claude Code hooks that BLOCK forbidden raw git commands.

Self-Evolving Skill: This skill improves through use. If instructions are wrong, parameters drifted, or a workaround was needed — fix this file immediately, don't defer. Only update for real, reproducible issues.

What Gets Blocked

Forbidden Command Reason Replacement
git checkout -b Creates untracked branches git town hack
git pull Bypasses sync workflow git town sync
git merge Manual merges break flow git town sync
git push origin main Direct main push dangerous git town sync
git branch -d Manual branch deletion git town delete
git rebase Complex, use git-town git town sync

What's Allowed

Allowed Command Reason
git add Staging files (git-town doesn't replace)
git commit Creating commits (git-town doesn't replace)
git status Viewing status (read-only)
git log Viewing history (read-only)
git diff Viewing changes (read-only)
git stash Stashing changes (utility)
git remote Remote management (setup only)
git config Configuration (setup only)

Hook Definition

The following hook will be added to ~/.claude/settings.json:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "/usr/bin/env bash -c 'CMD=\"$CLAUDE_TOOL_INPUT_command\"; case \"$CMD\" in \"git checkout -b\"*|\"git checkout -B\"*) echo \"BLOCKED: Use git town hack instead of git checkout -b\"; exit 1;; \"git pull\"*) echo \"BLOCKED: Use git town sync instead of git pull\"; exit 1;; \"git merge\"*) echo \"BLOCKED: Use git town sync or git town ship instead of git merge\"; exit 1;; \"git push origin main\"*|\"git push origin master\"*) echo \"BLOCKED: Use git town sync instead of pushing to main\"; exit 1;; \"git branch -d\"*|\"git branch -D\"*) echo \"BLOCKED: Use git town delete instead of git branch -d\"; exit 1;; \"git rebase\"*) echo \"BLOCKED: Use git town sync (rebase strategy) instead of git rebase\"; exit 1;; esac'"
          }
        ]
      }
    ]
  }
}

Installation

Step 1: Check Current Settings

/usr/bin/env bash -c 'cat ~/.claude/settings.json 2>/dev/null || echo "{}"'

Step 2: AskUserQuestion Confirmation

AskUserQuestion with questions:
- question: "Install git-town enforcement hooks to block forbidden raw git commands?"
  header: "Install Hooks"
  options:
    - label: "Yes, install hooks (Recommended)"
      description: "Blocks: git checkout -b, git pull, git merge, git push main"
    - label: "No, don't install"
      description: "I want to use raw git commands freely"
    - label: "Show what will be blocked"
      description: "Display full list of blocked commands"
  multiSelect: false

Step 3: Merge Hook into Settings

Read existing settings, merge hooks, write back:

/usr/bin/env bash << 'INSTALL_HOOK_EOF'
SETTINGS_FILE="$HOME/.claude/settings.json"

# Create file if doesn't exist
if [[ ! -f "$SETTINGS_FILE" ]]; then
    echo '{}' > "$SETTINGS_FILE"
fi

# Read existing settings
EXISTING=$(cat "$SETTINGS_FILE")

# Define the new hook
NEW_HOOK='{
  "matcher": "Bash",
  "hooks": [
    {
      "type": "command",
      "command": "/usr/bin/env bash -c '\''CMD=\"$CLAUDE_TOOL_INPUT_command\"; case \"$CMD\" in \"git checkout -b\"*|\"git checkout -B\"*) echo \"BLOCKED: Use git town hack instead of git checkout -b\"; exit 1;; \"git pull\"*) echo \"BLOCKED: Use git town sync instead of git pull\"; exit 1;; \"git merge\"*) echo \"BLOCKED: Use git town sync or git town ship instead of git merge\"; exit 1;; \"git push origin main\"*|\"git push origin master\"*) echo \"BLOCKED: Use git town sync instead of pushing to main\"; exit 1;; \"git branch -d\"*|\"git branch -D\"*) echo \"BLOCKED: Use git town delete instead of git branch -d\"; exit 1;; \"git rebase\"*) echo \"BLOCKED: Use git town sync (rebase strategy) instead of git rebase\"; exit 1;; esac'\''"
    }
  ]
}'

# Merge using jq
echo "$EXISTING" | jq --argjson hook "$NEW_HOOK" '
  .hooks.PreToolUse = ((.hooks.PreToolUse // []) + [$hook] | unique_by(.matcher + (.hooks[0].command // "")))
' > "$SETTINGS_FILE.tmp" && mv "$SETTINGS_FILE.tmp" "$SETTINGS_FILE"

echo "✅ Hook installed successfully"
cat "$SETTINGS_FILE" | jq '.hooks'

INSTALL_HOOK_EOF

Step 4: Verify Installation

/usr/bin/env bash -c 'cat ~/.claude/settings.json | jq ".hooks.PreToolUse"'

Uninstallation

Step 1: Confirm Uninstall

AskUserQuestion with questions:
- question: "Remove git-town enforcement hooks?"
  header: "Uninstall"
  options:
    - label: "Yes, remove hooks"
      description: "Allow raw git commands again"
    - label: "No, keep hooks"
      description: "Keep enforcement active"
  multiSelect: false

Step 2: Remove Hook

/usr/bin/env bash << 'UNINSTALL_HOOK_EOF'
SETTINGS_FILE="$HOME/.claude/settings.json"

if [[ ! -f "$SETTINGS_FILE" ]]; then
    echo "No settings file found"
    exit 0
fi

# Remove git-town enforcement hook
cat "$SETTINGS_FILE" | jq '
  .hooks.PreToolUse = [.hooks.PreToolUse[]? | select(.matcher != "Bash" or (.hooks[0].command | contains("git town") | not))]
' > "$SETTINGS_FILE.tmp" && mv "$SETTINGS_FILE.tmp" "$SETTINGS_FILE"

echo "✅ Hook removed successfully"

UNINSTALL_HOOK_EOF

Status Check

Show Current Hook Status

/usr/bin/env bash << 'STATUS_HOOK_EOF'
SETTINGS_FILE="$HOME/.claude/settings.json"

echo "=== GIT-TOWN ENFORCEMENT HOOK STATUS ==="

if [[ ! -f "$SETTINGS_FILE" ]]; then
    echo "❌ No settings file found"
    echo "   Run: /git-town-workflow:tether install"
    exit 0
fi

# Check if hook exists
HOOK_EXISTS=$(cat "$SETTINGS_FILE" | jq '[.hooks.PreToolUse[]? | select(.hooks[0].command | contains("git town"))] | length')

if [[ "$HOOK_EXISTS" -gt 0 ]]; then
    echo "✅ Git-town enforcement hook is ACTIVE"
    echo ""
    echo "Blocked commands:"
    echo "  - git checkout -b → use git town hack"
    echo "  - git pull → use git town sync"
    echo "  - git merge → use git town sync"
    echo "  - git push origin main → use git town sync"
    echo "  - git branch -d → use git town delete"
    echo "  - git rebase → use git town sync"
else
    echo "❌ Git-town enforcement hook is NOT installed"
    echo "   Run: /git-town-workflow:tether install"
fi

STATUS_HOOK_EOF

Arguments

  • install - Install enforcement hooks
  • uninstall - Remove enforcement hooks
  • status - Show current hook status

Examples

# Install hooks
/git-town-workflow:tether install

# Check status
/git-town-workflow:tether status

# Remove hooks
/git-town-workflow:tether uninstall

Troubleshooting

Issue Cause Solution
jq not found jq not installed brew install jq
Settings file not found ~/.claude/ doesn't exist Create with mkdir -p ~/.claude
Hook not blocking Session not restarted Restart Claude Code session
Invalid JSON error Corrupted settings.json Check JSON syntax or restore backup
Hook still active Multiple hooks registered Uninstall and reinstall to dedupe

Post-Execution Reflection

After this skill completes, reflect before closing the task:

  1. Locate yourself. — Find this SKILL.md's canonical path before editing.
  2. What failed? — Fix the instruction that caused it.
  3. What worked better than expected? — Promote to recommended practice.
  4. What drifted? — Fix any script, reference, or dependency that no longer matches reality.
  5. Log it. — Evolution-log entry with trigger, fix, and evidence.

Do NOT defer. The next invocation inherits whatever you leave behind.