Skip to content

Pin huggingface_hub to latest version 1.22.0#891

Open
pyup-bot wants to merge 1 commit into
mainfrom
pyup-pin-huggingface_hub-1.22.0
Open

Pin huggingface_hub to latest version 1.22.0#891
pyup-bot wants to merge 1 commit into
mainfrom
pyup-pin-huggingface_hub-1.22.0

Conversation

@pyup-bot

@pyup-bot pyup-bot commented Jul 3, 2026

Copy link
Copy Markdown
Collaborator

This PR pins huggingface_hub to the latest release 1.22.0.

Changelog

1.22.0

🖥️ Sandboxes: isolated cloud machines on top of Jobs

Sandboxes are isolated cloud machines you can spin up in seconds, run commands in with live-streamed output, and move files in and out of — all from Python or the CLI. They are built entirely on top of Jobs: under the hood a sandbox is just a Job running a tiny static server, so any Docker image with `/bin/sh` works and it inherits Jobs' billing, hardware flavors, and namespace permissions for free. Two flavors are available: `Sandbox.create` for a dedicated VM (GPU workloads, untrusted code, full isolation) and `SandboxPool` to pack many cheap CPU sandboxes into a few shared host VMs for fan-out workloads like RL rollouts. This release also adds background processes (`sbx.run(..., background=True)` / `hf sandbox spawn`) and a port proxy (`Sandbox.proxy_url_for`) so you can reach a server running inside a sandbox from the outside over HTTP or WebSocket.

python
from huggingface_hub import Sandbox

with Sandbox.create(image="python:3.12") as sbx:    ready in ~6s
 sbx.files.write("/app/main.py", "print(40 + 2)")
 print(sbx.run("python /app/main.py").stdout)     42


bash
Create, run, copy files, and terminate from the terminal
hf sandbox create
hf sandbox exec <id> -- python -c "print('hi')"
hf sandbox cp data.csv <id>:/data/data.csv
hf sandbox kill <id>


- [Sandbox] Add Sandbox API and `hf sandbox` CLI on top of Jobs by Wauplin in 4350
- [Sandbox] Background processes + proxy to reach in-sandbox servers by Wauplin in 4444

📚 **Documentation:** [Sandboxes guide](https://huggingface.co/docs/huggingface_hub/main/en/guides/sandbox), [Sandbox reference](https://huggingface.co/docs/huggingface_hub/main/en/package_reference/sandbox)

⚡ Faster snapshot downloads with a tree cache

`snapshot_download` now caches a repository's file listing on disk under a new `trees/` folder, so re-downloading a commit that's already cached costs a single network call — resolving the branch or tag to a commit hash — instead of one metadata request per file. The listing is immutable per commit and shared by both `snapshot_download` and `hf_hub_download`; for Xet-enabled files it also skips the per-file HEAD `/resolve` request entirely, rebuilding the metadata from the cached listing. As a deliberate side effect of the completeness check, when the Hub can't be reached and the local snapshot is missing requested files, `snapshot_download` now raises `IncompleteSnapshotError` instead of silently returning a partial folder.

- [Download] Cache repo tree listing on disk in snapshot_download by Wauplin in 4394

📚 **Documentation:** [Manage your cache](https://huggingface.co/docs/huggingface_hub/main/en/guides/manage-cache)

🛠️ CLI rebuilt on Click (drops Typer)

The entire `hf` CLI now runs on a small in-house layer over Click 8.x instead of Typer, which had vendored Click in a way that broke the CLI's custom help rendering, error enrichment, and shell completion — and forced capping `typer<0.26`. The migration preserves existing behavior: `--help` output is byte-identical, the generated `cli.md` reference is unchanged apart from a header comment, and shell completion now uses Click's native completion. The public `typer_factory` helper is kept so downstream libraries like `transformers` that register their own commands keep working.

- [CLI] Add a minimal Click framework for the CLI by hanouticelina in 4462

💔 Breaking Change

- [Upload] Deprecate upload_large_folder (API + CLI) by Wauplin in 4414 — `upload_large_folder` and `hf upload-large-folder` are now deprecated in favor of `upload_folder` / `hf upload`, which handle very large and resumable uploads out of the box.
- Make filter_repo_objects pattern matching case-sensitive on all platforms by Sreekant13 in 4435 — `allow_patterns`/`ignore_patterns` now match case-sensitively on every OS (aligned with case-sensitive Hub paths). On Windows this is a behavior change: patterns like `*.PDF` no longer match `file.pdf`.
- [Inference Providers] Remove dead inference providers by hanouticelina in 4447 — removes six providers no longer routed by the Hub (`black-forest-labs`, `clarifai`, `hyperbolic`, `nebius`, `nvidia`, `sambanova`) — [docs](https://huggingface.co/docs/huggingface_hub/main/en/guides/inference)

🖥️ CLI

- [CLI] Add `hf discussions edit` by Wauplin in 4415 — [docs](https://huggingface.co/docs/huggingface_hub/main/en/guides/cli)
- [CLI] hf cache: surface & prune incomplete downloads by Wauplin in 4416 — `hf cache ls` now flags leftover `.incomplete` files and `hf cache prune` removes them automatically — [docs](https://huggingface.co/docs/huggingface_hub/main/en/guides/manage-cache)
- [CLI] Point users at hf jobs wait in job hints by davanstrien in 4429
- [CLI] Expose `out` singleton publicly + add `out.log` method by Wauplin in 4471

🤖 Inference

- [Inference Providers] deepinfra: add automatic-speech-recognition support by ovuruska in 4382

📊 Jobs

- [Jobs] Add sync_job_volume helper and local paths in hf jobs -v by Wauplin in 4346 — sync a local directory to a `jobs-artifacts` bucket and mount it; `-v` accepts local directories in `hf jobs run`/`uv run` (and scheduled variants) — [docs](https://huggingface.co/docs/huggingface_hub/main/en/guides/jobs)
- [Jobs] Add `hf jobs scheduled trigger ...` to trigger scheduled jobs on demand by Wauplin in 4459 — [docs](https://huggingface.co/docs/huggingface_hub/main/en/guides/jobs)

🔧 Other QoL Improvements

- [Http] Support standard Retry-After header in http_backoff by Wauplin in 4460 — `http_backoff` now honors the standard `Retry-After` header (delay-seconds form); HF rate-limit headers still take precedence when present.
- Expose base_model filter param on get_dataset_leaderboard by NathanHB in 4474 — pass `base_model=False` to `get_dataset_leaderboard` to include fine-tuned/derivative repos that declare a parent model.

📖 Documentation

- Docs: Jobs are no longer Pro-only — update availability note in jobs guide by davanstrien in 4479 — [docs](https://huggingface.co/docs/huggingface_hub/main/en/guides/jobs)
- Fix misleading max_retries docstring in http_backoff by Sreekant13 in 4436
- fix docstring by hunterhogan in 4443

🐛 Bug and typo fixes

- [CLI] Fix escaped backslash handling in .env value parsing by sarathfrancis90 in 4413
- [URIs] Percent-encode the revision in HfUri.to_url by sarathfrancis90 in 4418
- Accept two-letter byte units (KB/MB/GB/TB/PB) in parse_size by Sreekant13 in 4468 — documented `hf cache ls --filter` thresholds like `size>1GB` now parse instead of raising.
- Fix KeyError in get_dataset_leaderboard when entry has no source by NathanHB in 4473
- Do not suggest reporting if colab vault error by Wauplin in 4437
- [Build] Include huggingface_hub.templates via find_namespace_packages by Wauplin in 4438 — model/dataset card templates are now shipped in wheels (previously skipped due to the missing `__init__.py`).

🏗️ Internal

- [Tests] Migrate test_hf_api.py from unittest to pytest by Wauplin in 4407
- Post-release: bump version to 1.22.0.dev0 by huggingface-hub-bot[bot] in 4410
- [Tests] Migrate everything from unittest to pytest by Wauplin in 4439
- [Tests] Continue pytest migration/cleaning by Wauplin in 4453
- [Tests] last time we need to refacto tests by Wauplin in 4455
- [Fix] fix TestConfigDictNotRequired skipped tests by Wauplin in 4461
- Bump the actions group across 1 directory with 4 updates by dependabot[bot] in 4457
- [CLI] Remove module-level Usage command lists from CLI files by moon-bot-app[bot] in 4472

1.21.0

📊 Jobs listing revamped: filter, paginate, and `ls` instead of `ps`

The Jobs listing API and CLI have been overhauled with server-side filtering, proper pagination, and a CLI rename that aligns with the rest of `hf`. `list_jobs()` now accepts `status` and `labels` parameters that push filtering to the server, and returns a lazy iterator (matching `list_models`, `list_datasets`, etc.) so large result sets are fetched page by page. On the CLI side, `hf jobs ps` has been renamed to `hf jobs ls` for consistency with `hf repos ls`, `hf models ls`, and friends — `ps` and `list` still work as aliases.

⚠️ **Breaking changes:**
- `list_jobs()` now returns an `Iterable[JobInfo]` instead of `list[JobInfo]`. If you indexed the result (`jobs[0]`), wrap it with `list(...)`.
- `-f`/`--filter` in `hf jobs ls` is deprecated. Use `--status` and `--label` instead. Glob patterns (`data-*`), negation (`key!=value`), and filtering by `id`/`image`/`command` are no longer supported.

python
from huggingface_hub import list_jobs

Filter by status and labels
list_jobs(status=["RUNNING", "SCHEDULING"], labels={"env": "prod"})

Iterate lazily
for job in list_jobs():
 print(job.id)

Materialize all results
all_jobs = list(list_jobs())


bash
Filter by status and labels
hf jobs ls --status running,scheduling --label env=prod --label team=ml

Paginate with --limit
hf jobs ls -a --limit 500
hf jobs ls -a --limit 0   no limit


- [Jobs] Add stage/label filtering to list_jobs API and CLI by Wauplin in 4395
- [Jobs] Paginate list_jobs and add --limit to `hf jobs ps` by Wauplin in 4403
- [CLI] [Jobs] Rename job listing to 'hf jobs ls' (and keep 'hf jobs ps' alias) by Wauplin in 4409

📚 **Documentation:** [CLI guide](https://huggingface.co/docs/huggingface_hub/main/en/guides/cli), [Jobs guide](https://huggingface.co/docs/huggingface_hub/main/en/guides/jobs)

🐛 Fix circular import on `from huggingface_hub import login`

A regression introduced in v1.20.0 caused `from huggingface_hub import login` to raise an `ImportError` on a fresh interpreter, due to a circular dependency between `_oauth_device` and `utils._http`. The fix moves `_oauth_device.py` into the `utils` layer so all imports resolve downward, eliminating the cycle. No lazy imports or workarounds required.

- Fix circular import on `from huggingface_hub import login` by hanouticelina in 4385

🔧 Other QoL Improvements

- Retry requests on httpx.RemoteProtocolError by hanouticelina in 4398

📖 Documentation

- Add Kannada (kn) translation of README by spideyashith in 4370
- docs: put `hf jobs uv run` flags before the script for consistency by davanstrien in 4396
- [i18n-HI] Add Hindi translation for guides overview by Mr-Abhinav-Pandey in 4405

🐛 Bug and typo fixes

- [Serialization] Exclude skipped string tensors from single-shard index by nyxst4ck in 4391
- Fix IndexError in filter_repo_objects on an empty allow/ignore pattern by CharlesCNorton in 4402

🏗️ Internal

- Post-release: bump version to 1.21.0.dev0 by huggingface-hub-bot[bot] in 4383
- [CI] Catch circular imports in the check-imports job by hanouticelina in 4386
- [Tests] Fix kernel tests for moved file on production by Wauplin in 4387
- [Release] Report trigger actor, drop social drafts, archive raw + edited notes by Wauplin in 4388
- [Tests] Fix flaky security-scan assertions by Wauplin in 4392
- [Bot] Update hardware flavor enums and docs by huggingface-hub-bot[bot] in 4406
- [CLI] Fix ty/mypy errors with click 8.4.2 by Wauplin in 4408

1.20.1

**Full Changelog**: https://github.com/huggingface/huggingface_hub/compare/v1.20.0...v1.20.1

1.20.0

🔒 Browser-based OAuth login

`hf auth login` now defaults to a browser-based OAuth Device Code flow instead of asking you to copy-paste a token. The command prints a URL and a short code, you authorize in the browser, and the CLI retrieves and saves the token for you. The same applies to `login()` in Python. In an interactive terminal you still get a `gh`-style arrow-key menu to pick between browser login and pasting a token, and `--token` works exactly as before.

OAuth tokens expire after 30 days, but they come with a refresh token: `get_token()` transparently refreshes them when less than a day of validity remains, so long-running setups keep working without re-authenticating. `hf auth list` now shows the expiry date for OAuth tokens.

bash
> hf auth login
? How would you like to log in? Log in with your browser

 Open this URL in your browser:
     https://hf.co/oauth/device

 And enter the code: 52AT-FLYZ

 Waiting for authorization.


When the command is run by an AI agent, it never prompts. Instead it streams structured events so the agent can surface the URL and code to its user, then blocks until a terminal `auth_success` / `auth_error` event:

console
$ hf auth login --format json
{"event": "device_code", "verification_uri": "https://hf.co/oauth/device", "user_code": "52AT-FLYZ", "verification_uri_complete": "https://hf.co/oauth/device", "expires_in": 300, "interval": 5}
{"event": "auth_success", "user": "celinah", "token_name": "oauth-celinah"}


`hf auth list` surfaces the new expiry column:

console
$ hf auth list
name          token       expires
- ------------- ----------- -------------------
my-token      hf_****5678
* oauth-user    hf_****1234 2026-07-09
oauth-old     hf_****9999 2026-06-09 (expired)


Finally, `notebook_login()` now renders the link and code with plain `IPython.display.HTML`, dropping the `ipywidgets` dependency.

- [Auth] Browser-based OAuth login by hanouticelina in 4354

⚡ Faster, more reliable `hf upload` for large folders

`hf upload` and the underlying `upload_folder` have been revamped to be faster and far more robust on large folders. When `hf_xet` is installed (the default), uploads now run through a streamed, multi-commit pipeline built on the `XetSession` API: the folder is scanned and fed into a background Xet upload while previous batches are committed in parallel, and files are hashed in a single read pass while they are chunked (the old flow read every large file twice). Nothing changes in how you call it:

bash
hf upload <repo-id> <path/to/folder>


This is a drop-in replacement for experimental `hf upload-large-folder` used until today, which will be **deprecated** in a future release.

> 🚨🚨 **Breaking change:** With the `upload_folder` and `hf upload` revamp, uploading a folder might result in multiple commits. It is also not possible to open a PR against a specific revision while using `upload_folder`. If you pass `create_pr=True`, it will necessarily create a PR against main. It will open the PR no matter if some changes have been committed (previously an empty commit was resulting in no PR opened at all).

What you get on large folders:

- **More reliable.** Uploads are resumable and stateless. If an upload is interrupted, just re-run the same command: already-committed files are detected and skipped, and already-uploaded chunks are deduplicated by the Xet backend (≈0 bytes re-transferred). There are no local state files to go stale, so resume even works from a different machine.
- **Faster.** Files are hashed while being chunked (single read pass) and batches commit in the background while the next batch is already uploading, so there is no separate hashing phase blocking the upload.
- **Multi-commit by default.** Large folders are automatically split into adaptive commits that scale between 64 and 1024 files based on commit duration. Folders that fit in a single batch still produce exactly one commit, as before; follow-up commits get a ` (part N)` suffix.
- **Live progress bar** tracking the preparing, uploading, and committing stages (with a plain-log fallback when output is not a TTY):


Found 301 files to upload
Preparing   ████████████████████  301 / 301 ✓
Uploading   █████████████████░░░  255 / 300 files  25.5MB · 1.86MB/s
Committing  ░░░░░░░░░░░░░░░░░░░░  0 / 301


> `upload_large_folder` / `hf upload-large-folder` are intentionally left untouched in this release; their deprecation will follow once `hf upload` has fully absorbed the use case.


- [Upload] Streamed multi-commit upload_folder powered by Xet by Wauplin in 4331

💻 Jobs: `wait`, SSH access, and cleaner error messages

This release adds three major capabilities to Hugging Face Jobs.

**Wait for completion.** `HfApi.wait_for_job()` and `hf jobs wait` block until one or more Jobs reach a terminal stage, which makes it easy to chain commands in CI scripts. `wait_for_job` accepts a single id or a list, returns the final `JobInfo` even on failure (check `job.status.stage`), and only raises `TimeoutError` on timeout. The CLI exits `0` only if **all** waited-on Jobs ended `COMPLETED`.

bash
Wait on a single job, then run the next step only if it succeeded
hf jobs wait <job_id> && next-step

Wait on a batch, with a timeout
hf jobs wait <id1> <id2> --timeout 10m


> ⚠️ **Breaking change:** non-detached `hf jobs run` / `hf jobs uv run` now exit with the Job's outcome (exit code `1` if the Job errored) instead of always exiting `0`. We consider this a bugfix — scripts relying on the old behavior were being silently misled — but it is called out here in case you depend on the previous exit code.

**SSH access.** With `--ssh` at launch and an SSH key registered on [huggingface.co/settings/keys](https://huggingface.co/settings/keys), you can connect straight into a running Job's container with `hf jobs ssh <job_id>`. Thanks to `wait_for_job`, `hf jobs ssh` now waits for the Job to reach `RUNNING` before connecting (with a status spinner) instead of failing immediately while it is still scheduling.

console
$ hf jobs run --ssh --detach python:3.12 sleep infinity
✓ Job started
id: 6a33ba2aef9220ea67d98a03
url: https://huggingface.co/jobs/Wauplin/6a33ba2aef9220ea67d98a03
Hint: Use `hf jobs ssh Wauplin/6a33ba2aef9220ea67d98a03` to open an SSH session into the job.

$ hf jobs ssh Wauplin/6a33ba2aef9220ea67d98a03
Job is running.
Running `ssh 6a33ba2aef9220ea67d98a03ssh.hf.jobs`
rootj-wauplin-6a33ba2aef9220ea67d98a03-do4bduvn-5f153-458k4:/


**Readable errors.** A new `JobNotFoundError` and the switch from `response.raise_for_status` to `hf_raise_for_status` turn raw `httpx` tracebacks into clean, actionable messages. Per-command `try/except` blocks were removed in favor of the global CLI error handling.

console
$ hf jobs inspect 000
Error: 404 Client Error. (Request ID: Root=1-6a316470-...)

Job Not Found for url: https://huggingface.co/api/jobs/Wauplin/000.
Please make sure you specified the correct job ID and namespace.
Set HF_DEBUG=1 as environment variable for full traceback.


- [Jobs] Add `hf jobs wait` and `HfApi.wait_for_job` by Wauplin in 4345
- [Jobs] Add SSH support to run a Job and connect to it by Wauplin in 4352
- [CLI] Make `hf jobs ssh` wait for job to be running by Wauplin in 4379
- Add new JobNotFound error by Wauplin in 4367

🖥️ Custom-container deploy for Inference Endpoints

`hf endpoints deploy` can now deploy custom Docker containers end-to-end, no more hand-writing JSON and POSTing the raw endpoints API. New flags wire up the image and its runtime: `--custom-image`, `--health-route`, `--port`, `--command`, and `--container-args`. Environment variables and secrets can be injected with `--env`/`--env-file` and `--secrets`/`--secrets-file`. On the SDK side, `create_inference_endpoint` gains `container_command` and `container_args` parameters.

bash
hf endpoints deploy nex-n2-pro \
--repo nex-agi/Nex-N2-Pro \
--framework custom \
--accelerator gpu --vendor aws --region us-east-1 \
--instance-type nvidia-h200 --instance-size x8 \
--custom-image nexagi/sglang:v0.5.12 \
--health-route /health --port 30000 \
--container-args "--reasoning-parser qwen3 --tool-call-parser qwen3_coder --mamba-scheduler-strategy extra_buffer --tp 8" \
--env MODEL_ID=/repository \
--type authenticated


The `type` parameter now defaults to `authenticated` instead of the deprecated `protected` (passing `protected` emits a `FutureWarning`). The custom-container flags raise a clean error if used without `--custom-image`.

- [Inference Endpoints] Custom-container deploy CLI + deprecate protected endpoint type by gary149 in 4329

⏳ Wait for a Space with `wait_for_space` and `hf spaces wait`

Mirroring the new `wait_for_job` primitive, `HfApi.wait_for_space()` and `hf spaces wait` block until a Space leaves an intermediate stage (`BUILDING`, `APP_STARTING`, …) and settles on a final state. The CLI exits `0` if the Space is `RUNNING`, non-zero otherwise. `hf spaces ssh` and `hf spaces dev-mode` were refactored to use `wait_for_space` internally instead of the old CLI-only helper.

bash
Wait after a restart
hf spaces restart username/my-space && hf spaces wait username/my-space

With a timeout
hf spaces wait username/my-space --timeout 5m


python
>>> from huggingface_hub import restart_space, wait_for_space
>>> restart_space("username/my-space")
>>> runtime = wait_for_space("username/my-space")
>>> runtime.stage
'RUNNING'


📚 **Documentation:** [CLI guide — wait for a Space](https://huggingface.co/docs/huggingface_hub/main/en/guides/cli#wait-for-a-space) · [Space runtime reference](https://huggingface.co/docs/huggingface_hub/main/en/package_reference/space_runtime)

- [Spaces] Add `wait_for_space` API and `hf spaces wait` CLI by Wauplin in 4380

💔 Breaking Changes

🚨🚨 With the `upload_folder` and `hf upload` revamp, uploading a folder might result in multiple commits. 
It is also not possible to open a PR against a specific revision while using `upload_folder`. If you pass `create_pr=True`, it will necessarily create a PR against main. It will open the PR no matter if some changes have been committed (previously an empty commit was resulting in no PR opened at all).

- [Upload] Streamed multi-commit upload_folder powered by Xet in 4331 by Wauplin 

`RepoUrl` now rejects canonical single-segment repo IDs like `"gpt2"` or `"datasets/squad"` (use `"user/gpt2"` or `"datasets/user/squad"` instead). `repo_type_and_id_from_hf_id` is softly deprecated. `parse_hf_uri` gains an `endpoint` argument to parse URLs from self-hosted Hub instances.

- [URIs] Use `parse_hf_uri` in `RepoUrl` + soft-deprecate `repo_type_and_id_from_hf_id` by Wauplin in 4324

Non-detached `hf jobs run` / `hf jobs uv run` now exit with the Job's outcome (exit `1` on Job error) instead of always exiting `0` 

- [Jobs] Add hf jobs wait and HfApi.wait_for_job by Wauplin in 4345 — see the Jobs highlight above.

🖥️ CLI

- [CLI] Suggest creating repo/bucket on NotFound errors by Wauplin in 4372 — when a repo or bucket can't be found, the CLI now hints at the matching `create` command instead of just reporting the 404.

🔧 Other QoL Improvements

- [HTTP] Retry on HTTP 408 Request Timeout by default by Wauplin in 4360 — `408 Request Timeout` is now part of the default retry status set, alongside the existing 5xx codes.

📖 Documentation

- Polish CLI migration wording and collection docstrings by wunianze666-netizen in 4356
- Polish migration and collection API wording by wunianze666-netizen in 4358

🐛 Bug and typo fixes

- OIDC: Include `error_description` in HTTP error messages by coyotte508 in 4341 — failed OIDC exchanges now surface the server's `error_description`, making misconfigured Trusted Publishers far easier to debug.
- [Download] Retry on `RemoteProtocolError` in `http_get` by Wauplin in 4351 — transient connection drops mid-download are now retried instead of failing the download.
- Ignore Windows metadata files in cache scan by Chinmay1220 in 4357 — `desktop.ini` and similar Windows metadata files no longer trip up `scan-cache`.

🏗️ Internal

- [Tests] Add `inference` pytest marker to filter inference tests by Wauplin in 4338
- Post-release: bump version to 1.20.0.dev0 by huggingface-hub-bot[bot] in 4342
- [Tests] Mitigate transient CI failures by Wauplin in 4343
- [CI] Fix versioned docs not publishing on release by hanouticelina in 4344
- [Release] Skip `--prerelease=allow` injection for sentence-transformers by hanouticelina in 4366
- [CI] Do not fail on tmp repo deletion by Wauplin in 4371
- Bump codecov/codecov-action from 6.0.1 to 7.0.0 in the actions group by dependabot[bot] in 4373

1.19.0

🔐 Keyless CI/CD auth via OIDC token exchange

CI workflows can now authenticate to the Hub without storing an `HF_TOKEN` secret, using [Trusted Publishers](https://huggingface.co/docs/hub/trusted-publishers). Set `HF_OIDC_RESOURCE` to the repo (or username) you want to scope the token to, and `huggingface_hub` performs the OIDC exchange under the hood — no token, no setup code. GitHub Actions is supported out of the box (with `permissions: id-token: write`), and other providers can pass a pre-minted ID token via `HF_OIDC_ID_TOKEN`. Exchanged tokens are short-lived (1 hour), repo-scoped, and cached locally with automatic refresh.

yaml
Publish a model without storing any HF_TOKEN secret
- name: Push the model
env:
 HF_OIDC_RESOURCE: acme/awesome-model
run: hf upload acme/awesome-model ./model .


- [Auth] Keyless CI/CD auth via OIDC token exchange by hanouticelina in 4326

📚 **Documentation:** [Trusted Publishers](https://huggingface.co/docs/hub/trusted-publishers)

🖥️ hf:// URIs for upload and download

`hf upload` and `hf download` now accept an `hf://` URI in place of the positional repo ID. The URI encodes repo type, revision, and file path in a single string following the grammar `hf://[<TYPE>/]<ID>[<REVISION>][/<PATH>]`, so you no longer need separate `--repo-type` and `--revision` flags. When a URI is provided, it is the single source of truth — passing `--repo-type` or `--revision` on top of it raises an error, and a path in the URI cannot be combined with positional filenames (download) or `path_in_repo` (upload).

bash
Download a single file from a dataset at a given revision
hf download hf://datasets/HuggingFaceM4/FineVisionrefs/pr/1/data/train.parquet

Download an entire repo
hf download hf://datasets/google/fleurs

Upload a file to a dataset on a specific branch
hf upload hf://datasets/Wauplin/my-cool-datasetmy-branch/data/train.csv ./train.csv


- [CLI] Support hf:// URIs in `hf upload` and `hf download` by Wauplin in 4297

📚 **Documentation:** [CLI guide — hf:// URIs](https://huggingface.co/docs/huggingface_hub/main/en/guides/cli#use-an-hf-uri) · [Download guide](https://huggingface.co/docs/huggingface_hub/main/en/guides/download) · [Upload guide](https://huggingface.co/docs/huggingface_hub/main/en/guides/upload)

🚀 Expose job ports through the jobs proxy

Jobs can now expose container ports through the public jobs proxy using `--expose <port>` (CLI) or `expose=[8000]` (Python API). Each exposed port is reachable at `https://<job_id>--<port>.hf.jobs` and requires an HF token with read access to the job's namespace. This works on `hf jobs run`, `hf jobs uv run`, and their scheduled variants. Job responses now surface `expose_urls` on `JobStatus`.

bash
Expose a web server running on port 8000
> hf jobs run --expose 8000 python:3.12 python -m http.server 8000
✓ Job started
id: 6a2aa7cec4f53f9fc5aa4cff
url: https://huggingface.co/jobs/Wauplin/6a2aa7cec4f53f9fc5aa4cff
Hint: Exposed ports are reachable at (requires an HF token with read access to the job):
https://6a2aa7cec4f53f9fc5aa4cff--8000.hf.jobs
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...


python
from huggingface_hub import run_job
run_job(image="python:3.12", command=["python", "-m", "http.server", "8000"], expose=[8000])


- [Jobs] Add --expose <port> option to expose job ports through the jobs proxy by XciD in 4316

📚 **Documentation:** [Jobs guide](https://huggingface.co/docs/huggingface_hub/main/en/guides/jobs)


🖥️ CLI

- [CLI] Suppress hints in quiet output mode by davanstrien in 4310
- [CLI] Agent-friendly hints + examples for hf jobs by davanstrien in 4308
- [CLI] Accept web URLs in bucket CLI commands by Wauplin in 4315


⚡ XetSession API migration

All Xet upload and download code has been migrated from the old function-based `hf_xet` API to the new session-based `XetSession` API (`hf-xet >= 1.5.0`). A global singleton `get_xet_session()` provides fork-safe, thread-safe, and SIGINT-safe session reuse across all call sites — repo commits, `hf_hub_download`, bucket uploads/downloads, and `snapshot_download` all share the same underlying Tokio runtime. Token refresh is now handled through a centralized `xet_connection_info_refresh_url()` builder, and progress reporting follows the new `(group_report, item_reports)` contract.

- Use the new XetSession API by seanses in 4116

🔧 Other QoL Improvements

- [Auth] Take google colab token from env first by Wauplin in 4323 — `get_token()` now checks `HF_TOKEN`/`HUGGING_FACE_HUB_TOKEN` and the on-disk token file before the Colab secrets vault, so an explicit `login()` or env variable always wins over the notebook's stored secret.
- [Agent] Dynamic agent harness registry by Wauplin in 4325 — Agent harness detection now fetches the registry from `GET /api/agent-harnesses` instead of using a hardcoded list, with a 24-hour on-disk cache and in-process caching for hot paths.

🐛 Bug and typo fixes

- [Fix] Remove private `_MISSING_TYPE` import from dataclasses module by xsuchy in 4322 — fixes `ImportError` on Python 3.15 where `dataclasses._MISSING_TYPE` was removed upstream.
- Fix ignored-pattern warning grammar in download CLI by wunianze666-netizen in 4337 — corrects `"have being"` to `"have been"` in `hf download` warning output.
- [fix] Transient location error due to CDN by Wauplin in 4339 — fixes flaky `test_get_hf_file_metadata_from_a_lfs_file` by accepting `cdn.hf.co` in addition to `xethub.hf.co` in the redirect URL check.

🏗️ Internal

- Post-release: bump version to 1.19.0.dev0 by huggingface-hub-bot[bot] in 4313
- [CI] Run tests on internal workers by Wauplin in 4321
- [Tests] Add xet/no_xet pytest markers to filter Xet vs non-Xet tests by Wauplin in 4336
- Bump the actions group with 6 updates by dependabot[bot] in 4332
- chore: update release.yml by hf-security-analysis[bot] in 4334
- [CI] Remove .github/workflows/python-prerelease.yml by Wauplin in 4335

1.18.0

🖥️ Unified `hf cp` command

A single `hf cp` command now handles all file-copy workflows (upload a local file, download from the Hub, or copy between two remote locations) with consistent `hf://` URI syntax for both repositories and buckets. It is also available as `hf repos cp` and `hf buckets cp`; all three aliases are identical, so you can use whichever reads best for your workflow. You can stream from stdin (`-`) or to stdout (`-`), and a trailing `/` on the source path gives you rsync-style semantics (copy the folder contents, not the folder itself). Note that remote-to-remote copies only work within the same [storage region](https://huggingface.co/docs/hub/storage-regions), and bucket-to-repo is not yet supported.

bash
Upload a local file to a repo
hf cp ./model.safetensors hf://username/my-model/model.safetensors

Download a file to stdout
hf cp hf://username/my-model/config.json - | jq .

Copy between two Hub repos
hf cp hf://username/source-model/config.json hf://username/dest-model/config.json


📚 **Documentation:** [CLI guide — Copy files](https://huggingface.co/docs/huggingface_hub/main/en/guides/cli#copy-files)

- [CLI] Add unified `hf cp` command (aliased as `hf repos cp` and `hf buckets cp`) by Wauplin in 4295

:egg: Easter egg:explore your storage usage

<img width="2282" height="832" alt="image" src="https://github.com/user-attachments/assets/fa4047b2-c62e-4e92-b556-ae18db8c98a8" />

- [CLI] Easter egg: city skyline in `hf repos ls` by Wauplin in 4287

🔗 Paste web URLs directly

`parse_hf_uri` now accepts Hugging Face **web URLs** so you can paste a link straight into the CLI or the library and it "just works".

bash
Copy-paste a URL from the website
hf cp https://huggingface.co/nvidia/LocateAnything-3B/blob/main/config.json - | jq '.architectures'


📚 **Documentation:** [HF URIs — Web URLs](https://huggingface.co/docs/huggingface_hub/main/en/package_reference/hf_uris#web-urls)

- [URIs] Parse web URLs in `parse_hf_uri` + add `HfUri.to_url` by Wauplin in 4296

🚨 Breaking change

On Lustre, GPFS, and some NFS mounts, `flock(2)` silently succeeds for every caller, which means `filelock` provides no mutual exclusion. When multiple `hf_hub_download` calls race for the same file, they can append to the same `.incomplete` file and silently corrupt the blob cache. This release fixes that by always downloading to a fresh temporary file instead of resuming an incomplete one, making the download path safe even when file locking is broken. `filelock` is still used as a "best-effort" hint to avoid unnecessary duplicate downloads, but correctness no longer depends on it. **This is a breaking change: resuming a previously failed partial download is no longer possible. However, file resumability was already a niche use case only applicable when `hf_xet` is disabled.**

- [Fix] Make concurrent downloads safe even when file locking is broken by Wauplin in 4306


🖥️ CLI

- [CLI] inline enum choices in the generated CLI skill by hanouticelina in 4299

🐛 Bug and typo fixes

- Fix ~ user home not expanded in local_dir and cache_dir on file download by Wauplin in 4293
- Do not fail on repo/bucket creation if HTTP 401 and already exists by Wauplin in 4294
- Fix umask probe writing tmp file outside download dir by Wauplin in 4305

📖 Documentation

- [Docs] Document missing endpoint and template_str parameters by aicayzer in 4298
- [Docs] Document missing parameters in hf_hub_url and preupload_lfs_files by aicayzer in 4300
- [Docs] Mention storage region limitation for server-side copy by Wauplin in 4302

🏗️ Internal

- Post-release: bump version to 1.18.0.dev0 by huggingface-hub-bot[bot] in 4291
- Bump the actions group with 2 updates by dependabot[bot] in 4309

1.17.0

📋 Copy files between repositories

You can now copy files or entire folders between different repositories on the Hub — model to model, model to dataset, any combination — without downloading or re-uploading data. `CommitOperationCopy` accepts `src_repo_id` and `src_repo_type` for cross-repo sources, and LFS blobs are deduplicated server-side via the `/lfs-files/duplicate` endpoint. Non-LFS files are fetched from the source repo and committed as regular payloads. `copy_files` and `hf buckets cp` now support repo-to-repo in addition to the existing bucket destinations.

python
>>> from huggingface_hub import copy_files

Copy an entire folder
>>> copy_files(
...     "hf://datasets/username/source-dataset/data/",
...     "hf://datasets/username/target-dataset/data/",
... )


- [Copy] Support cross-repo file copies by Wauplin in 4203

📚 **Documentation:** [Upload guide — Copy files between repositories](https://huggingface.co/docs/huggingface_hub/main/en/guides/upload#copy-files-between-repositories)

🖥️ SSH into a Space with `hf spaces ssh`

A new `hf spaces ssh` command opens an SSH session directly into a Space's Dev Mode container. If Dev Mode is not enabled yet, the CLI prompts you to enable it. You can also use `--dry-run` to print the SSH command without running it, or `-i` to forward a specific key. Your SSH public key must be registered in your HF user settings.

bash
SSH into a Space
$ hf spaces ssh username/my-space

Print the SSH command without running it
$ hf spaces ssh username/my-space --dry-run


- [CLI] Add `hf spaces ssh` by gary149 in 4241

📚 **Documentation:** [CLI guide — SSH into a Space](https://huggingface.co/docs/huggingface_hub/main/en/guides/cli#ssh-into-a-space-dev-mode) | [Spaces guide — SSH into a Space](https://huggingface.co/docs/huggingface_hub/main/en/guides/manage-spaces#ssh-into-a-space-dev-mode)

📂 List all your repos with `hf repos ls`

A new `hf repos ls` command lists all your repositories — models, datasets, spaces, and buckets — with storage size and percentage of namespace total, sorted by storage usage. It supports `--type`, `--search`, `--namespace`, and `--limit` (default 30, `--limit 0` for all), plus the standard `--format` family.

bash
List all your repos
$ hf repos ls

List all datasets under org with JSON output
$ hf repos ls --namespace my-org --type dataset --limit 0 --format json | jq '.[].id'


- [CLI] Add `hf repos ls` command by Wauplin in 4283

📚 **Documentation:** [CLI guide — List repos](https://huggingface.co/docs/huggingface_hub/main/en/guides/cli#list-repos) | [Repository guide — List your repositories](https://huggingface.co/docs/huggingface_hub/main/en/guides/repository#list-your-repositories)


📊 CLI tables auto-fit terminal width and right-align numbers

Human-mode CLI tables now use a column-aware algorithm that computes per-column width caps from the actual terminal width, shrinking only the widest columns when needed. Non-TTY output keeps the legacy fixed cap, and `--no-truncate` bypasses truncation entirely. Numeric columns (all `int`/`float` values) are automatically right-aligned.

bash
Tables adapt to your terminal width
$ hf models ls --search qwen3

Force full values regardless of width
$ hf models ls --no-truncate


- [CLI] Auto-fit human tables to terminal width by hanouticelina in 4251
- [CLI] Auto right-align numeric columns in human table output by Wauplin in 4288

📚 **Documentation:** [CLI guide — Output formatting](https://huggingface.co/docs/huggingface_hub/main/en/guides/cli#output-formatting)


🔧 Jobs hardware decoupled from Spaces, auto-synced with Hub API

Jobs now have their own `JobHardware` enum, independent of `SpaceHardware`, so the two catalogs can diverge as needed. The old `JobHardware` dataclass (return type of `list_jobs_hardware()`) has been renamed to `JobHardwareInfo`. CLI `--flavor` / `--hardware` flags use a new `SoftChoice` type that shows known values for autocomplete but accepts any string — older CLI versions won't reject new server-side flavors. A daily CI workflow (`update-hardware-flavors.yaml`) runs `utils/check_hardware_flavors.py` to sync both enums from the live Hub API and opens a bot PR when something changes.

bash
Unknown flavors pass through instead of raising a validation error
$ hf jobs run --flavor future-gpu-x99 python:3.12 echo "works with unknown flavors"


- [Jobs] Decouple Job hardware from Spaces, auto-sync enums with Hub API by Wauplin in 4266

📚 **Documentation:** [Jobs guide](https://huggingface.co/docs/huggingface_hub/main/en/guides/jobs)

💔 Breaking Change

- [Inference] Remove Together ASR task to drop urllib3 dependency by Wauplin in 4248
- [CLI] migrate `hf jobs` to `out` singleton by hanouticelina in 4254

> **Note:** The second item changes `hf jobs ps` and `hf jobs scheduled ps` to use `--format auto|human|agent|json|quiet` (removing `--format table` and `-q`). JSON output for `hf jobs ps` now flattens `command` to a string and `status` to a stage string.

🖥️ CLI

- [CLI] Migrate `extensions`, `lfs-enable-largefiles`, `version` to `out` singleton by hanouticelina in 4284
- [CLI] Fix parent aliases leaking into subcommand headers in CLI reference by Wauplin in 4253

📊 Jobs

- [Jobs] Add update_job_labels and update_scheduled_job_labels by Wauplin in 4252
- feat: add rtx-pro-6000 hardware flavors by christophe-rannou in 4259

📚 **Documentation:** [Jobs guide — Update labels](https://huggingface.co/docs/huggingface_hub/main/en/guides/jobs#update-labels) | [Jobs guide — Hardware](https://huggingface.co/docs/huggingface_hub/main/en/guides/jobs#select-the-hardware)

🔧 Other QoL Improvements

- Fix failing on read-only file system even if the non-existence of file is already cached by ydshieh in 4274
- [CLI] Add `click` as an explicit dependency (typer 0.26.0 fix) by hanouticelina in 4270

📖 Documentation

- [Docs] Document missing parameters in lfs, hf_file_system, and repocard_data by kratos0718 in 4289

🐛 Bug and typo fixes

- fix `local_files_only` grammar by hunterhogan in 4255
- Fix typos in comments and debug log message by Sanjays2402 in 4278

🏗️ Internal

- Post-release: bump version to 1.17.0.dev0 by huggingface-hub-bot[bot] in 4247
- ci(release): migrate PyPI publish to Trusted Publishing + attestations by XciD in 4249
- [CI] Add import check with base dependencies only by Wauplin in 4250
- [Internal] Update style bot permissions by hanouticelina in 4260
- chore: enable Dependabot weekly GitHub Actions bumps by hf-dependantbot-rollout[bot] in 4262
- Bump actions in the actions group by dependabot[bot] in 4263
- chore: update release.yml by hf-security-analysis[bot] in 4264
- fix(release.yml): restore env: block on 'Detect version' step by paulinebm in 4267
- [Internal] Cap typer below 0.26.0 (CLI incompatibility) by hanouticelina in 4272
- [Internal] Run pinact (lock versions in workflow files) by Wauplin in 4275
- [Internal] Use Comment bot in model card gh action by Wauplin in 4277
- [CI] fix collection test by making its name unique by Wauplin in 4279
- Bump astral-sh/setup-uv from 7.6.0 to 8.1.0 in the actions group by dependabot[bot] in 4281
- [CLI] Drop legacy printing helpers from `_cli_utils.py` by hanouticelina in 4285

1.16.4

- [CI] Cap typer below 0.26.0 (CLI incompatibility) 4272

- [CI] Add click as explicit dependency 4270

**Full Changelog**: https://github.com/huggingface/huggingface_hub/compare/v1.16.1...v1.16.4

1.16.1

- [Hot-fix] [Inference] Remove Together ASR task to drop urllib3 dependency by Wauplin in  4248

**Full Changelog**: https://github.com/huggingface/huggingface_hub/compare/v1.16.0...v1.16.1

1.16.0

:zap: Together goes multimodal on Inference Providers

Together now supports five additional task types beyond chat and text-to-image on Inference Providers:
- `feature_extraction`
- `text_to_speech`
- ~`automatic_speech_recognition`~ **EDIT:** hot-fix **v1.16.1** removed this task (see https://github.com/huggingface/huggingface_hub/pull/4248) to fix a dependency issue. We will add it back in a future release.
- `image_to_image`
- `text_to_video`

python
from huggingface_hub import InferenceClient

client = InferenceClient(provider="together")

Embeddings
embeddings = client.feature_extraction("Hello world", model="intfloat/multilingual-e5-large-instruct")

Text-to-speech
audio = client.text_to_speech("Hello world", model="hexgrad/Kokoro-82M", extra_body={'voice': 'af_heart'})

Text-to-video
video = client.text_to_video("A cat on the moon", model="Wan-AI/Wan2.2-T2V-A14B")


- [Inference] Add embeddings, TTS, ASR, image-to-image and video tasks for Together by nbroad1881 in 4164

📚 **Documentation:** [Inference guide](https://huggingface.co/docs/huggingface_hub/main/en/guides/inference)

🔗 Centralized `hf://` URI parsing

All scattered ad-hoc `hf://` URI parsers throughout the codebase have been consolidated onto the new `parse_hf_uri`/`parse_hf_mount` helpers. This brings consistent parsing behavior, a new `is_hf_uri` public helper for validating URIs, and proper handling of `` in filenames (now treated as literal). The CLI error handler now catches `HfUriError` and displays a clean message instead of a raw traceback.

🚨 Breaking Changes

This migration includes several breaking changes: `BucketUrl.handle` has been renamed to `BucketUrl.uri` (type changed from `str` to `HfUri`, use `.to_uri()` for the string form), `Volume.to_hf_handle()` has been renamed to `Volume.to_uri()`, single-segment repo IDs (e.g. `gpt2`) are no longer supported in `HfFileSystem` paths or CLI `-v` flags — you must use the `namespace/name` format instead.

- [Core] Migrate hf:// URI parsing to centralized parse_hf_uri by Wauplin in 4189

📚 **Documentation:** [CLI guide](https://huggingface.co/docs/huggingface_hub/main/en/guides/cli) | [Buckets guide](https://huggingface.co/docs/huggingface_hub/main/en/guides/buckets)

🖥️ CLI

Global `--no-truncate` flag for CLI tables

A new `--no-truncate` global formatting flag disables the `...` shortening of scalar values in human-mode tables, letting you see full IDs, names, and other long text at a glance. List- and dict-valued columns (e.g. `tags`) remain shortened in human mode since they can be arbitrarily long; use `--format json` for those. When any cell is truncated, human tables now print a one-line hint at the bottom pointing you to the right flag.

bash
Show full scalar values in table output
hf models ls --no-truncate


- [CLI] Add global `--no-truncate` flag for human tables by hanouticelina in 4229

📚 **Documentation:** [CLI guide](https://huggingface.co/docs/huggingface_hub/main/en/guides/cli)

Miscellaneous

- [CLI] Surface job runtime fields in ps + inspect by davanstrien in 4211
- [CLI] Parse `initiator` field on jobs API responses by davanstrien in 4212
- [CLI] Support hf:// URIs in cache rm by abhinavgautam01 in 4235
- [CLI] Expose linked repos in PaperInfo by mishig25 in 4240
- [CLI] Raise error when both --local-dir and --cache-dir are provided by Wauplin in 4245

🔒 Token file permissions hardened

Token files written by `huggingface_hub` (`~/.cache/huggingface/token` and `~/.cache/huggingface/stored_tokens`) were previously created with Python's default modes, leaving them world-readable on most systems. This PR sets file permissions to `0o600` and parent directory permissions to `0o700` after every write, bringing `huggingface_hub` in line with industry-standard tools like GitHub CLI, AWS CLI, and Google Cloud SDK. Pre-existing installations will converge to safe permissions on the next token save. The `chmod` calls are wrapped in try/except for Windows, which doesn't support POSIX modes.

- [Auth] Harden HF_TOKEN_PATH and HF_STORED_TOKENS_PATH to 0o600 / 0o700 by JAE0Y2N in 4234

📊 Jobs

- Use server-side support to tail job logs by coyotte508 in 4202
- [Jobs] Add `ephemeral_storage` field to `JobHardware` by Wauplin in 4233

🐛 Bug and typo fixes

- [Download] Fix snapshot bar inflation on http_get retry by popfido in 4209

📖 Documentation

- [Docs] Refresh contributing guide and README by Wauplin in 4237

🏗️ Internal

- Post-release: bump version to 1.16.0.dev0 by huggingface-hub-bot[bot] in 4230
- Fix catch-all empty string in CI pytest --only-rerun by albertvillanova in 4239
- [Internal] Silence `ty` `invalid-type-form` on `WebhooksServer` annotations by hanouticelina in 4242
- [CI] make test_model_info_with_security for robust by Wauplin in 4246

1.15.0

🌍 Pick a region when creating buckets and repos

`create_bucket` and `create_repo` now accept an optional `region` argument (`"us"` or `"eu"`) so you can pin a new bucket or repo to a specific cloud region at creation time. The same option is exposed on the CLI via a `--region` flag on `hf buckets create` and `hf repos create`.

python
>>> from huggingface_hub import create_bucket, create_repo
>>> create_bucket("my-bucket", region="us")
>>> create_repo("my-model", region="eu")


bash
$ hf buckets create my-bucket --region us
$ hf repos create username/my-model --region eu


- [Bucket/Repo] Support 'region' option in create_bucket and create_repo by Wauplin in 4194

🧩 Discover marketplace skills with `hf skills list`

A new `hf skills list` (alias `ls`) command lists every skill available in the Hugging Face marketplace and shows whether each one is already installed in the four supported locations (project, global, project Claude, global Claude). Handy when you want to check what's installable and what you've already got before running `hf skills add`.

bash
$ hf skills ls
NAME                        DESCRIPTION                         PROJECT PROJECT (CLAUDE) GLOBAL GLOBAL (CLAUDE)
--------------------------- ----------------------------------- ------- ---------------- ------ ---------------
hf-cli                      Execute Hugging Face Hub operati...     yes              yes    yes             yes                                


- [CLI] Add `hf skills list` command by Wauplin in 4180

🎨 Polished `--help` output with ANSI styling

`hf --help` and every subcommand now render with underlined section headings and bold option/command names, making the help screens much easier to scan in a terminal. The new styling is automatically disabled when `NO_COLOR` is set or when the CLI detects it's running under an AI agent, so script and agent output stays clean.

- [CLI] Pretty-print `--help` with ANSI styling by Wauplin in 4192

🖥️ CLI

- [CLI] Check Homebrew registry for updates when installed via brew by Wauplin in 4204 — `hf update` no longer suggests a version that isn't on `brew` yet for Homebrew installs.
- [CLI] No traceback on LocalEntryNotFoundError by Wauplin in 4190 — offline/cache-miss errors now print a clean message instead of a Python traceback (set `HF_DEBUG=1` for the full stack).

🐛 Bug and typo fixes

- Make HF_HUB_ENABLE_HF_TRANSFER deprecation warning visible to users by Adithya191101 in 4220
- Fix hint message to use 'hf skills update' by Pierrci in 4206

📖 Documentation

- [docs] Drop duplicated Key Features list from hf jobs CLI section by davanstrien in 4222

🏗️ Internal

- [CI] Harden style-bot workflow against TOCTOU by paulinebm in 4183
- Only sync skill if SKILL.md has changed by evalstate in 4210

1.14.0

🖥️ Manage Space secrets and variables from the CLI

You can now manage Space secrets and environment variables directly from the command line with two new `hf spaces` subgroups: `secrets` and `variables`. Use `hf spaces secrets` to add, list, and delete write-only secrets, and `hf spaces variables` to add, list, and delete readable environment variables. Both `add` commands support multiple `-s`/`-e` flags and `--secrets-file`/`-env-file` for loading from dotenv files. On the Python side, `HfApi.get_space_secrets()` returns secret metadata (key, description, updated timestamp) without ever revealing values.

bash
List secrets (values are write-only — only keys and timestamps are shown)
$ hf spaces secrets ls username/my-space

Add secrets
$ hf spaces secrets add username/my-space -s OPENAI_API_KEY=sk-...
$ hf spaces secrets add username/my-space --secrets-file .env.secrets

Delete a secret (confirmation prompt, use --yes to skip)
$ hf spaces secrets delete username/my-space OPENAI_API_KEY --yes

List, add, and delete variables (values are readable)
$ hf spaces variables ls username/my-space
$ hf spaces variables add username/my-space -e MODEL_ID=gpt2 -e MAX_TOKENS=512
$ hf spaces variables delete username/my-space MAX_TOKENS --yes


- [CLI] Add hf spaces secrets and variables subgroups by davanstrien in 4170
- [CLI] Add get_space_secrets + hf spaces secrets ls by Wauplin in 4182

📚 **Documentation:** [CLI guide](https://huggingface.co/docs/huggingface_hub/main/en/guides/cli) · [Manage your Space](https://huggingface.co/docs/huggingface_hub/main/en/guides/manage-spaces)

🪣 Rsync-style trailing slash for bucket folder copies

`hf buckets cp` now supports rsync-style trailing slash semantics when copying folders. A trailing `/` on the source path copies only the folder's contents to the destination, while omitting it nests the folder itself — matching the behavior you'd expect from `rsync`. This makes it possible to flatten directory structures during copies, which was not possible before. Additionally, `copy_files` now raises an explicit `EntryNotFoundError` when the source path resolves to no files, instead of silently succeeding with zero operations.

bash
Without trailing slash: "logs" dir is nested => dst/logs/...
$ hf buckets cp hf://buckets/username/src-bucket/logs hf://buckets/username/dst/

With trailing slash: only contents of "logs" are copied => dst/...
$ hf buckets cp hf://buckets/username/src-bucket/logs/ hf://buckets/username/dst/


- [Buckets] Support rsync-style trailing slash in copy_files by Wauplin in 4187
- [CLI] Raise error when copy_files source doesn't exist by Wauplin in 4186

📚 **Documentation:** [Buckets guide](https://huggingface.co/docs/huggingface_hub/main/en/guides/buckets) · [CLI guide](https://huggingface.co/docs/huggingface_hub/main/en/guides/cli)

💔 Breaking Change

- [CLI] Rename `hf skills upgrade` -> `hf skills update` by hanouticelina in 4176 — `hf skills upgrade` no longer exists; use `hf skills update` instead.
- [CLI] Add `out.status()` by hanouticelina in 4171 — status updates (spinners/progress) on `hf extensions install` and `hf spaces dev-mode` are now suppressed when using `--format json`, `--quiet`, or `--format agent`.

🖥️ CLI

- [CLI] Add hints and example to `hf datasets leaderboard` by Wauplin in 4174
- [CLI] Shortcut `hf update` when already on latest version by julien-c in 4177
- [CLI] Remove progress bars on skills update by Wauplin in 4179
- [CLI] Increase default --limit from 10 to 30 for list commands by Wauplin in 4181
- [CLI] Support hf -v to print version by Wauplin in 4185
- [CLI] migrate `hf skills` to bucket by hanouticelina in 4175

🐛 Bug and typo fixes

- Update typer dependency version in setup.py by tomaarsen in 4193

🏗️ Internal

- Post-release: bump version to 1.14.0.dev0 by huggingface-hub-bot[bot] in 4172
- [Release] Move social drafts to minor-release and archive release notes to bucket by Wauplin in 4173
- Update unit test warnings check to ignore unrelated deprecation warnings by seanses in 4188
- [internal] Untrack useless files by Wauplin in 4191

1.13.0

🖥️ New CLI commands: repo cards, file listings, and dataset leaderboards

This release adds three new CLI capabilities for exploring Hub content. `hf models card`, `hf datasets card`, and `hf spaces card` fetch the README of any repo and print it to stdout, with `--metadata` (YAML frontmatter as JSON) and `--text` (prose only) flags for splitting the card into its structured and unstructured parts. Calling `hf models ls <repo_id>`, `hf datasets ls <repo_id>`, or `hf spaces ls <repo_id>` now switches from listing repos to listing files inside that repo, with `--tree`, `-R`, `-h`, and `--revision` options mirroring the existing `hf buckets ls` behavior. And `hf datasets leaderboard <dataset_id>` surfaces model scores submitted to a benchmark dataset, making it easy to compare models by score from the terminal.

bash
Get model card metadata as JSON
hf models card google/gemma-4-31B-it --metadata --format json

List files in a model repo (tree view with sizes)
hf models ls meta-llama/Llama-3.2-1B-Instruct --tree -h

Show top 5 models on SWE-bench
hf datasets leaderboard SWE-bench/SWE-bench_Verified --limit 5


📚 **Documentation:** [CLI guide](https://huggingface.co/docs/huggingface_hub/main/en/guides/cli)

- [CLI] Add hf models card and hf datasets card commands by davanstrien in 4118
- [CLI] Add file listing to models/datasets/spaces ls by Wauplin in 4166
- [CLI] add `hf datasets leaderboard` by hanouticelina in 4154

:rocket: Manage Spaces from the CLI

Three new `hf spaces` subcommands bring full lifecycle control to the terminal. `hf spaces pause` and `hf spaces restart` stop or rebuild a Space (with `--factory-reboot` for a clean rebuild), and `hf spaces settings` lets you configure sleep time and hardware in one call. A companion `hf spaces hardware` command lists all available hardware flavors with pricing, so you can discover options before changing settings. Pause and restart include a confirmation prompt (`-y` to skip) since they tear down the running container.

bash
Pause a Space when not in use (not billed while paused)
hf spaces pause username/my-space

Restart with a GPU
hf spaces settings username/my-space --hardware t4-medium --sleep-time 3600

List available hardware options
hf spaces hardware


📚 **Documentation:** [CLI guide — Spaces](https://huggingface.co/docs/huggingface_hub/main/en/guides/cli#hf-spaces)

- [CLI] Add spaces lifecycle commands: pause, restart, sleep by davanstrien in 4155
- [CLI] Add `hf spaces hardware` command by Wauplin in 4169
- [CLI] Add `--hardware` flag to `hf spaces settings` by davanstrien in 4163

:arrows_clockwise: `hf update` replaces the auto-update prompt

The blocking interactive Y/n auto-update prompt at CLI startup is gone. It was catching too many non-interactive contexts (CI runners, Homebrew post-install hooks, Jupyter notebooks) and hanging automation. In its place, a single yellow stderr warning suggests running `hf update` — a new command that detects how `hf` was installed (Homebrew, standalone installer, or pip) and runs the right upgrade command. Set `HF_HUB_DISABLE_UPDATE_CHECK=1` to silence the startup check entirely, for example in offline CI.

bash
hf update


📚 **Documentation:** [CLI guide — Updating](https://huggingface.co/docs/huggingface_hub/main/en/guides/cli#updating)

- [CLI] Add `hf update` + drop interactive update prompt by Wauplin in 4131

:pencil2: Global output formatting for every command

The `--format`, `--json`, and `-q` / `--quiet` flags are now handled globally by the CLI framework instead of being declared individually on each command. This means every `hf` command automatically accepts them — no more per-command `--format` boilerplate, and the flags are properly documented in a dedicated "Formatting options" section in every `--help` page. `--format auto` (the default) picks `human` for interactive terminals and `agent` when invoked by an AI agent, making CLI output automatically suitable for both people and tools.

bash
JSON output for scripting
hf models ls --search bert --limit 2 --json | jq '.[].id'

IDs only, one per line
hf collections ls --owner nvidia -q


📚 **Documentation:** [CLI guide — Output formatting](https://huggingface.co/docs/huggingface_hub/main/en/guides/cli#output-formatting)

- [CLI] Make --format / --json / -q global by Wauplin in 4162

🔗 Centralized `hf://` URI parsing

A new `parse_hf_uri` function and `HfUri` dataclass provide a single source of truth for parsing `hf://...` strings across the library. Whether you reference a model, dataset, space, bucket, or file inside a repo, the parser handles all valid URI shapes — type prefixes, revisions, and paths — and rejects invalid ones with clear error messages. A companion `parse_hf_mount` / `HfMount` handles volume mount specifications (`hf://...:/mnt:ro`). Both are pure string parsers (no network calls) and round-trippable via `.to_uri()`.

python
from huggingface_hub import parse_hf_uri, parse_hf_mount

parse_hf_uri("hf://datasets/namespace/my-datasetrefs/pr/3/train.json")
HfUri(type='dataset', id='namespace/my-dataset', revision='refs/pr/3', path_in_repo='train.json')

parse_hf_mount("hf://buckets/my-org/my-bucket/sub/dir:/mnt:ro")
HfMount(source=HfUri(type='bucket', id='my-org/my-bucket', ...), mount_path='/mnt', read_only=True)


📚 **Documentation:** [HF URIs reference](https://huggingface.co/docs/huggingface_hub/main/en/package_reference/hf_uris)

- Centralize hf:// URI parsing by Wauplin in 4158

🚀 Bucket transport for Jobs script upload

Local scripts uploaded by `hf jobs uv run` are now stored in a `{namespace}/jobs-artifacts` bucket and mounted into the job container at `/data` instead of being base64-encoded into an environment variable. The old `bash -c` + `xargs` + `base64 -d` pipeline was fragile and required manual shell quoting. Bucket transport is simpler, easier to debug, and supports write-back: jobs can persist output artifacts to `/data/` since the mount is read-write. The base64 transport path has been fully removed with no fallback.

- Add bucket+mount transport for Jobs script upload by davanstrien in 4025

🖥️ CLI

- [CLI] Print help when leaf command with required args is called without args by Wauplin in 4135

🤖 Inference

- [Inference Providers] Add DeepInfra support by hanouticelina in 4114
- Support list[str] inputs in feature_extraction by SJeffZhang in 4115

📖 Documentation

- [CLI] Add benchmark dataset filter examples by hanouticelina in 4156

🐛 Bug and typo fixes

- [BUG FIX]: hf_hub_download crashes when stderr lacks a real file descriptor by tobocop2 in 4065
- [CLI] Fix datasets list table rendering by hanouticelina in 4157
- [CLI] Fix installation method detection for curl-installed hf with Homebrew Python by Wauplin in 4142
- Avoid reuploading preuploaded LFS files in upload-large-folder by Dev-Jahn in 4165

🏗️ Internal

- [Release] Make release-notes job fail loudly on bad model/empty output by Wauplin in 4138
- [Release] Fix bucket URL in social posts Slack notification by Wauplin in 4139
- Post-release: bump version to 1.13.0.dev0 by huggingface-hub-bot[bot] in 4140
- [CI] Fix two flaky Windows tests (root causes, not skips) by Wauplin in 4141
- [Quality] Fix uvx ty check src errors by Wauplin in 4159
- [Release] Mark minor releases as "latest" on GitHub by Wauplin in 4167

1.12.2

- [Inference Providers] Add DeepInfra support in https://github.com/huggingface/huggingface_hub/pull/4114 by hanouticelina 


**Full Changelog**: https://github.com/huggingface/huggingface_hub/compare/v1.12.1...v1.12.2

1.12.0

🖥️ Unified output format for `hf buckets` commands

All `hf buckets` commands now use the unified `--format [auto|human|agent|json|quiet]` flag and the `out` singleton for consistent, scriptable output. The previous `--quiet` and `--format table|json` flags have been replaced by a single `--format` option that works across `create`, `list`, `info`, `delete`, `rm`, `move`, and `cp`. Success messages use `out.result()`, detail views use `out.dict()`, and listings use `out.table()` with proper empty-results handling — making the buckets CLI consistent with the rest of the `hf` command suite.

bash
Quiet mode: print only bucket IDs
hf buckets list --format quiet

JSON output for scripting
hf buckets create my-bucket --format json

Agent-friendly structured output
hf buckets info username/my-bucket --format agent


- [CLI] Migrate buckets commands to out singleton by hanouticelina in 4111

📚 **Documentation:** [Buckets guide](https://huggingface.co/docs/huggingface_hub/main/en/guides/buckets) · [CLI guide](https://huggingface.co/docs/huggingface_hub/main/en/guides/cli)

🪣 Search buckets by name

You can now filter buckets by name when listing them, both from the Python API and the CLI. Pass `search="checkpoint"` to `list_buckets()` or `--search "checkpoint"` to `hf buckets list` to find buckets matching a name pattern, without having to list and filter client-side.

bash
Filter buckets by name
hf buckets list --search "checkpoint"


py
Filter buckets by name in Python
for bucket in list_buckets(search="checkpoint"):
 print(bucket.id)


- [Buckets] Add search param to list_buckets by alexpouliquen in 4130

📚 **Documentation:** [Buckets guide](https://huggingface.co/docs/huggingface_hub/main/en/guides/buckets) · [CLI guide](https://huggingface.co/docs/huggingface_hub/main/en/guides/cli)

🖥️ CLI

- [CLI] spaces hot-reload: misc improvements by cbensimon in 4049
- [CLI] Detect `pi` agent by hanouticelina in 4125

🐛 Bug and typo fixes

- Apply fsspec config in HfFileSystem metaclass by joaquinhuigomez in 4062

🔧 Other QoL Improvements

- [Buckets] Skip local walk for download sync without delete by abidlabs in 4123
- [HfApi] Add `mainSize` to `ExpandDatasetProperty_T` by Wauplin in 4136

🏗️ Internal

- [Internal] Fix slack-message draft release permissions + update model by hanouticelina in 4119
- Post-release: bump version to 1.12.0.dev0 by huggingface-hub-bot[bot] in 4120
- [Internal] Make RELEASE_NOTES_MODEL configurable via repo variable by Wauplin in 4126
- [Release] Add social media draft generation to release workflow by Wauplin in 4132
- chore: bump doc-builder SHA for main doc build workflow by rtrompier in 4137
- [Release] Make release-notes job fail loudly on bad model/empty output by Wauplin in 4138

1.11.0

🔍 Semantic search for Spaces

Discover Spaces using natural language. The new `search_spaces()` API and `hf spaces search` CLI use embedding-based semantic search to find relevant Spaces based on what they do - not just keyword matching on their name.

python
>>> from huggingface_hub import search_spaces

>>> results = search_spaces("remove background from photo")
>>> for sp

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant