CLI Reference

Command-line interface

On first run, the tool prompts for configuration (database path and kernel storage directory). These are saved to ~/.config/spice-kernel-db/config.toml. All commands share a --db option to override the configured database path.

scan

Recursively scan a directory and register all kernel files.

spice-kernel-db scan <directory> [--mission NAME] [-v] [--archive]
Option Description
directory Root directory to scan recursively
--mission Override auto-detected mission name
-v, --verbose Print each registered file
--archive Move files to the configured kernel directory and leave symlinks at the original locations
# Auto-detect mission from path structure
spice-kernel-db scan /data/spice/JUICE/kernels

# Explicit mission label
spice-kernel-db scan /data/spice/generic_kernels --mission generic

# Verbose output
spice-kernel-db scan /data/spice/MRO/kernels -v

# Import kernels from a random directory into the central archive
spice-kernel-db scan /tmp/downloaded_kernels --mission JUICE --archive

With --archive, each kernel file is moved into the configured kernel directory (organized as {kernel_dir}/{mission}/{type}/{filename}) and a symlink is left at the original location. This lets you import kernels from anywhere while keeping the original paths functional.

Note

Symlinks require filesystem support. On Windows, Developer Mode or administrator privileges are needed. If symlink creation fails, the file is still moved and registered — only the symlink is skipped (with a warning).

stats

Print database summary statistics.

spice-kernel-db stats

Shows unique kernels, total locations, total size, number of duplicates, registered missions, and a breakdown by kernel type.

duplicates

Report all duplicated kernels.

spice-kernel-db duplicates

Lists each kernel that exists in 2+ locations, showing all paths and missions, with a total wasted space calculation.

check

Check which kernels from a metakernel are available locally.

spice-kernel-db check [metakernel] [--mission NAME] [-v]
Option Description
metakernel Path to a .tm file or registry filename. Omit to select interactively from locally acquired metakernels.
--mission Mission name for preferred-mission resolution
-v, --verbose Show full per-file warnings instead of compact summary
# Interactive — pick from local metakernels
spice-kernel-db check

# Explicit metakernel
spice-kernel-db check juice_crema_5_1.tm --mission JUICE

# Full per-file warnings
spice-kernel-db check juice_crema_5_1.tm -v

Reports found/missing counts, lists missing files, and shows warnings for cross-mission fallbacks. By default, warnings are grouped into a compact summary (dedup resolutions, cross-mission lookups). Use -v to see full per-file details.

If the metakernel was fetched from a remote server, check also queries the server to see if a newer version is available and prints a notice if so. This adds one HTTP request but does not download anything.

rewrite

Rewrite a metakernel with a local symlink tree.

spice-kernel-db rewrite <metakernel> -o <output> [--link-root DIR] [--mission NAME]
Option Description
metakernel Path to original .tm file
-o, --output Output .tm path (required)
--link-root Root for symlink tree (default: kernels/ next to output)
--mission Mission name for preferred-mission resolution
# Basic usage
spice-kernel-db rewrite juice_crema_5_1.tm -o juice_local.tm

# Custom symlink root
spice-kernel-db rewrite juice_crema_5_1.tm -o juice_local.tm \
    --link-root /data/spice/unified

# Explicit mission
spice-kernel-db rewrite juice_crema_5_1.tm -o juice_local.tm --mission JUICE

resolve

Find the local path for a single kernel filename.

spice-kernel-db resolve <filename> [--mission NAME]
Option Description
filename Kernel filename to look up
--mission Preferred mission for resolution
spice-kernel-db resolve naif0012.tls --mission JUICE
# /data/spice/JUICE/kernels/lsk/naif0012.tls

spice-kernel-db resolve mro_sc_2024.bc --mission JUICE
# /data/spice/MRO/kernels/ck/mro_sc_2024.bc
#   ⚠ mro_sc_2024.bc: not found in [JUICE] registry, using copy from [MRO]

Prints the resolved path to stdout and any warnings to stderr.

aliases

Show every filename a deduplicated kernel is known under. Content-addressed deduplication stores one physical file per unique content hash under a single canonical name; other filenames with identical content become aliases. This command lets you follow that trail from any name (or hash) back to the content and to all the sibling names it shares.

spice-kernel-db aliases [name-or-hash]
Option Description
name_or_hash A kernel filename (canonical or alias) or a SHA-256 (full or ≥6-char prefix). Omit to pick from the deduplicated kernels interactively.
# Direct lookup
spice-kernel-db aliases bc_mpo_hga_scm_20220101_20230101_s20221229_v01.bc

# No argument → interactive picker over deduplicated kernels
spice-kernel-db aliases

Prints the content hash, canonical name, kernel type and size, the full list of alias filenames (with the canonical one marked), and every on-disk location. With no argument it lists every deduplicated kernel (those whose content is shared under more than one filename), sorted most-aliased first, and lets you pick one. Exits non-zero if a supplied name or hash is unknown.

The get, update, and list commands also annotate any deduplicated kernel inline with (+N aliases) in their kernel tables, pointing you at aliases <name> for the full trail.

TipDiscover upstream aliases without deduplicating

Because identity is content-based, aliases surfaces names an archive (e.g. ESA) publishes the same bytes under — revealing, for example, that a _v13 kernel is byte-identical to _v12, or that two trajectory scenarios reuse the same solar-array/antenna kernels. This is a pure discovery feature: it needs no dedup step (symlinking duplicates is a separate, optional space-saving operation). See Discovering archive-side aliases.

verify

Deeply cross-check a metakernel against the database. Every entry in KERNELS_TO_LOAD is walked through PATH_VALUES/PATH_SYMBOLS substitution and validated.

spice-kernel-db verify [metakernel] [--deep] [--strict] [--json] [--mission NAME]
Option Description
metakernel Path to .tm file. Omit to select interactively from the registry.
--deep Recompute SHA-256 of every entry’s target (slow). Default: size-only checks.
--strict Exit non-zero on any non-OK finding. Default: only on fatal P0 issues.
--json Emit structured JSON instead of a rich table.
--mission Filter the interactive picker by mission.

Per-entry status codes:

Status Severity Meaning
OK Verified
DANGLING fatal Symlink target missing
NOT_FOUND fatal No file at the resolved path
NOT_FILE fatal Path exists but isn’t a regular file
TRAVERSAL fatal Entry resolves outside every PATH_VALUE root
HASH_MISMATCH fatal (deep mode) target’s SHA-256 ≠ DB record
SIZE_MISMATCH fatal File size disagrees with DB record
AMBIGUOUS fatal Multiple non-superseded kernels rows for the same filename
BAD_PATH_VALUE fatal PATH_VALUES entry not absolute or directory missing
UNREGISTERED warning File exists but no kernels row — run scan
# Quick check (size + presence)
spice-kernel-db verify ~/spice/juice/mk/juice_ops.tm

# Full hash recompute
spice-kernel-db verify ~/spice/juice/mk/juice_ops.tm --deep

# CI-friendly
spice-kernel-db verify juice_ops.tm --json --strict

Use this after a get/update to confirm the rewritten metakernel is sound. --deep is the only mode that catches content corruption that preserves file size.

prune

Remove stale database or filesystem state. Three mutually exclusive modes:

# Mode 1 (default): locations whose file no longer exists on disk
spice-kernel-db prune [--execute]

# Mode 2: metakernel registry rows whose source URL returns 4xx
spice-kernel-db prune --metakernels [--execute] [--delete-files]

# Mode 3: dangling symlinks under each mission's download tree
spice-kernel-db prune --orphan-symlinks [--execute]
Option Description
--execute Actually remove entries. Default: dry run.
--metakernels, --mk Metakernel-registry mode. Sends HEAD to each row’s effective URL (source_url if set, otherwise mission.mk_dir_url + filename); 403/404/410 = dead.
--orphan-symlinks Walk each mission’s download tree (derived from metakernel_registry.mk_path) recursively and find symlinks whose target no longer exists. These accumulate when an underlying kernel store moves, or after Mode 1 removes a location row.
--delete-files With --metakernels --execute: also unlink the on-disk .tm files.

Network errors (timeouts, DNS failures) in --metakernels mode are never treated as dead — pruning would otherwise discard real state when you happened to be offline.

--metakernels and --orphan-symlinks are mutually exclusive — run them sequentially if you want both.

# Default — preview stale kernel locations
spice-kernel-db prune

# Find dead metakernel registry rows
spice-kernel-db prune --metakernels --execute

# Sweep up dangling symlinks left behind
spice-kernel-db prune --orphan-symlinks --execute

dedup

Replace duplicate kernel files with symlinks.

spice-kernel-db dedup [--execute]
Option Description
--execute Actually replace files (default: dry run)
# Preview (default, safe)
spice-kernel-db dedup

# Do it
spice-kernel-db dedup --execute

The canonical copy (the file that symlinks point to) is chosen with a preference for files in the generic mission.

metakernels (alias: mk)

List tracked metakernels or show detailed info about a specific one.

spice-kernel-db metakernels [name] [--mission NAME]
spice-kernel-db mk [name] [--mission NAME]
Option Description
name Optional: show info for a specific metakernel (by filename)
--mission Filter listing by mission name
# List all tracked metakernels
spice-kernel-db metakernels

# Filter by mission
spice-kernel-db metakernels --mission JUICE

# Detailed info for a specific metakernel
spice-kernel-db metakernels juice_crema_5_1.tm

When no name is given, prints a summary table with kernel counts and availability. When a name is given, shows per-kernel status with type, size, and whether each kernel is in the database or missing.

get

Fetch a remote metakernel, show which kernels are needed, and download missing ones.

spice-kernel-db get [url] [--download-dir DIR] [--mission NAME] [-y] [--force]
Option Description
url URL to a remote .tm metakernel, or just a filename (e.g. juice_ops.tm). Omit to select interactively.
--download-dir Override default kernel storage directory
--mission Override auto-detected mission name (required if multiple missions known and using filename)
-y, --yes Skip confirmation prompt
--force Re-download all kernels even if already on disk (skips DB lookups and remote size queries)
# By filename (after browsing a mission at least once)
spice-kernel-db get juice_ops.tm

# By filename with explicit mission (when multiple missions are known)
spice-kernel-db get juice_ops.tm --mission JUICE

# By full URL
spice-kernel-db get https://naif.jpl.nasa.gov/pub/naif/JUICE/kernels/mk/juice_ops.tm

# Auto-confirm download
spice-kernel-db get juice_ops.tm -y

When a filename is given instead of a URL, the tool looks up the mk/ directory URL from the missions table (configured via mission add). Mission names support case-insensitive prefix matching (e.g. --mission bepi matches BEPICOLOMBO). If multiple missions are known, use --mission to disambiguate.

The tool fetches the remote metakernel, resolves each kernel entry to a full URL, checks your local database, queries remote file sizes (in parallel), and displays a summary table. Downloaded kernels are stored preserving the remote subdirectory structure (e.g. lsk/, spk/, ck/) and automatically registered in the database.

Archived metakernels. ESA (and some NAIF directories) rotate older versioned metakernels into a former_versions/ subdirectory once a newer version supersedes them. When a filename you request is not present in the live mk/ listing, get automatically retries under former_versions/<filename> before failing. The kernels referenced by the older metakernel are typically still available at their original locations (ESA in particular is purely additive — old kernel files are kept alongside new ones), so the rest of the download proceeds unchanged:

# A 2022-era versioned metakernel — auto-fetched from former_versions/
spice-kernel-db get juice_crema_2_0_ops_v200.tm --mission JUICE

If both the live and former_versions/ URLs 404, the error names both attempted URLs so you can diagnose archive layouts that don’t follow this convention.

update

Re-fetch a metakernel from its source URL and download any new or missing kernels.

spice-kernel-db update [metakernel] [--mission NAME] [--download-dir DIR] [-y] [--force]
Option Description
metakernel Metakernel filename or path. Omit to select interactively.
--mission Override mission name
--download-dir Override default kernel storage directory
-y, --yes Skip confirmation prompt
--force Re-download all kernels even if already on disk
# Interactive selection
spice-kernel-db update

# By filename
spice-kernel-db update juice_ops.tm

# Auto-confirm
spice-kernel-db update juice_ops.tm -y

This is a convenience command that combines looking up the source URL from the metakernel registry and calling get. It’s the recommended action after check or browse reports that a remote update is available. Metakernels added via scan (without a source URL) cannot be updated this way — use get with an explicit URL instead.

browse

Browse remote metakernels in a NAIF mission mk/ directory, or list known directories.

spice-kernel-db browse [url] [--mission NAME]
Option Description
url URL to a mission’s mk/ directory, or a mission name (omit to list known directories)
--mission Override auto-detected mission name
--show-versioned Show versioned snapshots under each metakernel
--sort {name,date} Row ordering. name (default) is alphabetical. date sorts by the Latest remote modification date ascending, so the most recently updated metakernels appear at the bottom — handy for spotting fresh updates at a glance.
--archived Browse the mission’s former_versions/ subdirectory instead of the live mk/ listing. Each archived metakernel is rendered on its own row (no base-name aggregation) because archived snapshots are distinct historical files, not byte-identical copies of a current file.
--filter SUBSTRING Case-insensitive substring filter on metakernel filenames. Particularly useful when combined with --archived to narrow listings of a thousand-plus entries.
# List all known mk/ directories (from missions table and previously acquired metakernels)
spice-kernel-db browse

# Browse by mission name (prefix matching, case-insensitive)
spice-kernel-db browse JUICE
spice-kernel-db browse bepi    # matches BEPICOLOMBO

# Browse by full URL
spice-kernel-db browse https://naif.jpl.nasa.gov/pub/naif/JUICE/kernels/mk/

# Sort by latest remote modification date (newest at the bottom)
spice-kernel-db browse JUICE --sort date

# Browse only the archived versions in former_versions/
spice-kernel-db browse JUICE --archived
spice-kernel-db browse JUICE --archived --sort date  # combine with sort

# Narrow a large listing with a substring filter (combinable with --archived)
spice-kernel-db browse JUICE --archived --filter crema_5_1

Without a URL, lists configured missions from the missions table:

Configured missions

  Mission  mk/ URL
  ───────  ──────────────────────────────────────────────────────────
  JUICE    https://spiftp.esac.esa.int/data/SPICE/JUICE/kernels/mk/
  MRO      https://naif.jpl.nasa.gov/pub/naif/MRO/kernels/mk/

Use 'spice-kernel-db browse <mission>' to scan a specific directory.
Use 'spice-kernel-db mission add' to add another mission.

With a URL, fetches the Apache directory listing, parses .tm file entries, groups them by base name (stripping version tags like _v461_20251127_001), and displays a compact summary:

Remote metakernels: JUICE (https://naif.jpl.nasa.gov/.../mk/)

  Metakernel                         Versions  Latest           Local
  ─────────────────────────────────  ────────  ──────────────── ────────
  juice_crema_5_0.tm                        1  2025-08-15 11:00 no
  juice_ops.tm                              3  2025-11-27 09:30 yes
  juice_plan.tm                             2  2026-02-02 14:00 outdated

  Total: 3 unique | 6 files | 1 locally acquired
  Run 'spice-kernel-db get <name>' to update outdated metakernels.
  Use --show-versioned to see individual snapshots.

The Local column shows three states:

  • yes — locally acquired and up to date (or scan-acquired, where remote date is unknown)
  • outdated — locally acquired but the remote copy has been modified since acquisition
  • no — not acquired locally

With --show-versioned, versioned snapshots are listed under each base metakernel:

  juice_ops.tm                                 2025-11-27 09:30    12K  yes
    snapshot: juice_ops_v230_20221128_001.tm   2022-11-28 10:00     8K
    snapshot: juice_ops_v461_20251127_001.tm   2025-11-27 09:30    12K

coverage

Check SPK body coverage in a metakernel. See the Coverage page for full details.

spice-kernel-db coverage <body> [metakernel] [--mission NAME]
Option Description
body NAIF body ID (e.g. 399) or body name (e.g. Earth)
metakernel Path to a .tm file or registry filename. Omit to select interactively.
--mission Mission name for preferred-mission resolution
# Interactive — pick metakernel, resolve body name
spice-kernel-db coverage Earth

# Explicit
spice-kernel-db coverage 399 juice_ops.tm --mission JUICE

Requires the optional spiceypy dependency: pip install spice-kernel-db[spice]

mission

Configure missions for filename-based acquisition and browsing. Mission names are matched case-insensitively and support prefix matching — e.g. bepi matches BEPICOLOMBO, ju matches JUICE (as long as the prefix is unambiguous).

mission add

Set up a new mission. Runs interactively with no arguments; non-interactive when a name (or --mk-dir-url) is given.

Interactive flow:

  1. Choose a server: [1] NASA [2] ESA
  2. View available missions from that server (split into “with metakernels” and “no default mk/”)
  3. Select one by number; or type the name of a “no default mk/” mission to consult the curated registry
  4. Configure deduplication: Enable deduplication for this mission? [Y/n]:
  5. Store in database
spice-kernel-db mission add
Option Description
name (positional, optional) Mission name. When given, prompts are skipped.
--server-url <URL> Archive server base URL. Required with positional name unless the mission name is unambiguous on a known server.
--mk-dir-url <URL> Override the metakernel directory URL (bypasses auto-discovery). Validated with a HEAD request.
--no-dedup Disable deduplication for this mission.
--use-planetarypy Delegate kernel management to planetarypy if the [planetarypy] extra is installed and the mission is registry-flagged.
# Interactive
spice-kernel-db mission add

# Non-interactive, explicit metakernel directory
spice-kernel-db mission add LRO \
  --server-url https://naif.jpl.nasa.gov/pub/naif/ \
  --mk-dir-url https://naif.jpl.nasa.gov/pub/naif/LRO/data/spice/mk/

# Non-interactive, let the tool auto-discover (curated registry + alt-path probe)
spice-kernel-db mission add OSIRIS-REX --server-url https://naif.jpl.nasa.gov/pub/naif/

When discovery finds multiple candidate metakernel directories, the command lists them and asks you to re-run with --mk-dir-url. When it finds none, it points at the troubleshooting docs.

Curated metakernel registry

For missions whose metakernels live outside the default {server}/{MISSION}/kernels/mk/ path — typically on PDS nodes rather than NAIF — the package ships mission_registry.toml, a curated list of verified alternate locations. The mission add flow checks this registry first, then falls back to the standard kernels/mk/ probe.

An empirical NAIF survey found that no missions use the speculative patterns (spice_kernels/mk/, data/spice/mk/, etc.) one might expect from naming convention alone; the registry is therefore deliberately sparse and only grows through verified contributions. See docs/troubleshooting.qmd for the contribution format. Registry entries may use absolute URLs (PDS nodes, mission websites), not just {server}/{m} placeholders.

After setup, the command prints next steps for acquiring metakernels.

mission list

Show all configured missions with their server, deduplication status, and mk/ directory URL.

spice-kernel-db mission list

Example output:

Configured missions:

  Mission  Server  Dedup  mk/ URL
  ───────  ──────  ─────  ──────────────────────────────
  JUICE    ESA     yes    https://spiftp.esac.esa.int/data/SPICE/JUICE/kernels/mk/
  MRO      NASA    no     https://naif.jpl.nasa.gov/pub/naif/MRO/kernels/mk/

mission remove

Remove a configured mission from the database.

spice-kernel-db mission remove <name>
Option Description
name Mission name to remove
spice-kernel-db mission remove MRO

config

Show or update configuration.

spice-kernel-db config [--setup]
Option Description
--setup Re-run the interactive first-time setup
# Show current settings
spice-kernel-db config

# Re-run setup (change database path, kernel directory, etc.)
spice-kernel-db config --setup

Without --setup, prints the current configuration: database path, kernel directory, and config file location.

reset

Delete the database and start fresh.

spice-kernel-db reset [-y]
Option Description
-y, --yes Skip confirmation prompt
# Interactive (asks for confirmation)
spice-kernel-db reset

# Skip confirmation
spice-kernel-db reset -y

Deletes only the DuckDB database file. Kernel files in the configured kernel directory are not touched. After resetting, you can re-index existing kernels:

spice-kernel-db scan ~/.local/share/spice-kernel-db/kernels