| name | run-librariarr |
| description | Launch, build, run, start, screenshot, or smoke-test the Librariarr Next.js webapp end-to-end. Use when asked to run librariarr, bring up the dev stack, take a screenshot of the dashboard or any UI page, verify a change in the running app, or check that the app boots cleanly. |
/run-librariarr
Drive a clean Librariarr dev stack to authenticated dashboard, then verify behaviour via curl smoke checks or headless-Chromium screenshots. The orchestration is driver.sh (in this directory); SKILL.md is its man page.
All paths below are relative to the repo root. driver.sh resolves the repo root from its own location, so you can invoke it via the absolute path from anywhere.
Prerequisites
- Docker + Compose v2 (
pnpm docker:dev:* is the project's standard dev flow).
pnpm, curl, jq, node on PATH.
- For screenshots only: just Docker — the official
mcr.microsoft.com/playwright image carries Chromium and its OS libs. Do not install libnss3/libnspr4/libasound2 on the host; the skill runs Playwright inside a container.
Run (agent path)
./.claude/skills/run-librariarr/driver.sh up
./.claude/skills/run-librariarr/driver.sh setup
./.claude/skills/run-librariarr/driver.sh smoke
setup is idempotent: on a fresh DB it POSTs /api/auth/setup (the same endpoint the onboarding page calls — [src/app/api/auth/setup/route.ts](src/app/api/auth/setup/route.ts)); if a user already exists (HTTP 403) it falls through to /api/auth/local/login. The session cookie lands at .claude/skills/run-librariarr/.cookies and is reused by smoke and screenshot.
Defaults — override via env:
| Env var | Default |
|---|
LIBRARIARR_BASE_URL | http://localhost:3000 |
LIBRARIARR_ADMIN_USER | admin |
LIBRARIARR_ADMIN_PASS | librariarr-dev-pw-1234 (8-char min per authSetupSchema) |
LIBRARIARR_APP_CONTAINER | librariarr-dev |
LIBRARIARR_PLAYWRIGHT_IMAGE | mcr.microsoft.com/playwright:v1.61.0-noble |
Run (human path)
pnpm docker:dev
Useless headless because the onboarding page expects browser interaction. Use driver.sh setup instead.
Screenshot
./.claude/skills/run-librariarr/driver.sh screenshot /
./.claude/skills/run-librariarr/driver.sh screenshot /library/movies /tmp/movies.png
PNGs land in .claude/skills/run-librariarr/screenshots/<timestamp>.png by default. First run does a one-time pnpm install --ignore-workspace (Playwright JS, ~5MB) and a one-time docker pull of the Playwright image (~2GB). After that, screenshots take a few seconds each.
The screenshot container joins the dev stack's docker network and reaches the app by its compose service name (http://librariarr-dev:3000) — not localhost — so the same command works under WSL, Docker Desktop, and native Linux without --network=host tricks.
Formal browser E2E suite
This skill is for ad-hoc running/screenshots. The committed regression browser E2E suite lives in e2e/ (Playwright) and runs the same way conceptually — Postgres + the real production app image + the official Playwright image (browsers pre-baked, no download):
pnpm e2e:docker
pnpm e2e:docker:down
It uses a dedicated librariarr_e2e database and an in-suite first-run flow to create the admin (no manual setup step needed). See CLAUDE.md → "Browser E2E (Playwright)". Add new user-journey specs there, not here.
Reset between runs
./.claude/skills/run-librariarr/driver.sh clean
./.claude/skills/run-librariarr/driver.sh down
./.claude/skills/run-librariarr/driver.sh logs
clean also deletes the saved session cookie since it would point at a now-gone user.
What smoke checks
GET, with the saved session cookie, asserting HTTP 200 on each. All four return non-empty JSON even on a totally fresh install (no media synced, no servers connected):
/api/auth/check-setup — public; confirms setupRequired:false
/api/system/info — authenticated; app version, DB size, migration status
/api/servers — authenticated; returns {"servers":[]} until a Plex/Jellyfin/Emby server is linked
/api/settings/auth — authenticated; auth method flags + localUsername
Pick these because they don't depend on any user-supplied state. Adding more (media routes, lifecycle, etc.) would require seeding.
Gotchas
pnpm install in this skill dir silently no-ops without --ignore-workspace. pnpm-workspace.yaml lives at the repo root with global supply-chain config but no packages: key. pnpm still walks up and treats the skill dir as part of the parent project, so a bare pnpm install reports "Already up to date" against the wrong lockfile. The driver passes --ignore-workspace for this exact reason.
- The official Playwright Docker image ships browsers + OS libs but no Playwright JS package. That's intentional — you BYO the SDK version. The driver installs
playwright into the skill dir's node_modules and bind-mounts it into the container with NODE_PATH=/node_modules.
- curl's Netscape cookie jar prefixes HttpOnly entries with
#HttpOnly_. A naive !line.startsWith("#") filter (used by most "parse Netscape cookie jar" snippets) drops the only cookie we care about. screenshot.mjs strips the prefix before filtering.
- Plex login is disabled on a local-only setup.
/api/auth/setup creates the admin with plexLoginEnabled:false (src/app/api/auth/setup/route.ts:52) because no Plex account is linked yet. Don't expect the Plex OAuth button on the screenshot of /login.
- DB volume survives
down. A second up reuses the existing admin user — setup will hit the 403 path and log in instead of creating. Use clean if you need a virgin DB (slower: re-pushes schema + reruns Prisma generate).
/api/auth/setup 403 on setupRequired:false is the success-case fallthrough, not an error. The driver logs "setup already done — falling back to local login" and continues.
- Cookie's
domain is rewritten on injection. curl saves it as localhost; the screenshot runs inside the docker network where the host is librariarr-dev. screenshot.mjs overrides domain to match LIBRARIARR_BASE_URL's hostname so the cookie is sent.
Troubleshooting
| Symptom | Fix |
|---|
app did not become ready within 120s from up | ./driver.sh logs — Prisma schema push can take 30-60s on first start; if it's stuck on "Waiting for database", the dev DB container may have failed health checks. ./driver.sh clean && ./driver.sh up. |
setup returns 500 | Almost always a serializable-isolation conflict from two concurrent setup attempts. Re-run setup. |
screenshot says could not import 'playwright' | The bind-mount of node_modules didn't land. Delete .claude/skills/run-librariarr/node_modules and re-run. |
screenshot says Host system is missing dependencies | You're running screenshot.mjs outside the container. The skill never expects this — use ./driver.sh screenshot, which runs it inside the Playwright image. |
could not find docker network for container 'librariarr-dev' | Dev stack isn't up. ./driver.sh up first. |
setupRequired:true after setup succeeded | Stale cookie jar from a prior clean. The driver clears it on clean — if it's still there, rm .claude/skills/run-librariarr/.cookies && ./driver.sh setup. |
Port 3000 already in use on up | docker ps — another container is bound to it. ./driver.sh down first, or stop the other container. |
Files
.claude/skills/run-librariarr/
SKILL.md ← this file
driver.sh ← bash dispatcher (up | setup | smoke | logs | down | clean | screenshot)
screenshot.mjs ← Playwright helper called from `driver.sh screenshot`
package.json ← declares playwright@1.61.0 (installed via --ignore-workspace)
.gitignore ← excludes node_modules/, pnpm-lock.yaml, .cookies, screenshots/