How we do human-in-the-loop (HITL)
Approval and oversight for dependency upgrades and AI-generated fixes—so you can run in auto mode when you want, and stay in the loop when you don’t.
Some teams want Upshift to run fully automatic (-y, CI, no prompts). Others want to approve risky changes—major upgrades, package replaces, or AI-generated code fixes—before anything is applied. Here’s how we support both.
Three ways to get approval
We support three modes. You choose per project (or globally) via config.
| Mode | What happens | When to use it |
|---|---|---|
| prompt | CLI asks “Upgrade X from A to B (major)? [y/N]” (or “Apply? (y/n)” in batch). You answer in the terminal. | Default. Good for local dev and anyone who wants to approve major/replace before we touch files. |
| webhook | We POST to your URL with the pending action; you respond { "approved": true } or false. We wait (with timeout) and proceed or skip. | CI gates, team approval servers, or custom policy (e.g. “approve only if not major”). |
| none | No approval. We apply the change (with tests and rollback as usual). | CI or scripts where you’re okay with full auto (e.g. upshift upgrade --all -y). |
So: prompt = you stay in the loop in the terminal. webhook = your server or pipeline stays in the loop. none = no loop; we run and you rely on tests + rollback.
What needs approval?
You control which actions require approval. Typical setup:
- Major upgrades — Bumping a package across a major version (e.g. React 18 → 19). Default: require approval.
- Package replace — Swapping one package for another (e.g.
request→got). Default: require approval. - Patch/minor — Usually safe to auto-apply; no approval by default.
In config you set something like approval.requireFor: ["major", "replace"]. Then only those actions go through the approval gate (prompt or webhook). Everything else runs without asking.
Main Upshift CLI: .upshiftrc.json
For the main upshift CLI (scan, explain, upgrade, fix):
- Create config with
upshift init. You get a.upshiftrc.jsonwithapproval.mode: "prompt"andapproval.requireFor: ["major"]. - Single upgrade: When you run
upshift upgrade <pkg>and it’s a major bump, we prompt Upgrade X from A to B (major)? [y/N] (unless you pass-yor setapproval.mode: "none"orautoConfirm: true). - Non-interactive (e.g. CI): If approval would be required and there’s no TTY, we exit with a clear message: use
-yto apply anyway or setapproval.mode: "none". We don’t silently apply major upgrades in CI unless you opt in. - Batch:
upshift upgrade --all(or--all-minor) already asks once before applying;-yskips that.
So out of the box: major upgrades get a prompt; patch/minor and -y skip it.
UpshiftAI: .upshiftai.json and webhooks
For the full HITL story (webhooks, event stream, approval server), we use UpshiftAI and .upshiftai.json:
- approval.mode —
prompt(CLI y/n),webhook(POST to your URL; you respond{ "approved": true }), ornone. - approval.requireFor — e.g.
["replace", "major"]: replace and major upgrades require approval; patch/minor do not. - approval.webhookUrl — Where we POST when
mode === "webhook". We send the pending action (pkg, targetVersion, isMajor, etc.) and wait for your JSON response. - webhooks — Optional list of URLs. We POST every event (checkpoint.created, apply.started, apply.completed, apply.failed, rollback.triggered, rollback.completed) so you can log, notify, or trigger your own rollback.
Copy .upshiftai.example.json to .upshiftai.json and set your webhook URL and approval policy. Defaults already give you prompt-for-major and prompt-for-replace.
Quick setup: “I want oversight”
If you don’t want fully automatic upgrades:
- Main CLI: Run
upshift init. Don’t setapproval.mode: "none"orautoConfirm: true. Don’t pass-ywhen you run upgrades. You’ll get a prompt for major upgrades. - UpshiftAI: Copy
.upshiftai.example.jsonto.upshiftai.json. Leaveapproval.mode: "prompt"andapproval.requireFor: ["replace", "major"]. Run apply without--yeswhen you want to be asked.
Override for a single run: use -y or --yes to skip approval that time (e.g. “I’ve already reviewed; just do it”).
LLM-generated code fixes
upshift fix suggests and can apply code changes (e.g. for breaking API updates). We treat that as human-in-the-loop by default:
upshift fix --dry-run— Preview all suggested edits. Review the diff, then run without--dry-runwhen you’re satisfied, or apply changes manually.- Without
--dry-run, we prompt “Apply N fixes? [y/N]” unless you pass-y.
So: dependency upgrades can be guardrailed by tests + optional approval; LLM-generated fixes are always reviewable (dry-run or confirm) unless you explicitly use -y.
Summary: we support prompt, webhook, and none. Default is prompt for major (and replace in UpshiftAI). Use config and -y to tune. For webhook payloads, response format, and a sample approval server, see the full approval (HITL) docs. For the “when it breaks” and guardrails story, see When it breaks, who fixes it, and why human-in-the-loop still matters.