App runs & CLI bridge
How app.kprompt.ai/run works: device login, Connect CLI, kprompt run listen, why jobs stay queued, approve modes, and troubleshooting. No cluster credentials in the control plane.
Team /run lets you compose a prompt in the browser. Execution always happens on an enrolled laptop with local kubeconfig — never inside api.kprompt.ai. If nobody is running kprompt run listen, the job stays queued forever. That is intentional (ADR-0021), not a hang.
Flow at a glance
Browser compose → queue → local bridge → PlanResult
You (browser) app.kprompt.ai/run → POST /v1/runs (status: queued)
Laptop bridge kprompt run listen → POST /v1/runs/claim
local plan pipeline → kubeconfig stays on the laptop
POST /v1/runs/{id}/result → app shows plan / awaiting_approve- Control plane stores prompt + status + PlanResult summary — never kubeconfig or cluster tokens
- Same local safety + cached org policy as normal CLI plans
- Mutations never auto-apply from the plane; plan_only never applies; require_approve waits for Approve in the app
1. Enroll the CLI (device login)
On the laptop that can reach the cluster:
kprompt login # prints a user code + Connect URL
kprompt login --open # also opens the browser
kprompt whoami # confirm org + member- CLI shows a short user code (for example WXYZ-ABCD) and a URL under app.kprompt.ai/connect
- Sign in to the Team app in the browser if needed
- Open Connect CLI, enter or confirm the user code, Approve
- CLI receives a kp_… token → ~/.kprompt/credentials.yaml (mode 0600)
If whoami or doctor shows Team enrollment Forbidden, run kprompt logout then kprompt login again. See Team enrollment for policy and audit details.
2. Start the bridge worker
Leave this running in a terminal while you use /run in the app:
kprompt run listen
# optional:
# kprompt run listen --interval 3s --worker-label laptop-muhtalipThe worker polls POST /v1/runs/claim, runs the same plan pipeline as the CLI (never auto-applies), and posts the result. One active claim per worker; kubeconfig and LLM keys stay local.
3. Compose and queue in the app
- Open app.kprompt.ai/run
- Enter the prompt (for example deploy redis), optional namespace and context hint
- Pick approve_mode: plan_only (never apply), require_approve (pause for Approve/Deny), or auto_if_policy_allows (still subject to hard denies)
- Queue run — status starts as queued
The /run page itself says: Jobs stay queued until claimed. The empty-state copy points at kprompt login && kprompt run listen (also linked from Connect CLI).
Why status stays queued
queued means the job is waiting for a bridge. The app does not browse or mutate the live cluster from the browser. Common causes:
| Symptom | Likely cause | Fix |
|---|---|---|
| Stuck on queued | No kprompt run listen on an enrolled laptop | Start the bridge; keep the terminal open |
| listen errors / claim fails | Stale or missing kp_… token | kprompt logout && kprompt login && kprompt whoami |
| Wrong cluster / context | context_hint does not match a local kubeconfig context or alias | Fix hint, or kprompt config alias set …; check kubectl config get-contexts |
| Doctor: Team enrollment FAIL | API Forbidden or expired device session | Re-login; confirm org membership in the app |
Approve modes
| Mode | Bridge behavior |
|---|---|
| plan_only | Plans and posts PlanResult; never applies (including Replay / drill) |
| require_approve | Mutating plans pause at awaiting_approve until Approve in the app; then the bridge may apply |
| auto_if_policy_allows | May apply only when org policy allows; hard denies and wipe-class still block |
Replay / drill
From a run or audit detail, Queue drill run re-queues the same prompt as plan_only with a staging-ish context hint. Prod-like hints are blocked. Still needs a live run listen worker — drill is not an in-browser executor.
Gotcha: drill often sets context_hint to staging. If that name is not a local kubeconfig context or alias, the bridge fails after claim. Map it with kprompt config alias set staging kind-kprompt-demo, or queue a fresh run with an empty / real context hint.
Why status is failed (after claim)
queued → running → failed means the laptop claimed the job but the local plan pipeline errored before a PlanResult existed. Check the red error field on the run detail page (authoritative), the bridge terminal (Posted run_… → failed: … on recent builds), and kprompt doctor on the same machine as run listen.
| Error (typical) | Cause | Fix |
|---|---|---|
| missing API key / provider | No BYOK key for the configured provider | export KPROMPT_GEMINI_API_KEY=… (or use Ollama) · or kprompt secrets pull |
| kube context "staging" not found | Drill / compose hint ≠ local contexts | Empty hint, real context name, or config alias set |
| 429 / quota exceeded | Gemini (or other) free-tier limit | Wait for reset, switch model, or use Ollama — see Providers |
| Org policy max_risk … exceeds | Plan risk above cached org ceiling | Soften org max_risk, or use a read-only / lower-risk prompt |
| unknown intent | Prompt outside supported ops (e.g. create a cluster) | Rephrase to a supported intent — see Commands |
Providers details for Gemini free tier: Providers. Capability map: Commands.
Local sanity check (same kube + provider as the bridge)
kprompt doctor
kprompt --context kind-kprompt-demo "list pods" -n default
# then re-queue in the app and keep: kprompt run listenWhat this is not
- Not a hosted cluster browser (Lens-style live inventory in the plane)
- Not the in-cluster Observe agent (Helm kprompt-agent) — that watches namespaces; this worker is laptop-side Team jobs
- Not silent Autopilot apply — mutations stay gated
Related: Team enrollment · Safety · Observe agent.