Skip to main content
ClaudeWave
Skill417 repo starsupdated 3d ago

test-error-states

Force the states a happy-path run never reaches (a failing API, an empty list, a slow request, a timeout, an expired session, a toast that auto-dismisses) and check the UI actually handles them. Use when error handling was written but never run, when a loading or empty state needs verifying, when a bug only happens on a slow connection, or when a timer, poll, debounce or retry needs testing without sleeping.

Install in Claude Code
Copy
git clone --depth 1 https://github.com/reticlehq/reticle /tmp/test-error-states && cp -r /tmp/test-error-states/skills/test-error-states ~/.claude/skills/test-error-states
Then start a new Claude Code session; the skill loads automatically.

SKILL.md

# The error state has never run

Every app has a `catch` block nobody has executed and an empty state nobody has seen. They are written from imagination, shipped untested, and discovered by a user on a bad day.

**Reticle** can force those conditions in the running app. Not installed? `RETICLE_INSTALL_SOURCE=npx_skill npx @reticlehq/server@latest init`, then the [`install-and-verify`](https://github.com/reticlehq/reticle/blob/main/skills/install-and-verify/SKILL.md) skill.

## Read this before you start: network mocking needs a driven browser

`reticle_network_mock` applies mocks through CDP, and **the always-on SDK cannot do it.** A pooled lease is not enough either: `reticle_lease` returns `{ ok: false, reason: "no-cdp-provider" }`.

Your route is `RETICLE_CDP_URL` pointed at a Chrome started with remote debugging:

```bash
# macOS — the user runs this once, in their own Chrome
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222

RETICLE_CDP_URL=http://localhost:9222 npx @reticlehq/server@latest mcp
```

If that is not set up, **say so in one line and offer the clock half of this skill anyway**: `reticle_clock` needs none of it. What you may not do is drive the happy path, watch it pass, and report that error handling works.

## Force a failure

```
reticle_run({ tool: "reticle_network_mock", sessionId, args: {
  mocks: [{ urlContains: "/api/deploys", status: 500 }],
}})
```

Then drive the flow and **name the recovery you expect before you act**:

```
reticle_act_and_wait({ sessionId, ref, action: "click", until: { kind: "allOf", predicates: [
  { kind: "element", query: { testid: "error-banner" } },
  { kind: "console", level: "error", absent: true },
]}})
```

Note the second predicate. A UI that "handles" an error by logging an uncaught exception has not handled it. Clear mocks with `{ clear: true }` when you are done, or every later check runs against a lie.

Worth forcing, in rough order of how often they are broken: `500`, a `4xx` with a real error body, an empty `200` (`[]`, the empty state), a malformed payload, and a request that never resolves (the spinner that spins forever).

## Skip time instead of sleeping

```
reticle_clock({ sessionId, freeze: true })
reticle_clock({ sessionId, advanceMs: 5000 })
reticle_clock({ sessionId, reset: true })
```

Toasts that auto-dismiss, debounced search, polling, session timeouts, retry backoff. All of these are normally verified by sleeping, which is slow and flaky in equal measure. A timing assertion is a statement about the machine, so it passes on your laptop and fails in CI.

Freeze, advance by exactly the interval, assert the consequence. Same result on a fast laptop and a loaded runner. **Always `reset` when you finish**, or a frozen clock silently breaks everything that runs after you.

## What to assert

The recovery, not the absence of a crash:

1. The error is **shown to the user**: a specific element, not just "the page did not blank".
2. The app **stayed usable**: retry works, the form still has its input, navigation is not stuck.
3. **State is honest**: `reticle_state` shows the failure, not a half-applied optimistic update. A UI that rolled back visually while the store kept the optimistic value is the classic bug here, and only the store read finds it.
4. **No uncaught error** in the console.

## Honesty

Mocking changes the app's world, so a verdict taken under a mock is a statement about the mocked condition and nothing else. Say which mock was active when you report a pass, and clear every mock and reset the clock before handing back. An audit that leaves a `500` pinned on `/api/deploys` breaks the next person's session and looks like a real outage.

---

Capability reference: `curl https://docs.reticle.sh/capabilities.md`. Everything else: `curl https://docs.reticle.sh/llms.txt`.
SKILLSkill
reticleSkill

Install, instrument and verify this running web app from the inside (DOM, network, routing, console and framework state) instead of screenshots or guessing. Drives one real flow end to end and returns a verdict with the file:line to fix. Use when the user asks to set up or install Reticle, when a user-facing change needs proving before you call it done, when a test passes but the UI is broken, or when the user types /reticle.

agentic-tddSkill

Test-driven development for behaviour a unit test cannot reach, by writing the expectation against the running app before writing the code. Declare the consequence first, watch it fail, implement, watch it pass. Use when building a user-facing feature, when the user asks for TDD on UI or full-stack work, when a unit test cannot express the outcome that matters, or when you want a red-green loop that runs against the real app instead of mocks.

audit-my-appSkill

Sweep a whole running web app for what is broken, without writing a script or knowing the codebase. Clicks every reachable control and reports dead buttons, console errors, failed requests, and places where the API and the screen disagree. Use on an unfamiliar codebase, before a release, after a big merge or dependency bump, when the user asks for a smoke test or a health check, or when someone says "just check everything still works".

debug-broken-uiSkill

Find out why something in a running web app does not work, when the console is empty and the code looks correct. Reads the click, the request, the store and the console together and returns the file:line to open. Use when a button does nothing, a form will not submit, data will not load, a page renders blank or stale, a modal will not close, or the user says "it's broken" and the code review says it is fine.

design-system-complianceSkill

Check that the UI you actually rendered uses the design system, by reading computed styles in the running app against the project's design tokens. Catches hardcoded hex colors, off-palette backgrounds, invisible or unusable controls, and animations that never ran. Use after building or restyling a component, when a design review is wanted, when a UI looks slightly off but nobody can say why, or when a design system exists and nothing checks whether the code follows it.

drive-desktop-appSkill

Drive and verify an Electron or Tauri desktop app from the inside, including the main-process and Rust IPC calls a browser tool cannot see. Use when a desktop app needs testing, when a feature works in the browser but not in the packaged app, when an IPC or invoke call needs proving, when a desktop screenshot or visual diff is wanted, or when you need a headless run of a desktop UI in CI.

false-green-testsSkill

Find out why the tests pass but the app is broken. Catches false greens: a green suite over a feature that does not work, a mocked API standing in for a real one, an assertion that holds no matter what the app does, a click handler wired to nothing. Use when the suite is green and the user says it is broken, when a test never fails, when coverage looks fine but bugs still ship, or before trusting a passing run you did not watch.