looprinter-interview
Interview the user about what a loop harness should accomplish, then generate KEY_OBJECTIVE, verify_objective(), prompt functions, and the verify() gate directly into loop.sh. Use when the user wants to configure a new loop task, or says "looprinter-interview", "new loop", or "loop interview".
Install
mkdir -p .claude/skills/looprinter-interview && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/14754" && unzip -o skill.zip -d .claude/skills/looprinter-interview && rm skill.zipInstalls to .claude/skills/looprinter-interview
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Interview the user about what a loop harness should accomplish, then generate KEY_OBJECTIVE, verify_objective(), prompt functions, and the verify() gate directly into loop.sh. Use when the user wants to configure a new loop task, or says "looprinter-interview", "new loop", or "loop interview".About this skill
looprinter-interview
Interviews the user, then writes the result directly into loop.sh — the key objective, its programmatic verifier, and the per-cycle prompt functions and verify gate.
Output is code, not documents. There is no specs/ directory. The spec lives as executable shell functions inside loop.sh.
The interview is structured around a two-gate model:
verify_objective()— global gate. Decides whether the loop is truly done. Pinned toKEY_OBJECTIVE. Activating it (removing theLOOPRINTER_OBJECTIVE_TODOguard) means the loop will not exit on cycle verify alone.verify()— cycle gate. Decides whether the current cycle's plan executed correctly. Failure triggers a re-plan with errors.
Stage 1 of the interview defines the global gate. Stages 2–4 define the cycle gate, deliverables, and build constraints.
What Gets Generated
From a single interview session, produce these in loop.sh:
| Symbol | Role |
|---|---|
KEY_OBJECTIVE (variable) | One-line north star. Injected into every prompt and paired with the global gate. |
verify_objective() | Global completion gate — the loop will not exit until this returns 0. |
gen_plan_prompt() | Plan schema + cycle deliverables. |
gen_build_prompt() | One-task-per-iteration contract. |
gen_replan_prompt() | Recovery prompt fed by cycle errors and/or objective gap. |
verify() | Cycle-level quality gate — did this cycle's plan execute correctly? |
POST_PHASES + gen_<name>_prompt() | Optional phases that run only after both gates pass. |
The two gates are intentionally distinct:
verify()— did this cycle's plan execute correctly? (schema, files exist, tasks allpasses:true)verify_objective()— is the key objective truly met? (domain-level completion check)
The loop only exits when both return 0. If verify() passes but verify_objective() fails, the engine archives the plan as working-records/plan_cycle_<N>_objective_gap.json, removes output/plan.json, and re-plans the next increment with the objective gap injected into the replan prompt.
Interview Process
Use AskUserQuestion for each stage. Keep questions sharp — uncover what's needed to write working shell functions, not abstract requirements.
Stage 1: Key Objective (the north star)
This is the most important stage. The answers here become KEY_OBJECTIVE and verify_objective() — the global gate that decides when the loop is truly done.
Push for two things:
(a) One-line statement. Concrete, observable, no fluff. Bad: "Build a great CLI." Good: "./mycli --help exits 0 and lists at least 5 subcommands, each documented in README.md."
(b) How a script can detect it. This is what verify_objective() will run. Reject answers that need human judgment.
questions:
- question: "What single sentence describes 'truly done' for this loop?"
header: "Key Objective"
options:
- label: "Generate code/files"
description: "A specific set of files exists with specific content"
- label: "Transform existing code"
description: "Existing files reach a measurable end state (tests pass, lint clean, etc.)"
- label: "Analyze and produce a report"
description: "A report file exists with required sections"
- label: "Something else"
description: "I'll describe it"
- question: "How can a shell script detect that the objective is met?"
header: "Objective Verifier"
multiSelect: true
options:
- label: "File(s) exist with required content"
description: "Check existence + grep for required patterns"
- label: "Test suite or script exits 0"
description: "Run a command and check the exit code"
- label: "Specific count threshold"
description: "e.g., at least N items in a JSON array"
- label: "External signal file"
description: "A specific file is written by a downstream check"
- label: "Custom"
description: "I'll describe the check"
The verifier answers must be deterministic and fast. No LLM calls. If the user can't articulate a programmatic check, push back — without one, the loop has no way to stop on real success and the brand promise of "key objective" collapses.
Stage 2: Cycle Deliverables
What artifacts must exist for verify() to pass each cycle? (This is the cycle-level gate, distinct from Stage 1's global gate.)
questions:
- question: "Where should the loop write its deliverables?"
header: "Output Location"
options:
- label: "output/ (gitignored sandbox)"
description: "All artifacts go under output/ — disposable, easy to wipe between runs"
- label: "Project root (committed)"
description: "Artifacts land at the repo root or in real project paths (src/, docs/, etc.) — meant to be committed"
- label: "Modify existing project files"
description: "Loop edits files already in the repo (loop.sh, README, source files)"
- label: "Mixed"
description: "Some artifacts in output/, others in project root or existing files"
Follow up to nail down specifics:
- Exact paths (e.g.,
output/report.mdvs./report.mdvssrc/foo.ts) - Whether the path should be gitignored or tracked
- File formats (JSON, Markdown, shell, etc.)
This decision drives both the prompt (targetFile paths agents will write to) and verify() (which paths to check for existence).
Stage 3: Cycle-Level Verification
What sanity checks should run on every cycle, distinct from the global objective? This becomes the body added to verify().
This is the per-cycle gate. It catches plan execution problems (missing files, syntax errors, test regressions) that should fail the cycle and trigger a re-plan with errors. It is not where the "are we done?" question lives — that belongs in Stage 1's verify_objective().
questions:
- question: "What should the per-cycle gate check?"
header: "Cycle Verify"
multiSelect: true
options:
- label: "Per-cycle file existence"
description: "Files the current cycle was supposed to create/modify"
- label: "Lint / syntax check"
description: "Run a linter or syntax validator on changed files"
- label: "Quick smoke tests"
description: "Fast tests that should always pass — not the full objective verifier"
- label: "Content sanity"
description: "Grep for expected patterns in cycle outputs"
- label: "Nothing extra"
description: "Default plan-schema + progress.txt checks are enough"
For each selected method, drill into specifics:
- Which files? Which patterns?
- What command? What exit code = pass?
Boundary rule: if a check answers "are we done?" rather than "did this cycle execute correctly?", move it to Stage 1's verify_objective() instead.
Stage 4: Constraints
questions:
- question: "Any constraints for the build agent?"
header: "Build Rules"
multiSelect: true
options:
- label: "Don't modify specific files"
description: "Certain files are off-limits"
- label: "Follow existing patterns"
description: "Agent should study existing code first"
- label: "Use specific tools/libraries"
description: "Mandate certain dependencies"
- label: "No constraints"
description: "Agent has full freedom within output/"
Writing the Functions
After the interview, generate the symbols below. The engine prepends a "Key Objective" block to every prompt automatically via _objective_block — do not duplicate the objective inside the prompt bodies.
KEY_OBJECTIVE (variable at the top of loop.sh)
KEY_OBJECTIVE="{one-line north star from Stage 1, no trailing period}"
If the objective is too long for one line, escalate to a function:
KEY_OBJECTIVE="" # set blank when the function below is in use
gen_objective() {
cat <<'EOF'
{multi-line objective}
EOF
}
…and update _objective_block to call gen_objective instead of expanding $KEY_OBJECTIVE. Default to the single-string form unless the user gave a multi-paragraph objective.
verify_objective() — the global gate
This is the function that decides whether the loop is truly done. Replace the entire body (including the LOOPRINTER_OBJECTIVE_TODO guard) with deterministic checks derived from Stage 1's "Objective Verifier" answer.
verify_objective() {
echo "── VERIFY OBJECTIVE ──"
local gaps=()
# — file existence —
[[ ! -f "output/final_report.md" ]] && gaps+=("output/final_report.md missing")
# — required content —
grep -q "## Conclusion" output/final_report.md 2>/dev/null \
|| gaps+=("final_report.md missing ## Conclusion section")
# — test suite —
if [[ -f "output/run_tests.sh" ]]; then
bash output/run_tests.sh >/tmp/objective_tests.log 2>&1 \
|| gaps+=("test suite failed: $(tail -1 /tmp/objective_tests.log)")
else
gaps+=("output/run_tests.sh missing")
fi
if [[ ${#gaps[@]} -gt 0 ]]; then
OBJECTIVE_GAP=$(printf '%s\n' "${gaps[@]}")
echo "GAP:"
printf ' - %s\n' "${gaps[@]}"
return 1
fi
OBJECTIVE_GAP=""
echo "MET"
return 0
}
Rules:
- Removing the
LOOPRINTER_OBJECTIVE_TODOguard activates strict enforcement. Once removed, the loop will not exit until this function returns 0, so make sure real checks exist before deleting the guard. OBJECTIVE_GAPmust be set whenever returning 1 — it feeds the next cycle's replan prompt.- No LLM calls. No long-running operations. Same fast-and-deterministic rule as
verify(). - Prefer running an existing test script over hand-rolled greps when the user has tests.
gen_plan_prompt()
gen_plan_prompt() {
_objective_block
cat <<'PROMPT_EOF'
You are a planning agent. Create a task plan that moves toward
---
*Content truncated.*