Skip to content
Back to skills

Livewire

BSecurity

Drive the real GUI against the real engine via the standalone dev HTTP bridge (`npm run dev:bridge`). Use whenever "does the wiring test actually hold up against real code?" matters — smoke verification, UI development with live engine state, real-engine bug repro, exploratory debugging with Chrome DevTools instruments.

  • 116 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 4, 2026
developmentpythonrustgoshellbashreactnodedebugginggitapi

Works with

  • cli
  • api
  • mcp

Security analysis

B75/100
  • criticalDownloads and executes remote scripts — classic supply chain attack

Pro shows the line behind each finding and how to fix it

Scanned October 4, 2026

npx -y skills add Artexis10/endstate-gui --skill livewire --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Livewire?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Livewire
[![Security: B — Skills Directory](https://www.skillsdirectory.com/api/skills/artexis10-livewire/badge)](https://www.skillsdirectory.com/skills/artexis10-livewire)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: livewire
description: Drive the real GUI against the real engine via the standalone dev HTTP bridge (`npm run dev:bridge`). Use whenever "does the wiring test actually hold up against real code?" matters — smoke verification, UI development with live engine state, real-engine bug repro, exploratory debugging with Chrome DevTools instruments.
---

Real Chromium ↔ real HTTP bridge ↔ real engine. No mocks, no fixtures. The
GUI runs in a regular Chrome tab; every `invoke()` / `listen()` goes over
the bridge to the bundled `endstate.exe` binary. The same DevTools you'd
use on a webapp (network panel, console, evaluate, snapshots) work on the
real production code path.

**Input**: short description of what to do. Examples:
- `/livewire smoke the backup subscribe flow`
- `/livewire drive setup with dry-run and confirm no UAC fires`
- `/livewire hot-iterate on the subscription banner — change copy, see it live`

**Modes (pick before driving)**

- **Smoke** — verify a flow works end-to-end against the real engine.
  Order: curl envelope checks first (cheap, proves protocol), then UI
  drive. Section *Smoke* below.
- **Dev** — iterate on the GUI with the real engine wired up. Vite HMR
  hot-reloads frontend changes; the bridge persists. Section *Dev* below.
- **Debug** — reproduce a real-engine bug. Drive to the failure, inspect
  state via evaluate, scrub network/console panels. Section *Debug*
  below.

All three share the same launch + watcher + hazard handling.

---

## Pre-flight (always)

1. **Check sibling engine version.** The bridge speaks to whatever
   `endstate.exe` is bundled in `src-tauri/binaries/`. If a recent engine
   command is needed, pull the sibling and force a rebuild:
   ```
   git -C ../endstate fetch --tags
   git -C ../endstate checkout v<X.Y.Z>
   rm -f src-tauri/binaries/endstate-x86_64-pc-windows-msvc.exe
   node scripts/rebuild-engine.cjs
   ```
   Verify the binary has what you need:
   `./src-tauri/binaries/endstate-x86_64-pc-windows-msvc.exe <cmd> --help`
2. **Direct envelope check** (smoke mode only — cheap ground truth, no
   Tauri): `./src-tauri/binaries/endstate-x86_64-pc-windows-msvc.exe backup subscribe --json`
   Treat those bytes as the assertion target.

## Launch the bridge

3. **Clear orphan listeners on 1420 + 9876 first.** Earlier crashed runs
   often leave Vite still listening on 1420 (npm doesn't reap it) or
   stranded sockets on 9876. Without this check, the launch fails
   silently: Vite errors with "Port 1420 is already in use" and exits
   via `beforeDevCommand`, OR the Tauri bridge fails to bind and keeps
   running without it (no crash signal, no success signal — watcher
   waits forever).
   ```bash
   for P in $(netstat -ano | grep "LISTENING" | grep -E ":(1420|9876) " | awk '{print $NF}' | sort -u); do
     taskkill //F //PID "$P" 2>/dev/null || true
   done
   sleep 1
   netstat -ano | grep "LISTENING" | grep -E ":(1420|9876) " || echo "ports clear"
   ```
   The `awk '{print $NF}'` is load-bearing — `$5` is `LISTENING`, not the
   PID. On Git Bash, `//F //PID` (double-slash) prevents Msys from
   mangling the args into paths.
4. Run `SKIP_ENGINE_BUILD=1 npm run dev:bridge` in the background.
   This starts Vite (1420) + the **standalone `endstate-dev-bridge`
   binary** (9876) — a non-Tauri process that links none of the native
   GUI stack. (`npm run tauri:dev:browser` is now an alias for
   `dev:bridge`.) First run compiles the bridge crate (fast; usually
   already built). `ENDSTATE_ROOT` defaults to the sibling `../endstate`
   repo; override via env if needed.
5. **Arm a single-shot watcher** that emits when ANY of these signals
   land:
   ```bash
   until grep -qE "Browser bridge listening|Browser bridge failed to bind|error\[|panicked|exited" /tmp/dev-bridge.log; do
     sleep 2
   done
   ```
   Run that in `run_in_background:true` with a 5-minute timeout. The
   bind-failure literal is `Browser bridge failed to bind port 9876` —
   match the prefix so it works across OS-error wording.

**STABILITY — the dev bridge no longer runs inside Tauri.** The
intermittent ~12% `0xc0000374` heap corruption (see
`memory/project_tauri_dev_server_crash.md`) lived in the native GUI
layer (tao/wry/webview2-com) that the *in-process* bridge dragged in.
The standalone `endstate-dev-bridge` binary links none of it
(`cargo tree -p endstate-dev-bridge` shows no tao/wry/webview2-com), so
that crash surface is structurally gone. If the bridge process dies now,
it's a real bug in our (safe) Rust or the engine subprocess — investigate
it, don't write it off as "the known Tauri flake."

Response policy:
- **In smoke mode**, curl is enough for envelope-shape verification. Do
  the curl pass first so you have protocol proof regardless of whether
  the UI drive lands.
- **In dev mode**, if the bridge dies mid-iteration, relaunch — Vite HMR
  and engine/keychain state persist. But also capture the stderr: a
  standalone-bridge crash is now signal, not noise.

## Tool choice — chrome-devtools MCP is primary

First check `ToolSearch` with `+chrome devtools` to see if the
`mcp__plugin_chrome-devtools-mcp_*` tools are loaded. Use them by default
(real DevTools artifacts: `list_network_requests` for the network panel,
`list_console_messages` for console, `take_snapshot` for uid-based a11y
trees, `evaluate_script` for arbitrary JS, `get_network_request` for
request/response bodies). If chrome-devtools isn't connected this
session, use `mcp__plugin_playwright_playwright__*` as fallback and note
that in the report. Don't mix the two in one session. (See
[feedback-chrome-devtools-over-playwright].)

## Open the GUI in Chromium (separate from Tauri's webview)

6. ```
   mcp__plugin_chrome-devtools-mcp_chrome-devtools__new_page(url="http://127.0.0.1:1420")
   ```
   Don't drive the Tauri webview window itself — chrome-devtools MCP
   can't attach to WebView2. Both webviews talk to the same bridge, so
   a separate Chromium is fine and gives you full DevTools access.

---

## Smoke mode

The verification flow. Order matters — curl first, drive after.

7. **Curl `engine_is_running`** through the bridge:
   ```bash
   curl -sS -X POST http://127.0.0.1:9876/api/invoke \
     -H 'Content-Type: application/json' \
     -d '{"cmd":"engine_is_running","args":{}}'
   ```
   Expect `{"ok":true,"data":false}`.
8. **Curl the engine command** itself. Dispatch goes through `endstate_exec`
   — `exe` is `__bundled__` in bundled mode, `args` are the engine
   subcommand flags. The response embeds the engine envelope in
   `data.stdout` as a JSON string:
   ```bash
   curl -sS -X POST http://127.0.0.1:9876/api/invoke \
     -H 'Content-Type: application/json' \
     -d '{"cmd":"endstate_exec","args":{"exe":"__bundled__","args":["backup","--json","subscribe"]}}' \
     | python -c "import sys,json; print(json.dumps(json.loads(json.load(sys.stdin)['data']['stdout']), indent=2))"
   ```
   Compare to step 2's ground-truth bytes — they should match.
9. **Drive Chromium through the flow.** Use the command palette
   (`Ctrl+K → "Go to <pane>"`) — sidebar is hidden on landing/save/setup
   (intent pages). Take a snapshot, click the target, then immediately
   check `list_network_requests({resourceTypes: ["fetch"]})` for the
   POST(s) to `127.0.0.1:9876/api/invoke` — that's proof the click
   round-tripped through the real bridge.
10. **Capture screenshot for the report:**
    ```
    take_screenshot({filePath: ".claude/scratch/livewire-<step>.png", fullPage: false})
    ```

## Dev mode

Hot-iterate on the GUI while everything stays live.

- **Vite HMR is on.** Edit `src/**/*.tsx`, save, and the running Chromium
  tab updates immediately. The bridge connection persists. You can keep
  the Tauri dev process running across many edits.
- **No reload needed for most changes.** If a change does require a full
  reload (route changes, mount-time effects), use
  `navigate_page({type:"reload"})`.
- **Inspect/seed local state with `evaluate_script`**. Examples:
  ```ts
  // Read all endstate-related localStorage
  () => Object.fromEntries(
    Object.entries(localStorage)
      .filter(([k]) => k.includes('endstate'))
      .map(([k, v]) => [k, JSON.parse(v)])
  )

  // Force advanced UI mode
  () => {
    localStorage.setItem('web:endstate-ui-mode', 'advanced');
    localStorage.setItem('web:endstate-sidebar-visible', 'true');
  }

  // Flip dryRunEnabled to test the apply path
  () => {
    const k = 'web:endstate-gui-settings';
    const s = JSON.parse(localStorage.getItem(k));
    s.dryRunEnabled = false;
    localStorage.setItem(k, JSON.stringify(s));
  }
  ```
  Hit `navigate_page({type:"reload"})` after seeding state if the app
  reads settings at mount.
- **Watch the network panel.** `list_network_requests({resourceTypes:
  ["fetch"]})` shows every bridge call as you interact. Filter to
  `9876` mentally; everything else is HMR / asset traffic.
- **Console panel for errors.** `list_console_messages({types:
  ["error", "warn"]})` surfaces React errors, prop-type warnings, etc.,
  the same as opening DevTools in a normal browser.

## Debug mode

When you're reproducing a real-engine bug:

- **Diff direct-invoke vs bridge-invoke.** Step 2 (binary directly)
  and step 8 (binary through bridge) should produce identical
  envelopes. If they don't, the bridge is the culprit (rare).
- **Look at the engine's own debug dump** if the bug involves apply /
  capture / verify. The engine writes per-run logs to
  `C:\Users\<user>\AppData\Local\Endstate\debug\` —
  `ts-parsed-envelope-<cmd>-<ts>.json` has the structured envelope
  including counters and the `dryRun` flag. Useful for confirming the
  CLI received the args you think it did.
- **Use `get_network_request(reqid)`** to inspect a specific bridge
  request body — that's how you confirm a flag like `--dry-run` was
  actually sent (the request body contains the full args array).

## Teardown

11. Stop the background `dev:bridge` task. Note `TaskStop` does NOT reap
    the detached child processes — kill the orphan listeners on 1420 +
    9876 with the step-3 command, and if a `cargo`/`endstate-dev-bridge`
    process sticks, `taskkill //F //IM endstate-dev-bridge.exe`.
12. If the sibling engine was checked out to a specific tag, switch it
    back: `git -C ../endstate switch <previous-branch>`.

## Report (smoke mode)

End with a tight summary:
- What was verified (bridge round-trip; envelope shape; click triggered
  network POST(s) to `:9876`; final DOM state; any engine flags
  confirmed via the debug dump)
- What was *not* verified, with the reason (e.g. "Tauri host crashed
  before click — see memory/project_tauri_dev_server_crash.md")
- Screenshot paths

## Anti-patterns

- **Don't mock anything.** This skill exists *because* the wiring e2e
  already covers mocks. If your assertions need mocks, write a
  Playwright spec instead.
- **Don't drive the Tauri webview window.** chrome-devtools MCP can't
  attach to WebView2. Use a separate Chromium against the same Vite URL.
- **Don't loop-retry on Tauri crashes** beyond one restart — the crash
  is intermittent, not transient. Report the gap.
- **Don't `cd` in Bash on this Windows box** — PowerShell cwd resets
  fight it. Use absolute paths with `git -C` / `yadm -C` style flags.
- **Don't conflate dev and smoke.** In dev you're iterating and tolerate
  flakiness; in smoke you're producing a verifiable report. Pick the
  mode up front so the report writes itself.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…