Skip to content
hf

Resource URIs

Use hf as a database/sql-style driver so a host program can address the hub as hf:// URIs.

hf is a command line, but the hf Go package is also a driver that makes huggingface.co addressable as resource URIs. A host program registers it the way a program registers a database driver with database/sql, then dereferences hf:// URIs without knowing anything about how the hub is fetched.

The host that does this today is ant, a single binary that puts one URI namespace over a family of site tools. The examples below use ant; any program that links the package gets the same behaviour.

Mounting the driver

A host enables the driver with one blank import, exactly like import _ "github.com/lib/pq":

import _ "github.com/tamnd/hf-cli/hf"

The package's init registers a domain with the scheme hf for the host huggingface.co. The standalone hf binary does not change.

The addressable types

A URI is scheme://authority/id, and the authority is the kind:

URI What it is
hf://model/google-bert/bert-base-uncased a model
hf://dataset/rajpurkar/squad a dataset
hf://space/black-forest-labs/FLUX.1-dev a space
hf://kernel/kernels-community/activation a compute kernel
hf://user/julien-c a user
hf://org/google an organization
hf://namespace/huggingface a name that is one of the two, before you know which
hf://collection/fdtn-ai/antares-6a5804c889e78b51c447c38a a collection
hf://paper/1810.04805 a paper
hf://post/PeetPedro/340848718906662 a community post
hf://blog/gradio-mcp a blog entry
hf://discussion/model/google-bert/bert-base-uncased#1 a discussion or pull request
hf://tag/arxiv:1810.04805 a vocabulary term
hf://task/text-generation a curated task page
hf://file/model/google-bert/bert-base-uncased@main/config.json a file at a revision
hf://ref/model/google-bert/bert-base-uncased@main a branch, tag, or sha
hf://split/rajpurkar/squad/plain_text/train a dataset split

The last few look busier than the rest because they have to carry the repo's kind and its revision. A file is only identified once you know which of the four repo kinds owns it and which revision you meant, and an id that leaves either out would not round trip.

ant get hf://model/google-bert/bert-base-uncased    # the record
ant cat hf://model/google-bert/bert-base-uncased    # the README body
ant url hf://dataset/rajpurkar/squad                # the live https URL
ant resolve https://huggingface.co/google/gemma-3-27b-it   # a pasted link, back to its URI

The same resolution works in the binary without a host:

hf uri https://huggingface.co/datasets/rajpurkar/squad
hf url hf://paper/1810.04805

Walking the graph

ls lists the members of a collection, and every member is itself an addressable URI, so a host can follow the graph and write it to disk:

ant ls     hf://org/google              # the org's repos, each addressable
ant ls     hf://dataset/rajpurkar/squad # its splits
ant export hf://org/google --follow 1 --to ./data

Because the records carry typed edges, ant export --follow and ant graph walk those edges too, and across tools when an edge points at another site's scheme. An arxiv: tag on a model is a citation edge to a paper, and a host that also mounts an arXiv driver can follow it off the hub entirely.

Why this is the same code

The driver and the binary share one definition per operation. A resolver op answers both hf model on the command line and ant get hf://model/... through a host, from the same handler and the same client. There is no second implementation to keep in step.