Skip to content
Back to skills

Run App

ASecurity

Launch and drive the ClaudeLens Electron app (mock data) via Playwright to verify UI changes or take screenshots.

  • 64 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added August 30, 2026
ai-agentsgobashnode

Works with

  • cli

Security analysis

A100/100

Pro scans all 2 files and shows the line behind each finding

Scanned September 22, 2026

npx -y skills add giulio333/ClaudeLens --skill run-app --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Run App?

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

Security grade badge for Run App
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/giulio333-run-app/badge)](https://www.skillsdirectory.com/skills/giulio333-run-app)

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: run-app
description: Launch and drive the ClaudeLens Electron app (mock data) via Playwright to verify UI changes or take screenshots.
---

Drive ClaudeLens either from the REPL (`driver.mjs`, for humans) or from a
script of the same commands (`run.mjs`, for agents). Both share one command
table in `app.mjs`, so a sequence worked out at the REPL pastes into a script
file unchanged. Default launch uses `SCREENSHOT_MODE` (mock fixtures from
`electron/screenshotFixtures.ts` — no real `~/.claude/` reads); `launch real`
uses real data.

## Setup (from repo root)

```bash
npx tsc -p tsconfig.electron.json          # build main/preload
npx vite --port 5173 &                     # renderer dev server
```

If the launch fails with `spawn …/Electron ENOENT`, npm skipped Electron's
postinstall: `node node_modules/electron/install.js`.

## Run

Interactive: `node .claude/skills/run-app/driver.mjs`

Scripted — **the path for agents**, no tty and no tmux needed:

```bash
node .claude/skills/run-app/run.mjs shots.txt      # or `-` to read stdin
```

Each command is awaited before the next, the run stops at the first failure
(exit 1, naming the command), and `quit` always runs, so no Electron process is
left behind. Do not pipe into `driver.mjs` instead: readline emits every piped
line at once and the async handlers interleave.

The README gallery has a ready script — see `readme-shots.txt`:

```bash
SCREENSHOT_DIR=/tmp/shots node .claude/skills/run-app/run.mjs \
  .claude/skills/run-app/readme-shots.txt
```

Screenshots land in `/tmp/claudelens-shots/` (override: `SCREENSHOT_DIR`).
**Always open and look at the screenshots** — a blank frame means launch failed.
Kill the Vite process when done.

## Commands

| command                      | effect                                                     |
| ---------------------------- | ---------------------------------------------------------- |
| `launch [real]`              | start app (mock data; `real` = real `~/.claude/`)          |
| `reset`                      | reload → back to the global home                           |
| `ss [name]`                  | screenshot → `$SCREENSHOT_DIR/<name>.png`                  |
| `click-text <text>`          | DOM-click button/link/card by text (exact, then substring) |
| `click <css>` / `wait <css>` | DOM-click / wait for selector                              |
| `text [css]`                 | print innerText (body if omitted)                          |
| `eval <js>`                  | evaluate in page, print JSON                               |
| `theme [light\|dark]`        | force `data-theme`                                         |
| `errors`                     | page errors seen since launch, with stacks                 |
| `sleep <ms>`                 | wait                                                       |
| `quit`                       | close app and exit                                         |

In a script, `#` comments and blank lines are skipped.

## Gotchas

- Clicks go through `page.evaluate(el.click())`, not coordinates — reliable
  with the app's custom chrome. Navigation is client-side state (no router):
  reach views by clicking like a user (e.g. `click-text webapp` →
  `click-text Teams` → `click-text Open team`).
- **There is no way back from a detail view** — a skill, a plan and the other
  detail pages hide the top bar. Use `reset` between views instead of trying to
  click home.
- **Match the DOM text, not what you see.** Labels like `Edit`, `Graph`, `List`
  are title-case in the markup and only uppercased by CSS, so `click-text EDIT`
  does not match.
- `theme` does not disturb navigation state: navigate once, then shoot both
  themes from the same view.
- The window needs ~2.5s after `domcontentloaded` (baked into `launch`);
  each click already waits ~1.2s.
- An error-boundary card ("Something went wrong") carries no stack — run
  `errors` to get it. A view that only the fixtures feed can crash because the
  fixtures drifted behind the type, not because the view is broken.
- On Linux add xvfb (`xvfb-run -a node …`); `--no-sandbox` is already applied.

Files in this skill

  • SKILL.md2.7 KB
  • driver.mjs4.3 KB

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…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.