runninghub-cli 0.1.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.
@@ -0,0 +1,290 @@
1
+ # RunningHub CLI (`rh`) — AI Handoff Document
2
+
3
+ > **For:** Next AI agent or developer taking over this project
4
+ > **Written by:** Claude (claude-opus-4-5) after completing initial implementation + live API validation
5
+ > **Date:** 2026-04-12
6
+ > **Status:** v0.1.0 — fully working, all smoke tests passed
7
+
8
+ ---
9
+
10
+ ## 1. What Was Built and Why
11
+
12
+ `rh` is an agent-native CLI for [RunningHub](https://www.runninghub.cn) — a cloud ComfyUI platform.
13
+
14
+ **Origin:** Two existing projects existed but were not usable by AI agents:
15
+ - `OpenClaw_RH_Skills/` — Python scripts covering 209 standard model endpoints, written as a conversational persona tool (OpenClaw), not a CLI
16
+ - `RunningHub-AI-Client/` — React/TypeScript/Tauri desktop GUI with clean `services/api.ts` layer
17
+
18
+ This CLI distils both into a single `rh` command following CLI-Anything methodology: every command prints JSON to stdout, errors go to stderr with exit code 1.
19
+
20
+ ---
21
+
22
+ ## 2. Critical Architecture: Two Completely Separate API Systems
23
+
24
+ > **This is the most important thing to understand.** The two API systems have different auth, different upload endpoints, different response shapes, and different polling protocols. They cannot be mixed.
25
+
26
+ ### System A — Standard Model API
27
+
28
+ | Property | Value |
29
+ |----------|-------|
30
+ | Purpose | 209 pre-built model endpoints (image/video/audio/3D) |
31
+ | Base URL | `https://www.runninghub.cn/openapi/v2` |
32
+ | Auth | `Authorization: Bearer <apiKey>` header |
33
+ | Run endpoint | `POST /openapi/v2/{model}/{task}` |
34
+ | Poll endpoint | `POST /openapi/v2/query` with body `{"taskId":"..."}` |
35
+ | Poll response | `{"taskId":"..","status":"SUCCESS|FAILED|QUEUED|RUNNING","results":[...],"errorCode":"","errorMessage":""}` |
36
+ | Upload endpoint | `POST /openapi/v2/media/upload/binary` (multipart, Bearer auth) |
37
+ | Upload returns | `{"code":0,"data":{"download_url":"https://cdn..."}}` |
38
+ | Key type required | **SHARED / enterprise key only** (NORMAL keys return code=1014) |
39
+ | Key field in poll | Bearer header |
40
+
41
+ **IMPORTANT:** Standard model run response is NOT a `{"code":0,"data":{}}` envelope. It directly returns `{"taskId":"..","errorCode":"..","errorMessage":"..","results":null}`. The `errorCode` field signals errors (non-empty and non-"0" = error).
42
+
43
+ ### System B — AI Apps API
44
+
45
+ | Property | Value |
46
+ |----------|-------|
47
+ | Purpose | Custom ComfyUI workflow apps (user-created) |
48
+ | Auth | `apiKey` field **inside the JSON body** (no Authorization header) |
49
+ | Run endpoint | `POST /task/openapi/ai-app/run` with `{"webappId":"..","apiKey":"..","nodeInfoList":[...]}` |
50
+ | Poll endpoint | `POST /task/openapi/outputs` with body `{"apiKey":"..","taskId":"..."}` |
51
+ | Poll response | `{"code":804,...}` = running; `{"code":0,"data":[{fileUrl,fileType},...]}` = done |
52
+ | Upload endpoint | `POST /task/openapi/upload` (multipart, `apiKey` + `fileType` in form fields) |
53
+ | Upload returns | `{"code":0,"data":{"fileName":"abc.png"}}` — use `fileName` as fieldValue |
54
+ | Key type required | Works with NORMAL key |
55
+ | App list | `POST /api/webapp/list` (no auth, public catalog) |
56
+ | App info | `GET /api/webapp/apiCallDemo?apiKey=...&webappId=...` |
57
+
58
+ **IMPORTANT:** AI Apps poll `data` is a **list** directly, not `{"outputs":[...]}`. `code=804` means still running; loop until `code=0`.
59
+
60
+ ---
61
+
62
+ ## 3. Project Structure
63
+
64
+ ```
65
+ runninghub-cli/
66
+ ├── rh/
67
+ │ ├── __init__.py # version = "0.1.0"
68
+ │ ├── cli.py # Click entry point, registers 4 command groups
69
+ │ ├── client.py # ALL HTTP logic — the most critical file
70
+ │ ├── catalog.py # Loads data/capabilities.json; unwraps {"endpoints":[...]} wrapper
71
+ │ ├── output.py # JSON stdout + stderr progress dots
72
+ │ └── commands/
73
+ │ ├── account.py # rh account status
74
+ │ ├── model.py # rh model list/info/run/auto
75
+ │ ├── app.py # rh app list/info/run/batch
76
+ │ └── task.py # rh task status/outputs
77
+ ├── data/
78
+ │ └── capabilities.json # 209 endpoints, shape: {"endpoints":[...],"total":209,"version":"..."}
79
+ ├── tests/
80
+ │ ├── test_catalog.py # 8 tests
81
+ │ └── test_cli.py # 9 tests — 17 total, all passing
82
+ ├── setup.py # entry_points: rh=rh.cli:main
83
+ ├── SKILL.md # Agent discovery — command reference and JSON schemas
84
+ └── HANDOFF.md # ← this file
85
+ ```
86
+
87
+ ---
88
+
89
+ ## 4. Key Implementation Details in `client.py`
90
+
91
+ ### API Key Resolution (priority order)
92
+ ```python
93
+ def _resolve_api_key(api_key=None):
94
+ 1. explicit --api-key argument
95
+ 2. RH_API_KEY environment variable ← recommended
96
+ 3. ~/.rh/config.json → {"apiKey": "..."}
97
+ → raises RunningHubError("auth_missing", ...) if none found
98
+ ```
99
+
100
+ ### File Upload Logic
101
+ Two separate upload functions — **never mix them**:
102
+ - `_upload_file_for_model(api_key, path)` → Standard API → returns CDN `download_url` (https://...)
103
+ - `_upload_file_for_app(api_key, path)` → AI Apps API → returns `fileName` (short string)
104
+
105
+ For standard model, small images can be base64-encoded inline (`data:image/png;base64,...`).
106
+ Videos and files ≥5 MB are always uploaded to CDN first (threshold: `FILE_UPLOAD_THRESHOLD_MB = 5`).
107
+
108
+ ### `_resolve_key()` — The `--image` → `imageUrls` Problem
109
+ CLI accepts `--image`, `--video`, `--audio` as convenience flags, but the actual endpoint schema parameter key may be `imageUrls`, `imageUrl`, `videoInput`, etc.
110
+
111
+ The function in `run_model()` builds a `media_type_to_key` map from the catalog schema and remaps CLI names to actual keys:
112
+ ```python
113
+ # Example: endpoint uses {"key":"imageUrls","type":"IMAGE","multiple":true}
114
+ # CLI: --image photo.jpg → resolves to {"imageUrls": ["https://cdn.../photo.jpg"]}
115
+ ```
116
+ Also handles `multiple: true` params by wrapping single values in a list.
117
+
118
+ ### Polling Timeouts
119
+ - `MAX_POLL_SECONDS = 1200` (20 minutes)
120
+ - `POLL_INTERVAL = 5` seconds
121
+ - Both pollers tolerate up to 5 consecutive HTTP errors before giving up
122
+
123
+ ---
124
+
125
+ ## 5. `capabilities.json` — Catalog Format
126
+
127
+ ```json
128
+ {
129
+ "endpoints": [
130
+ {
131
+ "endpoint": "rhart-image-n-pro/text-to-image",
132
+ "name_cn": "...",
133
+ "name_en": "...",
134
+ "task": "text-to-image",
135
+ "output_type": "image",
136
+ "popularity": 1,
137
+ "tags": ["official"],
138
+ "params": [
139
+ {"key": "prompt", "type": "STRING", "required": true},
140
+ {"key": "imageUrls", "type": "IMAGE", "required": false, "multiple": true, "maxSizeMB": 10},
141
+ {"key": "aspectRatio", "type": "LIST", "required": false, "options": ["1:1","16:9"], "default": "1:1"}
142
+ ]
143
+ }
144
+ ],
145
+ "total": 209,
146
+ "version": "..."
147
+ }
148
+ ```
149
+
150
+ `catalog.py` must unwrap the `{"endpoints":[...]}` wrapper — do NOT pass the raw dict to list functions.
151
+
152
+ ---
153
+
154
+ ## 6. Known Catalog Validity Issues
155
+
156
+ **Not all 209 catalog entries are live.** Some return `code=1001 "Invalid URL"` from the API.
157
+
158
+ Confirmed WORKING endpoints (tested 2026-04-12):
159
+ - `rhart-image-n-pro/text-to-image` ✅
160
+ - `rhart-video-v3.1-fast/text-to-video` ✅ (103s, SHARED key)
161
+ - `rhart-video-v3.1-fast/image-to-video` ✅ (129s, SHARED key)
162
+ - `rhart-video-v3.1-fast-official/video-extend` ✅ (119s, SHARED key, "video-to-video")
163
+ - AI Apps (any `webappId` from `rh app list`) ✅ (NORMAL key works)
164
+
165
+ Confirmed BROKEN endpoints:
166
+ - `rhart-video-s/text-to-video` → code=1001 "Invalid URL"
167
+
168
+ When an endpoint returns 1001, try the next endpoint for the same task type (`rh model list --task <X>` and pick one with low popularity number).
169
+
170
+ ---
171
+
172
+ ## 7. Live Test Results Summary
173
+
174
+ | Test | Mode | Key Type | Result | Time |
175
+ |------|------|----------|--------|------|
176
+ | `rh account status` | Standard | NORMAL | ✅ coins balance | <1s |
177
+ | `rh app list` | AI Apps | — | ✅ 20 apps | <1s |
178
+ | `rh app run` (全能图片2.0) | AI Apps | NORMAL | ✅ `test_robot_cat.png` | ~30s |
179
+ | `rh model run rhart-video-v3.1-fast/text-to-video` | Standard | SHARED | ✅ `test_t2v.mp4` | 103s |
180
+ | `rh model run rhart-video-v3.1-fast/image-to-video` | Standard | SHARED | ✅ `test_i2v.mp4` | 129s |
181
+ | `rh model run rhart-video-v3.1-fast-official/video-extend` | Standard | SHARED | ✅ `test_v2v.mp4` | 119s |
182
+ | `pytest tests/` | — | — | ✅ 17/17 | 0.03s |
183
+
184
+ ---
185
+
186
+ ## 8. API Response Field Mapping Gotchas
187
+
188
+ These field names differ from what you might assume — all were discovered by live testing:
189
+
190
+ | Context | Expected | Actual |
191
+ |---------|----------|--------|
192
+ | App list record ID | `webappId` | `id` |
193
+ | App list record name | `webappName` | `name` |
194
+ | App list description | `description` | `intro` |
195
+ | App info node list | `nodeList` or `nodes` | `nodeInfoList` |
196
+ | App info English desc | `description` | `descriptionEn` |
197
+ | Standard model error | `code`, `message` | `errorCode`, `errorMessage` |
198
+ | Standard model results | `data.outputs` | `results` (top-level array) |
199
+ | AI Apps outputs | `data.outputs` | `data` is the list itself |
200
+ | Standard upload URL | `/task/openapi/upload` | `/openapi/v2/media/upload/binary` |
201
+
202
+ ---
203
+
204
+ ## 9. Security
205
+
206
+ - **Zero API keys hardcoded** anywhere in `rh/` source code
207
+ - Keys only come from: env var `RH_API_KEY`, `--api-key` flag, or `~/.rh/config.json`
208
+ - `.claude/settings.local.json` was cleaned after testing — now uses wildcard rules only
209
+
210
+ **For new environments:**
211
+ ```bash
212
+ # Option A — env var (recommended)
213
+ export RH_API_KEY=your_key_here
214
+
215
+ # Option B — config file
216
+ mkdir -p ~/.rh && echo '{"apiKey":"your_key_here"}' > ~/.rh/config.json
217
+ ```
218
+
219
+ ---
220
+
221
+ ## 10. Installation
222
+
223
+ ```bash
224
+ cd runninghub-cli
225
+ pip install -e . # dev install, editable
226
+ # OR
227
+ pip install . # production install
228
+
229
+ rh --help # verify
230
+ ```
231
+
232
+ Requires Python ≥ 3.8. Only external dependency: `click>=8.0`.
233
+
234
+ ---
235
+
236
+ ## 11. Running Tests
237
+
238
+ ```bash
239
+ cd runninghub-cli
240
+ python -m pytest tests/ -q
241
+ # Expected: 17 passed in ~0.03s (no network calls, all mocked/unit)
242
+ ```
243
+
244
+ ---
245
+
246
+ ## 12. Suggested Next Steps
247
+
248
+ ### High Priority
249
+ 1. **`rh model auto` endpoint validation** — `auto` picks by popularity rank, but some top-ranked endpoints return 1001. Add live probe/fallback: try the endpoint, if 1001 try next one in ranked list.
250
+ 2. **`~/.rh/config.json` init command** — `rh config set-key YOUR_KEY` to avoid users manually writing JSON.
251
+ 3. **`rh model list` live filter** — currently filters only from catalog (static). Add `--live` flag that probes each endpoint with a dry run.
252
+
253
+ ### Medium Priority
254
+ 4. **Streaming progress** — currently just prints dots to stderr. A `--progress` flag with JSON-lines progress events would help agents track long video jobs.
255
+ 5. **Batch mode for `rh model`** — `rh model batch` analogous to `rh app batch`, for running the same model on many inputs from CSV.
256
+ 6. **Update capabilities.json** — the catalog is a static snapshot. A `rh catalog update` command could fetch the live list from RunningHub and regenerate it.
257
+
258
+ ### Low Priority
259
+ 7. **Windows path handling** — tested on Windows; `Path()` objects work, but `~/.rh/` resolves to `C:\Users\<user>\.rh\`. Works correctly.
260
+ 8. **Async polling** — currently blocking. For batch use, `asyncio` would allow concurrent polls.
261
+ 9. **`rh app batch` CSV encoding** — currently assumes UTF-8. Add `--encoding` flag.
262
+
263
+ ---
264
+
265
+ ## 13. Important URLs
266
+
267
+ | Resource | URL |
268
+ |----------|-----|
269
+ | RunningHub platform | https://www.runninghub.cn |
270
+ | API key page | https://www.runninghub.cn/enterprise-api/sharedApi |
271
+ | Official API docs | https://www.runninghub.cn/runninghub-api-doc-cn/ |
272
+ | Pricing | https://www.runninghub.cn/third-party-fees |
273
+ | Membership tiers | https://www.runninghub.cn/vip-rights/2 |
274
+ | API Reference (agent-readable) | `../RUNNINGHUB_API_REFERENCE.md` (in parent dir) |
275
+
276
+ ---
277
+
278
+ ## 14. Key Type Reference
279
+
280
+ | API | NORMAL key | SHARED/enterprise key |
281
+ |-----|-----------|----------------------|
282
+ | AI Apps (`rh app *`) | ✅ works | ✅ works |
283
+ | Standard Models (`rh model *`) | ❌ code=1014 | ✅ required |
284
+ | Account status (`rh account *`) | ✅ works | ✅ works |
285
+
286
+ To get a SHARED key: RunningHub enterprise plan → https://www.runninghub.cn/enterprise-api/sharedApi
287
+
288
+ ---
289
+
290
+ *End of handoff. The codebase is clean, tested, and ready for Git push.*
@@ -0,0 +1,3 @@
1
+ include SKILL.md
2
+ include HANDOFF.md
3
+ include data/capabilities.json
@@ -0,0 +1,219 @@
1
+ Metadata-Version: 2.4
2
+ Name: runninghub-cli
3
+ Version: 0.1.0
4
+ Summary: Agent-native CLI for RunningHub AI platform (image/video/audio/3D generation)
5
+ Home-page: https://cnb.cool/101ya/runninghub-cli
6
+ Author: 101ya
7
+ License: MIT
8
+ Keywords: runninghub ai image video generation comfyui cli agent
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.8
14
+ Classifier: Programming Language :: Python :: 3.9
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Topic :: Multimedia :: Graphics
19
+ Classifier: Topic :: Multimedia :: Sound/Audio
20
+ Classifier: Topic :: Multimedia :: Video
21
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
22
+ Requires-Python: >=3.8
23
+ Description-Content-Type: text/markdown
24
+ Requires-Dist: click>=8.0
25
+ Dynamic: author
26
+ Dynamic: classifier
27
+ Dynamic: description
28
+ Dynamic: description-content-type
29
+ Dynamic: home-page
30
+ Dynamic: keywords
31
+ Dynamic: license
32
+ Dynamic: requires-dist
33
+ Dynamic: requires-python
34
+ Dynamic: summary
35
+
36
+ # RunningHub CLI (`rh`) — Agent Skill
37
+
38
+ ## What This Tool Does
39
+
40
+ `rh` is a command-line interface for the [RunningHub AI platform](https://www.runninghub.cn) — a cloud ComfyUI service with 209+ built-in AI model endpoints and support for custom ComfyUI workflow apps.
41
+
42
+ Use `rh` to:
43
+ - Generate images, videos, audio, and 3D models from text/image prompts
44
+ - Browse and run custom ComfyUI AI App workflows
45
+ - Check task status and download outputs
46
+ - Monitor account balance
47
+
48
+ ## Setup
49
+
50
+ ```bash
51
+ export RH_API_KEY=your_runninghub_api_key
52
+ ```
53
+
54
+ Or pass `--api-key KEY` to any command.
55
+
56
+ Get a key at: https://www.runninghub.cn/enterprise-api/sharedApi
57
+
58
+ ## Command Reference
59
+
60
+ ### Account
61
+
62
+ ```bash
63
+ rh account status
64
+ # → {"remainCoins": "150.0", "currentTaskCounts": "0", "apiType": "coins"}
65
+ ```
66
+
67
+ ### Built-in Models (`rh model`)
68
+
69
+ For quick AI generation using RunningHub's 209 pre-built models.
70
+
71
+ ```bash
72
+ # List available models
73
+ rh model list --type image
74
+ rh model list --task text-to-image --top 5
75
+ rh model list --type video
76
+
77
+ # Get parameter schema for an endpoint
78
+ rh model info rhart-image-n-pro/text-to-image
79
+
80
+ # Auto-select best model for a task (recommended for agents)
81
+ rh model auto --task text-to-image --prompt "a sunset over mountains" --output out.png
82
+ rh model auto --task image-to-video --image input.jpg --output out.mp4
83
+ rh model auto --task text-to-speech --prompt "Hello world" --output out.mp3
84
+ rh model auto --task text-to-3d --prompt "a ceramic teapot" --output model.glb
85
+
86
+ # Run a specific endpoint
87
+ rh model run rhart-image-n-pro/text-to-image --prompt "anime cat" --output cat.png
88
+ rh model run kling-video-o3-pro/image-to-video --image photo.jpg --output video.mp4
89
+ ```
90
+
91
+ **Available task types:**
92
+ - `text-to-image`, `image-to-image`, `image-upscale`
93
+ - `text-to-video`, `image-to-video`, `reference-to-video`, `start-end-to-video`
94
+ - `text-to-speech`, `music-generation`, `voice-clone`
95
+ - `text-to-3d`, `image-to-3d`, `multi-image-to-3d`
96
+
97
+ ### Custom AI Apps (`rh app`)
98
+
99
+ For custom ComfyUI workflows. Each app has a `webappId` and modifiable input nodes.
100
+
101
+ ```bash
102
+ # Browse public apps
103
+ rh app list --search "anime portrait" --sort RECOMMEND
104
+ rh app list --sort HOTTEST --size 10
105
+
106
+ # Inspect an app's input schema before running
107
+ rh app info 1234567890
108
+ # → {"webappId": "...", "name": "...", "nodes": [{"nodeId": "6", "fieldName": "prompt", "fieldType": "STRING", ...}]}
109
+
110
+ # Run an app
111
+ rh app run 1234567890 \
112
+ --node "6:prompt=a samurai cat warrior" \
113
+ --output result.mp4
114
+
115
+ # Run with a file input
116
+ rh app run 1234567890 \
117
+ --node "6:prompt=enhance this portrait" \
118
+ --file "10:image=/path/to/photo.jpg" \
119
+ --output enhanced.png
120
+
121
+ # Batch run from CSV
122
+ rh app batch 1234567890 --input params.csv --concurrency 3 --output-dir ./results/
123
+ ```
124
+
125
+ **Batch CSV format:**
126
+ ```csv
127
+ 6:prompt,10:image
128
+ "a ninja dog",/path/to/dog.jpg
129
+ "a robot cat",/path/to/cat.jpg
130
+ ```
131
+
132
+ ### Task Management
133
+
134
+ ```bash
135
+ # Check status of a task
136
+ rh task status abc123
137
+
138
+ # Get outputs for a completed task
139
+ rh task outputs abc123 --output result.png
140
+ ```
141
+
142
+ ## JSON Output Schema
143
+
144
+ All commands output JSON. Agents should parse stdout directly.
145
+
146
+ **`rh model auto` / `rh model run` success:**
147
+ ```json
148
+ {
149
+ "taskId": "abc123",
150
+ "status": "SUCCESS",
151
+ "outputs": [{"fileUrl": "https://cdn.runninghub.cn/...", "fileType": "image/png"}],
152
+ "cost": {"duration_s": 8},
153
+ "savedTo": "/path/to/out.png",
154
+ "selectedEndpoint": "rhart-image-n-pro/text-to-image"
155
+ }
156
+ ```
157
+
158
+ **`rh app run` success:**
159
+ ```json
160
+ {
161
+ "taskId": "xyz789",
162
+ "status": "SUCCESS",
163
+ "outputs": [{"fileUrl": "https://...", "fileType": "video/mp4"}],
164
+ "savedTo": "/path/to/result.mp4"
165
+ }
166
+ ```
167
+
168
+ **Errors (exit code 1):**
169
+ ```json
170
+ {"error": "auth_failed", "message": "Invalid API key or unauthorized"}
171
+ {"error": "insufficient_balance", "message": "Account balance is 0"}
172
+ {"error": "task_failed", "message": "Task failed: ..."}
173
+ {"error": "timeout", "message": "Task exceeded 20 minute timeout"}
174
+ ```
175
+
176
+ ## Typical Agent Workflows
177
+
178
+ ### 1. Generate an image
179
+
180
+ ```bash
181
+ rh model auto --task text-to-image --prompt "a photorealistic sunset over the ocean" --output sunset.png
182
+ ```
183
+
184
+ ### 2. Generate a video from an image
185
+
186
+ ```bash
187
+ rh model auto --task image-to-video --image portrait.jpg --output animation.mp4
188
+ ```
189
+
190
+ ### 3. Discover and run a custom ComfyUI app
191
+
192
+ ```bash
193
+ # Step 1: find apps
194
+ rh app list --search "anime portrait" --size 5
195
+
196
+ # Step 2: check the app's inputs
197
+ rh app info <webappId>
198
+
199
+ # Step 3: run it
200
+ rh app run <webappId> --node "6:prompt=anime warrior" --file "10:image=photo.jpg" --output result.png
201
+ ```
202
+
203
+ ### 4. Check balance before running
204
+
205
+ ```bash
206
+ rh account status | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['remainCoins'])"
207
+ ```
208
+
209
+ ## Error Handling
210
+
211
+ - All errors produce JSON with an `error` key and exit code 1
212
+ - Progress is written to **stderr** (polling dots); final JSON is on **stdout**
213
+ - Separate stderr from stdout: `rh model auto ... 2>/dev/null`
214
+
215
+ ## Notes
216
+
217
+ - Tasks may take 5 seconds to 20 minutes depending on the model
218
+ - Video generation is slower than image generation
219
+ - The `--instance plus` flag (for `rh app run`) uses premium compute
@@ -0,0 +1,184 @@
1
+ # RunningHub CLI (`rh`) — Agent Skill
2
+
3
+ ## What This Tool Does
4
+
5
+ `rh` is a command-line interface for the [RunningHub AI platform](https://www.runninghub.cn) — a cloud ComfyUI service with 209+ built-in AI model endpoints and support for custom ComfyUI workflow apps.
6
+
7
+ Use `rh` to:
8
+ - Generate images, videos, audio, and 3D models from text/image prompts
9
+ - Browse and run custom ComfyUI AI App workflows
10
+ - Check task status and download outputs
11
+ - Monitor account balance
12
+
13
+ ## Setup
14
+
15
+ ```bash
16
+ export RH_API_KEY=your_runninghub_api_key
17
+ ```
18
+
19
+ Or pass `--api-key KEY` to any command.
20
+
21
+ Get a key at: https://www.runninghub.cn/enterprise-api/sharedApi
22
+
23
+ ## Command Reference
24
+
25
+ ### Account
26
+
27
+ ```bash
28
+ rh account status
29
+ # → {"remainCoins": "150.0", "currentTaskCounts": "0", "apiType": "coins"}
30
+ ```
31
+
32
+ ### Built-in Models (`rh model`)
33
+
34
+ For quick AI generation using RunningHub's 209 pre-built models.
35
+
36
+ ```bash
37
+ # List available models
38
+ rh model list --type image
39
+ rh model list --task text-to-image --top 5
40
+ rh model list --type video
41
+
42
+ # Get parameter schema for an endpoint
43
+ rh model info rhart-image-n-pro/text-to-image
44
+
45
+ # Auto-select best model for a task (recommended for agents)
46
+ rh model auto --task text-to-image --prompt "a sunset over mountains" --output out.png
47
+ rh model auto --task image-to-video --image input.jpg --output out.mp4
48
+ rh model auto --task text-to-speech --prompt "Hello world" --output out.mp3
49
+ rh model auto --task text-to-3d --prompt "a ceramic teapot" --output model.glb
50
+
51
+ # Run a specific endpoint
52
+ rh model run rhart-image-n-pro/text-to-image --prompt "anime cat" --output cat.png
53
+ rh model run kling-video-o3-pro/image-to-video --image photo.jpg --output video.mp4
54
+ ```
55
+
56
+ **Available task types:**
57
+ - `text-to-image`, `image-to-image`, `image-upscale`
58
+ - `text-to-video`, `image-to-video`, `reference-to-video`, `start-end-to-video`
59
+ - `text-to-speech`, `music-generation`, `voice-clone`
60
+ - `text-to-3d`, `image-to-3d`, `multi-image-to-3d`
61
+
62
+ ### Custom AI Apps (`rh app`)
63
+
64
+ For custom ComfyUI workflows. Each app has a `webappId` and modifiable input nodes.
65
+
66
+ ```bash
67
+ # Browse public apps
68
+ rh app list --search "anime portrait" --sort RECOMMEND
69
+ rh app list --sort HOTTEST --size 10
70
+
71
+ # Inspect an app's input schema before running
72
+ rh app info 1234567890
73
+ # → {"webappId": "...", "name": "...", "nodes": [{"nodeId": "6", "fieldName": "prompt", "fieldType": "STRING", ...}]}
74
+
75
+ # Run an app
76
+ rh app run 1234567890 \
77
+ --node "6:prompt=a samurai cat warrior" \
78
+ --output result.mp4
79
+
80
+ # Run with a file input
81
+ rh app run 1234567890 \
82
+ --node "6:prompt=enhance this portrait" \
83
+ --file "10:image=/path/to/photo.jpg" \
84
+ --output enhanced.png
85
+
86
+ # Batch run from CSV
87
+ rh app batch 1234567890 --input params.csv --concurrency 3 --output-dir ./results/
88
+ ```
89
+
90
+ **Batch CSV format:**
91
+ ```csv
92
+ 6:prompt,10:image
93
+ "a ninja dog",/path/to/dog.jpg
94
+ "a robot cat",/path/to/cat.jpg
95
+ ```
96
+
97
+ ### Task Management
98
+
99
+ ```bash
100
+ # Check status of a task
101
+ rh task status abc123
102
+
103
+ # Get outputs for a completed task
104
+ rh task outputs abc123 --output result.png
105
+ ```
106
+
107
+ ## JSON Output Schema
108
+
109
+ All commands output JSON. Agents should parse stdout directly.
110
+
111
+ **`rh model auto` / `rh model run` success:**
112
+ ```json
113
+ {
114
+ "taskId": "abc123",
115
+ "status": "SUCCESS",
116
+ "outputs": [{"fileUrl": "https://cdn.runninghub.cn/...", "fileType": "image/png"}],
117
+ "cost": {"duration_s": 8},
118
+ "savedTo": "/path/to/out.png",
119
+ "selectedEndpoint": "rhart-image-n-pro/text-to-image"
120
+ }
121
+ ```
122
+
123
+ **`rh app run` success:**
124
+ ```json
125
+ {
126
+ "taskId": "xyz789",
127
+ "status": "SUCCESS",
128
+ "outputs": [{"fileUrl": "https://...", "fileType": "video/mp4"}],
129
+ "savedTo": "/path/to/result.mp4"
130
+ }
131
+ ```
132
+
133
+ **Errors (exit code 1):**
134
+ ```json
135
+ {"error": "auth_failed", "message": "Invalid API key or unauthorized"}
136
+ {"error": "insufficient_balance", "message": "Account balance is 0"}
137
+ {"error": "task_failed", "message": "Task failed: ..."}
138
+ {"error": "timeout", "message": "Task exceeded 20 minute timeout"}
139
+ ```
140
+
141
+ ## Typical Agent Workflows
142
+
143
+ ### 1. Generate an image
144
+
145
+ ```bash
146
+ rh model auto --task text-to-image --prompt "a photorealistic sunset over the ocean" --output sunset.png
147
+ ```
148
+
149
+ ### 2. Generate a video from an image
150
+
151
+ ```bash
152
+ rh model auto --task image-to-video --image portrait.jpg --output animation.mp4
153
+ ```
154
+
155
+ ### 3. Discover and run a custom ComfyUI app
156
+
157
+ ```bash
158
+ # Step 1: find apps
159
+ rh app list --search "anime portrait" --size 5
160
+
161
+ # Step 2: check the app's inputs
162
+ rh app info <webappId>
163
+
164
+ # Step 3: run it
165
+ rh app run <webappId> --node "6:prompt=anime warrior" --file "10:image=photo.jpg" --output result.png
166
+ ```
167
+
168
+ ### 4. Check balance before running
169
+
170
+ ```bash
171
+ rh account status | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['remainCoins'])"
172
+ ```
173
+
174
+ ## Error Handling
175
+
176
+ - All errors produce JSON with an `error` key and exit code 1
177
+ - Progress is written to **stderr** (polling dots); final JSON is on **stdout**
178
+ - Separate stderr from stdout: `rh model auto ... 2>/dev/null`
179
+
180
+ ## Notes
181
+
182
+ - Tasks may take 5 seconds to 20 minutes depending on the model
183
+ - Video generation is slower than image generation
184
+ - The `--instance plus` flag (for `rh app run`) uses premium compute