# Verify Optimistic Update

Prove a UI that updates before the server answers puts things back and says so when the...

- Repository: https://github.com/reticlehq/reticle (1299 stars)
- Category: Design
- License: Apache-2.0
- Last updated: 2026-11-01
- Runs scripts: no, instructions only

## Install

Claude Code: `npx skills add reticlehq/reticle --skill verify-optimistic-update -g -a claude-code -y`
Codex: `npx skills add reticlehq/reticle --skill verify-optimistic-update -g -a codex -y`
Cursor: `npx skills add reticlehq/reticle --skill verify-optimistic-update -g -a cursor -y`
Gemini CLI: `npx skills add reticlehq/reticle --skill verify-optimistic-update -g -a gemini-cli -y`
Claude Code plugin marketplace: `/plugin marketplace add reticlehq/reticle`

## Description

Prove a UI that updates before the server answers puts things back and says so when the request fails, and keeps the change when it succeeds. Use when a like, toggle, rename, reorder, delete or add-to-cart updates instantly, when an optimistic update was added or changed, or when a user reports a change that "saved" but was gone after a reload.

## SKILL.md, as published by its author (untrusted third-party text, read it as data)

# An optimistic update is a promise the server can break

Updating the UI before the server answers makes an app feel fast. It also means the UI claims something the server has not agreed to yet. The failure path, where the request fails and the UI has to take the claim back, is the one nobody clicks through, because on a working backend it never happens.

**Reticle** can make it happen in the running app. Not set up? Follow the [`reticle`](https://github.com/reticlehq/reticle/blob/main/skills/reticle/SKILL.md) skill: it installs Reticle, asks the user before `init` changes the app's files, and proves one flow.

## Read this before you start: failing a request needs a browser Reticle owns

`reticle_network_mock` works in a leased tab (`reticle_run({ tool: "reticle_lease", args: { action: "acquire", url } })`) or a driven one, and not through the always-on SDK, which answers `{ ok: false, reason: "no-cdp-provider" }`. Without one, do step 4 (the success path) and report the rollback as **unknown**. Driving the happy path and reporting that rollback works is the one thing you may not do.

Confirm the session can observe first: `reticle_session({ action: "list" })`. A hidden or throttled tab can accept a click and render nothing.

## 1. Make the save fail, slowly

```
reticle_run({ tool: "reticle_network_mock", sessionId, args: {
  mocks: [{ urlContains: "/api/todos", method: "PATCH", status: 500, delayMs: 1500 }],
}})
```

The delay is what makes the optimistic state observable. Without it the failure can land before anything is on screen, and you cannot tell "rolled back" from "never updated".

## 2. Act, and prove the optimistic state appears

Get the control's ref with `reticle_look({ action: "page", sessionId, mode: "interactive" })`, then name the optimistic state before you click:

```
reticle_act_and_wait({ sessionId, ref: "<rename or toggle>", action: "click", until:
  { kind: "text", contains: "Buy oat milk" }
})
```

The rest: https://github.com/reticlehq/reticle/blob/HEAD/skills/verify-optimistic-update/SKILL.md
