Edit an existing test suite — change one or more step bodies, assertions, headers, or remove/add steps. Returns a playbook that delegates to `keploy update-test-suite`, which validates the new state (static structural checks + 2 live runs for idempotency + GET-coupling check) and snapshot-replaces the suite via api-server.
POST-EDIT BEHAVIOUR: any structural change here (step method/url/body/headers/extract/assert, or add/delete steps) AUTOMATICALLY clears the suite's sandbox test server-side — the suite comes back as linked=false. Call record_sandbox_test on the updated suite before any sandbox replay; otherwise replay_sandbox_test will 400 with "no sandboxed tests". Cosmetic-only edits (name, description, labels) preserve the sandbox test.
═══════════════════════════════════════════════════════════════════
FETCH-FIRST RULE — required for the edit to be accepted:
═══════════════════════════════════════════════════════════════════
The api-server's replace handler rejects updates that preserve ZERO step IDs from the existing suite ("full rewrite, not an edit"). To make a real edit:
1. Call getTestSuite first (or use download_recording / get_app_testing_context if you already have the suite). Capture each existing step's "id" field.
2. Compose your new steps_json INCLUDING the existing "id" on every step you want to KEEP or EDIT. Omit "id" only on steps you're ADDING. Drop a step entirely from steps_json to DELETE it.
3. Call this tool with that merged steps_json.
If you author a fresh JSON without the existing step IDs, the server rejects it with "preserves no steps from the existing suite". When that happens, your two options are: (a) re-author with IDs preserved (preferred — keeps history), or (b) call delete_test_suite then create_test_suite (loses history, fresh suite_id).
═══════════════════════════════════════════════════════════════════
DISCOVERY — when the dev hands you a bare suite_id with no app_id / branch_id:
═══════════════════════════════════════════════════════════════════
Suites live on a (app_id, branch_id) tuple. A bare suite_id has no on-disk hint about which app or branch holds it; you have to RESOLVE both before calling this tool. Walk these steps in order — STOP as soon as getTestSuite returns 200:
1. Detect the dev's git branch: Bash `git rev-parse --abbrev-ref HEAD` in app_dir.
If exit non-zero / output is "HEAD" → not a git repo / detached HEAD; ASK the dev for the Keploy branch name.
2. Resolve candidate apps via the cwd basename: Bash `basename $(pwd)` → call listApps with q=<basename>. Usually 1–2 candidates. If 0 → ASK; if >1 → walk every candidate in step 4.
3. For each candidate app, call list_branches({app_id}) and find the branch whose `name` matches the git branch from step 1. That gives you {branch_id}. If no match → not this app, try next.
4. Verify with getTestSuite({app_id, suite_id, branch_id=<from step 3>}). 200 → resolved; 404 → wrong app/branch, try next.
5. If steps 2–4 exhaust, walk every OPEN branch on each candidate app, then try main (branch_id omitted). If still nothing → ASK the dev for the {app_id, branch_id} pair.
The getTestSuite call in step 4 is the one whose response you also use to capture every step's existing "id" for the FETCH-FIRST RULE above — so step 4 is actually a 2-for-1: discovery AND fetch-first happen on the same call.
After resolving once in a session, REUSE the {app_id, branch_id} for subsequent suite-targeted calls; don't re-walk discovery for every action.
═══════════════════════════════════════════════════════════════════
INPUTS
═══════════════════════════════════════════════════════════════════
* app_id (required) — Keploy app id
* suite_id (required) — UUID of the suite to update
* branch_id (required) — Keploy branch UUID (resolve via the two-step flow before calling)
* steps_json (required) — JSON array of the FULL desired step list. Each kept step MUST carry the existing "id". Same step shape as create_test_suite (response, extract, assert, etc — all static structural checks apply).
* name / description / labels (optional) — overrides for top-level suite metadata
* app_url (required) — base URL of the dev's running local app, e.g. http://localhost:8080. The CLI fires the new state TWICE against this for the idempotency check + GET-coupling check.
* app_dir (optional) — repo root the CLI cd's into; defaults to "."
═══════════════════════════════════════════════════════════════════
HOW THIS TOOL WORKS
═══════════════════════════════════════════════════════════════════
This tool DOES NOT call api-server itself. It returns a 3-step playbook for you (Claude) to walk via Bash — same shape as create_test_suite:
1. Write merged JSON to a temp file.
2. Run `keploy update-test-suite --suite-id <id> --file <path> --branch-id <uuid> --base-url <url>` — runs every static structural check, fires the new state twice locally, applies the GET-coupling check, then POSTs the snapshot-replace.
3. Cleanup the temp file.
Walk the playbook in order. If step 2 exits non-zero, surface stdout to the dev — it has the rule violation / failure detail.
OUTCOMES the AI should recognize:
* Exit 0 + stdout has "✓ suite updated:" + "View:" line → success. Surface the View URL to the dev.
* Exit 1 + "preserves no steps from the existing suite" → fetch-first rule was missed. Re-author with step IDs preserved (or call delete_test_suite + create_test_suite as the documented escape hatch).
* Exit 1 + structural-check violations → fix the suite per the violation messages, then REWRITE the suite file via Bash and RE-RUN this CLI command directly. DO NOT call update_test_suite again to retry — the playbook + file path are already valid; only the JSON content needs revision. The validator output includes a canonical step skeleton on structural failures.
* Exit 2 + "couldn't reach the dev's app" → ensure the app is up at app_url and retry.
PREREQUISITES the playbook assumes:
* The dev's app is up and reachable at app_url.
* `keploy` binary is on PATH. If missing, install before calling this tool: `curl --silent -O -L https://keploy.io/install.sh && source install.sh`.
* Either ~/.keploy/cred.yaml exists or KEPLOY_API_KEY is exported.