@firenet-designs/fnd-cli 2.4.0 → 2.7.0
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.
- package/README.md +194 -57
- package/bin/dev.js +1 -1
- package/dist/commands/alt-text.d.ts +105 -0
- package/dist/commands/alt-text.js +616 -0
- package/dist/commands/backfill-project.js +1 -1
- package/dist/commands/create-project.js +48 -5
- package/dist/commands/workspace/index.d.ts +19 -2
- package/dist/commands/workspace/index.js +171 -56
- package/dist/lib/alt-text.d.ts +87 -0
- package/dist/lib/alt-text.js +196 -0
- package/dist/lib/image-filter.d.ts +43 -0
- package/dist/lib/image-filter.js +71 -0
- package/dist/lib/mcp/bracket-args.d.ts +37 -0
- package/dist/lib/mcp/bracket-args.js +65 -0
- package/dist/lib/mcp/define-tool.d.ts +52 -0
- package/dist/lib/mcp/define-tool.js +2 -0
- package/dist/lib/mcp/registry.d.ts +38 -0
- package/dist/lib/mcp/registry.js +98 -0
- package/dist/lib/mcp/server.d.ts +66 -0
- package/dist/lib/mcp/server.js +176 -0
- package/dist/lib/mcp/tools/shopify-common.d.ts +139 -0
- package/dist/lib/mcp/tools/shopify-common.js +167 -0
- package/dist/lib/mcp/tools/shopify-execute.d.ts +2 -0
- package/dist/lib/mcp/tools/shopify-execute.js +105 -0
- package/dist/lib/mcp/tools/shopify-file-delete.d.ts +2 -0
- package/dist/lib/mcp/tools/shopify-file-delete.js +49 -0
- package/dist/lib/mcp/tools/shopify-file-replace.d.ts +2 -0
- package/dist/lib/mcp/tools/shopify-file-replace.js +79 -0
- package/dist/lib/mcp/tools/shopify-file-search.d.ts +2 -0
- package/dist/lib/mcp/tools/shopify-file-search.js +199 -0
- package/dist/lib/mcp/tools/shopify-file-upload.d.ts +2 -0
- package/dist/lib/mcp/tools/shopify-file-upload.js +76 -0
- package/dist/lib/shopify/graphql/AccessScopes.graphql +7 -0
- package/dist/lib/shopify/graphql/CurrentBulkOperation.graphql +8 -0
- package/dist/lib/shopify/graphql/FileCreate.graphql +25 -0
- package/dist/lib/shopify/graphql/FileDelete.graphql +11 -0
- package/dist/lib/shopify/graphql/FileReplace.graphql +26 -0
- package/dist/lib/shopify/graphql/FileStatus.graphql +19 -0
- package/dist/lib/shopify/graphql/FilesBulkQuery.graphql +27 -0
- package/dist/lib/shopify/graphql/ProductsBulkQuery.graphql +27 -0
- package/dist/lib/shopify/graphql/SearchFiles.graphql +36 -0
- package/dist/lib/shopify/graphql/StagedUploadsCreate.graphql +20 -0
- package/dist/lib/shopify/graphql/StartBulkQuery.graphql +16 -0
- package/dist/lib/shopify/graphql/UpdateFileAlt.graphql +9 -0
- package/dist/lib/shopify/shopify.d.ts +228 -0
- package/dist/lib/shopify/shopify.js +662 -0
- package/dist/lib/webflow.d.ts +80 -0
- package/dist/lib/webflow.js +122 -0
- package/dist/lib/workspace.d.ts +29 -10
- package/dist/lib/workspace.js +74 -39
- package/oclif.manifest.json +162 -78
- package/package.json +21 -10
- package/dist/commands/workspace/cleanup.d.ts +0 -14
- package/dist/commands/workspace/cleanup.js +0 -84
- package/dist/hooks/init/check-for-updates.d.ts +0 -3
- package/dist/hooks/init/check-for-updates.js +0 -15
- package/dist/lib/kv-flag.d.ts +0 -15
- package/dist/lib/kv-flag.js +0 -75
- package/dist/lib/rpc.d.ts +0 -69
- package/dist/lib/rpc.js +0 -313
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ $ npm install -g @firenet-designs/fnd-cli
|
|
|
20
20
|
$ fnd COMMAND
|
|
21
21
|
running command...
|
|
22
22
|
$ fnd (--version)
|
|
23
|
-
@firenet-designs/fnd-cli/2.
|
|
23
|
+
@firenet-designs/fnd-cli/2.7.0 node-v24.18.0
|
|
24
24
|
$ fnd --help [COMMAND]
|
|
25
25
|
USAGE
|
|
26
26
|
$ fnd COMMAND
|
|
@@ -29,13 +29,90 @@ USAGE
|
|
|
29
29
|
<!-- usagestop -->
|
|
30
30
|
# Commands
|
|
31
31
|
<!-- commands -->
|
|
32
|
+
* [`fnd alt-text`](#fnd-alt-text)
|
|
32
33
|
* [`fnd backfill-project [SHOP]`](#fnd-backfill-project-shop)
|
|
34
|
+
* [`fnd caption`](#fnd-caption)
|
|
33
35
|
* [`fnd create-app`](#fnd-create-app)
|
|
34
36
|
* [`fnd create-project [SHOP]`](#fnd-create-project-shop)
|
|
35
37
|
* [`fnd help [COMMAND]`](#fnd-help-command)
|
|
36
38
|
* [`fnd token`](#fnd-token)
|
|
37
39
|
* [`fnd workspace`](#fnd-workspace)
|
|
38
|
-
|
|
40
|
+
|
|
41
|
+
## `fnd alt-text`
|
|
42
|
+
|
|
43
|
+
Generate alt text for a site's images with a local Ollama vision model and write it back.
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
USAGE
|
|
47
|
+
$ fnd alt-text [--api-key <value>] [--dry] [--filter <value>] [--limit <value>] [--ollama-host <value>]
|
|
48
|
+
[--ollama-model <value>] [--only <value>... --cms] [--output-stats <value>] [--platform webflow|shopify] [--select ]
|
|
49
|
+
[--site-id <value>] [--skip]
|
|
50
|
+
|
|
51
|
+
FLAGS
|
|
52
|
+
--api-key=<value> Webflow API token (site-scoped). Webflow only — Shopify auth comes from the Shopify CLI.
|
|
53
|
+
Prompted for if omitted.
|
|
54
|
+
--cms also add alt text to the images in CMS collection items. Webflow only. Off by default — only
|
|
55
|
+
the site asset library is walked.
|
|
56
|
+
--dry report how many images the run would caption without describing or writing anything. Every
|
|
57
|
+
image is still downloaded and run through --filter so the count is accurate, but nothing
|
|
58
|
+
reaches the model. The --ollama-host/--ollama-model and --output-stats flags are ignored in
|
|
59
|
+
this mode, so --dry can be added to (and removed from) a full command without changing the
|
|
60
|
+
rest.
|
|
61
|
+
--filter=<value> a JavaScript expression deciding which images are worth describing, e.g.
|
|
62
|
+
"fileSize>=sizes.KB(100) && width>=100 && height>=100". Available: fileSize (bytes), width,
|
|
63
|
+
height (pixels), url, type ("webp", "png", "jpeg", "svg", …), and sizes.KB/MB/GB helpers.
|
|
64
|
+
Images that fail it are skipped and reported separately. Evaluated after the download, since
|
|
65
|
+
dimensions can't be known before it.
|
|
66
|
+
--limit=<value> stop after this many images have been transcribed (counted across assets and CMS together)
|
|
67
|
+
--ollama-host=<value> base URL of the Ollama server. Prompted for if omitted.
|
|
68
|
+
--ollama-model=<value> the model used to describe the images. Omit it to pick from the vision-capable models pulled
|
|
69
|
+
on the host.
|
|
70
|
+
--only=<value>... only touch these CMS collections, matched case-insensitively against a collection's name or
|
|
71
|
+
slug. Repeat the flag for more than one.
|
|
72
|
+
--output-stats=<value> also write the run stats to this file as Markdown: totals, a row per image (url, description,
|
|
73
|
+
tokens, time, size), and the failures. Parent directories are created.
|
|
74
|
+
--platform=<option> which platform to run against. Prompted for if omitted.
|
|
75
|
+
<options: webflow|shopify>
|
|
76
|
+
--select fetch the CMS collections and pick which ones to process interactively
|
|
77
|
+
--site-id=<value> Webflow site ID, or the Shopify store (mystore or mystore.myshopify.com). Prompted for if
|
|
78
|
+
omitted.
|
|
79
|
+
--skip leave images that already have alt text alone instead of overwriting them
|
|
80
|
+
|
|
81
|
+
DESCRIPTION
|
|
82
|
+
Generate alt text for a site's images with a local Ollama vision model and write it back.
|
|
83
|
+
|
|
84
|
+
Pick a platform with --platform (webflow or shopify). For Webflow, walks the site asset library and (with --cms) the
|
|
85
|
+
image fields of CMS collection items and PATCHes each description back through the Data API. For Shopify, walks the
|
|
86
|
+
store's file library and writes alt text back through the Shopify CLI (which owns the auth — no --api-key). Images are
|
|
87
|
+
fetched and described one at a time; nothing but the platform API calls leaves your network.
|
|
88
|
+
|
|
89
|
+
Webflow CMS writes go to STAGING, so publish the site in Webflow to make them live. Any required flag you omit is
|
|
90
|
+
prompted for.
|
|
91
|
+
|
|
92
|
+
ALIASES
|
|
93
|
+
$ fnd caption
|
|
94
|
+
|
|
95
|
+
EXAMPLES
|
|
96
|
+
$ fnd alt-text --platform webflow --api-key <key> --site-id <id> --ollama-host http://localhost:11434 --ollama-model qwen3-vl:8b
|
|
97
|
+
|
|
98
|
+
$ fnd alt-text --platform shopify --site-id mystore
|
|
99
|
+
|
|
100
|
+
$ fnd alt-text --platform shopify --site-id mystore --dry
|
|
101
|
+
|
|
102
|
+
$ fnd alt-text --platform webflow --skip --limit 20
|
|
103
|
+
|
|
104
|
+
$ fnd alt-text --platform webflow --cms --select
|
|
105
|
+
|
|
106
|
+
$ fnd alt-text --platform webflow --cms --only products --only sku
|
|
107
|
+
|
|
108
|
+
$ fnd alt-text --platform webflow --output-stats ./alt-text-run.md
|
|
109
|
+
|
|
110
|
+
$ fnd alt-text --platform webflow --filter "fileSize>=sizes.KB(100) && width>=100 && height>=100"
|
|
111
|
+
|
|
112
|
+
$ fnd alt-text --platform webflow --filter "type !== 'svg' && !url.includes('/icons/')"
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
_See code: [src/commands/alt-text.ts](https://github.com/FireNet-Designs/fnd-cli/blob/v2.7.0/src/commands/alt-text.ts)_
|
|
39
116
|
|
|
40
117
|
## `fnd backfill-project [SHOP]`
|
|
41
118
|
|
|
@@ -62,7 +139,81 @@ EXAMPLES
|
|
|
62
139
|
$ fnd backfill-project my-store "extra hints"
|
|
63
140
|
```
|
|
64
141
|
|
|
65
|
-
_See code: [src/commands/backfill-project.ts](https://github.com/FireNet-Designs/fnd-cli/blob/v2.
|
|
142
|
+
_See code: [src/commands/backfill-project.ts](https://github.com/FireNet-Designs/fnd-cli/blob/v2.7.0/src/commands/backfill-project.ts)_
|
|
143
|
+
|
|
144
|
+
## `fnd caption`
|
|
145
|
+
|
|
146
|
+
Generate alt text for a site's images with a local Ollama vision model and write it back.
|
|
147
|
+
|
|
148
|
+
```
|
|
149
|
+
USAGE
|
|
150
|
+
$ fnd caption [--api-key <value>] [--dry] [--filter <value>] [--limit <value>] [--ollama-host <value>]
|
|
151
|
+
[--ollama-model <value>] [--only <value>... --cms] [--output-stats <value>] [--platform webflow|shopify] [--select ]
|
|
152
|
+
[--site-id <value>] [--skip]
|
|
153
|
+
|
|
154
|
+
FLAGS
|
|
155
|
+
--api-key=<value> Webflow API token (site-scoped). Webflow only — Shopify auth comes from the Shopify CLI.
|
|
156
|
+
Prompted for if omitted.
|
|
157
|
+
--cms also add alt text to the images in CMS collection items. Webflow only. Off by default — only
|
|
158
|
+
the site asset library is walked.
|
|
159
|
+
--dry report how many images the run would caption without describing or writing anything. Every
|
|
160
|
+
image is still downloaded and run through --filter so the count is accurate, but nothing
|
|
161
|
+
reaches the model. The --ollama-host/--ollama-model and --output-stats flags are ignored in
|
|
162
|
+
this mode, so --dry can be added to (and removed from) a full command without changing the
|
|
163
|
+
rest.
|
|
164
|
+
--filter=<value> a JavaScript expression deciding which images are worth describing, e.g.
|
|
165
|
+
"fileSize>=sizes.KB(100) && width>=100 && height>=100". Available: fileSize (bytes), width,
|
|
166
|
+
height (pixels), url, type ("webp", "png", "jpeg", "svg", …), and sizes.KB/MB/GB helpers.
|
|
167
|
+
Images that fail it are skipped and reported separately. Evaluated after the download, since
|
|
168
|
+
dimensions can't be known before it.
|
|
169
|
+
--limit=<value> stop after this many images have been transcribed (counted across assets and CMS together)
|
|
170
|
+
--ollama-host=<value> base URL of the Ollama server. Prompted for if omitted.
|
|
171
|
+
--ollama-model=<value> the model used to describe the images. Omit it to pick from the vision-capable models pulled
|
|
172
|
+
on the host.
|
|
173
|
+
--only=<value>... only touch these CMS collections, matched case-insensitively against a collection's name or
|
|
174
|
+
slug. Repeat the flag for more than one.
|
|
175
|
+
--output-stats=<value> also write the run stats to this file as Markdown: totals, a row per image (url, description,
|
|
176
|
+
tokens, time, size), and the failures. Parent directories are created.
|
|
177
|
+
--platform=<option> which platform to run against. Prompted for if omitted.
|
|
178
|
+
<options: webflow|shopify>
|
|
179
|
+
--select fetch the CMS collections and pick which ones to process interactively
|
|
180
|
+
--site-id=<value> Webflow site ID, or the Shopify store (mystore or mystore.myshopify.com). Prompted for if
|
|
181
|
+
omitted.
|
|
182
|
+
--skip leave images that already have alt text alone instead of overwriting them
|
|
183
|
+
|
|
184
|
+
DESCRIPTION
|
|
185
|
+
Generate alt text for a site's images with a local Ollama vision model and write it back.
|
|
186
|
+
|
|
187
|
+
Pick a platform with --platform (webflow or shopify). For Webflow, walks the site asset library and (with --cms) the
|
|
188
|
+
image fields of CMS collection items and PATCHes each description back through the Data API. For Shopify, walks the
|
|
189
|
+
store's file library and writes alt text back through the Shopify CLI (which owns the auth — no --api-key). Images are
|
|
190
|
+
fetched and described one at a time; nothing but the platform API calls leaves your network.
|
|
191
|
+
|
|
192
|
+
Webflow CMS writes go to STAGING, so publish the site in Webflow to make them live. Any required flag you omit is
|
|
193
|
+
prompted for.
|
|
194
|
+
|
|
195
|
+
ALIASES
|
|
196
|
+
$ fnd caption
|
|
197
|
+
|
|
198
|
+
EXAMPLES
|
|
199
|
+
$ fnd caption --platform webflow --api-key <key> --site-id <id> --ollama-host http://localhost:11434 --ollama-model qwen3-vl:8b
|
|
200
|
+
|
|
201
|
+
$ fnd caption --platform shopify --site-id mystore
|
|
202
|
+
|
|
203
|
+
$ fnd caption --platform shopify --site-id mystore --dry
|
|
204
|
+
|
|
205
|
+
$ fnd caption --platform webflow --skip --limit 20
|
|
206
|
+
|
|
207
|
+
$ fnd caption --platform webflow --cms --select
|
|
208
|
+
|
|
209
|
+
$ fnd caption --platform webflow --cms --only products --only sku
|
|
210
|
+
|
|
211
|
+
$ fnd caption --platform webflow --output-stats ./alt-text-run.md
|
|
212
|
+
|
|
213
|
+
$ fnd caption --platform webflow --filter "fileSize>=sizes.KB(100) && width>=100 && height>=100"
|
|
214
|
+
|
|
215
|
+
$ fnd caption --platform webflow --filter "type !== 'svg' && !url.includes('/icons/')"
|
|
216
|
+
```
|
|
66
217
|
|
|
67
218
|
## `fnd create-app`
|
|
68
219
|
|
|
@@ -83,11 +234,11 @@ EXAMPLES
|
|
|
83
234
|
$ fnd create-app
|
|
84
235
|
```
|
|
85
236
|
|
|
86
|
-
_See code: [src/commands/create-app.ts](https://github.com/FireNet-Designs/fnd-cli/blob/v2.
|
|
237
|
+
_See code: [src/commands/create-app.ts](https://github.com/FireNet-Designs/fnd-cli/blob/v2.7.0/src/commands/create-app.ts)_
|
|
87
238
|
|
|
88
239
|
## `fnd create-project [SHOP]`
|
|
89
240
|
|
|
90
|
-
Scaffold a new client project: git on branch production, ignore files, Shopify theme pull, a Claude-generated CLAUDE.md, then a private GitHub repo under the FireNet-Designs org.
|
|
241
|
+
Scaffold a new client project: git on branch production, ignore files, Shopify theme pull, a Claude-generated CLAUDE.md, then a private GitHub repo under the FireNet-Designs org with production and staging branches pushed.
|
|
91
242
|
|
|
92
243
|
```
|
|
93
244
|
USAGE
|
|
@@ -98,7 +249,7 @@ ARGUMENTS
|
|
|
98
249
|
|
|
99
250
|
DESCRIPTION
|
|
100
251
|
Scaffold a new client project: git on branch production, ignore files, Shopify theme pull, a Claude-generated
|
|
101
|
-
CLAUDE.md, then a private GitHub repo under the FireNet-Designs org.
|
|
252
|
+
CLAUDE.md, then a private GitHub repo under the FireNet-Designs org with production and staging branches pushed.
|
|
102
253
|
|
|
103
254
|
Requires the claude CLI (npm install -g @anthropic-ai/claude-code) for the CLAUDE.md step.
|
|
104
255
|
|
|
@@ -113,7 +264,7 @@ EXAMPLES
|
|
|
113
264
|
$ fnd create-project my-store "Acme storefront, Klaviyo"
|
|
114
265
|
```
|
|
115
266
|
|
|
116
|
-
_See code: [src/commands/create-project.ts](https://github.com/FireNet-Designs/fnd-cli/blob/v2.
|
|
267
|
+
_See code: [src/commands/create-project.ts](https://github.com/FireNet-Designs/fnd-cli/blob/v2.7.0/src/commands/create-project.ts)_
|
|
117
268
|
|
|
118
269
|
## `fnd help [COMMAND]`
|
|
119
270
|
|
|
@@ -165,7 +316,7 @@ EXAMPLES
|
|
|
165
316
|
$ fnd token -s mystore -i <id> -c <secret> --write ./.mcp.json
|
|
166
317
|
```
|
|
167
318
|
|
|
168
|
-
_See code: [src/commands/token.ts](https://github.com/FireNet-Designs/fnd-cli/blob/v2.
|
|
319
|
+
_See code: [src/commands/token.ts](https://github.com/FireNet-Designs/fnd-cli/blob/v2.7.0/src/commands/token.ts)_
|
|
169
320
|
|
|
170
321
|
## `fnd workspace`
|
|
171
322
|
|
|
@@ -173,10 +324,16 @@ Open a remote workspace: two-way sync the current directory to a remote Linux bo
|
|
|
173
324
|
|
|
174
325
|
```
|
|
175
326
|
USAGE
|
|
176
|
-
$ fnd workspace --ssh <value> [--delete-remote-dir] [--devtools <value>] [--ignore-vcs]
|
|
177
|
-
<value>] [--
|
|
327
|
+
$ fnd workspace --ssh <value> [--cleanup] [--delete-remote-dir] [--devtools <value>] [--ignore-vcs]
|
|
328
|
+
[--remote-base <value>] [--site-id <value>] [--source remote|local] [--with-tool <value>...]
|
|
178
329
|
|
|
179
330
|
FLAGS
|
|
331
|
+
--cleanup
|
|
332
|
+
tear down a leftover session instead of opening one — don't connect, just terminate this directory's Mutagen sync
|
|
333
|
+
and (using whatever other flags are set) strip the remote --devtools/--with-tool MCP entries and, with
|
|
334
|
+
--delete-remote-dir, remove the remote dir. Re-run your original command with --cleanup appended after a session
|
|
335
|
+
that dropped without cleaning up.
|
|
336
|
+
|
|
180
337
|
--delete-remote-dir
|
|
181
338
|
on exit, delete the remote workspace directory instead of leaving the synced copy in place
|
|
182
339
|
|
|
@@ -193,13 +350,10 @@ FLAGS
|
|
|
193
350
|
--remote-base=<value>
|
|
194
351
|
[default: /home/fnd] base dir on the remote; the workspace lands at <base>/<local-user>/<dir-name>
|
|
195
352
|
|
|
196
|
-
--
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
tunnel (ssh -R <remote>:localhost:<local>) to a command server started here; shell defaults to the shell fnd
|
|
201
|
-
workspace was called from; profile (default true) controls whether the shell loads its startup files — with it on,
|
|
202
|
-
POSIX shells run interactively (-i) so rc files like ~/.bashrc or ~/.zshrc are sourced and tools such as nvm work.
|
|
353
|
+
--site-id=<value>
|
|
354
|
+
the Shopify store (mystore or mystore.myshopify.com) the Shopify --with-tool tools operate on. Required when any
|
|
355
|
+
Shopify tool (shopify-file-* or shopify-execute) is selected; fixing the store here is a safety boundary — the
|
|
356
|
+
remote AI cannot target another store.
|
|
203
357
|
|
|
204
358
|
--source=<option>
|
|
205
359
|
which side wins on conflict: "remote" = this server (where the workspace shell runs), "local" = the machine you ran
|
|
@@ -209,6 +363,21 @@ FLAGS
|
|
|
209
363
|
--ssh=<value>
|
|
210
364
|
(required) remote to connect to, as user@host
|
|
211
365
|
|
|
366
|
+
--with-tool=<value>...
|
|
367
|
+
expose an fnd tool to Claude on the remote via a loopback MCP server on THIS machine (the one running fnd
|
|
368
|
+
workspace), reached through a reverse tunnel. Repeatable. Value is <name> or <name>[options]; available:
|
|
369
|
+
shopify-execute[<scopes=all|<list>[,ask]>], shopify-file-delete[[<ask>]], shopify-file-replace[[<ask>]],
|
|
370
|
+
shopify-file-search[[<ask>]], shopify-file-upload[[<ask>]]. e.g. shopify-file-upload (with --site-id mystore) lets
|
|
371
|
+
the remote AI upload files from the workspace into that Shopify store using your local Shopify CLI;
|
|
372
|
+
shopify-file-replace and shopify-file-delete add in-place replace and delete; shopify-file-search looks up files by
|
|
373
|
+
name/size/type/url (metadata only, no image bytes) to dedupe before upload or find oversized images; shopify-execute
|
|
374
|
+
runs arbitrary Admin GraphQL and REQUIRES a scopes option — shopify-execute[scopes=all] for broad access or
|
|
375
|
+
shopify-execute[scopes=read_products+write_orders] for an explicit set (which the store is then trimmed to, revoking
|
|
376
|
+
anything extra, so the AI is held to least privilege). Append ,ask (e.g. shopify-file-delete[ask],
|
|
377
|
+
shopify-execute[ask,scopes=all]) to make that tool prompt for confirmation before EVERY call, even under the
|
|
378
|
+
remote's auto-accept/bypass permissions — use it to gate the powerful/destructive tools. Prerequisites (auth,
|
|
379
|
+
scopes) are checked and set up before connecting.
|
|
380
|
+
|
|
212
381
|
DESCRIPTION
|
|
213
382
|
Open a remote workspace: two-way sync the current directory to a remote Linux box with Mutagen and drop into a shell
|
|
214
383
|
there, tearing the sync down on exit.
|
|
@@ -232,52 +401,20 @@ EXAMPLES
|
|
|
232
401
|
|
|
233
402
|
$ fnd workspace --ssh user@host --devtools 9333:9222
|
|
234
403
|
|
|
235
|
-
$ fnd workspace --ssh user@host --
|
|
404
|
+
$ fnd workspace --ssh user@host --with-tool shopify-file-upload --site-id mystore
|
|
236
405
|
|
|
237
|
-
$ fnd workspace --ssh user@host --
|
|
406
|
+
$ fnd workspace --ssh user@host --with-tool shopify-file-upload --with-tool shopify-file-search --with-tool "shopify-file-delete[ask]" --site-id mystore
|
|
238
407
|
|
|
239
|
-
$ fnd workspace --ssh user@host --delete-
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
_See code: [src/commands/workspace/index.ts](https://github.com/FireNet-Designs/fnd-cli/blob/v2.4.0/src/commands/workspace/index.ts)_
|
|
243
|
-
|
|
244
|
-
## `fnd workspace cleanup`
|
|
245
|
-
|
|
246
|
-
Tear down a leftover workspace — use this if a `workspace` session dropped before it could clean up after itself.
|
|
247
|
-
|
|
248
|
-
```
|
|
249
|
-
USAGE
|
|
250
|
-
$ fnd workspace cleanup --ssh <value> [--delete-remote-dir] [--devtools] [--remote-base <value>] [--remote-dir
|
|
251
|
-
<value>] [--rpc]
|
|
408
|
+
$ fnd workspace --ssh user@host --with-tool shopify-file-upload --with-tool shopify-file-replace --with-tool shopify-file-delete --site-id mystore.myshopify.com
|
|
252
409
|
|
|
253
|
-
|
|
254
|
-
--delete-remote-dir also delete the remote workspace directory (by default the synced files are left in place)
|
|
255
|
-
--devtools also strip the chrome-devtools MCP entry from the remote (only if the dropped session used
|
|
256
|
-
--devtools)
|
|
257
|
-
--remote-base=<value> [default: /home/fnd] base dir on the remote, used to derive the default remote directory path
|
|
258
|
-
--remote-dir=<value> exact remote directory to target (defaults to the current dir mapping)
|
|
259
|
-
--rpc also strip the local-shell MCP entry from the remote (only if the dropped session used --rpc)
|
|
260
|
-
--ssh=<value> (required) remote to connect to, as user@host
|
|
261
|
-
|
|
262
|
-
DESCRIPTION
|
|
263
|
-
Tear down a leftover workspace — use this if a `workspace` session dropped before it could clean up after itself.
|
|
264
|
-
|
|
265
|
-
Terminates any Mutagen sync sessions this machine started for the directory. Pass --devtools or --rpc to also strip
|
|
266
|
-
the matching MCP entries from the remote (only do this if the dropped session used those flags). With no --remote-dir,
|
|
267
|
-
it targets the same path `workspace` would use for the current directory. The synced files themselves are left in
|
|
268
|
-
place unless you pass --delete-remote-dir.
|
|
410
|
+
$ fnd workspace --ssh user@host --with-tool "shopify-execute[scopes=read_products+read_orders]" --site-id mystore
|
|
269
411
|
|
|
270
|
-
|
|
271
|
-
$ fnd workspace cleanup --ssh user@host
|
|
272
|
-
|
|
273
|
-
$ fnd workspace cleanup --ssh user@host --remote-dir /home/fnd/cole/fnd-cli
|
|
412
|
+
$ fnd workspace --ssh user@host --with-tool "shopify-execute[ask,scopes=all]" --site-id mystore
|
|
274
413
|
|
|
275
|
-
$ fnd workspace
|
|
276
|
-
|
|
277
|
-
$ fnd workspace cleanup --ssh user@host --rpc
|
|
414
|
+
$ fnd workspace --ssh user@host --delete-remote-dir
|
|
278
415
|
|
|
279
|
-
$ fnd workspace
|
|
416
|
+
$ fnd workspace --ssh user@host --with-tool shopify-file-upload --site-id mystore --cleanup
|
|
280
417
|
```
|
|
281
418
|
|
|
282
|
-
_See code: [src/commands/workspace/
|
|
419
|
+
_See code: [src/commands/workspace/index.ts](https://github.com/FireNet-Designs/fnd-cli/blob/v2.7.0/src/commands/workspace/index.ts)_
|
|
283
420
|
<!-- commandsstop -->
|
package/bin/dev.js
CHANGED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { Command, Interfaces } from '@oclif/core';
|
|
2
|
+
export default class AltText extends Command {
|
|
3
|
+
static aliases: string[];
|
|
4
|
+
static description: string;
|
|
5
|
+
static examples: string[];
|
|
6
|
+
static flags: {
|
|
7
|
+
'api-key': Interfaces.OptionFlag<string | undefined, Interfaces.CustomOptions>;
|
|
8
|
+
cms: Interfaces.BooleanFlag<boolean>;
|
|
9
|
+
dry: Interfaces.BooleanFlag<boolean>;
|
|
10
|
+
filter: Interfaces.OptionFlag<string | undefined, Interfaces.CustomOptions>;
|
|
11
|
+
limit: Interfaces.OptionFlag<number | undefined, Interfaces.CustomOptions>;
|
|
12
|
+
'ollama-host': Interfaces.OptionFlag<string | undefined, Interfaces.CustomOptions>;
|
|
13
|
+
'ollama-model': Interfaces.OptionFlag<string | undefined, Interfaces.CustomOptions>;
|
|
14
|
+
only: Interfaces.OptionFlag<string[] | undefined, Interfaces.CustomOptions>;
|
|
15
|
+
'output-stats': Interfaces.OptionFlag<string | undefined, Interfaces.CustomOptions>;
|
|
16
|
+
platform: Interfaces.OptionFlag<string | undefined, Interfaces.CustomOptions>;
|
|
17
|
+
select: Interfaces.BooleanFlag<boolean>;
|
|
18
|
+
'site-id': Interfaces.OptionFlag<string | undefined, Interfaces.CustomOptions>;
|
|
19
|
+
skip: Interfaces.BooleanFlag<boolean>;
|
|
20
|
+
};
|
|
21
|
+
run(): Promise<void>;
|
|
22
|
+
/**
|
|
23
|
+
* Describe one image and account for it. Returns undefined when the model or
|
|
24
|
+
* the download failed — one bad image must not abort a run that may have
|
|
25
|
+
* hundreds of good ones behind it.
|
|
26
|
+
*
|
|
27
|
+
* Also the fallback for a --dry run: when an image's metadata wasn't known up
|
|
28
|
+
* front (so the caller couldn't filter it cheaply), the describer downloads it
|
|
29
|
+
* just far enough to measure it, and this counts it via recordDry.
|
|
30
|
+
*/
|
|
31
|
+
private describe;
|
|
32
|
+
/**
|
|
33
|
+
* Guarantee the store's app installation has the scopes this run needs before
|
|
34
|
+
* any captioning. `required` is the minimal set for the run — the full
|
|
35
|
+
* REQUIRED_SCOPES for a real run, just DRY_RUN_SCOPES (read_files) for a --dry
|
|
36
|
+
* one, which never writes or maps product context. A non-zero exit from the
|
|
37
|
+
* scope probe is the CLI's way of saying the store isn't authenticated at all;
|
|
38
|
+
* a clean exit with a scope missing means it's authenticated but under-scoped.
|
|
39
|
+
* Either way `shopify store auth` with `required` fixes it — it adds only
|
|
40
|
+
* what's missing, and a write scope already covers its read counterpart.
|
|
41
|
+
*/
|
|
42
|
+
private ensureShopifyScopes;
|
|
43
|
+
/** The `[n/limit] label — file` progress line, shared by real and dry counting. */
|
|
44
|
+
private logImageLine;
|
|
45
|
+
/** Which CMS collections this run should walk. */
|
|
46
|
+
private pickCollections;
|
|
47
|
+
/**
|
|
48
|
+
* Ask which model to use, offering only the vision-capable models the host has
|
|
49
|
+
* already pulled — a text-only model would happily accept the request and
|
|
50
|
+
* describe nothing, and a model that isn't pulled would stall the run behind a
|
|
51
|
+
* silent download.
|
|
52
|
+
*/
|
|
53
|
+
private pickModel;
|
|
54
|
+
/** The site asset library pass. Always runs; --cms only adds work on top of it. */
|
|
55
|
+
private processAssets;
|
|
56
|
+
private processCollection;
|
|
57
|
+
/**
|
|
58
|
+
* Fill in every image field on one item, then PATCH the item once. Fields that
|
|
59
|
+
* didn't change are left out of the payload entirely, and an item with no
|
|
60
|
+
* changed fields is never PATCHed.
|
|
61
|
+
*/
|
|
62
|
+
private processItem;
|
|
63
|
+
/**
|
|
64
|
+
* The Shopify path: make sure the CLI is present and the store is authenticated
|
|
65
|
+
* with the file scopes, then caption every image in the file library. Always
|
|
66
|
+
* returns false — there's no separate staging step to warn about.
|
|
67
|
+
*/
|
|
68
|
+
private processShopify;
|
|
69
|
+
/**
|
|
70
|
+
* The Webflow path: the site asset library, then (with --cms) whichever CMS
|
|
71
|
+
* collections the flags select. Returns whether any CMS work was done, so the
|
|
72
|
+
* summary can remind the user to publish staging.
|
|
73
|
+
*/
|
|
74
|
+
private processWebflow;
|
|
75
|
+
/**
|
|
76
|
+
* Count one image toward a --dry total from metadata already in hand — no
|
|
77
|
+
* download, no model. Applies --filter to decide caption-vs-skip; the caller
|
|
78
|
+
* has already logged the image line.
|
|
79
|
+
*/
|
|
80
|
+
private recordDry;
|
|
81
|
+
/** Totals and averages only — the per-image rows live in the --output-stats file. */
|
|
82
|
+
private report;
|
|
83
|
+
/**
|
|
84
|
+
* The --dry summary: how many images a real run would caption, the ones the
|
|
85
|
+
* --filter would skip, and any that couldn't even be downloaded. No tokens,
|
|
86
|
+
* time, or descriptions to report — nothing was described.
|
|
87
|
+
*/
|
|
88
|
+
private reportDry;
|
|
89
|
+
/** The --platform value, or ask when it was omitted. */
|
|
90
|
+
private resolvePlatform;
|
|
91
|
+
/**
|
|
92
|
+
* Stop a spinner and undo ora's parting cursor move. On stop, ora's clear()
|
|
93
|
+
* runs cursorTo(indent) on its stream (stderr) — and since stdout shares the
|
|
94
|
+
* terminal's cursor, the very next this.log would start at that column and be
|
|
95
|
+
* pushed right by `indent` spaces. Resetting to column 0 keeps the following
|
|
96
|
+
* line at exactly the indent it asks for.
|
|
97
|
+
*/
|
|
98
|
+
private stopSpinner;
|
|
99
|
+
/**
|
|
100
|
+
* Write the Markdown report. This runs after everything else, so a run that
|
|
101
|
+
* gets this far has already written its alt text back to Webflow — failing to
|
|
102
|
+
* save the report loses the record, not the work, and the message says so.
|
|
103
|
+
*/
|
|
104
|
+
private writeStats;
|
|
105
|
+
}
|