Skip to content

Conversation

hanouticelina
Copy link
Contributor

@hanouticelina hanouticelina commented Sep 15, 2025

Resolves #3363 and #3364.

This PR migrates the hf CLI from built-in argparse to Typer using idiomatic, function based commands. this significantly reduces boilerplate, making the CLI easier to maintain, less error prone, and faster to extend with new HfApi features.

What changed

  • new dependencies:

    • typer, latest version is 0.17.4, it should be stable enough and it's widely adopted.
    • click, typer s foundation, pure Python, should be stable too. latest version is 8.2.2.
    • ⚠️ rich has been disabled in all cases in commit (#3364) disable rich in all cases to keep a consistent UI regardless of having rich installed or not.
  • Main entrypoint: cli/hf.py now uses typer.Typer and mounts:

    • Top level single commands: download, upload, upload-large-folder, env, version (all defined in their respective files).
    • Groups: auth, cache, repo (with tag subgroup), repo-files, jobs (with scheduled and uv subgroups).
    • LFS helpers are still available but hidden in help: lfs-enable-largefiles, lfs-multipart-upload.
    • All argparse classes removed and replaced by Typer commands.
> hf --help
Usage: hf [OPTIONS] COMMAND [ARGS]...

  Hugging Face Hub CLI

Options:
  --install-completion  Install completion for the current shell.
  --show-completion     Show completion for the current shell, to copy it or
                        customize the installation.
  --help                Show this message and exit.

Commands:
  auth                 Manage authentication (login, logout, etc.).
  cache                Manage local cache directory.
  download             Download files from the Hub.
  env                  Print information about the environment.
  jobs                 Run and manage Jobs on the Hub.
  repo                 Manage repos on the Hub.
  repo-files           Manage files in a repo on the Hub.
  upload               Upload a file or a folder to the Hub.
  upload-large-folder  Upload a large folder to the Hub.
  version              Print information about the hf version.

Copy link
Contributor

@Wauplin Wauplin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very excited about this switch! I left some very high level comments on code organization :)

setup.py Outdated
@@ -28,6 +28,7 @@ def get_version() -> str:

extras["cli"] = [
"InquirerPy==0.3.4", # Note: installs `prompt-toolkit` in the background
"typer",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would move typer to a required dependency otherwise doing pip install huggingface_hub would install a CLI but unusable (since typer would be missing).

To reduce dependency overhead, especially the rich package, let's add typer-slim which is a lighter version without rich / shellingham included. More details here: https://typer.tiangolo.com/?h=typer+slim#typer-slim

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

About shellingham I still think it's good to have it. Either by default or in the (soon-to-come?) "hf installer script". It's a pure-python package that helps detecting the current shell to install shell completion correctly.

(for now let's skip it but mentioning it to have it in mind)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agree! it's an oversight from me, fixed in 8ee6892

@hanouticelina hanouticelina marked this pull request as ready for review September 17, 2025 08:19
Copy link
Contributor

@Wauplin Wauplin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks promising assuming commands implementations have not been changed^^

(I did not review the tests yet)

) -> None:
logging.set_verbosity_info()
repo_type = validate_repo_type(repo_type)
api = HfApi(token=token, library_name="hf")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's actually a really good idea to track usage of our CLI. I think it'd be good to centralize this (some other HfApi instantiations are not defining the library_name) but can be done in a later PR. (we have a subticket about analytics specifically)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
api = HfApi(token=token, library_name="hf")
api = HfApi(token=token, library_name="hf", library_version=__version__)

might be nice to add huggingface_hub version as well (would make things easier to works with in Kibana even though we already have the info in hf_hub user agent)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for CLI, i addressed it directly in this PR (in f2eb79b) but yes let's do the same for other HfApi instantiations

@HuggingFaceDocBuilderDev

The docs for this PR live here. All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update.

@hanouticelina
Copy link
Contributor Author

This PR resolves #3370 in 3e5bc64.

Screenshot 2025-09-17 at 15 00 29

Copy link
Contributor

@Wauplin Wauplin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pre-approving ✔️ Feel free to ignore my last comments if annoying 😄

Let's get this merge soon! 🎉

(note: I also tested autocompletion locally which worked like a charm)

Comment on lines 34 to 72
# top level single commands (defined in their respective files)
app.command(
name="download",
help="Download files from the Hub.",
)(download)
app.command(
name="upload",
help="Upload a file or a folder to the Hub.",
)(upload)
app.command(
name="upload-large-folder",
help="Upload a large folder to the Hub. Recommended for resumable uploads.",
)(upload_large_folder)
app.command(
name="env",
help="Print information about the environment.",
)(env)
app.command(
name="version",
help="Print information about the hf version.",
)(version)
app.command(
name="lfs-enable-largefiles",
help="Configure your repository to enable upload of files > 5GB.",
hidden=True,
)(lfs_enable_largefiles)
app.command(
name="lfs-multipart-upload",
help="Upload large files to the Hub.",
hidden=True,
)(lfs_multipart_upload)


# command groups
app.add_typer(auth_cli, name="auth")
app.add_typer(cache_cli, name="cache")
app.add_typer(repo_cli, name="repo")
app.add_typer(repo_files_cli, name="repo-files")
app.add_typer(jobs_cli, name="jobs")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fine for me yes! Thanks for looking into this :)

@hanouticelina
Copy link
Contributor Author

Let's get this merged once the CI is green! 🔥

@hanouticelina hanouticelina merged commit c5c185d into cli-improvements Sep 18, 2025
18 checks passed
@hanouticelina hanouticelina deleted the typer-migration branch September 18, 2025 09:57
hanouticelina added a commit that referenced this pull request Sep 18, 2025
* Refactor CLI implementation using Typer (#3365)

* migrate CLI to typer

* (#3364) disable rich in all cases

* update tests

* make typer-slim a required dep

* use Annotated

* fix linting issues

* fix tests

* refactoring

* update docs

* use built in types

* fix mypy

* call whoami directly

* lint

* Apply suggestions from code review

Co-authored-by: Lucain <[email protected]>

* import Annotated from typing

* Use Enums

* set verbosity globally

* refactor scan cache and update version docstring

* centralize where Typer is defined

* no need for ...

* rename enum

* no need for extra param name

* docstring

* revert

* centralize arguments and options definition

* add library version when initializing HfApi

* add auto-completion

* sort commands alphabetically

* suggestions

* centralize jobs params and HfApi initialization

* fix

---------

Co-authored-by: Lucain <[email protected]>

* update docs

---------

Co-authored-by: Lucain <[email protected]>
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.

3 participants