← Blog

February 2026 · 6 min read

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.

ModeWhat happensWhen to use it
promptCLI 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.
webhookWe 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”).
noneNo 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:

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):

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:

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:

  1. Main CLI: Run upshift init. Don’t set approval.mode: "none" or autoConfirm: true. Don’t pass -y when you run upgrades. You’ll get a prompt for major upgrades.
  2. UpshiftAI: Copy .upshiftai.example.json to .upshiftai.json. Leave approval.mode: "prompt" and approval.requireFor: ["replace", "major"]. Run apply without --yes when 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:

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.

Try Upshift

Run with oversight by default; use -y when you want auto.

Get Started
More from the blog Introducing Upshift · When it breaks, guardrails, and HITL

— The Upshift Team