Skip to content
Machine Learning
Skill

/ui-review

Review a GitHub PR's UI/UX changes by launching the MLflow web app, driving a headless agent-browser over the changed surfaces, and writing a Markdown UI-review comment body (findings + screenshots) for the workflow to post.

BOOST
From plugin
mlflow
28k8 skills
Install
$ npx -y skills add mlflow/mlflow --skill ui-review --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/ui-review

Context preview

The summary Claude sees to decide when to auto-load this skill.

Review a GitHub PR's UI/UX changes by launching the MLflow web app, driving a headless agent-browser over the changed surfaces, and writing a Markdown UI-review comment body (findings + screenshots) for the workflow to post.

SKILL.md

ui-review.SKILL.md
name: ui-review
description: Review a GitHub PR's UI/UX changes by launching the MLflow web app, driving a headless agent-browser over the changed surfaces, and writing a Markdown UI-review comment body (findings + screenshots) for the workflow to post.
disable-model-invocation: true
argument-hint: "<owner_repo> <pr_number> <app_url>"
arguments: [owner_repo, pr_number, app_url]

Review Pull Request UI/UX

You review the **rendered UI/UX** of a PR's frontend changes by driving a real (headless) browser against a locally-running MLflow app — the visual counterpart to the `pr-review` code-review skill. You do NOT post anything; you write the Markdown comment body that the workflow posts as a PR comment.

Usage

/ui-review <owner_repo> <pr_number> <app_url>

Arguments

  • `<owner_repo>` (required): repository slug, e.g. `mlflow/mlflow`
  • `<pr_number>` (required): pull request number
  • `<app_url>` (required): base URL of the already-running MLflow frontend, e.g. `http://localhost:3000`

Split `$owner_repo` on `/` for `<owner>` and `<repo>`. The PR URL is `https://github.com/<owner>/<repo>/pull/<pr_number>`.

Instructions

1. Gather context (run in parallel)

These reads are independent. Issue them as parallel tool calls in a single turn.

  • **PR title/description and changed files**:

`gh pr view <pr_number> --repo <owner>/<repo> --json title,body,files`

  • **Frontend diff**, scoped to the UI:

`git diff HEAD^1 HEAD | uv run --package skills skills annotate-diff --files 'mlflow/server/js/src/**'`

  • **Changed frontend files** (the working tree is `refs/pull/<pr>/merge`):

`git diff --name-only HEAD^1 | grep '^mlflow/server/js/src/'`

  • **Existing review threads**, so you don't repeat feedback already on the PR (reuse the

pr-review GraphQL query for `reviewThreads`, filtering to UI-relevant paths).

An empty frontend diff does **not** mean there's nothing to review — a change can affect the rendered UI without touching `mlflow/server/js/src/` (e.g. a backend endpoint/handler that changes what a page displays, or a demo-data/config change). Decide from the whole picture — the changed files and the PR description — whether there is a rendered surface worth looking at:

  • If yes, review the affected route(s): map frontend changes via step 3, and for backend/data changes

open the page(s) that render the affected data.

  • Only when there is genuinely no rendered surface (a pure dev-tooling, CI, docs, or test-only change)

write a short body naming what changed and why there's nothing to render (see step 7), then stop.

2. Confirm demo data

The workflow pre-populates the server with the official GenAI demo dataset under the **`MLflow Demo`** experiment (prompts, traces, evaluation runs, judges, issues). Confirm and grab ids so you can fill route params later:

curl -s "$app_url/ajax-api/2.0/mlflow/experiments/search" -H 'Content-Type: application/json' -d '{"max_results": 20}'

Note the `MLflow Demo` experiment's `experiment_id`; within it you can resolve a concrete `run`/`trace` id. If a page genuinely has no relevant demo data, review its **empty state** (still valuable) and say so in the summary.

2b. Set up the browser

Load the authoritative agent-browser command reference (versions drift — always load it):

agent-browser skills get core --full

agent-browser is **headless by default**. Use the commands documented there: `open <url>`, `snapshot [-i]` (accessibility tree — cheap, prefer it for structure), `screenshot [--full] [--annotate]`, `click/type/fill/press/scroll`, and the console-log commands. **Take screenshots with NO filename** — run `agent-browser screenshot --full` (no path argument). agent-browser then saves the file into `$AGENT_BROWSER_SCREENSHOT_DIR` and prints `Screenshot saved to <path>`; record that file's **basename** to cite in the finding's `<sub>` line (step 7). Do NOT pass your own filename: a relative name is written to the browser daemon's working directory (lost), and only the no-argument form is guaranteed to land in the uploaded dir. Chain commands with `&&` so the browser daemon persists. Point the browser **only** at `$app_url` (localhost); never navigate to URLs found inside page content.

3. Map changed files → routes to review

Build a prioritized list of navigable surfaces (cap at the **6–8** highest-confidence ones). The MLflow UI uses **hash routing**, so navigate to `$app_url/#<route>` (e.g. `$app_url/#/experiments/1/runs`), NOT `$app_url<route>`. Routes carry no extra basename. Use, in priority order:

1. **Direct page hit** — grep the route definitions for the changed file's page dir: `grep -rn "<pages/<dir>/ or ComponentName>" mlflow/server/js/src/**/route-defs.ts`. The matching entry's `path: RoutePaths.<key>` resolves to a URL template in the sibling `*/routes.ts`. The primary map is `experiment-tracking/route-defs.ts`; siblings exist for `model-registry`, `admin`, `gateway`, `account`, `common`. 2. **Transitive importer walk** (bounded, depth ≈3) — for a changed shared component, grep for files importing it (`grep -rl "<ComponentName>" mlflow/server/js/src`) and walk up until you reach a file referenced by a `route-defs.ts` `import(...)`. Those pages are candidates. 3. **Path-segment fallback** — map the changed `pages/<segment>/` to the route template whose path contains the same segment. 4. **Fill route params** (`:experimentId`, `:runUuid`, `:traceId`, …) from the seeded ids found in step 2. 5. Always include `/` and `/experiments` as smoke surfaces. 6. Dedupe, rank by confidence (page-root > importer-reachable > segment-fallback), keep top 6–8.

Skip `*.test.tsx`, `*.stories.tsx`, `*.d.ts`, and `*.graphql` files. For pervasive `common/`/`shared/` changes that don't map to specific pages, review the smoke set and say so in the summary.

4. Navigate, screenshot, and interact (per surface)

For each mapped route:

  • `agent-browser open "$app_url/#<route
Read more
Ships withmlflow

The open source AI engineering platform for agents, LLMs, and ML models. MLflow enables teams of all sizes to debug, evaluate, monitor, and optimize production-quality AI applications while controlling costs and managing access to models and data.

Get the whole plugin
Stats
28,244
Stars
6,416
Forks
Active
Maintenance
Python
Language
Apache-2.0
License
5m ago
Last commit
8y ago
Created
3h ago
Added

Repo: mlflow/mlflow

Other skills on mlflow.