@bgicli/bgicli 2.2.8 → 2.2.10

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 (113) hide show
  1. package/data/skills/anthropic-algorithmic-art/SKILL.md +405 -0
  2. package/data/skills/anthropic-canvas-design/SKILL.md +130 -0
  3. package/data/skills/anthropic-claude-api/SKILL.md +243 -0
  4. package/data/skills/anthropic-doc-coauthoring/SKILL.md +375 -0
  5. package/data/skills/anthropic-docx/SKILL.md +590 -0
  6. package/data/skills/anthropic-frontend-design/SKILL.md +42 -0
  7. package/data/skills/anthropic-internal-comms/SKILL.md +32 -0
  8. package/data/skills/anthropic-mcp-builder/SKILL.md +236 -0
  9. package/data/skills/anthropic-pdf/SKILL.md +314 -0
  10. package/data/skills/anthropic-pptx/SKILL.md +232 -0
  11. package/data/skills/anthropic-skill-creator/SKILL.md +485 -0
  12. package/data/skills/anthropic-webapp-testing/SKILL.md +96 -0
  13. package/data/skills/anthropic-xlsx/SKILL.md +292 -0
  14. package/data/skills/arxiv-database/SKILL.md +362 -0
  15. package/data/skills/astropy/SKILL.md +329 -0
  16. package/data/skills/ctx-advanced-evaluation/SKILL.md +402 -0
  17. package/data/skills/ctx-bdi-mental-states/SKILL.md +311 -0
  18. package/data/skills/ctx-context-compression/SKILL.md +272 -0
  19. package/data/skills/ctx-context-degradation/SKILL.md +206 -0
  20. package/data/skills/ctx-context-fundamentals/SKILL.md +201 -0
  21. package/data/skills/ctx-context-optimization/SKILL.md +195 -0
  22. package/data/skills/ctx-evaluation/SKILL.md +251 -0
  23. package/data/skills/ctx-filesystem-context/SKILL.md +287 -0
  24. package/data/skills/ctx-hosted-agents/SKILL.md +260 -0
  25. package/data/skills/ctx-memory-systems/SKILL.md +225 -0
  26. package/data/skills/ctx-multi-agent-patterns/SKILL.md +257 -0
  27. package/data/skills/ctx-project-development/SKILL.md +291 -0
  28. package/data/skills/ctx-tool-design/SKILL.md +271 -0
  29. package/data/skills/dhdna-profiler/SKILL.md +162 -0
  30. package/data/skills/generate-image/SKILL.md +183 -0
  31. package/data/skills/geomaster/SKILL.md +365 -0
  32. package/data/skills/get-available-resources/SKILL.md +275 -0
  33. package/data/skills/hamelsmu-build-review-interface/SKILL.md +96 -0
  34. package/data/skills/hamelsmu-error-analysis/SKILL.md +164 -0
  35. package/data/skills/hamelsmu-eval-audit/SKILL.md +183 -0
  36. package/data/skills/hamelsmu-evaluate-rag/SKILL.md +177 -0
  37. package/data/skills/hamelsmu-generate-synthetic-data/SKILL.md +131 -0
  38. package/data/skills/hamelsmu-validate-evaluator/SKILL.md +212 -0
  39. package/data/skills/hamelsmu-write-judge-prompt/SKILL.md +144 -0
  40. package/data/skills/hf-cli/SKILL.md +174 -0
  41. package/data/skills/hf-mcp/SKILL.md +178 -0
  42. package/data/skills/hugging-face-dataset-viewer/SKILL.md +121 -0
  43. package/data/skills/hugging-face-datasets/SKILL.md +542 -0
  44. package/data/skills/hugging-face-evaluation/SKILL.md +651 -0
  45. package/data/skills/hugging-face-jobs/SKILL.md +1042 -0
  46. package/data/skills/hugging-face-model-trainer/SKILL.md +717 -0
  47. package/data/skills/hugging-face-paper-pages/SKILL.md +239 -0
  48. package/data/skills/hugging-face-paper-publisher/SKILL.md +624 -0
  49. package/data/skills/hugging-face-tool-builder/SKILL.md +110 -0
  50. package/data/skills/hugging-face-trackio/SKILL.md +115 -0
  51. package/data/skills/hugging-face-vision-trainer/SKILL.md +593 -0
  52. package/data/skills/huggingface-gradio/SKILL.md +245 -0
  53. package/data/skills/matlab/SKILL.md +376 -0
  54. package/data/skills/modal/SKILL.md +381 -0
  55. package/data/skills/openai-cloudflare-deploy/SKILL.md +224 -0
  56. package/data/skills/openai-develop-web-game/SKILL.md +149 -0
  57. package/data/skills/openai-doc/SKILL.md +80 -0
  58. package/data/skills/openai-figma/SKILL.md +42 -0
  59. package/data/skills/openai-figma-implement-design/SKILL.md +264 -0
  60. package/data/skills/openai-gh-address-comments/SKILL.md +25 -0
  61. package/data/skills/openai-gh-fix-ci/SKILL.md +69 -0
  62. package/data/skills/openai-imagegen/SKILL.md +174 -0
  63. package/data/skills/openai-jupyter-notebook/SKILL.md +107 -0
  64. package/data/skills/openai-linear/SKILL.md +87 -0
  65. package/data/skills/openai-netlify-deploy/SKILL.md +247 -0
  66. package/data/skills/openai-notion-knowledge-capture/SKILL.md +56 -0
  67. package/data/skills/openai-notion-meeting-intelligence/SKILL.md +60 -0
  68. package/data/skills/openai-notion-research-documentation/SKILL.md +59 -0
  69. package/data/skills/openai-notion-spec-to-implementation/SKILL.md +58 -0
  70. package/data/skills/openai-openai-docs/SKILL.md +69 -0
  71. package/data/skills/openai-pdf/SKILL.md +67 -0
  72. package/data/skills/openai-playwright/SKILL.md +147 -0
  73. package/data/skills/openai-render-deploy/SKILL.md +479 -0
  74. package/data/skills/openai-screenshot/SKILL.md +267 -0
  75. package/data/skills/openai-security-best-practices/SKILL.md +86 -0
  76. package/data/skills/openai-security-ownership-map/SKILL.md +206 -0
  77. package/data/skills/openai-security-threat-model/SKILL.md +81 -0
  78. package/data/skills/openai-sentry/SKILL.md +123 -0
  79. package/data/skills/openai-sora/SKILL.md +178 -0
  80. package/data/skills/openai-speech/SKILL.md +144 -0
  81. package/data/skills/openai-spreadsheet/SKILL.md +145 -0
  82. package/data/skills/openai-transcribe/SKILL.md +81 -0
  83. package/data/skills/openai-vercel-deploy/SKILL.md +77 -0
  84. package/data/skills/openai-yeet/SKILL.md +28 -0
  85. package/data/skills/pennylane/SKILL.md +224 -0
  86. package/data/skills/polars-bio/SKILL.md +374 -0
  87. package/data/skills/primekg/SKILL.md +97 -0
  88. package/data/skills/pymatgen/SKILL.md +689 -0
  89. package/data/skills/qiskit/SKILL.md +273 -0
  90. package/data/skills/qutip/SKILL.md +316 -0
  91. package/data/skills/recursive-decomposition/SKILL.md +185 -0
  92. package/data/skills/rowan/SKILL.md +427 -0
  93. package/data/skills/scholar-evaluation/SKILL.md +298 -0
  94. package/data/skills/sentry-create-alert/SKILL.md +210 -0
  95. package/data/skills/sentry-fix-issues/SKILL.md +126 -0
  96. package/data/skills/sentry-pr-code-review/SKILL.md +105 -0
  97. package/data/skills/sentry-python-sdk/SKILL.md +317 -0
  98. package/data/skills/sentry-setup-ai-monitoring/SKILL.md +217 -0
  99. package/data/skills/stable-baselines3/SKILL.md +297 -0
  100. package/data/skills/sympy/SKILL.md +498 -0
  101. package/data/skills/trailofbits-ask-questions-if-underspecified/SKILL.md +85 -0
  102. package/data/skills/trailofbits-audit-context-building/SKILL.md +302 -0
  103. package/data/skills/trailofbits-differential-review/SKILL.md +220 -0
  104. package/data/skills/trailofbits-insecure-defaults/SKILL.md +117 -0
  105. package/data/skills/trailofbits-modern-python/SKILL.md +333 -0
  106. package/data/skills/trailofbits-property-based-testing/SKILL.md +123 -0
  107. package/data/skills/trailofbits-semgrep-rule-creator/SKILL.md +172 -0
  108. package/data/skills/trailofbits-sharp-edges/SKILL.md +292 -0
  109. package/data/skills/trailofbits-variant-analysis/SKILL.md +142 -0
  110. package/data/skills/transformers.js/SKILL.md +637 -0
  111. package/data/skills/writing/SKILL.md +419 -0
  112. package/dist/bgi.js +66 -2
  113. package/package.json +1 -1
@@ -0,0 +1,1042 @@
1
+ ---
2
+ name: hugging-face-jobs
3
+ description: This skill should be used when users want to run any workload on Hugging Face Jobs infrastructure. Covers UV scripts, Docker-based jobs, hardware selection, cost estimation, authentication with tokens, secrets management, timeout configuration, and result persistence. Designed for general-purpose compute workloads including data processing, inference, experiments, batch jobs, and any Python-based tasks. Should be invoked for tasks involving cloud compute, GPU workloads, or when users mention running jobs on Hugging Face infrastructure without local setup.
4
+ license: Complete terms in LICENSE.txt
5
+ ---
6
+
7
+ # Running Workloads on Hugging Face Jobs
8
+
9
+ ## Overview
10
+
11
+ Run any workload on fully managed Hugging Face infrastructure. No local setup required—jobs run on cloud CPUs, GPUs, or TPUs and can persist results to the Hugging Face Hub.
12
+
13
+ **Common use cases:**
14
+ - **Data Processing** - Transform, filter, or analyze large datasets
15
+ - **Batch Inference** - Run inference on thousands of samples
16
+ - **Experiments & Benchmarks** - Reproducible ML experiments
17
+ - **Model Training** - Fine-tune models (see `model-trainer` skill for TRL-specific training)
18
+ - **Synthetic Data Generation** - Generate datasets using LLMs
19
+ - **Development & Testing** - Test code without local GPU setup
20
+ - **Scheduled Jobs** - Automate recurring tasks
21
+
22
+ **For model training specifically:** See the `model-trainer` skill for TRL-based training workflows.
23
+
24
+ ## When to Use This Skill
25
+
26
+ Use this skill when users want to:
27
+ - Run Python workloads on cloud infrastructure
28
+ - Execute jobs without local GPU/TPU setup
29
+ - Process data at scale
30
+ - Run batch inference or experiments
31
+ - Schedule recurring tasks
32
+ - Use GPUs/TPUs for any workload
33
+ - Persist results to the Hugging Face Hub
34
+
35
+ ## Key Directives
36
+
37
+ When assisting with jobs:
38
+
39
+ 1. **ALWAYS use `hf_jobs()` MCP tool** - Submit jobs using `hf_jobs("uv", {...})` or `hf_jobs("run", {...})`. The `script` parameter accepts Python code directly. Do NOT save to local files unless the user explicitly requests it. Pass the script content as a string to `hf_jobs()`.
40
+
41
+ 2. **Always handle authentication** - Jobs that interact with the Hub require `HF_TOKEN` via secrets. See Token Usage section below.
42
+
43
+ 3. **Provide job details after submission** - After submitting, provide job ID, monitoring URL, estimated time, and note that the user can request status checks later.
44
+
45
+ 4. **Set appropriate timeouts** - Default 30min may be insufficient for long-running tasks.
46
+
47
+ ## Prerequisites Checklist
48
+
49
+ Before starting any job, verify:
50
+
51
+ ### ✅ **Account & Authentication**
52
+ - Hugging Face Account with [Pro](https://hf.co/pro), [Team](https://hf.co/enterprise), or [Enterprise](https://hf.co/enterprise) plan (Jobs require paid plan)
53
+ - Authenticated login: Check with `hf_whoami()`
54
+ - **HF_TOKEN for Hub Access** ⚠️ CRITICAL - Required for any Hub operations (push models/datasets, download private repos, etc.)
55
+ - Token must have appropriate permissions (read for downloads, write for uploads)
56
+
57
+ ### ✅ **Token Usage** (See Token Usage section for details)
58
+
59
+ **When tokens are required:**
60
+ - Pushing models/datasets to Hub
61
+ - Accessing private repositories
62
+ - Using Hub APIs in scripts
63
+ - Any authenticated Hub operations
64
+
65
+ **How to provide tokens:**
66
+ ```python
67
+ # hf_jobs MCP tool — $HF_TOKEN is auto-replaced with real token:
68
+ {"secrets": {"HF_TOKEN": "$HF_TOKEN"}}
69
+
70
+ # HfApi().run_uv_job() — MUST pass actual token:
71
+ from huggingface_hub import get_token
72
+ secrets={"HF_TOKEN": get_token()}
73
+ ```
74
+
75
+ **⚠️ CRITICAL:** The `$HF_TOKEN` placeholder is ONLY auto-replaced by the `hf_jobs` MCP tool. When using `HfApi().run_uv_job()`, you MUST pass the real token via `get_token()`. Passing the literal string `"$HF_TOKEN"` results in a 9-character invalid token and 401 errors.
76
+
77
+ ## Token Usage Guide
78
+
79
+ ### Understanding Tokens
80
+
81
+ **What are HF Tokens?**
82
+ - Authentication credentials for Hugging Face Hub
83
+ - Required for authenticated operations (push, private repos, API access)
84
+ - Stored securely on your machine after `hf auth login`
85
+
86
+ **Token Types:**
87
+ - **Read Token** - Can download models/datasets, read private repos
88
+ - **Write Token** - Can push models/datasets, create repos, modify content
89
+ - **Organization Token** - Can act on behalf of an organization
90
+
91
+ ### When Tokens Are Required
92
+
93
+ **Always Required:**
94
+ - Pushing models/datasets to Hub
95
+ - Accessing private repositories
96
+ - Creating new repositories
97
+ - Modifying existing repositories
98
+ - Using Hub APIs programmatically
99
+
100
+ **Not Required:**
101
+ - Downloading public models/datasets
102
+ - Running jobs that don't interact with Hub
103
+ - Reading public repository information
104
+
105
+ ### How to Provide Tokens to Jobs
106
+
107
+ #### Method 1: Automatic Token (Recommended)
108
+
109
+ ```python
110
+ hf_jobs("uv", {
111
+ "script": "your_script.py",
112
+ "secrets": {"HF_TOKEN": "$HF_TOKEN"} # ✅ Automatic replacement
113
+ })
114
+ ```
115
+
116
+ **How it works:**
117
+ - `$HF_TOKEN` is a placeholder that gets replaced with your actual token
118
+ - Uses the token from your logged-in session (`hf auth login`)
119
+ - Most secure and convenient method
120
+ - Token is encrypted server-side when passed as a secret
121
+
122
+ **Benefits:**
123
+ - No token exposure in code
124
+ - Uses your current login session
125
+ - Automatically updated if you re-login
126
+ - Works seamlessly with MCP tools
127
+
128
+ #### Method 2: Explicit Token (Not Recommended)
129
+
130
+ ```python
131
+ hf_jobs("uv", {
132
+ "script": "your_script.py",
133
+ "secrets": {"HF_TOKEN": "hf_abc123..."} # ⚠️ Hardcoded token
134
+ })
135
+ ```
136
+
137
+ **When to use:**
138
+ - Only if automatic token doesn't work
139
+ - Testing with a specific token
140
+ - Organization tokens (use with caution)
141
+
142
+ **Security concerns:**
143
+ - Token visible in code/logs
144
+ - Must manually update if token rotates
145
+ - Risk of token exposure
146
+
147
+ #### Method 3: Environment Variable (Less Secure)
148
+
149
+ ```python
150
+ hf_jobs("uv", {
151
+ "script": "your_script.py",
152
+ "env": {"HF_TOKEN": "hf_abc123..."} # ⚠️ Less secure than secrets
153
+ })
154
+ ```
155
+
156
+ **Difference from secrets:**
157
+ - `env` variables are visible in job logs
158
+ - `secrets` are encrypted server-side
159
+ - Always prefer `secrets` for tokens
160
+
161
+ ### Using Tokens in Scripts
162
+
163
+ **In your Python script, tokens are available as environment variables:**
164
+
165
+ ```python
166
+ # /// script
167
+ # dependencies = ["huggingface-hub"]
168
+ # ///
169
+
170
+ import os
171
+ from huggingface_hub import HfApi
172
+
173
+ # Token is automatically available if passed via secrets
174
+ token = os.environ.get("HF_TOKEN")
175
+
176
+ # Use with Hub API
177
+ api = HfApi(token=token)
178
+
179
+ # Or let huggingface_hub auto-detect
180
+ api = HfApi() # Automatically uses HF_TOKEN env var
181
+ ```
182
+
183
+ **Best practices:**
184
+ - Don't hardcode tokens in scripts
185
+ - Use `os.environ.get("HF_TOKEN")` to access
186
+ - Let `huggingface_hub` auto-detect when possible
187
+ - Verify token exists before Hub operations
188
+
189
+ ### Token Verification
190
+
191
+ **Check if you're logged in:**
192
+ ```python
193
+ from huggingface_hub import whoami
194
+ user_info = whoami() # Returns your username if authenticated
195
+ ```
196
+
197
+ **Verify token in job:**
198
+ ```python
199
+ import os
200
+ assert "HF_TOKEN" in os.environ, "HF_TOKEN not found!"
201
+ token = os.environ["HF_TOKEN"]
202
+ print(f"Token starts with: {token[:7]}...") # Should start with "hf_"
203
+ ```
204
+
205
+ ### Common Token Issues
206
+
207
+ **Error: 401 Unauthorized**
208
+ - **Cause:** Token missing or invalid
209
+ - **Fix:** Add `secrets={"HF_TOKEN": "$HF_TOKEN"}` to job config
210
+ - **Verify:** Check `hf_whoami()` works locally
211
+
212
+ **Error: 403 Forbidden**
213
+ - **Cause:** Token lacks required permissions
214
+ - **Fix:** Ensure token has write permissions for push operations
215
+ - **Check:** Token type at https://huggingface.co/settings/tokens
216
+
217
+ **Error: Token not found in environment**
218
+ - **Cause:** `secrets` not passed or wrong key name
219
+ - **Fix:** Use `secrets={"HF_TOKEN": "$HF_TOKEN"}` (not `env`)
220
+ - **Verify:** Script checks `os.environ.get("HF_TOKEN")`
221
+
222
+ **Error: Repository access denied**
223
+ - **Cause:** Token doesn't have access to private repo
224
+ - **Fix:** Use token from account with access
225
+ - **Check:** Verify repo visibility and your permissions
226
+
227
+ ### Token Security Best Practices
228
+
229
+ 1. **Never commit tokens** - Use `$HF_TOKEN` placeholder or environment variables
230
+ 2. **Use secrets, not env** - Secrets are encrypted server-side
231
+ 3. **Rotate tokens regularly** - Generate new tokens periodically
232
+ 4. **Use minimal permissions** - Create tokens with only needed permissions
233
+ 5. **Don't share tokens** - Each user should use their own token
234
+ 6. **Monitor token usage** - Check token activity in Hub settings
235
+
236
+ ### Complete Token Example
237
+
238
+ ```python
239
+ # Example: Push results to Hub
240
+ hf_jobs("uv", {
241
+ "script": """
242
+ # /// script
243
+ # dependencies = ["huggingface-hub", "datasets"]
244
+ # ///
245
+
246
+ import os
247
+ from huggingface_hub import HfApi
248
+ from datasets import Dataset
249
+
250
+ # Verify token is available
251
+ assert "HF_TOKEN" in os.environ, "HF_TOKEN required!"
252
+
253
+ # Use token for Hub operations
254
+ api = HfApi(token=os.environ["HF_TOKEN"])
255
+
256
+ # Create and push dataset
257
+ data = {"text": ["Hello", "World"]}
258
+ dataset = Dataset.from_dict(data)
259
+ dataset.push_to_hub("username/my-dataset", token=os.environ["HF_TOKEN"])
260
+
261
+ print("✅ Dataset pushed successfully!")
262
+ """,
263
+ "flavor": "cpu-basic",
264
+ "timeout": "30m",
265
+ "secrets": {"HF_TOKEN": "$HF_TOKEN"} # ✅ Token provided securely
266
+ })
267
+ ```
268
+
269
+ ## Quick Start: Two Approaches
270
+
271
+ ### Approach 1: UV Scripts (Recommended)
272
+
273
+ UV scripts use PEP 723 inline dependencies for clean, self-contained workloads.
274
+
275
+ **MCP Tool:**
276
+ ```python
277
+ hf_jobs("uv", {
278
+ "script": """
279
+ # /// script
280
+ # dependencies = ["transformers", "torch"]
281
+ # ///
282
+
283
+ from transformers import pipeline
284
+ import torch
285
+
286
+ # Your workload here
287
+ classifier = pipeline("sentiment-analysis")
288
+ result = classifier("I love Hugging Face!")
289
+ print(result)
290
+ """,
291
+ "flavor": "cpu-basic",
292
+ "timeout": "30m"
293
+ })
294
+ ```
295
+
296
+ **CLI Equivalent:**
297
+ ```bash
298
+ hf jobs uv run my_script.py --flavor cpu-basic --timeout 30m
299
+ ```
300
+
301
+ **Python API:**
302
+ ```python
303
+ from huggingface_hub import run_uv_job
304
+ run_uv_job("my_script.py", flavor="cpu-basic", timeout="30m")
305
+ ```
306
+
307
+ **Benefits:** Direct MCP tool usage, clean code, dependencies declared inline, no file saving required
308
+
309
+ **When to use:** Default choice for all workloads, custom logic, any scenario requiring `hf_jobs()`
310
+
311
+ #### Custom Docker Images for UV Scripts
312
+
313
+ By default, UV scripts use `ghcr.io/astral-sh/uv:python3.12-bookworm-slim`. For ML workloads with complex dependencies, use pre-built images:
314
+
315
+ ```python
316
+ hf_jobs("uv", {
317
+ "script": "inference.py",
318
+ "image": "vllm/vllm-openai:latest", # Pre-built image with vLLM
319
+ "flavor": "a10g-large"
320
+ })
321
+ ```
322
+
323
+ **CLI:**
324
+ ```bash
325
+ hf jobs uv run --image vllm/vllm-openai:latest --flavor a10g-large inference.py
326
+ ```
327
+
328
+ **Benefits:** Faster startup, pre-installed dependencies, optimized for specific frameworks
329
+
330
+ #### Python Version
331
+
332
+ By default, UV scripts use Python 3.12. Specify a different version:
333
+
334
+ ```python
335
+ hf_jobs("uv", {
336
+ "script": "my_script.py",
337
+ "python": "3.11", # Use Python 3.11
338
+ "flavor": "cpu-basic"
339
+ })
340
+ ```
341
+
342
+ **Python API:**
343
+ ```python
344
+ from huggingface_hub import run_uv_job
345
+ run_uv_job("my_script.py", python="3.11")
346
+ ```
347
+
348
+ #### Working with Scripts
349
+
350
+ ⚠️ **Important:** There are *two* "script path" stories depending on how you run Jobs:
351
+
352
+ - **Using the `hf_jobs()` MCP tool (recommended in this repo)**: the `script` value must be **inline code** (a string) or a **URL**. A local filesystem path (like `"./scripts/foo.py"`) won't exist inside the remote container.
353
+ - **Using the `hf jobs uv run` CLI**: local file paths **do work** (the CLI uploads your script).
354
+
355
+ **Common mistake with `hf_jobs()` MCP tool:**
356
+
357
+ ```python
358
+ # ❌ Will fail (remote container can't see your local path)
359
+ hf_jobs("uv", {"script": "./scripts/foo.py"})
360
+ ```
361
+
362
+ **Correct patterns with `hf_jobs()` MCP tool:**
363
+
364
+ ```python
365
+ # ✅ Inline: read the local script file and pass its *contents*
366
+ from pathlib import Path
367
+ script = Path("hf-jobs/scripts/foo.py").read_text()
368
+ hf_jobs("uv", {"script": script})
369
+
370
+ # ✅ URL: host the script somewhere reachable
371
+ hf_jobs("uv", {"script": "https://huggingface.co/datasets/uv-scripts/.../raw/main/foo.py"})
372
+
373
+ # ✅ URL from GitHub
374
+ hf_jobs("uv", {"script": "https://raw.githubusercontent.com/huggingface/trl/main/trl/scripts/sft.py"})
375
+ ```
376
+
377
+ **CLI equivalent (local paths supported):**
378
+
379
+ ```bash
380
+ hf jobs uv run ./scripts/foo.py -- --your --args
381
+ ```
382
+
383
+ #### Adding Dependencies at Runtime
384
+
385
+ Add extra dependencies beyond what's in the PEP 723 header:
386
+
387
+ ```python
388
+ hf_jobs("uv", {
389
+ "script": "inference.py",
390
+ "dependencies": ["transformers", "torch>=2.0"], # Extra deps
391
+ "flavor": "a10g-small"
392
+ })
393
+ ```
394
+
395
+ **Python API:**
396
+ ```python
397
+ from huggingface_hub import run_uv_job
398
+ run_uv_job("inference.py", dependencies=["transformers", "torch>=2.0"])
399
+ ```
400
+
401
+ ### Approach 2: Docker-Based Jobs
402
+
403
+ Run jobs with custom Docker images and commands.
404
+
405
+ **MCP Tool:**
406
+ ```python
407
+ hf_jobs("run", {
408
+ "image": "python:3.12",
409
+ "command": ["python", "-c", "print('Hello from HF Jobs!')"],
410
+ "flavor": "cpu-basic",
411
+ "timeout": "30m"
412
+ })
413
+ ```
414
+
415
+ **CLI Equivalent:**
416
+ ```bash
417
+ hf jobs run python:3.12 python -c "print('Hello from HF Jobs!')"
418
+ ```
419
+
420
+ **Python API:**
421
+ ```python
422
+ from huggingface_hub import run_job
423
+ run_job(image="python:3.12", command=["python", "-c", "print('Hello!')"], flavor="cpu-basic")
424
+ ```
425
+
426
+ **Benefits:** Full Docker control, use pre-built images, run any command
427
+ **When to use:** Need specific Docker images, non-Python workloads, complex environments
428
+
429
+ **Example with GPU:**
430
+ ```python
431
+ hf_jobs("run", {
432
+ "image": "pytorch/pytorch:2.6.0-cuda12.4-cudnn9-devel",
433
+ "command": ["python", "-c", "import torch; print(torch.cuda.get_device_name())"],
434
+ "flavor": "a10g-small",
435
+ "timeout": "1h"
436
+ })
437
+ ```
438
+
439
+ **Using Hugging Face Spaces as Images:**
440
+
441
+ You can use Docker images from HF Spaces:
442
+ ```python
443
+ hf_jobs("run", {
444
+ "image": "hf.co/spaces/lhoestq/duckdb", # Space as Docker image
445
+ "command": ["duckdb", "-c", "SELECT 'Hello from DuckDB!'"],
446
+ "flavor": "cpu-basic"
447
+ })
448
+ ```
449
+
450
+ **CLI:**
451
+ ```bash
452
+ hf jobs run hf.co/spaces/lhoestq/duckdb duckdb -c "SELECT 'Hello!'"
453
+ ```
454
+
455
+ ### Finding More UV Scripts on Hub
456
+
457
+ The `uv-scripts` organization provides ready-to-use UV scripts stored as datasets on Hugging Face Hub:
458
+
459
+ ```python
460
+ # Discover available UV script collections
461
+ dataset_search({"author": "uv-scripts", "sort": "downloads", "limit": 20})
462
+
463
+ # Explore a specific collection
464
+ hub_repo_details(["uv-scripts/classification"], repo_type="dataset", include_readme=True)
465
+ ```
466
+
467
+ **Popular collections:** OCR, classification, synthetic-data, vLLM, dataset-creation
468
+
469
+ ## Hardware Selection
470
+
471
+ > **Reference:** [HF Jobs Hardware Docs](https://huggingface.co/docs/hub/en/spaces-config-reference) (updated 07/2025)
472
+
473
+ | Workload Type | Recommended Hardware | Use Case |
474
+ |---------------|---------------------|----------|
475
+ | Data processing, testing | `cpu-basic`, `cpu-upgrade` | Lightweight tasks |
476
+ | Small models, demos | `t4-small` | <1B models, quick tests |
477
+ | Medium models | `t4-medium`, `l4x1` | 1-7B models |
478
+ | Large models, production | `a10g-small`, `a10g-large` | 7-13B models |
479
+ | Very large models | `a100-large` | 13B+ models |
480
+ | Batch inference | `a10g-large`, `a100-large` | High-throughput |
481
+ | Multi-GPU workloads | `l4x4`, `a10g-largex2`, `a10g-largex4` | Parallel/large models |
482
+ | TPU workloads | `v5e-1x1`, `v5e-2x2`, `v5e-2x4` | JAX/Flax, TPU-optimized |
483
+
484
+ **All Available Flavors:**
485
+ - **CPU:** `cpu-basic`, `cpu-upgrade`
486
+ - **GPU:** `t4-small`, `t4-medium`, `l4x1`, `l4x4`, `a10g-small`, `a10g-large`, `a10g-largex2`, `a10g-largex4`, `a100-large`
487
+ - **TPU:** `v5e-1x1`, `v5e-2x2`, `v5e-2x4`
488
+
489
+ **Guidelines:**
490
+ - Start with smaller hardware for testing
491
+ - Scale up based on actual needs
492
+ - Use multi-GPU for parallel workloads or large models
493
+ - Use TPUs for JAX/Flax workloads
494
+ - See `references/hardware_guide.md` for detailed specifications
495
+
496
+ ## Critical: Saving Results
497
+
498
+ **⚠️ EPHEMERAL ENVIRONMENT—MUST PERSIST RESULTS**
499
+
500
+ The Jobs environment is temporary. All files are deleted when the job ends. If results aren't persisted, **ALL WORK IS LOST**.
501
+
502
+ ### Persistence Options
503
+
504
+ **1. Push to Hugging Face Hub (Recommended)**
505
+
506
+ ```python
507
+ # Push models
508
+ model.push_to_hub("username/model-name", token=os.environ["HF_TOKEN"])
509
+
510
+ # Push datasets
511
+ dataset.push_to_hub("username/dataset-name", token=os.environ["HF_TOKEN"])
512
+
513
+ # Push artifacts
514
+ api.upload_file(
515
+ path_or_fileobj="results.json",
516
+ path_in_repo="results.json",
517
+ repo_id="username/results",
518
+ token=os.environ["HF_TOKEN"]
519
+ )
520
+ ```
521
+
522
+ **2. Use External Storage**
523
+
524
+ ```python
525
+ # Upload to S3, GCS, etc.
526
+ import boto3
527
+ s3 = boto3.client('s3')
528
+ s3.upload_file('results.json', 'my-bucket', 'results.json')
529
+ ```
530
+
531
+ **3. Send Results via API**
532
+
533
+ ```python
534
+ # POST results to your API
535
+ import requests
536
+ requests.post("https://your-api.com/results", json=results)
537
+ ```
538
+
539
+ ### Required Configuration for Hub Push
540
+
541
+ **In job submission:**
542
+ ```python
543
+ # hf_jobs MCP tool:
544
+ {"secrets": {"HF_TOKEN": "$HF_TOKEN"}} # auto-replaced
545
+
546
+ # HfApi().run_uv_job():
547
+ from huggingface_hub import get_token
548
+ secrets={"HF_TOKEN": get_token()} # must pass real token
549
+ ```
550
+
551
+ **In script:**
552
+ ```python
553
+ import os
554
+ from huggingface_hub import HfApi
555
+
556
+ # Token automatically available from secrets
557
+ api = HfApi(token=os.environ.get("HF_TOKEN"))
558
+
559
+ # Push your results
560
+ api.upload_file(...)
561
+ ```
562
+
563
+ ### Verification Checklist
564
+
565
+ Before submitting:
566
+ - [ ] Results persistence method chosen
567
+ - [ ] Token in secrets if using Hub (MCP: `"$HF_TOKEN"`, Python API: `get_token()`)
568
+ - [ ] Script handles missing token gracefully
569
+ - [ ] Test persistence path works
570
+
571
+ **See:** `references/hub_saving.md` for detailed Hub persistence guide
572
+
573
+ ## Timeout Management
574
+
575
+ **⚠️ DEFAULT: 30 MINUTES**
576
+
577
+ Jobs automatically stop after the timeout. For long-running tasks like training, always set a custom timeout.
578
+
579
+ ### Setting Timeouts
580
+
581
+ **MCP Tool:**
582
+ ```python
583
+ {
584
+ "timeout": "2h" # 2 hours
585
+ }
586
+ ```
587
+
588
+ **Supported formats:**
589
+ - Integer/float: seconds (e.g., `300` = 5 minutes)
590
+ - String with suffix: `"5m"` (minutes), `"2h"` (hours), `"1d"` (days)
591
+ - Examples: `"90m"`, `"2h"`, `"1.5h"`, `300`, `"1d"`
592
+
593
+ **Python API:**
594
+ ```python
595
+ from huggingface_hub import run_job, run_uv_job
596
+
597
+ run_job(image="python:3.12", command=[...], timeout="2h")
598
+ run_uv_job("script.py", timeout=7200) # 2 hours in seconds
599
+ ```
600
+
601
+ ### Timeout Guidelines
602
+
603
+ | Scenario | Recommended | Notes |
604
+ |----------|-------------|-------|
605
+ | Quick test | 10-30 min | Verify setup |
606
+ | Data processing | 1-2 hours | Depends on data size |
607
+ | Batch inference | 2-4 hours | Large batches |
608
+ | Experiments | 4-8 hours | Multiple runs |
609
+ | Long-running | 8-24 hours | Production workloads |
610
+
611
+ **Always add 20-30% buffer** for setup, network delays, and cleanup.
612
+
613
+ **On timeout:** Job killed immediately, all unsaved progress lost
614
+
615
+ ## Cost Estimation
616
+
617
+ **General guidelines:**
618
+
619
+ ```
620
+ Total Cost = (Hours of runtime) × (Cost per hour)
621
+ ```
622
+
623
+ **Example calculations:**
624
+
625
+ **Quick test:**
626
+ - Hardware: cpu-basic ($0.10/hour)
627
+ - Time: 15 minutes (0.25 hours)
628
+ - Cost: $0.03
629
+
630
+ **Data processing:**
631
+ - Hardware: l4x1 ($2.50/hour)
632
+ - Time: 2 hours
633
+ - Cost: $5.00
634
+
635
+ **Batch inference:**
636
+ - Hardware: a10g-large ($5/hour)
637
+ - Time: 4 hours
638
+ - Cost: $20.00
639
+
640
+ **Cost optimization tips:**
641
+ 1. Start small - Test on cpu-basic or t4-small
642
+ 2. Monitor runtime - Set appropriate timeouts
643
+ 3. Use checkpoints - Resume if job fails
644
+ 4. Optimize code - Reduce unnecessary compute
645
+ 5. Choose right hardware - Don't over-provision
646
+
647
+ ## Monitoring and Tracking
648
+
649
+ ### Check Job Status
650
+
651
+ **MCP Tool:**
652
+ ```python
653
+ # List all jobs
654
+ hf_jobs("ps")
655
+
656
+ # Inspect specific job
657
+ hf_jobs("inspect", {"job_id": "your-job-id"})
658
+
659
+ # View logs
660
+ hf_jobs("logs", {"job_id": "your-job-id"})
661
+
662
+ # Cancel a job
663
+ hf_jobs("cancel", {"job_id": "your-job-id"})
664
+ ```
665
+
666
+ **Python API:**
667
+ ```python
668
+ from huggingface_hub import list_jobs, inspect_job, fetch_job_logs, cancel_job
669
+
670
+ # List your jobs
671
+ jobs = list_jobs()
672
+
673
+ # List running jobs only
674
+ running = [j for j in list_jobs() if j.status.stage == "RUNNING"]
675
+
676
+ # Inspect specific job
677
+ job_info = inspect_job(job_id="your-job-id")
678
+
679
+ # View logs
680
+ for log in fetch_job_logs(job_id="your-job-id"):
681
+ print(log)
682
+
683
+ # Cancel a job
684
+ cancel_job(job_id="your-job-id")
685
+ ```
686
+
687
+ **CLI:**
688
+ ```bash
689
+ hf jobs ps # List jobs
690
+ hf jobs logs <job-id> # View logs
691
+ hf jobs cancel <job-id> # Cancel job
692
+ ```
693
+
694
+ **Remember:** Wait for user to request status checks. Avoid polling repeatedly.
695
+
696
+ ### Job URLs
697
+
698
+ After submission, jobs have monitoring URLs:
699
+ ```
700
+ https://huggingface.co/jobs/username/job-id
701
+ ```
702
+
703
+ View logs, status, and details in the browser.
704
+
705
+ ### Wait for Multiple Jobs
706
+
707
+ ```python
708
+ import time
709
+ from huggingface_hub import inspect_job, run_job
710
+
711
+ # Run multiple jobs
712
+ jobs = [run_job(image=img, command=cmd) for img, cmd in workloads]
713
+
714
+ # Wait for all to complete
715
+ for job in jobs:
716
+ while inspect_job(job_id=job.id).status.stage not in ("COMPLETED", "ERROR"):
717
+ time.sleep(10)
718
+ ```
719
+
720
+ ## Scheduled Jobs
721
+
722
+ Run jobs on a schedule using CRON expressions or predefined schedules.
723
+
724
+ **MCP Tool:**
725
+ ```python
726
+ # Schedule a UV script that runs every hour
727
+ hf_jobs("scheduled uv", {
728
+ "script": "your_script.py",
729
+ "schedule": "@hourly",
730
+ "flavor": "cpu-basic"
731
+ })
732
+
733
+ # Schedule with CRON syntax
734
+ hf_jobs("scheduled uv", {
735
+ "script": "your_script.py",
736
+ "schedule": "0 9 * * 1", # 9 AM every Monday
737
+ "flavor": "cpu-basic"
738
+ })
739
+
740
+ # Schedule a Docker-based job
741
+ hf_jobs("scheduled run", {
742
+ "image": "python:3.12",
743
+ "command": ["python", "-c", "print('Scheduled!')"],
744
+ "schedule": "@daily",
745
+ "flavor": "cpu-basic"
746
+ })
747
+ ```
748
+
749
+ **Python API:**
750
+ ```python
751
+ from huggingface_hub import create_scheduled_job, create_scheduled_uv_job
752
+
753
+ # Schedule a Docker job
754
+ create_scheduled_job(
755
+ image="python:3.12",
756
+ command=["python", "-c", "print('Running on schedule!')"],
757
+ schedule="@hourly"
758
+ )
759
+
760
+ # Schedule a UV script
761
+ create_scheduled_uv_job("my_script.py", schedule="@daily", flavor="cpu-basic")
762
+
763
+ # Schedule with GPU
764
+ create_scheduled_uv_job(
765
+ "ml_inference.py",
766
+ schedule="0 */6 * * *", # Every 6 hours
767
+ flavor="a10g-small"
768
+ )
769
+ ```
770
+
771
+ **Available schedules:**
772
+ - `@annually`, `@yearly` - Once per year
773
+ - `@monthly` - Once per month
774
+ - `@weekly` - Once per week
775
+ - `@daily` - Once per day
776
+ - `@hourly` - Once per hour
777
+ - CRON expression - Custom schedule (e.g., `"*/5 * * * *"` for every 5 minutes)
778
+
779
+ **Manage scheduled jobs:**
780
+ ```python
781
+ # MCP Tool
782
+ hf_jobs("scheduled ps") # List scheduled jobs
783
+ hf_jobs("scheduled inspect", {"job_id": "..."}) # Inspect details
784
+ hf_jobs("scheduled suspend", {"job_id": "..."}) # Pause
785
+ hf_jobs("scheduled resume", {"job_id": "..."}) # Resume
786
+ hf_jobs("scheduled delete", {"job_id": "..."}) # Delete
787
+ ```
788
+
789
+ **Python API for management:**
790
+ ```python
791
+ from huggingface_hub import (
792
+ list_scheduled_jobs,
793
+ inspect_scheduled_job,
794
+ suspend_scheduled_job,
795
+ resume_scheduled_job,
796
+ delete_scheduled_job
797
+ )
798
+
799
+ # List all scheduled jobs
800
+ scheduled = list_scheduled_jobs()
801
+
802
+ # Inspect a scheduled job
803
+ info = inspect_scheduled_job(scheduled_job_id)
804
+
805
+ # Suspend (pause) a scheduled job
806
+ suspend_scheduled_job(scheduled_job_id)
807
+
808
+ # Resume a scheduled job
809
+ resume_scheduled_job(scheduled_job_id)
810
+
811
+ # Delete a scheduled job
812
+ delete_scheduled_job(scheduled_job_id)
813
+ ```
814
+
815
+ ## Webhooks: Trigger Jobs on Events
816
+
817
+ Trigger jobs automatically when changes happen in Hugging Face repositories.
818
+
819
+ **Python API:**
820
+ ```python
821
+ from huggingface_hub import create_webhook
822
+
823
+ # Create webhook that triggers a job when a repo changes
824
+ webhook = create_webhook(
825
+ job_id=job.id,
826
+ watched=[
827
+ {"type": "user", "name": "your-username"},
828
+ {"type": "org", "name": "your-org-name"}
829
+ ],
830
+ domains=["repo", "discussion"],
831
+ secret="your-secret"
832
+ )
833
+ ```
834
+
835
+ **How it works:**
836
+ 1. Webhook listens for changes in watched repositories
837
+ 2. When triggered, the job runs with `WEBHOOK_PAYLOAD` environment variable
838
+ 3. Your script can parse the payload to understand what changed
839
+
840
+ **Use cases:**
841
+ - Auto-process new datasets when uploaded
842
+ - Trigger inference when models are updated
843
+ - Run tests when code changes
844
+ - Generate reports on repository activity
845
+
846
+ **Access webhook payload in script:**
847
+ ```python
848
+ import os
849
+ import json
850
+
851
+ payload = json.loads(os.environ.get("WEBHOOK_PAYLOAD", "{}"))
852
+ print(f"Event type: {payload.get('event', {}).get('action')}")
853
+ ```
854
+
855
+ See [Webhooks Documentation](https://huggingface.co/docs/huggingface_hub/guides/webhooks) for more details.
856
+
857
+ ## Common Workload Patterns
858
+
859
+ This repository ships ready-to-run UV scripts in `hf-jobs/scripts/`. Prefer using them instead of inventing new templates.
860
+
861
+ ### Pattern 1: Dataset → Model Responses (vLLM) — `scripts/generate-responses.py`
862
+
863
+ **What it does:** loads a Hub dataset (chat `messages` or a `prompt` column), applies a model chat template, generates responses with vLLM, and **pushes** the output dataset + dataset card back to the Hub.
864
+
865
+ **Requires:** GPU + **write** token (it pushes a dataset).
866
+
867
+ ```python
868
+ from pathlib import Path
869
+
870
+ script = Path("hf-jobs/scripts/generate-responses.py").read_text()
871
+ hf_jobs("uv", {
872
+ "script": script,
873
+ "script_args": [
874
+ "username/input-dataset",
875
+ "username/output-dataset",
876
+ "--messages-column", "messages",
877
+ "--model-id", "Qwen/Qwen3-30B-A3B-Instruct-2507",
878
+ "--temperature", "0.7",
879
+ "--top-p", "0.8",
880
+ "--max-tokens", "2048",
881
+ ],
882
+ "flavor": "a10g-large",
883
+ "timeout": "4h",
884
+ "secrets": {"HF_TOKEN": "$HF_TOKEN"},
885
+ })
886
+ ```
887
+
888
+ ### Pattern 2: CoT Self-Instruct Synthetic Data — `scripts/cot-self-instruct.py`
889
+
890
+ **What it does:** generates synthetic prompts/answers via CoT Self-Instruct, optionally filters outputs (answer-consistency / RIP), then **pushes** the generated dataset + dataset card to the Hub.
891
+
892
+ **Requires:** GPU + **write** token (it pushes a dataset).
893
+
894
+ ```python
895
+ from pathlib import Path
896
+
897
+ script = Path("hf-jobs/scripts/cot-self-instruct.py").read_text()
898
+ hf_jobs("uv", {
899
+ "script": script,
900
+ "script_args": [
901
+ "--seed-dataset", "davanstrien/s1k-reasoning",
902
+ "--output-dataset", "username/synthetic-math",
903
+ "--task-type", "reasoning",
904
+ "--num-samples", "5000",
905
+ "--filter-method", "answer-consistency",
906
+ ],
907
+ "flavor": "l4x4",
908
+ "timeout": "8h",
909
+ "secrets": {"HF_TOKEN": "$HF_TOKEN"},
910
+ })
911
+ ```
912
+
913
+ ### Pattern 3: Streaming Dataset Stats (Polars + HF Hub) — `scripts/finepdfs-stats.py`
914
+
915
+ **What it does:** scans parquet directly from Hub (no 300GB download), computes temporal stats, and (optionally) uploads results to a Hub dataset repo.
916
+
917
+ **Requires:** CPU is often enough; token needed **only** if you pass `--output-repo` (upload).
918
+
919
+ ```python
920
+ from pathlib import Path
921
+
922
+ script = Path("hf-jobs/scripts/finepdfs-stats.py").read_text()
923
+ hf_jobs("uv", {
924
+ "script": script,
925
+ "script_args": [
926
+ "--limit", "10000",
927
+ "--show-plan",
928
+ "--output-repo", "username/finepdfs-temporal-stats",
929
+ ],
930
+ "flavor": "cpu-upgrade",
931
+ "timeout": "2h",
932
+ "env": {"HF_XET_HIGH_PERFORMANCE": "1"},
933
+ "secrets": {"HF_TOKEN": "$HF_TOKEN"},
934
+ })
935
+ ```
936
+
937
+ ## Common Failure Modes
938
+
939
+ ### Out of Memory (OOM)
940
+
941
+ **Fix:**
942
+ 1. Reduce batch size or data chunk size
943
+ 2. Process data in smaller batches
944
+ 3. Upgrade hardware: cpu → t4 → a10g → a100
945
+
946
+ ### Job Timeout
947
+
948
+ **Fix:**
949
+ 1. Check logs for actual runtime
950
+ 2. Increase timeout with buffer: `"timeout": "3h"`
951
+ 3. Optimize code for faster execution
952
+ 4. Process data in chunks
953
+
954
+ ### Hub Push Failures
955
+
956
+ **Fix:**
957
+ 1. Add token to secrets: MCP uses `"$HF_TOKEN"` (auto-replaced), Python API uses `get_token()` (must pass real token)
958
+ 2. Verify token in script: `assert "HF_TOKEN" in os.environ`
959
+ 3. Check token permissions
960
+ 4. Verify repo exists or can be created
961
+
962
+ ### Missing Dependencies
963
+
964
+ **Fix:**
965
+ Add to PEP 723 header:
966
+ ```python
967
+ # /// script
968
+ # dependencies = ["package1", "package2>=1.0.0"]
969
+ # ///
970
+ ```
971
+
972
+ ### Authentication Errors
973
+
974
+ **Fix:**
975
+ 1. Check `hf_whoami()` works locally
976
+ 2. Verify token in secrets — MCP: `"$HF_TOKEN"`, Python API: `get_token()` (NOT `"$HF_TOKEN"`)
977
+ 3. Re-login: `hf auth login`
978
+ 4. Check token has required permissions
979
+
980
+ ## Troubleshooting
981
+
982
+ **Common issues:**
983
+ - Job times out → Increase timeout, optimize code
984
+ - Results not saved → Check persistence method, verify HF_TOKEN
985
+ - Out of Memory → Reduce batch size, upgrade hardware
986
+ - Import errors → Add dependencies to PEP 723 header
987
+ - Authentication errors → Check token, verify secrets parameter
988
+
989
+ **See:** `references/troubleshooting.md` for complete troubleshooting guide
990
+
991
+ ## Resources
992
+
993
+ ### References (In This Skill)
994
+ - `references/token_usage.md` - Complete token usage guide
995
+ - `references/hardware_guide.md` - Hardware specs and selection
996
+ - `references/hub_saving.md` - Hub persistence guide
997
+ - `references/troubleshooting.md` - Common issues and solutions
998
+
999
+ ### Scripts (In This Skill)
1000
+ - `scripts/generate-responses.py` - vLLM batch generation: dataset → responses → push to Hub
1001
+ - `scripts/cot-self-instruct.py` - CoT Self-Instruct synthetic data generation + filtering → push to Hub
1002
+ - `scripts/finepdfs-stats.py` - Polars streaming stats over `finepdfs-edu` parquet on Hub (optional push)
1003
+
1004
+ ### External Links
1005
+
1006
+ **Official Documentation:**
1007
+ - [HF Jobs Guide](https://huggingface.co/docs/huggingface_hub/guides/jobs) - Main documentation
1008
+ - [HF Jobs CLI Reference](https://huggingface.co/docs/huggingface_hub/guides/cli#hf-jobs) - Command line interface
1009
+ - [HF Jobs API Reference](https://huggingface.co/docs/huggingface_hub/package_reference/hf_api) - Python API details
1010
+ - [Hardware Flavors Reference](https://huggingface.co/docs/hub/en/spaces-config-reference) - Available hardware
1011
+
1012
+ **Related Tools:**
1013
+ - [UV Scripts Guide](https://docs.astral.sh/uv/guides/scripts/) - PEP 723 inline dependencies
1014
+ - [UV Scripts Organization](https://huggingface.co/uv-scripts) - Community UV script collection
1015
+ - [HF Hub Authentication](https://huggingface.co/docs/huggingface_hub/quick-start#authentication) - Token setup
1016
+ - [Webhooks Documentation](https://huggingface.co/docs/huggingface_hub/guides/webhooks) - Event triggers
1017
+
1018
+ ## Key Takeaways
1019
+
1020
+ 1. **Submit scripts inline** - The `script` parameter accepts Python code directly; no file saving required unless user requests
1021
+ 2. **Jobs are asynchronous** - Don't wait/poll; let user check when ready
1022
+ 3. **Always set timeout** - Default 30 min may be insufficient; set appropriate timeout
1023
+ 4. **Always persist results** - Environment is ephemeral; without persistence, all work is lost
1024
+ 5. **Use tokens securely** - MCP: `secrets={"HF_TOKEN": "$HF_TOKEN"}`, Python API: `secrets={"HF_TOKEN": get_token()}` — `"$HF_TOKEN"` only works with MCP tool
1025
+ 6. **Choose appropriate hardware** - Start small, scale up based on needs (see hardware guide)
1026
+ 7. **Use UV scripts** - Default to `hf_jobs("uv", {...})` with inline scripts for Python workloads
1027
+ 8. **Handle authentication** - Verify tokens are available before Hub operations
1028
+ 9. **Monitor jobs** - Provide job URLs and status check commands
1029
+ 10. **Optimize costs** - Choose right hardware, set appropriate timeouts
1030
+
1031
+ ## Quick Reference: MCP Tool vs CLI vs Python API
1032
+
1033
+ | Operation | MCP Tool | CLI | Python API |
1034
+ |-----------|----------|-----|------------|
1035
+ | Run UV script | `hf_jobs("uv", {...})` | `hf jobs uv run script.py` | `run_uv_job("script.py")` |
1036
+ | Run Docker job | `hf_jobs("run", {...})` | `hf jobs run image cmd` | `run_job(image, command)` |
1037
+ | List jobs | `hf_jobs("ps")` | `hf jobs ps` | `list_jobs()` |
1038
+ | View logs | `hf_jobs("logs", {...})` | `hf jobs logs <id>` | `fetch_job_logs(job_id)` |
1039
+ | Cancel job | `hf_jobs("cancel", {...})` | `hf jobs cancel <id>` | `cancel_job(job_id)` |
1040
+ | Schedule UV | `hf_jobs("scheduled uv", {...})` | - | `create_scheduled_uv_job()` |
1041
+ | Schedule Docker | `hf_jobs("scheduled run", {...})` | - | `create_scheduled_job()` |
1042
+