---
name: setup
description: "Manage hook installation and uninstallation for autoloop heartbeat. Install or remove the PostToolUse hook from ~/.claude/settings.json."
allowed-tools: Bash, Read, Write, AskUserQuestion
argument-hint: "[install|uninstall|status]"
disable-model-invocation: false
---

# autoloop: Setup

> **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.

Manage the heartbeat hook installation for autoloop. This skill allows explicit control over when the hook is installed or uninstalled from `~/.claude/settings.json`.

## Arguments

- Optional: `install`, `uninstall`, or `status`. Defaults to `status`.

## Step 1: Determine action

If no argument provided, use `AskUserQuestion` to present three options:

- **Check current status** — Display whether hook is installed
- **Install the hook** — Add heartbeat hook to settings.json (idempotent)
- **Uninstall the hook** — Remove heartbeat hook from settings.json (idempotent)

Otherwise, use the provided argument (`install`, `uninstall`, or `status`).

## Step 2: Check current install status

```bash
# Source the hook install library
PLUGIN_ROOT="${CLAUDE_PLUGIN_ROOT:-$HOME/.claude/plugins/marketplaces/cc-skills/plugins/autoloop}"
source "$PLUGIN_ROOT/scripts/hook-install-lib.sh"

# Wave 5 A4: strip macOS quarantine xattr from plugin scripts. After
# `claude plugin marketplace add`, files downloaded via curl/zip/tar inherit
# com.apple.quarantine and refuse to execute with "operation not permitted".
# This is a no-op on Linux and idempotent on macOS.
STRIPPED=$(strip_plugin_quarantine_xattrs "$PLUGIN_ROOT" 2>&1)
COUNT=$(echo "$STRIPPED" | tail -1)
if [ "$COUNT" -gt 0 ] 2>/dev/null; then
  echo "  Removed com.apple.quarantine from $COUNT plugin scripts (one-time cleanup)"
fi

# Check installation status
SETTINGS_PATH="$HOME/.claude/settings.json"
INSTALLED=$(is_hook_installed "$SETTINGS_PATH")

if [ "$INSTALLED" = "yes" ]; then
  echo "✓ Hook is currently INSTALLED"
  echo "  Path: $SETTINGS_PATH"
else
  echo "✗ Hook is currently NOT INSTALLED"
  echo "  Path: $SETTINGS_PATH"
fi
```

## Step 3: Perform requested action

### If action is `install`

```bash
if [ "$(is_hook_installed "$SETTINGS_PATH")" = "yes" ]; then
  echo "Hook already installed; no action needed"
else
  if install_hook "$SETTINGS_PATH"; then
    echo "✓ Hook installed successfully"
    echo "  The heartbeat will now tick on each tool invocation"
  else
    echo "✗ Failed to install hook"
    exit 1
  fi
fi

# Wave 5 A1: runtime self-test. is_hook_installed only verifies that a
# command path matching our hook is present in settings.json — it cannot
# detect a hook that's registered but crashes on invocation (broken
# shebang, missing dependency, syntax error from a botched edit, stale
# sibling-lib path). Run each hook with a synthetic Claude Code event
# payload in a sandbox HOME and confirm exit 0.
echo ""
echo "Verifying hooks run cleanly..."
if run_hook_runtime_selftest "$PLUGIN_ROOT" 2>&1; then
  echo "✓ All hooks invoke cleanly"
else
  echo "✗ One or more hooks failed runtime self-test (see lines above)"
  echo "  This means the hooks are registered but won't actually fire."
  echo "  Reinstall the plugin or investigate the failing script."
  exit 1
fi
```

### If action is `uninstall`

```bash
if [ "$(is_hook_installed "$SETTINGS_PATH")" = "no" ]; then
  echo "Hook not installed; no action needed"
  exit 0
fi

if uninstall_hook "$SETTINGS_PATH"; then
  echo "✓ Hook uninstalled successfully"
  echo "  The heartbeat will no longer tick on tool invocations"
else
  echo "✗ Failed to uninstall hook"
  exit 1
fi
```

### If action is `status`

Report installation status (already done in Step 2). No further action.

## Anti-patterns

- Do NOT force-uninstall when there are active loops — recommend stopping the loop first
- Do NOT install the hook into a malformed settings.json — report the error and ask user to fix it manually

## Troubleshooting

| Symptom                      | Fix                                                        |
| ---------------------------- | ---------------------------------------------------------- |
| "settings.json is malformed" | Manually edit `~/.claude/settings.json` to fix JSON syntax |
| "Hook not found"             | Reinstall the autoloop plugin                              |
| Lock contention error        | Wait a few seconds; another process is updating settings   |

## Implementation Notes

- All operations use `_with_settings_lock` internally for concurrency safety
- Install is idempotent; running twice in a row has no effect
- Uninstall is idempotent; no error if hook is not present
- Backup is created on first install to `~/.claude/.settings.backup.<timestamp>.json`

## Post-Execution Reflection

0. **Locate yourself.** — Confirm this SKILL.md is the canonical file before any edit.
1. **What failed?** — Fix the instruction that caused it.
2. **What drifted?** — Update if the install pattern, settings.json shape, or lock conventions changed.
3. **Log it.** — Evolution-log entry with trigger, fix, evidence.
