Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/source/_toctree.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
- sections:
- local: cli
title: Overview
- local: cli-cache
title: kernels cache ls
- local: cli-info
title: kernels info
- local: cli-describe-api
Expand Down
21 changes: 15 additions & 6 deletions docs/source/basic-usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,25 @@ This fetches version `1` of the kernel `kernels-community/activation`.
Kernels are versioned using a major version number. Using `version=1` will
get the latest kernel build from the `v1` branch.

You can check whether a kernel was downloaded with `hf cache ls`:
You can check which kernels and build variants are cached with

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

We can remove this when we overhaul this page soon and have a dedicated caching page.

[`kernels cache ls`](cli-cache.md):

```bash
# pip install hf
$ hf cache ls
ID SIZE LAST_ACCESSED LAST_MODIFIED REFS
----------------------------------- ---- -------------- -------------- ----
kernel/kernels-community/activation 2.5M 45 minutes ago 45 minutes ago
kernels cache ls
```

Example output (the values depend on your cache):

```text
ID SIZE LAST_ACCESSED LAST_MODIFIED REFS VARIANTS
----------------------------------- ---- -------------- -------------- ---- --------------------------------
kernel/kernels-community/activation 2.5M 45 minutes ago 45 minutes ago v1 torch28-cxx11-cu128-x86_64-linux
```

Each row includes variants from all cached revisions of that repository.
Use `kernels cache ls --no-truncate` or `--json` to see full values when the
table is shortened to fit your terminal.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Closely follows hf cache ls.


Kernels within a version branch must never break the API or remove builds
for older PyTorch versions. This ensures that your code will continue to work.

Expand Down
66 changes: 66 additions & 0 deletions docs/source/cli-cache.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# kernels cache ls

List kernels stored in the local Hugging Face cache. The output includes the
same repository details as `hf cache ls`, plus all cached build variants.
The command runs locally and does not download or load kernel code.

## Usage

```bash
kernels cache ls [--cache-dir PATH] [--json] [--no-truncate] [--show-warnings]
```

| Option | Description |
| --- | --- |
| `--cache-dir PATH` | Inspect a specific cache directory. |
| `--json` | Print cached kernel information as JSON. |
| `--no-truncate` | Display full table values regardless of terminal width. |
| `--show-warnings` | Show individual cache inconsistencies instead of a short summary. |

By default, the command uses the same cache as `get_kernel`: `KERNELS_CACHE`
when set, otherwise the Hugging Face Hub cache configured by `HF_HUB_CACHE`
or `HF_HOME`. An explicit `--cache-dir` takes precedence over these settings.

## Output

Example output in a wide terminal:

```text
ID SIZE LAST_ACCESSED LAST_MODIFIED REFS VARIANTS
----------------------------------- ---- -------------- -------------- ---- --------------------------------
kernel/kernels-community/activation 2.5M 45 minutes ago 45 minutes ago v1 torch28-cxx11-cu128-x86_64-linux

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I am not sure about using refs. We use and promote versions everywhere, so I think the default column rendering should be versions. Maybe a --refs argument could be used to override it.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I changed to VERSION. I didn't do any option for REFS, though. I don't think it's that useful in the context of kernels.

```

`VARIANTS` contains a sorted, comma-separated list of all build variants present
in the repository's cached snapshots. Repeated variant names appear once.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Hmmm. If they were duplicated, they were different versions. I think it'd be better to list different refs on different lines, so that one can see what variants are stored for a particular version.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Agreed. Fixed.

Variants are included regardless of compatibility with the current environment.
Only recognized build directories with cached files are listed; empty build
directories are excluded. If there are no cached variants, the column shows `-`.

Every cached revision contributes to the repository's row, including detached
snapshots without refs. `REFS` lists all locally cached branches and tags.

Like `hf cache ls`, the table shortens long values to fit the terminal width.
Use `--no-truncate` or `--json` to see all values in full. Cache inconsistencies
produce a short summary by default; use `--show-warnings` to see their details.
Comment on lines +54 to +56

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think it would be nicer if the row got multiple lines in this case, so that all variants can always be listed. Truncation is not nice, but lines wider than the terminal is also not nice.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Should be fixed now.


## JSON output

```bash
kernels cache ls --json
```

The output contains `cache_dir` and a `repos` list. Each repository contains:

- `repo_id`: the kernel repository ID.
- `size_on_disk`: the repository's cached size in bytes.
- `last_accessed`: the repository's last access time as a Unix timestamp.
- `last_modified`: the repository's last modification time as a Unix timestamp.
- `refs`: all cached refs, or an empty list.
- `variants`: all cached build variant names, without duplicates.

## See also

- [kernels variants](cli-variants.md) - Inspect build variants available on the Hub
- [kernels download](cli-download.md) - Download locked kernels
- [Environment variables](env.md) - Configure cache locations
1 change: 1 addition & 0 deletions docs/source/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ The `kernels` CLI provides commands for managing compute kernels.
| Command | Description |
| ------------------------------------------- | ---------------------------------- |
| [benchmark](cli-benchmark.md) | Run benchmark results for a kernel |
| [cache ls](cli-cache.md) | List cached kernels and build variants |
| [download](cli-download.md) | Download a kernel |
| [describe-api](cli-describe-api.md) | List public functions and layers |
| [info](cli-info.md) | Describe a kernel |
Expand Down
2 changes: 1 addition & 1 deletion kernels/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ license = { text = "Apache-2.0" }
readme = "README.md"
requires-python = ">= 3.10"
dependencies = [
"huggingface-hub>=1.31.0",
"huggingface-hub>=1.32.0",

@sayakpaul sayakpaul Oct 23, 2026 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

So that we can rely on huggingface_hub utilities as much as possible.

"packaging>=20.0",
"pyyaml>=6",
"sigstore>=4,<5",
Expand Down
21 changes: 21 additions & 0 deletions kernels/src/kernels/cli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from pathlib import Path
from typing import Literal

from kernels.cli.cache import print_cached_kernels
from kernels.cli.describe_api import print_kernel_api
from kernels.cli.download import download_kernels
from kernels.cli.info import print_kernel_info
Expand All @@ -16,6 +17,17 @@ def main():
parser = argparse.ArgumentParser(prog="kernel", description="Manage compute kernels")
subparsers = parser.add_subparsers(required=True)

cache_parser = subparsers.add_parser("cache", help="Inspect cached kernels")
cache_subparsers = cache_parser.add_subparsers(required=True)
cache_ls_parser = cache_subparsers.add_parser("ls", help="List cached kernels and their build variants")
cache_ls_parser.add_argument("--cache-dir", type=Path, help="Inspect a specific cache directory")
cache_ls_parser.add_argument("--json", action="store_true", help="Print cached kernel information as JSON")
cache_ls_parser.add_argument("--show-warnings", action="store_true", help="Show details of cache inconsistencies")
cache_ls_parser.add_argument(
"--no-truncate", action="store_true", help="Display full values regardless of terminal width"
)
cache_ls_parser.set_defaults(func=kernel_cache_ls)

check_parser = subparsers.add_parser("check", help="Check a kernel for compliance")
check_parser.add_argument("repo_id", type=str, nargs="?")
check_parser.set_defaults(func=_check_moved)
Expand Down Expand Up @@ -179,6 +191,15 @@ def kernel_info(args):
)


def kernel_cache_ls(args):
print_cached_kernels(
cache_dir=args.cache_dir,
json_output=args.json,
show_warnings=args.show_warnings,
no_truncate=args.no_truncate,
)


def kernel_api(args):
print_kernel_api(
args.kernel,
Expand Down
98 changes: 98 additions & 0 deletions kernels/src/kernels/cli/cache.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import json
import sys
from pathlib import Path
from typing import cast

from huggingface_hub import CachedRepoInfo, constants, scan_cache_dir
from huggingface_hub.utils import CacheNotFound, tabulate

from kernels.hf_hub import _get_cache_dir
from kernels.variants import get_variants_local


def print_cached_kernels(
*,
cache_dir: Path | None = None,
json_output: bool = False,
show_warnings: bool = False,
no_truncate: bool = False,
) -> None:
"""List cached kernel repositories and all their cached build variants."""
cache_dir = Path(cache_dir or _get_cache_dir() or constants.HF_HUB_CACHE).expanduser().resolve()
try:
cache = scan_cache_dir(cache_dir)
except CacheNotFound:
cache = None
except (OSError, ValueError) as error:
print(f"Cannot scan kernel cache: {error}", file=sys.stderr)
sys.exit(1)

repos = []
rows: list[list[str]] = []
if cache is not None:
for repo in sorted(cache.repos, key=lambda repo: repo.repo_id):
if repo.repo_type != "kernel":
continue
variants = _cached_variants(repo)
refs = sorted(repo.refs)
repos.append(
{
"repo_id": repo.repo_id,
"size_on_disk": repo.size_on_disk,
"last_accessed": repo.last_accessed,
"last_modified": repo.last_modified,
"refs": refs,
"variants": variants,
}
)
rows.append(
[
f"kernel/{repo.repo_id}",
repo.size_on_disk_str,
repo.last_accessed_str,
repo.last_modified_str,
", ".join(refs) or "-",
", ".join(variants) or "-",
]
)

if json_output:
print(json.dumps({"cache_dir": str(cache_dir), "repos": repos}, indent=2))
elif not rows:
print(f"No cached kernels found in {cache_dir}.")
else:
# Use the same terminal-width handling as `hf cache ls`.
from huggingface_hub.cli._output import _truncate_columns

headers = ["ID", "SIZE", "LAST_ACCESSED", "LAST_MODIFIED", "REFS", "VARIANTS"]
truncated = _truncate_columns(headers, rows, no_truncate=no_truncate)
print(tabulate(cast(list[list[str | int]], rows), headers=headers, alignments={"SIZE": "right"}))
if truncated:
print("Hint: Use `--no-truncate` or `--json` to display full values.", file=sys.stderr)

if cache is not None and cache.warnings:
if show_warnings:
for warning in cache.warnings:
print(f"Warning: {str(warning).rstrip('.')}. Repo ignored.", file=sys.stderr)
else:
print(
f"Warning: Found {len(cache.warnings)} cache inconsistencies. "
"Re-run with `--show-warnings` to display them.",
file=sys.stderr,
)


def _cached_variants(repo: CachedRepoInfo) -> list[str]:
names: set[str] = set()
for revision in repo.revisions:
build_path = revision.snapshot_path / "build"
# Empty build directories do not contain a cached variant.
cached_dirs = {
file.file_path.relative_to(build_path).parts[0]
for file in revision.files
if build_path in file.file_path.parents
}
names.update(
variant.variant_str for variant in get_variants_local(build_path) if variant.variant_str in cached_dirs
)
return sorted(names)
Loading
Loading