Hook Setup
A general guide to wiring novetest test into your own workflow as a hook, so the develop-with-novetest loop fires automatically each cycle — a code change happens, the tests run, the routed result comes back, the next action is acted on — instead of relying on anyone (human or agent) remembering to run it.
This guide is deliberately agent-agnostic: it describes the shape of a good hook and the criteria for placing it, not a config recipe for one particular tool. If you are a coding agent reading this, the single action to derive is: identify the natural trigger point in your own workflow and wire novetest test there, suited to yourself. novetest ships no hook mechanism of its own — the hook lives in your workflow, and any mechanism that can run a shell command can drive it.
Why a hook
novetest test only pays off when it actually runs after changes. Left to memory, the loop decays: edits pile up untested, regressions surface late, and the stored run history that powers regression comparison develops gaps. A hook makes the loop structural:
- Every change is measured. Each
novetest testrun is stored, so the next run always has a baseline to compare against. - The result arrives routed, not raw. The envelope's exit code plus the ranked
data.recommendations[]name the single next action (the routing tables live in the Cheat Sheet). - The cycle closes itself. Fix → re-run → all green happens on autopilot instead of on discipline.
The shape of a good hook
Three parts: a trigger, the command, an interpretation.
1. The trigger — a point in YOUR workflow
Described as categories, not products — every agent framework and dev toolchain has at least one of these:
| Trigger category | Fires | Typical fit |
|---|---|---|
| Post-edit | after each file save / edit batch | tight loops; agents that edit in small steps |
| Pre-commit | before a commit is created | keeping every commit green |
| Pre-push / pre-PR | before sharing changes | cheaper than a CI round-trip |
| CI step | on push / PR in the pipeline | the backstop for everything the earlier triggers missed |
Prefer the earliest trigger your workflow can afford — the point of novetest is feedback before the expensive stages.
2. The command
NOVETEST_OUTPUT=json novetest testPin JSON output explicitly inside the hook — hooks rarely run on a TTY, and automation should never depend on output autodetection. One-time setup still applies: the project must be initialized once (novetest init — safe to re-run, a no-op on an existing store).
3. The interpretation — the exit-code trap to pin
Exit 3 is the trap. A conventional hook treats any non-zero exit as "abort". novetest's contract is different — route on the exit code:
| Exit | Meaning for the hook |
|---|---|
| 0 | All green — let the workflow proceed. |
| 3 | Tests failed or errored — product data, not a tool error (ok stays true). Do NOT treat this as a hook crash: read data.recommendations[] and surface or act on the top one. Whether exit 3 blocks your commit/push is your policy call. |
| 2 / 4 / 5 / 1 | Real tool-level error paths — fix the call, remediate the engine, or surface to the operator (one-line recoveries per errors[0].code are in the Cheat Sheet). |
A minimal shape (illustrative — POSIX shell shown, but any language that can read an exit code and parse JSON works):
#!/bin/sh
out=$(NOVETEST_OUTPUT=json novetest test)
code=$?
case "$code" in
0) exit 0 ;; # green — proceed
3) printf '%s\n' "$out" # tests failed/errored — routed data:
exit 0 ;; # surface data.recommendations[];
# block or proceed per YOUR policy
*) printf '%s\n' "$out" >&2
exit "$code" ;; # tool error — surface, do not proceed
esac"Suited to myself" — the decision is yours
This guide hands you criteria, not configuration. A hook is well-suited to your workflow when it is:
- Safe to re-fire (idempotent in effect). Firing twice does no harm —
novetest testis always retry-safe; each call simply records a new run. - Non-blocking on exit 3. Failing tests come back as routed data to act on, not as a crash that kills the workflow step.
- Surfacing. The top recommendation (
category, plusslots.file@slots.primary_lineorslots.test_id) reaches whoever acts next — you, your operator, or the log your next step reads. - Placed at your natural trigger. The point where your workflow already transitions from "editing" to "done editing".
If you can answer "where in my workflow does done editing happen?", wire NOVETEST_OUTPUT=json novetest test there and route the result — that is the entire setup.
What to read next
- Cheat Sheet — the routing tables your hook's output feeds into; the card to keep open while you work.
- Quick Start — the loop walked end-to-end, from
initto the first routed recommendation. - Understanding Results — the full envelope, exit codes, and the recommendation taxonomy.