Tether (install/uninstall) hooks that enforce git-town over raw git commands in Claude Code. Renamed from 'hooks' to avoid.
Scanned 9/2/2026
Install to Claude Code
npx -y skills add terrylica/cc-skills --skill tether --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Tether?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/terrylica-tether-62c0e342)More formats (shields.io, HTML) on the badges page.
---
name: tether
allowed-tools: Read, Write, Edit, Bash(cat:*), Bash(jq:*), Grep, Glob, AskUserQuestion
argument-hint: "[install|uninstall|status]"
description: Tether (install/uninstall) hooks that enforce git-town over raw git commands in Claude Code. Renamed from 'hooks' to avoid.
model: haiku
disable-model-invocation: true
---
<!-- ⛔⛔⛔ MANDATORY: READ THIS ENTIRE FILE BEFORE ANY ACTION ⛔⛔⛔ -->
# 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`:
```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
```bash
/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:**
```bash
/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
```bash
/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
```bash
/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
```bash
/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
```bash
# 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:
0. **Locate yourself.** — Find this SKILL.md's canonical path before editing.
1. **What failed?** — Fix the instruction that caused it.
2. **What worked better than expected?** — Promote to recommended practice.
3. **What drifted?** — Fix any script, reference, or dependency that no longer matches reality.
4. **Log it.** — Evolution-log entry with trigger, fix, and evidence.
Do NOT defer. The next invocation inherits whatever you leave behind.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!