Install
$ agentstack add skill-ccomkhj-skills-long-haul ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
long-haul
What this is
The orchestrator: the interactive Claude session the user runs. It drives a four-phase arc that forces work across the long horizon — a loop that does not stop until a measurable goal holds. You advance automatically, halting only at two human gates.
The phases are sibling skills; invoke each in turn:
sharpen-spec— turn the ask into a well-defined spec with a transcript-demonstrable success signal and a declared toolbox (the skills + MCP the haul may use). If the ask is vague, grill it first.define-goal— forge a/goal-ready completion condition from the spec. GATE: user approves + runs/goal.haul-loop— each/goalturn, run one round: decide explore vs exploit, implement the attempt in a worktree, keep it only if it beats the incumbent. Repeat until the goal clears.wrap-up— once the goal clears (or the cap trips), report goal-vs-achieved and open a PR. GATE: user confirms.
You are the orchestrator and the implementer. Unlike a race, there is one pair of hands — yours. The leverage is not a second agent; it's the explore/exploit discipline and the ratcheting incumbent that keep a long run from drifting.
The /goal mechanic (read this — the whole haul hinges on it)
/goal is a Claude Code built-in (v2.1.139+): it sets a completion condition, and after every turn a fast model checks the transcript to decide whether it holds. If not, it starts another turn automatically; when it holds, the goal auto-clears. Two consequences shape this skill:
- Slash commands are user-invoked. You cannot type
/goal,/grill-me, or/implementyourself. Where the arc needs one, you either run its model-invocable equivalent (thegrillingskill) or follow its contract inline (the/implementcontract, executed by you inside each/goalturn)./goalitself is a hard gate —define-goalproduces the exact line and the user runs it. - The evaluator only reads the conversation — it runs no tools. So every round
haul-loopmust surface the goal's stated check output in chat. A goal whose proof never lands in the transcript loops forever.
Once /goal is active it re-invokes you turn after turn. Your standing job each turn is at most one haul-loop round — ROUND in STATE.md is the source of truth, so a turn that does zero or (accidentally) two doesn't desync the count. When the condition is met haul-loop records STATUS: GOAL-MET and the goal clears — then proceed to wrap-up.
Flow
digraph long_haul {
"Init .longhaul/, record PHASE" [shape=box];
"sharpen-spec -> SPEC.md" [shape=box];
"define-goal -> GOAL.md" [shape=box];
"GATE: user approves + runs /goal" [shape=diamond];
"haul-loop: 1 round this turn (explore|exploit)" [shape=box];
"Goal met? (/goal cleared)" [shape=diamond];
"wrap-up -> SUMMARY.md + PR" [shape=doublecircle];
"Init .longhaul/, record PHASE" -> "sharpen-spec -> SPEC.md";
"sharpen-spec -> SPEC.md" -> "define-goal -> GOAL.md";
"define-goal -> GOAL.md" -> "GATE: user approves + runs /goal";
"GATE: user approves + runs /goal" -> "haul-loop: 1 round this turn (explore|exploit)" [label="approved"];
"haul-loop: 1 round this turn (explore|exploit)" -> "Goal met? (/goal cleared)";
"Goal met? (/goal cleared)" -> "haul-loop: 1 round this turn (explore|exploit)" [label="no (next /goal turn)"];
"Goal met? (/goal cleared)" -> "wrap-up -> SUMMARY.md + PR" [label="yes (or cap hit)"];
}
On invocation
- Preflight (next section). Stop on a hard failure; flag a soft one with the phase it will block at.
- Resume vs fresh. If
/.longhaul/STATE.mdexists, readPHASE/STATUSand jump to that phase — do not restart. Otherwise create.longhaul/under the target repo (REPO, resolved in preflight), append.longhaul/to its.gitignore, writeSTATE.md(PHASE: spec,STATUS: ACTIVE: orchestrator,ROUND: 0,ROUNDS: 8,MODE: -,STALL: 0,STALL_CAP: 2,INCUMBENT: none,SCORE: none,REPO:,BASE:,GATES: approve_goal=required confirm_pr=required,GOAL: pending), and record the user's ask. - Drive the phases in order, invoking each sibling skill. Update
PHASEas you cross each boundary so a re-invocation resumes cleanly. If the user gave no ask, don't enumerate the spec questions yourself — go straight intosharpen-spec, which collects them via tabbedAskUserQuestioncalls.
Preflight
Everything a later phase needs, checked before it's too late to fix cheaply. A hard failure stops the run; a soft one is flagged with the phase it will block at — say "this will block at X" rather than letting the user discover it after they've disconnected.
- Git —
git rev-parse --git-dir. Worktrees need it. Missing → stop. - Target repo. The deliverable's repo may differ from the invocation cwd. If the ask names a file, a PR, or an artifact ("the DAG") that lives outside cwd, or sibling git repos sit alongside it, ask which repo owns the deliverable before writing any state. That repo is
REPO; all.longhaul/state,BASE, worktrees, the incumbent branch, and the eventual PR live under it, not cwd. DefaultREPOto cwd's repo toplevel when they're the same. - Resolve "this PR". If the ask says "this PR" / "the PR", it has no referent until you pin it: in
REPO,gh pr viewfor the current branch, elsegh pr list --search. Echo the resolved PR (number, title, base) back for confirmation before sharpening — the branch you're on may have no PR while a sibling branch at the same SHA does. - /goal availability — Claude Code ≥ v2.1.139. Missing → offer to run the loop manually with a round cap instead.
- Wrap-up deps.
wrap-upopens a PR, so verify now, not at the end:ghpresent + authed (gh auth status),REPO's remote reachable, push permission. Missing → soft-flag "blocks at wrap-up". - Detach readiness (only if the run is meant to go unattended — foreground Auto-mode or
--background). An unattended haul that hits any interactive stop parks until a human returns, so confirm the whole path is clear:
- Auto mode on —
/goalonly auto-runs turns with it; otherwise every tool call prompts. (Foreground only.) - Hooks not disabled —
/goalis off underdisableAllHooks/allowManagedHooksOnly. confirm_pr=autoinGATES— the defaultrequiredparks forever before the PR.- Background only:
check.shwritten,haul_bg_startavailable (reference/haul-bg.sh), host stays powered.
Any unmet item → name it and the step it blocks at.
- Toolbox reachability + cost. The spec's toolbox may name heavy or paid
means — an MCP server (is it authed and responding?), an external/prod runner (SageMaker, a deploy target), a live DB. Two things to surface now: (a) any tool the haul will need but can't reach (unauthed MCP, missing CLI) → soft-flag with the phase it blocks at; (b) any toolbox step that spends real money or mutates production — typically the acceptance gate (GOAL.md) — → say so plainly ("this haul will incur prod compute at the acceptance gate"), so the user opts into the cost before the loop, not after a surprise bill. A long autonomous run that fires paid infra is not bounded by the per-round worktree.
The two gates — never skip these
| Gate | When | What you do | |---|---|---| | approve-goal | after define-goal | Show GOAL.md's condition and the /goal … line. Wait for the user to edit/approve and to actually run /goal. Do not start hauling until the goal is active. | | confirm-pr | in wrap-up | Show the branch name + commit list + PR body. Only push/open after the user confirms — unless GATES sets confirm_pr=auto. |
Set STATUS: WAITING-USER: while waiting so a resume knows it's parked on a human.
Gate policy. GATES in STATE.md sets each gate's mode. approve_goal is always required — only the user can run /goal. confirm_pr is required (default — wrap-up parks for a yes) or auto (for an unattended finish — wrap-up opens a draft PR without parking and never pushes to a protected or default branch). Set confirm_pr=auto only once the user has accepted an unattended finish.
Phase ownership
Each phase's mechanics live in its own skill — invoke it, don't reimplement it:
sharpen-specwritesSPEC.md(the deliverable, the success signal, the toolbox, constraints).define-goalwritesGOAL.md(+ the/goalline) fromSPEC.md.haul-loopruns one explore-or-exploit round per/goalturn againstGOAL.md, writesR.md, and ratchets theINCUMBENT.wrap-upwritesSUMMARY.md, then commits on a branch and opens the PR.
State-file templates live in [reference/file-formats.md](reference/file-formats.md).
Termination & escape hatches
- Normal: goal clears →
haul-loopsetsSTATUS: GOAL-MET→wrap-up→ user confirms → PR opened →STATUS: DONE. - Round cap hit, or the well is dry (
haul-loop's own stopping conditions): it setsSTATUS: WAITING-USER: cap-decisionand surfaces a partial against the incumbent. Decide with the user whether to raiseROUNDS, accept (→wrap-up), or stop. (Definitions live inhaul-loop; don't restate them here.) - Git unavailable /
/goalunavailable:STATUS: BLOCKED:, surface, stop. - Always tear down the attempt worktree before exiting on any path (
git worktree prune).
Resuming
/long-haul with an existing .longhaul/: read STATUS. First check .longhaul/bg.pid — if it names a live process, a background driver owns the haul; this session is read-only. Show haul_bg_status (tail of PROGRESS.log) and either watch or haul_bg_stop before taking over. Otherwise dispatch on STATUS:
ACTIVE: orchestrator→ resume the phase named byPHASE(spec→sharpen-spec,goal→define-goal,haul→haul-loop,wrap→wrap-up) from the top; the phases are re-entrant (e.g. a haul interrupted mid-grilling just re-asks).WAITING-USER:→ re-present that gate (approve-goal,confirm-pr, orcap-decision).HAULING: R→ an attempt may be mid-flight in.longhaul/attempt/; check it, judge if done, else continue it. Don't start a second attempt for the same round.GOAL-MET→ the loop is done and the goal holds; go straight towrap-up.BLOCKED→ report what's blocked.DONE→ showSUMMARY.md.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: ccomkhj
- Source: ccomkhj/skills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.