frameshot-mcp 0.8.0 → 0.9.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/README.md +68 -122
  2. package/action.yml +14 -5
  3. package/dist/{chunk-PYWXJZTZ.js → chunk-MEBQ7ZWA.js} +760 -109
  4. package/dist/{chunk-MA3FOIQY.js → chunk-VUYZHZBH.js} +1 -1
  5. package/dist/cli.js +128 -115
  6. package/dist/index.js +377 -528
  7. package/dist/renderer.d.ts +7 -3
  8. package/dist/renderer.js +1 -1
  9. package/dist/stubs/gatsby.js +20 -0
  10. package/dist/stubs/next-font.js +9 -0
  11. package/dist/stubs/next-headers.js +20 -0
  12. package/dist/stubs/next-image.js +34 -0
  13. package/dist/stubs/next-link.js +25 -0
  14. package/dist/stubs/next-navigation.js +17 -0
  15. package/dist/stubs/next-router.js +19 -0
  16. package/dist/stubs/nuxt-app.js +37 -0
  17. package/dist/stubs/nuxt-imports.js +13 -0
  18. package/dist/stubs/qwik-city.js +33 -0
  19. package/dist/stubs/react-router.js +67 -0
  20. package/dist/stubs/server-only.js +2 -0
  21. package/dist/stubs/solid-router.js +27 -0
  22. package/dist/stubs/solid-start.js +18 -0
  23. package/dist/stubs/stubs/gatsby.js +20 -0
  24. package/dist/stubs/stubs/next-font.js +9 -0
  25. package/dist/stubs/stubs/next-headers.js +20 -0
  26. package/dist/stubs/stubs/next-image.js +34 -0
  27. package/dist/stubs/stubs/next-link.js +25 -0
  28. package/dist/stubs/stubs/next-navigation.js +17 -0
  29. package/dist/stubs/stubs/next-router.js +19 -0
  30. package/dist/stubs/stubs/nuxt-app.js +37 -0
  31. package/dist/stubs/stubs/nuxt-imports.js +13 -0
  32. package/dist/stubs/stubs/qwik-city.js +33 -0
  33. package/dist/stubs/stubs/react-router.js +67 -0
  34. package/dist/stubs/stubs/server-only.js +2 -0
  35. package/dist/stubs/stubs/solid-router.js +27 -0
  36. package/dist/stubs/stubs/solid-start.js +18 -0
  37. package/dist/stubs/stubs/sveltekit-environment.js +5 -0
  38. package/dist/stubs/stubs/sveltekit-navigation.js +11 -0
  39. package/dist/stubs/stubs/sveltekit-stores.js +15 -0
  40. package/dist/stubs/stubs/vike.js +11 -0
  41. package/dist/stubs/sveltekit-environment.js +5 -0
  42. package/dist/stubs/sveltekit-navigation.js +11 -0
  43. package/dist/stubs/sveltekit-stores.js +15 -0
  44. package/dist/stubs/vike.js +11 -0
  45. package/package.json +8 -3
  46. package/scripts/render-changed.mjs +67 -12
  47. package/dist/chunk-3CDSNOX5.js +0 -869
  48. package/dist/chunk-3LVWVDET.js +0 -849
  49. package/dist/chunk-47YJG5HR.js +0 -690
  50. package/dist/chunk-67JZQ6OI.js +0 -819
  51. package/dist/chunk-AUACBLHM.js +0 -191
  52. package/dist/chunk-AZCGKIMU.js +0 -850
  53. package/dist/chunk-B3CLIGWU.js +0 -786
  54. package/dist/chunk-C6QSY4WR.js +0 -811
  55. package/dist/chunk-DX54PJKO.js +0 -603
  56. package/dist/chunk-EMCJGIMY.js +0 -984
  57. package/dist/chunk-FQNWGR62.js +0 -849
  58. package/dist/chunk-FTYTZW6D.js +0 -203
  59. package/dist/chunk-GVOEFYEX.js +0 -139
  60. package/dist/chunk-JGVKYXY2.js +0 -857
  61. package/dist/chunk-JYPEA4P2.js +0 -846
  62. package/dist/chunk-KHK35HDD.js +0 -855
  63. package/dist/chunk-L2CADTS7.js +0 -191
  64. package/dist/chunk-O7NWWFIU.js +0 -871
  65. package/dist/chunk-Q7A3DLED.js +0 -848
  66. package/dist/chunk-Q7NQA4ZM.js +0 -1095
  67. package/dist/chunk-SIA6XEHM.js +0 -811
  68. package/dist/chunk-ST35YDI6.js +0 -834
  69. package/dist/chunk-T5OBJK35.js +0 -855
  70. package/dist/chunk-U3GHS7KO.js +0 -837
  71. package/dist/chunk-WS2ASCD6.js +0 -683
  72. package/dist/chunk-WZMHVSUA.js +0 -847
  73. package/dist/chunk-ZZST6K7Y.js +0 -987
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/frameshot-mcp)](https://www.npmjs.com/package/frameshot-mcp) [![npm downloads](https://img.shields.io/npm/dm/frameshot-mcp)](https://www.npmjs.com/package/frameshot-mcp) [![GitHub stars](https://img.shields.io/github/stars/kamegoro/frameshot)](https://github.com/kamegoro/frameshot) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
4
4
 
5
- **Give your AI agent eyes.** Render any component — with real imports, Tailwind, and CSS Modules resolved via Vite directly in your terminal or AI chat. No stories. No config. Just point at a file.
5
+ **Give your AI agent eyes.** Render components with real Vite imports, Tailwind, and CSS Modules — right in your terminal or AI chat. No story files required.
6
6
 
7
7
  <p align="center">
8
8
  <img src="docs/demo.gif" alt="frameshot demo" width="720" />
@@ -32,51 +32,29 @@ claude mcp add frameshot -- npx frameshot-mcp@latest
32
32
 
33
33
  ---
34
34
 
35
- ## Using with Claude
35
+ ## Watch mode — live AI feedback loop
36
36
 
37
- Once installed, just tell Claude what you want:
37
+ The AI edits a file, saves it, and immediately sees how it looks — without you calling anything.
38
38
 
39
39
  ```
40
- "Render src/components/PricingCard.tsx and check the layout looks right"
41
- "Refactor the dashboard to use CSS grid render it before and after and make sure nothing broke"
42
- "Show me all components in src/components/ as screenshots"
40
+ watch_start({ patterns: ["src/components/Button.tsx"] })
41
+ renders on every save call watch_get_latest("watch-1") to see it
43
42
  ```
44
43
 
45
- Claude will automatically call `render_file`, `diff_component`, or `render_catalog` as needed. No manual tool calls required.
46
-
47
- ---
48
-
49
- ## Try it now
50
-
51
- No AI client required. Works with any React / Vue / Svelte project:
52
-
53
- ```bash
54
- npx frameshot render src/components/Button.tsx
55
- ```
56
-
57
- > First run installs Playwright's Chromium (~150MB). Subsequent renders are fast.
44
+ The agent fixes saves sees fixes again. You just watch.
58
45
 
59
46
  ---
60
47
 
61
- ## Render
48
+ ## GitHub Action — free Chromatic alternative
62
49
 
63
- Point to a file. Get a screenshot. All imports resolved.
50
+ Two lines. Auto-detects changed components. Posts before/after/diff screenshots directly in the PR comment.
64
51
 
52
+ ```yaml
53
+ - uses: actions/checkout@v7
54
+ with:
55
+ fetch-depth: 0
56
+ - uses: kamegoro/frameshot@v0.8.0
65
57
  ```
66
- render_file("src/components/Dashboard.tsx")
67
- ```
68
-
69
- <p align="center">
70
- <img src="docs/example-output.png" alt="Rendered PricingCard with full Tailwind styling" width="280" />
71
- </p>
72
-
73
- Real Tailwind. Real CSS Modules. Real dependencies — not a CDN polyfill.
74
-
75
- ---
76
-
77
- ## Visual diff
78
-
79
- Catch regressions before you ship. Before / after / changed pixels — all at once.
80
58
 
81
59
  <p align="center">
82
60
  <img src="docs/diff-before.png" alt="Before" width="210" />
@@ -86,68 +64,86 @@ Catch regressions before you ship. Before / after / changed pixels — all at on
86
64
  <img src="docs/diff-result.png" alt="Diff" width="210" />
87
65
  </p>
88
66
 
67
+ Changed `.tsx`, `.jsx`, `.vue`, `.svelte`, `.astro`, `.mdx` files detected automatically. No Storybook. No signup. Free forever.
68
+
69
+ <details>
70
+ <summary>Options</summary>
71
+
72
+ ```yaml
73
+ - uses: kamegoro/frameshot@v0.8.0
74
+ with:
75
+ paths: "./src/components/*.tsx" # default: auto-detect
76
+ extensions: ".jsx,.tsx,.vue" # default: .jsx,.tsx,.vue,.svelte,.astro,.mdx
77
+ exclude: "*.test.*,*.spec.*" # default: *.test.*,*.spec.*,*.stories.*
89
78
  ```
90
- diff_component("src/components/MetricCard.tsx")
91
- → 0.7% changed
92
- ```
79
+
80
+ </details>
93
81
 
94
82
  ---
95
83
 
96
- ## Tools
84
+ ## Render any component
85
+
86
+ Point to a file. Get a screenshot. Full Vite pipeline.
97
87
 
98
- ### `render_file` — Render a component with full dependency resolution
88
+ ```
89
+ render_file("src/components/Dashboard.tsx")
90
+ ```
99
91
 
100
92
  <p align="center">
101
- <img src="docs/example-output.png" alt="Rendered PricingCard" width="280" />
93
+ <img src="docs/example-output.png" alt="Rendered PricingCard with full Tailwind styling" width="280" />
102
94
  </p>
103
95
 
104
- Real Tailwind. Real CSS Modules. Real importsresolved by Vite.
96
+ Resolves your project's real imports, Tailwind config, CSS Modules, and path aliases not a CDN polyfill.
105
97
 
106
98
  ---
107
99
 
108
- ### `diff_component` Visual diff against git HEAD
100
+ ## Using with Claude
109
101
 
110
- <p align="center">
111
- <img src="docs/diff-before.png" alt="Before" width="200" />
112
- &nbsp;
113
- <img src="docs/diff-after.png" alt="After" width="200" />
114
- &nbsp;
115
- <img src="docs/diff-result.png" alt="Diff" width="200" />
116
- </p>
102
+ After installing, just describe what you want:
103
+
104
+ ```
105
+ "Render src/components/PricingCard.tsx does it look right?"
106
+ "Refactor the layout to CSS grid and show me before/after"
107
+ "Watch Button.tsx while I edit — tell me when something looks off"
108
+ ```
117
109
 
118
- Pixel-accurate before/after comparison. Returns diff percentage.
110
+ Claude calls `render_file`, `diff_component`, `watch_start`, or any other tool automatically.
119
111
 
120
112
  ---
121
113
 
122
- ### `render_catalog` Screenshot every component in a directory
114
+ ## Try it without an AI client
115
+
116
+ Works standalone on any React / Vue / Svelte project:
123
117
 
124
118
  ```bash
125
- npx frameshot catalog src/components/
119
+ npx frameshot render src/components/Button.tsx
120
+ npx frameshot diff src/components/Header.tsx
121
+ npx frameshot catalog src/components/ --recursive
126
122
  ```
127
123
 
128
- Renders all components at once and saves PNGs to the output directory.
129
-
130
- ---
131
-
132
- ### `audit_a11y` — Accessibility audit with axe-core
124
+ Images display inline in iTerm2, Kitty, and Sixel terminals. Saved to `.frameshot/` by default.
133
125
 
134
- Returns WCAG violations with severity and selector. No browser extension needed.
126
+ > First run installs Playwright's Chromium (~150MB). Subsequent renders are fast.
135
127
 
136
128
  ---
137
129
 
130
+ ## Tools
131
+
138
132
  | Tool | What it does |
139
133
  |------|-------------|
140
- | `render_file` | **Render a file via Vite**full dep resolution, props support |
141
- | `render_component` | Render a self-contained snippet (React / Vue / Svelte / HTML) |
134
+ | `render_file` | Render a file via Vite — real imports, Tailwind, CSS Modules |
135
+ | `diff_component` | Pixel diff before/after % changed, highlighted pixels |
136
+ | `watch_start` | Watch files — auto-render on every save |
137
+ | `watch_get_latest` | Get the latest render from a watch session |
138
+ | `render_catalog` | Render every component in a directory at once |
142
139
  | `screenshot_url` | Screenshot any URL — localhost, staging, prod |
143
- | `diff_component` | Pixel diff before/after with % changed |
144
140
  | `render_responsive` | Mobile + tablet + desktop in one call |
145
141
  | `render_theme` | Light + dark mode side by side |
146
- | `audit_a11y` | axe-core accessibility audit (WCAG) |
147
- | `render_catalog` | Render every component in a directory |
142
+ | `audit_a11y` | axe-core accessibility audit (WCAG violations) |
143
+ | `render_component` | Render a self-contained code snippet |
148
144
 
149
145
  <details>
150
- <summary>All 18 tools</summary>
146
+ <summary>All 22 tools</summary>
151
147
 
152
148
  | Tool | What it does |
153
149
  |------|-------------|
@@ -169,68 +165,17 @@ Returns WCAG violations with severity and selector. No browser extension needed.
169
165
  | `snapshot_save` | Save a render as named baseline |
170
166
  | `snapshot_check` | Compare current render against saved baseline |
171
167
  | `snapshot_list` | List all saved snapshots |
168
+ | `watch_start` | Start watching files — renders on every save |
169
+ | `watch_stop` | Stop a watch session |
170
+ | `watch_get_latest` | Get the latest rendered screenshot from a session |
171
+ | `watch_list` | List active watch sessions |
172
172
 
173
173
  </details>
174
174
 
175
175
  ---
176
176
 
177
- ## GitHub Action
178
-
179
- Free Chromatic alternative. Auto-detects changed components and posts before/after screenshots on every PR.
180
-
181
- Add this file to your repo:
182
-
183
- ```yaml
184
- # .github/workflows/visual-preview.yml
185
- name: Visual Preview
186
- on: [pull_request]
187
- jobs:
188
- preview:
189
- runs-on: ubuntu-latest
190
- steps:
191
- - uses: actions/checkout@v7
192
- with:
193
- fetch-depth: 0
194
- - uses: kamegoro/frameshot@v0.8.0
195
- ```
196
-
197
- That's it. No config needed — changed `.tsx`, `.jsx`, `.vue`, `.svelte` files are detected automatically.
198
-
199
- Optionally scope to specific paths or customize which files are included:
200
-
201
- ```yaml
202
- - uses: kamegoro/frameshot@v0.8.0
203
- with:
204
- # Render only these files (default: auto-detect changed components)
205
- paths: "./src/components/*.tsx"
206
-
207
- # File extensions to treat as components
208
- # Default: .jsx,.tsx,.vue,.svelte,.astro,.mdx
209
- extensions: ".jsx,.tsx,.vue"
210
-
211
- # Patterns to exclude (matched against filename)
212
- # Default: *.test.*,*.spec.*,*.stories.*,*.story.*
213
- exclude: "*.test.*,*.spec.*,*.stories.*"
214
- ```
215
-
216
- ---
217
-
218
- ## CLI — advanced usage
219
-
220
- ```bash
221
- npx frameshot render src/Card.tsx --props '{"title":"Hello"}'
222
- npx frameshot catalog src/components/ --recursive
223
- npx frameshot diff src/components/Header.tsx
224
- ```
225
-
226
- Images display inline in iTerm2, Kitty, and Sixel terminals. Saved to `.frameshot/` by default.
227
-
228
- ---
229
-
230
177
  ## Performance
231
178
 
232
- Typical measured times (varies by machine and project size):
233
-
234
179
  | Scenario | Time |
235
180
  |----------|------|
236
181
  | Warm render (Vite server cached) | **~200–500ms** |
@@ -249,9 +194,10 @@ Vite server is cached per project root. Browser pool stays warm between MCP call
249
194
  | Setup | Stories + config | SaaS signup | Browser install | **`npx` — done** |
250
195
  | Speed | Dev server startup | Cloud round-trip | 2–5s | **~200ms warm** |
251
196
  | Cost | Free (labor cost) | $149–800+/mo | Free | **Free forever** |
252
- | Stories needed | Yes | Yes | No | **No** |
253
- | Real imports | Via Storybook | Via Storybook | No | **Via Vite** |
197
+ | Story files needed | Yes | Yes | No | **No** |
198
+ | Real imports resolved | Via Storybook | Via Storybook | No | **Via Vite** |
254
199
  | Works offline | Yes | No | Yes | **Yes** |
200
+ | Watch mode | No | No | No | **Yes** |
255
201
  | AI-native (MCP) | No | No | Full-page only | **Component-level** |
256
202
 
257
203
  ---
package/action.yml CHANGED
@@ -46,7 +46,15 @@ runs:
46
46
  shell: bash
47
47
  run: |
48
48
  cd "${{ github.action_path }}"
49
- npm install --prefer-offline frameshot-mcp@latest
49
+ # Install frameshot from the action's own checked-out source (this repo)
50
+ # so users get exactly the version pinned by their `uses:` tag,
51
+ # regardless of npm publish state.
52
+ if [ -f package.json ] && [ -d src ]; then
53
+ npm install --prefer-offline --no-audit --no-fund
54
+ npm run build
55
+ else
56
+ npm install --prefer-offline --no-audit --no-fund frameshot-mcp@latest
57
+ fi
50
58
 
51
59
  - name: Install Playwright Chromium
52
60
  shell: bash
@@ -57,10 +65,11 @@ runs:
57
65
  - name: Install project dependencies (for Vite pipeline)
58
66
  shell: bash
59
67
  run: |
60
- # Install deps in any subdirectory that has vite as a dependency
68
+ # Install deps in any directory that has a package.json with a build framework
69
+ # Supports Vite, Next.js, Nuxt, SvelteKit, Astro, etc.
61
70
  for pkg in $(find "$GITHUB_WORKSPACE" -name "package.json" -not -path "*/node_modules/*" -maxdepth 3); do
62
71
  dir=$(dirname "$pkg")
63
- if grep -q '"vite"' "$pkg" 2>/dev/null; then
72
+ if grep -qE '"vite"|"next"|"nuxt"|"@sveltejs/kit"|"astro"' "$pkg" 2>/dev/null; then
64
73
  echo "Installing deps in $dir"
65
74
  cd "$dir" && npm install --legacy-peer-deps 2>/dev/null || true
66
75
  cd "$GITHUB_WORKSPACE"
@@ -194,13 +203,13 @@ runs:
194
203
  ? `<img src="${diffUrl}" width="240" /><br/>${entry.diffPercentage.toFixed(1)}% changed`
195
204
  : entry.hasBefore ? '✅ No change' : '—';
196
205
 
197
- body += `| \`${entry.name}\` | ${beforeCell} | ${afterCell} | ${diffCell} |\n`;
206
+ body += `| \`${entry.label ?? entry.name}\` | ${beforeCell} | ${afterCell} | ${diffCell} |\n`;
198
207
  } else {
199
208
  const afterUrl = await uploadImageToGitHub(afterFile);
200
209
  const afterCell = afterUrl
201
210
  ? `<img src="${afterUrl}" width="360" />`
202
211
  : '*(unavailable)*';
203
- body += `| \`${entry.name}\` | ${afterCell} |\n`;
212
+ body += `| \`${entry.label ?? entry.name}\` | ${afterCell} |\n`;
204
213
  }
205
214
  }
206
215