comfy-cli 1.7.3__tar.gz → 1.9.0__tar.gz
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.
- {comfy_cli-1.7.3 → comfy_cli-1.9.0}/PKG-INFO +80 -27
- {comfy_cli-1.7.3 → comfy_cli-1.9.0}/README.md +79 -26
- {comfy_cli-1.7.3 → comfy_cli-1.9.0}/comfy_cli/cmdline.py +19 -1
- {comfy_cli-1.7.3 → comfy_cli-1.9.0}/comfy_cli/command/code_search.py +46 -14
- {comfy_cli-1.7.3 → comfy_cli-1.9.0}/comfy_cli/command/custom_nodes/command.py +11 -0
- comfy_cli-1.9.0/comfy_cli/command/generate/__init__.py +3 -0
- comfy_cli-1.9.0/comfy_cli/command/generate/app.py +464 -0
- comfy_cli-1.9.0/comfy_cli/command/generate/client.py +152 -0
- comfy_cli-1.9.0/comfy_cli/command/generate/output.py +105 -0
- comfy_cli-1.9.0/comfy_cli/command/generate/poll.py +381 -0
- comfy_cli-1.9.0/comfy_cli/command/generate/schema.py +273 -0
- comfy_cli-1.9.0/comfy_cli/command/generate/spec.py +403 -0
- comfy_cli-1.9.0/comfy_cli/command/generate/upload.py +128 -0
- {comfy_cli-1.7.3 → comfy_cli-1.9.0}/comfy_cli/command/install.py +138 -9
- {comfy_cli-1.7.3 → comfy_cli-1.9.0}/comfy_cli/command/run.py +103 -23
- {comfy_cli-1.7.3 → comfy_cli-1.9.0}/comfy_cli/git_utils.py +20 -3
- {comfy_cli-1.7.3 → comfy_cli-1.9.0}/comfy_cli/registry/config_parser.py +203 -5
- {comfy_cli-1.7.3 → comfy_cli-1.9.0}/comfy_cli/tracking.py +9 -1
- comfy_cli-1.9.0/comfy_cli/workflow_to_api.py +1369 -0
- {comfy_cli-1.7.3 → comfy_cli-1.9.0}/comfy_cli.egg-info/PKG-INFO +80 -27
- {comfy_cli-1.7.3 → comfy_cli-1.9.0}/comfy_cli.egg-info/SOURCES.txt +9 -0
- {comfy_cli-1.7.3 → comfy_cli-1.9.0}/pyproject.toml +1 -1
- {comfy_cli-1.7.3 → comfy_cli-1.9.0}/LICENSE +0 -0
- {comfy_cli-1.7.3 → comfy_cli-1.9.0}/comfy_cli/__init__.py +0 -0
- {comfy_cli-1.7.3 → comfy_cli-1.9.0}/comfy_cli/__main__.py +0 -0
- {comfy_cli-1.7.3 → comfy_cli-1.9.0}/comfy_cli/command/__init__.py +0 -0
- {comfy_cli-1.7.3 → comfy_cli-1.9.0}/comfy_cli/command/custom_nodes/__init__.py +0 -0
- {comfy_cli-1.7.3 → comfy_cli-1.9.0}/comfy_cli/command/custom_nodes/bisect_custom_nodes.py +0 -0
- {comfy_cli-1.7.3 → comfy_cli-1.9.0}/comfy_cli/command/custom_nodes/cm_cli_util.py +0 -0
- {comfy_cli-1.7.3 → comfy_cli-1.9.0}/comfy_cli/command/github/pr_info.py +0 -0
- {comfy_cli-1.7.3 → comfy_cli-1.9.0}/comfy_cli/command/launch.py +0 -0
- {comfy_cli-1.7.3 → comfy_cli-1.9.0}/comfy_cli/command/models/models.py +0 -0
- {comfy_cli-1.7.3 → comfy_cli-1.9.0}/comfy_cli/command/pr_command.py +0 -0
- {comfy_cli-1.7.3 → comfy_cli-1.9.0}/comfy_cli/config_manager.py +0 -0
- {comfy_cli-1.7.3 → comfy_cli-1.9.0}/comfy_cli/constants.py +0 -0
- {comfy_cli-1.7.3 → comfy_cli-1.9.0}/comfy_cli/cuda_detect.py +0 -0
- {comfy_cli-1.7.3 → comfy_cli-1.9.0}/comfy_cli/env_checker.py +0 -0
- {comfy_cli-1.7.3 → comfy_cli-1.9.0}/comfy_cli/file_utils.py +0 -0
- {comfy_cli-1.7.3 → comfy_cli-1.9.0}/comfy_cli/logging.py +0 -0
- {comfy_cli-1.7.3 → comfy_cli-1.9.0}/comfy_cli/pr_cache.py +0 -0
- {comfy_cli-1.7.3 → comfy_cli-1.9.0}/comfy_cli/registry/__init__.py +0 -0
- {comfy_cli-1.7.3 → comfy_cli-1.9.0}/comfy_cli/registry/api.py +0 -0
- {comfy_cli-1.7.3 → comfy_cli-1.9.0}/comfy_cli/registry/types.py +0 -0
- {comfy_cli-1.7.3 → comfy_cli-1.9.0}/comfy_cli/resolve_python.py +0 -0
- {comfy_cli-1.7.3 → comfy_cli-1.9.0}/comfy_cli/standalone.py +0 -0
- {comfy_cli-1.7.3 → comfy_cli-1.9.0}/comfy_cli/typing.py +0 -0
- {comfy_cli-1.7.3 → comfy_cli-1.9.0}/comfy_cli/ui.py +0 -0
- {comfy_cli-1.7.3 → comfy_cli-1.9.0}/comfy_cli/update.py +0 -0
- {comfy_cli-1.7.3 → comfy_cli-1.9.0}/comfy_cli/utils.py +0 -0
- {comfy_cli-1.7.3 → comfy_cli-1.9.0}/comfy_cli/uv.py +0 -0
- {comfy_cli-1.7.3 → comfy_cli-1.9.0}/comfy_cli/workspace_manager.py +0 -0
- {comfy_cli-1.7.3 → comfy_cli-1.9.0}/comfy_cli.egg-info/dependency_links.txt +0 -0
- {comfy_cli-1.7.3 → comfy_cli-1.9.0}/comfy_cli.egg-info/entry_points.txt +0 -0
- {comfy_cli-1.7.3 → comfy_cli-1.9.0}/comfy_cli.egg-info/requires.txt +0 -0
- {comfy_cli-1.7.3 → comfy_cli-1.9.0}/comfy_cli.egg-info/top_level.txt +0 -0
- {comfy_cli-1.7.3 → comfy_cli-1.9.0}/setup.cfg +0 -0
- {comfy_cli-1.7.3 → comfy_cli-1.9.0}/tests/test_file_utils_network.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: comfy-cli
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.9.0
|
|
4
4
|
Summary: A CLI tool for installing and using ComfyUI.
|
|
5
5
|
Maintainer-email: Yoland Yan <yoland@drip.art>, James Kwon <hongilkwon316@gmail.com>, Robin Huang <robin@drip.art>, "Dr.Lt.Data" <dr.lt.data@gmail.com>
|
|
6
6
|
License: GPL-3.0-only
|
|
@@ -52,11 +52,10 @@ Dynamic: license-file
|
|
|
52
52
|
[](https://pypi.org/project/comfy-cli/)
|
|
53
53
|
[](https://github.com/Comfy-Org/comfy-cli/blob/main/LICENSE)
|
|
54
54
|
|
|
55
|
-
comfy-cli is a command
|
|
56
|
-
[ComfyUI](https://github.com/comfyanonymous/ComfyUI)
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
terminal.
|
|
55
|
+
comfy-cli is a command-line tool for installing, running, and extending
|
|
56
|
+
[ComfyUI](https://github.com/comfyanonymous/ComfyUI) — the open-source
|
|
57
|
+
generative-media engine. Set up ComfyUI, install custom nodes and models, run
|
|
58
|
+
workflows, and call hosted partner image models, all from your terminal.
|
|
60
59
|
|
|
61
60
|
## Demo
|
|
62
61
|
|
|
@@ -64,29 +63,32 @@ terminal.
|
|
|
64
63
|
|
|
65
64
|
## Features
|
|
66
65
|
|
|
67
|
-
- 🚀
|
|
68
|
-
-
|
|
69
|
-
- 🔧 Custom node management
|
|
70
|
-
-
|
|
71
|
-
-
|
|
72
|
-
-
|
|
73
|
-
-
|
|
66
|
+
- 🚀 One-command ComfyUI install and launch
|
|
67
|
+
- 🎨 Direct calls to partner image and video nodes (Flux, Ideogram, DALL·E, Recraft, Stability, Kling, Luma, Runway, Pika, Vidu, Hailuo, …) via `comfy generate`, no workflow JSON required
|
|
68
|
+
- 🔧 Custom node management — install, update, snapshot, bisect
|
|
69
|
+
- 📦 Fast dependency resolution with `uv` (`--fast-deps`, `--uv-compile`)
|
|
70
|
+
- 🗄️ Model downloads from CivitAI, Hugging Face, and direct URLs
|
|
71
|
+
- 🎬 Run workflows against a local ComfyUI server, including auto-conversion of UI-format JSON
|
|
72
|
+
- 🧪 Test ComfyUI and frontend pull requests with one flag
|
|
73
|
+
- 💻 Cross-platform: Windows, macOS, Linux
|
|
74
74
|
|
|
75
75
|
## Installation
|
|
76
76
|
|
|
77
|
-
1. (Recommended
|
|
77
|
+
1. (Recommended) Activate a virtual environment ([venv](https://docs.python.org/3/library/venv.html) or [conda](https://conda.io/projects/conda/en/latest/user-guide/getting-started.html)).
|
|
78
78
|
|
|
79
|
-
2.
|
|
79
|
+
2. Install with `pip` (requires Python 3.10+):
|
|
80
80
|
|
|
81
|
-
|
|
81
|
+
```bash
|
|
82
|
+
pip install comfy-cli
|
|
83
|
+
```
|
|
82
84
|
|
|
83
85
|
### Shell Autocomplete
|
|
84
86
|
|
|
85
|
-
|
|
87
|
+
Install shell completion so `comfy <TAB>` expands commands and options:
|
|
86
88
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
89
|
+
```bash
|
|
90
|
+
comfy --install-completion
|
|
91
|
+
```
|
|
90
92
|
|
|
91
93
|
## Usage
|
|
92
94
|
|
|
@@ -329,6 +331,57 @@ the bisect tool can help you pinpoint the custom node that causes the issue.
|
|
|
329
331
|
|
|
330
332
|
`comfy model list ?[--relative-path <PATH>]`
|
|
331
333
|
|
|
334
|
+
### Calling partner nodes (`comfy generate`)
|
|
335
|
+
|
|
336
|
+
`comfy generate` calls Comfy's partner nodes directly from the terminal — no
|
|
337
|
+
local ComfyUI or workflow JSON required. It hits the same hosted partner nodes
|
|
338
|
+
you'd otherwise wire into a ComfyUI workflow, but as one-shot CLI calls. Image
|
|
339
|
+
models (Flux, Ideogram, DALL·E, Recraft, Stability, Runway, Reve, xAI Grok, …)
|
|
340
|
+
and video models (Kling, Luma, Runway Gen-3, Pika, Vidu, Moonvalley, Hailuo,
|
|
341
|
+
Grok video) are all covered; video jobs run async and the CLI polls until the
|
|
342
|
+
result is ready.
|
|
343
|
+
|
|
344
|
+
Prerequisites — a Comfy API key and a credit balance:
|
|
345
|
+
|
|
346
|
+
- [Create an API key](https://docs.comfy.org/development/comfyui-server/api-key-integration)
|
|
347
|
+
- [Browse partner nodes and per-call credit costs](https://docs.comfy.org/tutorials/partner-nodes/overview) · [pricing table](https://docs.comfy.org/tutorials/partner-nodes/pricing)
|
|
348
|
+
- [Add credits](https://docs.comfy.org/interface/credits)
|
|
349
|
+
|
|
350
|
+
Set the key once, then go:
|
|
351
|
+
|
|
352
|
+
```bash
|
|
353
|
+
export COMFY_API_KEY=comfyui-... # or pass --api-key on each call
|
|
354
|
+
|
|
355
|
+
comfy generate list # browse available models
|
|
356
|
+
comfy generate schema flux-pro # see params for one model
|
|
357
|
+
comfy generate flux-pro --prompt "a cat on the moon" \
|
|
358
|
+
--width 1024 --height 1024 --download cat.png
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
Reference images can be passed as local paths — the CLI uploads them through
|
|
362
|
+
the cloud's storage endpoint (or base64-encodes inline, as each partner
|
|
363
|
+
requires):
|
|
364
|
+
|
|
365
|
+
```bash
|
|
366
|
+
comfy generate flux-kontext --prompt "add a top hat" \
|
|
367
|
+
--input_image ./photo.jpg --download out.png
|
|
368
|
+
|
|
369
|
+
comfy generate upload ./photo.jpg # explicit upload
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
Async models (every video model plus the Flux family) block until ready by
|
|
373
|
+
default. Pass `--async` to return immediately with a job id, then resume later
|
|
374
|
+
with `comfy generate resume <model> <job_id>`. Examples:
|
|
375
|
+
|
|
376
|
+
```bash
|
|
377
|
+
comfy generate kling --prompt "a paper boat drifting on a river at dusk" \
|
|
378
|
+
--duration 5 --download boat.mp4
|
|
379
|
+
|
|
380
|
+
comfy generate luma --prompt "..." --aspect_ratio 16:9 --async
|
|
381
|
+
# → prints job id; resume with:
|
|
382
|
+
comfy generate resume luma <job_id> --download out.mp4
|
|
383
|
+
```
|
|
384
|
+
|
|
332
385
|
### Managing ComfyUI-Manager
|
|
333
386
|
|
|
334
387
|
- Disable ComfyUI-Manager completely (no manager flags passed to ComfyUI):
|
|
@@ -414,19 +467,19 @@ Check out the usage here: [Mixpanel Board](https://mixpanel.com/p/13hGfPfEPdRkjP
|
|
|
414
467
|
|
|
415
468
|
## Contributing
|
|
416
469
|
|
|
417
|
-
We welcome contributions to comfy-cli!
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
please fork the repository and submit a pull request.
|
|
470
|
+
We welcome contributions to comfy-cli! For ideas, suggestions, or bug reports,
|
|
471
|
+
open an issue at [Comfy-Org/comfy-cli](https://github.com/Comfy-Org/comfy-cli/issues).
|
|
472
|
+
For code changes, fork the repo and open a pull request.
|
|
421
473
|
|
|
422
|
-
|
|
474
|
+
See the [Dev Guide](/DEV_README.md) for setup details.
|
|
423
475
|
|
|
424
476
|
## License
|
|
425
477
|
|
|
426
|
-
|
|
478
|
+
Released under the [GNU General Public License v3.0](https://github.com/Comfy-Org/comfy-cli/blob/main/LICENSE).
|
|
427
479
|
|
|
428
480
|
## Support
|
|
429
481
|
|
|
430
|
-
|
|
482
|
+
Questions or issues? [Open an issue](https://github.com/Comfy-Org/comfy-cli/issues)
|
|
483
|
+
or reach us on [Discord](https://discord.com/invite/comfyorg).
|
|
431
484
|
|
|
432
485
|
Happy diffusing with ComfyUI and comfy-cli! 🎉
|
|
@@ -7,11 +7,10 @@
|
|
|
7
7
|
[](https://pypi.org/project/comfy-cli/)
|
|
8
8
|
[](https://github.com/Comfy-Org/comfy-cli/blob/main/LICENSE)
|
|
9
9
|
|
|
10
|
-
comfy-cli is a command
|
|
11
|
-
[ComfyUI](https://github.com/comfyanonymous/ComfyUI)
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
terminal.
|
|
10
|
+
comfy-cli is a command-line tool for installing, running, and extending
|
|
11
|
+
[ComfyUI](https://github.com/comfyanonymous/ComfyUI) — the open-source
|
|
12
|
+
generative-media engine. Set up ComfyUI, install custom nodes and models, run
|
|
13
|
+
workflows, and call hosted partner image models, all from your terminal.
|
|
15
14
|
|
|
16
15
|
## Demo
|
|
17
16
|
|
|
@@ -19,29 +18,32 @@ terminal.
|
|
|
19
18
|
|
|
20
19
|
## Features
|
|
21
20
|
|
|
22
|
-
- 🚀
|
|
23
|
-
-
|
|
24
|
-
- 🔧 Custom node management
|
|
25
|
-
-
|
|
26
|
-
-
|
|
27
|
-
-
|
|
28
|
-
-
|
|
21
|
+
- 🚀 One-command ComfyUI install and launch
|
|
22
|
+
- 🎨 Direct calls to partner image and video nodes (Flux, Ideogram, DALL·E, Recraft, Stability, Kling, Luma, Runway, Pika, Vidu, Hailuo, …) via `comfy generate`, no workflow JSON required
|
|
23
|
+
- 🔧 Custom node management — install, update, snapshot, bisect
|
|
24
|
+
- 📦 Fast dependency resolution with `uv` (`--fast-deps`, `--uv-compile`)
|
|
25
|
+
- 🗄️ Model downloads from CivitAI, Hugging Face, and direct URLs
|
|
26
|
+
- 🎬 Run workflows against a local ComfyUI server, including auto-conversion of UI-format JSON
|
|
27
|
+
- 🧪 Test ComfyUI and frontend pull requests with one flag
|
|
28
|
+
- 💻 Cross-platform: Windows, macOS, Linux
|
|
29
29
|
|
|
30
30
|
## Installation
|
|
31
31
|
|
|
32
|
-
1. (Recommended
|
|
32
|
+
1. (Recommended) Activate a virtual environment ([venv](https://docs.python.org/3/library/venv.html) or [conda](https://conda.io/projects/conda/en/latest/user-guide/getting-started.html)).
|
|
33
33
|
|
|
34
|
-
2.
|
|
34
|
+
2. Install with `pip` (requires Python 3.10+):
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
```bash
|
|
37
|
+
pip install comfy-cli
|
|
38
|
+
```
|
|
37
39
|
|
|
38
40
|
### Shell Autocomplete
|
|
39
41
|
|
|
40
|
-
|
|
42
|
+
Install shell completion so `comfy <TAB>` expands commands and options:
|
|
41
43
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
44
|
+
```bash
|
|
45
|
+
comfy --install-completion
|
|
46
|
+
```
|
|
45
47
|
|
|
46
48
|
## Usage
|
|
47
49
|
|
|
@@ -284,6 +286,57 @@ the bisect tool can help you pinpoint the custom node that causes the issue.
|
|
|
284
286
|
|
|
285
287
|
`comfy model list ?[--relative-path <PATH>]`
|
|
286
288
|
|
|
289
|
+
### Calling partner nodes (`comfy generate`)
|
|
290
|
+
|
|
291
|
+
`comfy generate` calls Comfy's partner nodes directly from the terminal — no
|
|
292
|
+
local ComfyUI or workflow JSON required. It hits the same hosted partner nodes
|
|
293
|
+
you'd otherwise wire into a ComfyUI workflow, but as one-shot CLI calls. Image
|
|
294
|
+
models (Flux, Ideogram, DALL·E, Recraft, Stability, Runway, Reve, xAI Grok, …)
|
|
295
|
+
and video models (Kling, Luma, Runway Gen-3, Pika, Vidu, Moonvalley, Hailuo,
|
|
296
|
+
Grok video) are all covered; video jobs run async and the CLI polls until the
|
|
297
|
+
result is ready.
|
|
298
|
+
|
|
299
|
+
Prerequisites — a Comfy API key and a credit balance:
|
|
300
|
+
|
|
301
|
+
- [Create an API key](https://docs.comfy.org/development/comfyui-server/api-key-integration)
|
|
302
|
+
- [Browse partner nodes and per-call credit costs](https://docs.comfy.org/tutorials/partner-nodes/overview) · [pricing table](https://docs.comfy.org/tutorials/partner-nodes/pricing)
|
|
303
|
+
- [Add credits](https://docs.comfy.org/interface/credits)
|
|
304
|
+
|
|
305
|
+
Set the key once, then go:
|
|
306
|
+
|
|
307
|
+
```bash
|
|
308
|
+
export COMFY_API_KEY=comfyui-... # or pass --api-key on each call
|
|
309
|
+
|
|
310
|
+
comfy generate list # browse available models
|
|
311
|
+
comfy generate schema flux-pro # see params for one model
|
|
312
|
+
comfy generate flux-pro --prompt "a cat on the moon" \
|
|
313
|
+
--width 1024 --height 1024 --download cat.png
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
Reference images can be passed as local paths — the CLI uploads them through
|
|
317
|
+
the cloud's storage endpoint (or base64-encodes inline, as each partner
|
|
318
|
+
requires):
|
|
319
|
+
|
|
320
|
+
```bash
|
|
321
|
+
comfy generate flux-kontext --prompt "add a top hat" \
|
|
322
|
+
--input_image ./photo.jpg --download out.png
|
|
323
|
+
|
|
324
|
+
comfy generate upload ./photo.jpg # explicit upload
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
Async models (every video model plus the Flux family) block until ready by
|
|
328
|
+
default. Pass `--async` to return immediately with a job id, then resume later
|
|
329
|
+
with `comfy generate resume <model> <job_id>`. Examples:
|
|
330
|
+
|
|
331
|
+
```bash
|
|
332
|
+
comfy generate kling --prompt "a paper boat drifting on a river at dusk" \
|
|
333
|
+
--duration 5 --download boat.mp4
|
|
334
|
+
|
|
335
|
+
comfy generate luma --prompt "..." --aspect_ratio 16:9 --async
|
|
336
|
+
# → prints job id; resume with:
|
|
337
|
+
comfy generate resume luma <job_id> --download out.mp4
|
|
338
|
+
```
|
|
339
|
+
|
|
287
340
|
### Managing ComfyUI-Manager
|
|
288
341
|
|
|
289
342
|
- Disable ComfyUI-Manager completely (no manager flags passed to ComfyUI):
|
|
@@ -369,19 +422,19 @@ Check out the usage here: [Mixpanel Board](https://mixpanel.com/p/13hGfPfEPdRkjP
|
|
|
369
422
|
|
|
370
423
|
## Contributing
|
|
371
424
|
|
|
372
|
-
We welcome contributions to comfy-cli!
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
please fork the repository and submit a pull request.
|
|
425
|
+
We welcome contributions to comfy-cli! For ideas, suggestions, or bug reports,
|
|
426
|
+
open an issue at [Comfy-Org/comfy-cli](https://github.com/Comfy-Org/comfy-cli/issues).
|
|
427
|
+
For code changes, fork the repo and open a pull request.
|
|
376
428
|
|
|
377
|
-
|
|
429
|
+
See the [Dev Guide](/DEV_README.md) for setup details.
|
|
378
430
|
|
|
379
431
|
## License
|
|
380
432
|
|
|
381
|
-
|
|
433
|
+
Released under the [GNU General Public License v3.0](https://github.com/Comfy-Org/comfy-cli/blob/main/LICENSE).
|
|
382
434
|
|
|
383
435
|
## Support
|
|
384
436
|
|
|
385
|
-
|
|
437
|
+
Questions or issues? [Open an issue](https://github.com/Comfy-Org/comfy-cli/issues)
|
|
438
|
+
or reach us on [Discord](https://discord.com/invite/comfyorg).
|
|
386
439
|
|
|
387
440
|
Happy diffusing with ComfyUI and comfy-cli! 🎉
|
|
@@ -11,6 +11,7 @@ from rich.console import Console
|
|
|
11
11
|
|
|
12
12
|
from comfy_cli import constants, env_checker, logging, tracking, ui, utils
|
|
13
13
|
from comfy_cli.command import code_search, custom_nodes, pr_command
|
|
14
|
+
from comfy_cli.command import generate as generate_command
|
|
14
15
|
from comfy_cli.command import install as install_inner
|
|
15
16
|
from comfy_cli.command import run as run_inner
|
|
16
17
|
from comfy_cli.command.install import validate_version
|
|
@@ -446,7 +447,23 @@ def run(
|
|
|
446
447
|
int | None,
|
|
447
448
|
typer.Option(help="The timeout in seconds for the workflow execution."),
|
|
448
449
|
] = 30,
|
|
450
|
+
api_key: Annotated[
|
|
451
|
+
str | None,
|
|
452
|
+
typer.Option(
|
|
453
|
+
"--api-key",
|
|
454
|
+
envvar="COMFY_API_KEY",
|
|
455
|
+
help=(
|
|
456
|
+
"Comfy API key for API Nodes (Partner Nodes). "
|
|
457
|
+
"Embedded in the prompt body as extra_data.api_key_comfy_org on POST /prompt. "
|
|
458
|
+
"For scripting, prefer the COMFY_API_KEY environment variable so the secret "
|
|
459
|
+
"stays out of shell history."
|
|
460
|
+
),
|
|
461
|
+
),
|
|
462
|
+
] = None,
|
|
449
463
|
):
|
|
464
|
+
if api_key:
|
|
465
|
+
api_key = api_key.strip() or None
|
|
466
|
+
|
|
450
467
|
config = ConfigManager()
|
|
451
468
|
|
|
452
469
|
if host:
|
|
@@ -470,7 +487,7 @@ def run(
|
|
|
470
487
|
if not port:
|
|
471
488
|
port = 8188
|
|
472
489
|
|
|
473
|
-
run_inner.execute(workflow, host, port, wait, verbose, local_paths, timeout)
|
|
490
|
+
run_inner.execute(workflow, host, port, wait, verbose, local_paths, timeout, api_key=api_key)
|
|
474
491
|
|
|
475
492
|
|
|
476
493
|
def validate_comfyui(_env_checker):
|
|
@@ -682,6 +699,7 @@ def standalone(
|
|
|
682
699
|
sty.to_tarball()
|
|
683
700
|
|
|
684
701
|
|
|
702
|
+
generate_command.register_with(app)
|
|
685
703
|
app.add_typer(models_command.app, name="model", help="Manage models.")
|
|
686
704
|
app.add_typer(custom_nodes.app, name="node", help="Manage custom nodes.")
|
|
687
705
|
app.add_typer(custom_nodes.manager_app, name="manager", help="Manage ComfyUI-Manager.")
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
4
|
import re
|
|
5
|
+
import sys
|
|
5
6
|
from typing import Annotated
|
|
6
7
|
from urllib.parse import quote
|
|
7
8
|
|
|
@@ -20,12 +21,19 @@ DEFAULT_COUNT = 20
|
|
|
20
21
|
REQUEST_TIMEOUT = 30
|
|
21
22
|
|
|
22
23
|
|
|
24
|
+
_TYPE_FILTER_RE = re.compile(r"(^|\s)type:")
|
|
25
|
+
|
|
26
|
+
|
|
23
27
|
def _build_query(query: str, repo: str | None, count: int) -> str:
|
|
24
28
|
parts = []
|
|
25
29
|
if repo:
|
|
26
30
|
if "/" not in repo:
|
|
27
31
|
repo = f"Comfy-Org/{repo}"
|
|
28
32
|
parts.append(f"repo:^{re.escape(repo)}$")
|
|
33
|
+
# Only default to file matches when the user hasn't specified their own
|
|
34
|
+
# type: filter — otherwise respect whatever they passed (e.g. type:commit).
|
|
35
|
+
if not _TYPE_FILTER_RE.search(query):
|
|
36
|
+
parts.append("type:file")
|
|
29
37
|
parts.append(f"count:{count}")
|
|
30
38
|
parts.append(query)
|
|
31
39
|
return " ".join(parts)
|
|
@@ -56,20 +64,21 @@ def _format_results(search: dict) -> list[dict]:
|
|
|
56
64
|
commit_hash = (default_branch.get("target") or {}).get("commit", {}).get("oid", "")
|
|
57
65
|
ref = commit_hash or branch_name
|
|
58
66
|
|
|
67
|
+
encoded_path = quote(file_path, safe="/")
|
|
68
|
+
file_url = f"https://github.com/{clean_name}/blob/{ref}/{encoded_path}"
|
|
69
|
+
|
|
59
70
|
line_matches = result.get("lineMatches") or []
|
|
60
71
|
matches = []
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
line = m.get("lineNumber", 0) + 1
|
|
66
|
-
preview = m.get("preview", "").rstrip()
|
|
67
|
-
matches.append({"line": line, "preview": preview, "url": f"{base_url}#L{line}"})
|
|
72
|
+
for m in line_matches:
|
|
73
|
+
line = m.get("lineNumber", 0) + 1
|
|
74
|
+
preview = m.get("preview", "").rstrip()
|
|
75
|
+
matches.append({"line": line, "preview": preview, "url": f"{file_url}#L{line}"})
|
|
68
76
|
|
|
69
77
|
formatted.append(
|
|
70
78
|
{
|
|
71
79
|
"repository": clean_name,
|
|
72
80
|
"file": file_path,
|
|
81
|
+
"file_url": file_url,
|
|
73
82
|
"branch": branch_name,
|
|
74
83
|
"commit": commit_hash,
|
|
75
84
|
"matches": matches,
|
|
@@ -96,19 +105,34 @@ def _print_results(results: list[dict], stats: dict, json_output: bool) -> None:
|
|
|
96
105
|
console.print("[yellow]No results found.[/yellow]")
|
|
97
106
|
return
|
|
98
107
|
|
|
108
|
+
# Use raw isatty() rather than Rich's console.is_terminal: Rich treats
|
|
109
|
+
# FORCE_COLOR=1 / TTY_COMPATIBLE=1 as terminal-capable even when stdout
|
|
110
|
+
# is redirected, but OSC 8 escapes in a piped stream defeat the whole
|
|
111
|
+
# point of this branch (hiding URLs from humans, exposing them to AI).
|
|
112
|
+
is_tty = sys.stdout.isatty()
|
|
113
|
+
|
|
99
114
|
for file_result in results:
|
|
115
|
+
repo = file_result["repository"]
|
|
116
|
+
path = file_result["file"]
|
|
117
|
+
file_url = file_result["file_url"]
|
|
118
|
+
|
|
100
119
|
header = Text()
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
120
|
+
if is_tty:
|
|
121
|
+
# Humans: clickable OSC 8 hyperlink, URL hidden from visible output.
|
|
122
|
+
header.append(f"{repo} / {path}", style=f"bold cyan link {file_url}")
|
|
123
|
+
else:
|
|
124
|
+
# Non-TTY (pipes, AI agents): print the raw URL once per file so
|
|
125
|
+
# agents can synthesize #L<line> anchors themselves.
|
|
126
|
+
header.append(f"{repo} / {path}\n")
|
|
127
|
+
header.append(f" {file_url}", style="dim")
|
|
104
128
|
console.print(header)
|
|
105
129
|
|
|
106
130
|
for match in file_result["matches"]:
|
|
107
|
-
line_text = Text()
|
|
108
|
-
|
|
131
|
+
line_text = Text(" ")
|
|
132
|
+
line_style = f"green link {match['url']}" if is_tty else "green"
|
|
133
|
+
line_text.append(f"L{match['line']:>5}", style=line_style)
|
|
109
134
|
line_text.append(f" {match['preview']}")
|
|
110
135
|
console.print(line_text)
|
|
111
|
-
console.print(f" [dim]{match['url']}[/dim]")
|
|
112
136
|
|
|
113
137
|
console.print()
|
|
114
138
|
|
|
@@ -121,7 +145,15 @@ def _print_results(results: list[dict], stats: dict, json_output: bool) -> None:
|
|
|
121
145
|
@app.callback(invoke_without_command=True)
|
|
122
146
|
@tracking.track_command()
|
|
123
147
|
def code_search(
|
|
124
|
-
query: Annotated[
|
|
148
|
+
query: Annotated[
|
|
149
|
+
str,
|
|
150
|
+
typer.Argument(
|
|
151
|
+
help=(
|
|
152
|
+
"Search query (supports Sourcegraph syntax). Defaults to file matches; "
|
|
153
|
+
"pass your own `type:` filter (e.g. `type:commit`) to override."
|
|
154
|
+
),
|
|
155
|
+
),
|
|
156
|
+
],
|
|
125
157
|
repo: Annotated[
|
|
126
158
|
str | None,
|
|
127
159
|
typer.Option("--repo", "-r", help="Filter by repository (e.g. ComfyUI, Comfy-Org/ComfyUI)"),
|
|
@@ -975,6 +975,17 @@ def validate_node_for_publishing():
|
|
|
975
975
|
# Perform some validation logic here
|
|
976
976
|
typer.echo("Validating node configuration...")
|
|
977
977
|
config = extract_node_configuration()
|
|
978
|
+
if config is None:
|
|
979
|
+
raise typer.Exit(code=1)
|
|
980
|
+
|
|
981
|
+
if not config.project.version:
|
|
982
|
+
# Escape `[` chars so rich doesn't parse `[tool.comfy.version]` and
|
|
983
|
+
# `["version"]` as markup tags; `]` doesn't need escaping.
|
|
984
|
+
print(
|
|
985
|
+
"[red]Error: project version is empty. Set `project.version` in pyproject.toml, "
|
|
986
|
+
r'or configure `\[tool.comfy.version].path` if using `dynamic = \["version"]`.[/red]'
|
|
987
|
+
)
|
|
988
|
+
raise typer.Exit(code=1)
|
|
978
989
|
|
|
979
990
|
# Run security checks first
|
|
980
991
|
typer.echo("Running security checks...")
|