Use when a shell healthcheck script uses hint() functions to point users at fix commands, and those commands silently fail or require a separate manual step, or when you want users to be prompted to run the fix immediately after a failure is reported.
Installs into .claude/skills of the current project.
Are you the author of Healthcheck Interactive Hints?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/williamblair333-healthcheck-interactive-hints)
---
name: healthcheck-interactive-hints
description: Use when a shell healthcheck script uses hint() functions to point users at fix commands, and those commands silently fail or require a separate manual step, or when you want users to be prompted to run the fix immediately after a failure is reported.
---
# Healthcheck Interactive Hints
## Overview
Two complementary patterns for making shell healthchecks self-healing:
1. **Single-purpose fix scripts** — replace fire-and-forget maintenance scripts with dedicated scripts that exit non-zero on failure.
2. **Interactive hint prompts** — modify `hint()` to offer "Fix it now? [y/N]" when stderr is a terminal.
## When to Use
- A healthcheck `hint()` points at a general maintenance script (e.g. `auto-maintain.sh`) that calls nested processes non-fatally.
- The fix is achievable with a one-liner or short script but the hint just describes it passively.
- Users are running healthchecks interactively and would benefit from in-place remediation.
- A canary/index file is missing and must be regenerated by calling a tool directly.
**When NOT to use:** Cron or CI contexts where no TTY is attached — the TTY guard handles this automatically.
## Pattern 1 — Dedicated Fix Script
Replace the hint's target with a script that does exactly one thing and validates it worked:
```bash
#!/usr/bin/env bash
# scripts/pin-canary.sh — pins the embedding canary; exits non-zero if it fails
set -euo pipefail
claude -p "Call check_embedding_drift with capture=true" || {
echo "ERROR: claude -p failed" >&2; exit 1
}
CANARY="$HOME/.code-index/embed_canary.json"
[[ -f "$CANARY" ]] || { echo "ERROR: canary file not written: $CANARY" >&2; exit 1; }
echo "Canary pinned: $CANARY"
```
Key properties:
- `set -euo pipefail` — no silent failures
- Validates the side-effect (file existence, process output) before exiting 0
- Single responsibility — not wrapped inside a larger maintenance script
## Pattern 2 — Interactive hint() Function
Replace a passive `hint()` with one that offers to run `run: ...` hints immediately:
```bash
hint() {
local msg="$1"
echo " hint: $msg" >&2
# Only prompt when stderr is a TTY and hint is a runnable command
if [[ -t 2 ]] && [[ "$msg" == run:* ]]; then
# Strip leading "run: " and any trailing " (parenthetical note)"
local cmd
cmd="${msg#run: }"
cmd="${cmd%% (*}"
printf " Fix it now? [y/N] " >&2
read -r answer </dev/tty
if [[ "$answer" =~ ^[Yy]$ ]]; then
echo " Running: $cmd" >&2
bash -c "$cmd" || echo " (fix command exited non-zero; re-run healthcheck to verify)" >&2
fi
fi
}
```
Key properties:
- `-t 2` TTY guard — cron/pipe runs are unaffected
- Only `run: ...` hints get the prompt; advisory hints (`add: ...`, `check: ...`) don't
- Parenthetical stripping — `"run: foo (re-registers crons)"` → `bash -c "foo"`
- Non-fatal on failure — healthcheck continues regardless
## Implementation Steps
1. Identify hints that point at a general-purpose maintenance script.
2. Check whether that script's fix step is fire-and-forget (non-fatal `||`, background `&`, or nested `claude -p`).
3. Extract the fix into `scripts/<action>.sh` using the template above.
4. Update the hint string: `hint "run: scripts/<action>.sh"`.
5. Replace the `hint()` function body with the interactive version above.
6. Test: run the healthcheck in a TTY and answer `y` at the prompt; confirm it passes on re-run.
## Common Mistakes
| Mistake | Fix |
|---------|-----|
| Pointing hint at a script that still calls a nested `claude -p` non-fatally | Move the claude call to the dedicated script with `set -e` and file validation |
| Using `read` without `</dev/tty` | If stdin is redirected (pipe, heredoc), `read` blocks or errors — always use `</dev/tty` |
| Parenthetical not stripped before `bash -c` | `bash -c "foo (re-registers crons)"` is a syntax error — strip with `${cmd%% (*}` |
| Prompting in CI/non-TTY | The `-t 2` guard prevents this, but make sure stderr isn't redirected to a file that satisfies `-t` |
## Notes
This skill was derived from a live session on branch `dma64` of Uncle J's Refinery. The TDD pressure-scenario cycle (writing-skills iron law) was not run before writing — treat the session itself as RED-phase evidence, but add formal subagent pressure tests before considering this bulletproofed.