hyperhive/claude-plugins/plugins/base/skills/async-task-hygiene/SKILL.md

2.6 KiB

name description
async-task-hygiene Habits for background tasks and waiting. Don't truncate a background task's captured output with a tail/head pipe - the full output is saved regardless, so piping it away only throws away what you might need, slice it after the fact instead. Don't assume a background task from before a restart is still exactly where you left it - check its status rather than blindly re-running it. Prefer ending your turn (or a short bounded wait) over a sleep-based polling loop when waiting on something in progress. Use this whenever you launch, check on, or wait for background work.

Async Task Hygiene

Background tasks (a build, a long command, anything you fire off and check on later) have a few sharp edges worth knowing.

Don't pipe away captured output

Don't do some-long-command | tail -N (or | head -N) when launching a background task. The runner captures the full stdout/stderr to a file regardless of what you piped through - so truncating the live output doesn't save anything, it just means you can't slice the part you didn't think you'd need until you needed it. Run the full command, then read/grep the captured file however you want afterward. (Genuinely unbounded streams you'll never read in full are the rare exception to this - not normal command output.)

Don't blindly re-run a task after a restart

If your environment restarted (container rebuild, harness restart) and you had background tasks in flight, don't assume they're gone and re-launch them from scratch. Check their status first - a task may still be running, may have finished while you were down, or may genuinely need restarting. Re-running blind can duplicate work or step on a task that's still making progress.

Prefer ending the turn over a sleep-loop

When you're waiting on something (a build, a task you started, a fixed delay before retrying), a sleep-then-check loop blocks you from reacting to anything else for that whole window. Prefer:

  • Between units of work: just end the turn. Whatever wakes you next (the task's own completion, a new message) drives the follow-up - there's nothing to poll for.
  • Within a turn, if you must wait: a short bounded wait that can be interrupted by new input beats a blind sleep, since it lets you react immediately if something more urgent shows up instead of only after your poll interval elapses.

Concretely: if you started something and plan to check back, don't sleep N && check-status in a loop. Either end the turn and let the task's own completion (or the next message) drive the next step, or use an interruptible wait if you genuinely need to stay in-turn.