JuliaHub CLI (jh v0.4.3)
A command-line interface for interacting with JuliaHub, a platform for Julia computing that provides dataset management, job execution, project management, Git integration, and package hosting capabilities.
Features
- Authentication: OAuth2 device flow authentication with JWT token handling
- Dataset Management: List, download, upload, and check status of datasets
- Job Results: List and download a job's result files (and its other input/source/project files)
- Package Management: Search and explore Julia packages across registries via REST API (GraphQL fallback), with dependency analysis
- Registry Management: List, add, and update Julia package registries
- Project Management: List and filter projects using GraphQL API
- Git Integration: Clone, push, fetch, and pull with automatic JuliaHub authentication
- Julia Integration: Install Julia and run with JuliaHub package server configuration
- User Management: Display user information, list users and groups
- Vulnerability Scanning: Scan Julia packages for known security vulnerabilities
- Manifest Scanning: Upload a
Manifest.tomlfor a server-side Trivy vulnerability scan of its pinned dependencies - Search: Search package source code (regex), symbol definitions and uses, and rendered documentation across the indexed packages, with
--jsonoutput for scripts and agents - Administrative Commands: Manage users, groups, tokens, credentials, and system resources (requires admin permissions)
jh comes pre-installed in all services and applications on the JuliaHub platform, including VS Code, Windows Workstations, and any batch jobs or Applications. You only need to install it manually when you want to use it on your own machine.
Installation
Download the installation scripts directly
If you prefer to inspect or host the installers yourself, download them directly:
install.sh— Linux and macOSinstall.ps1— Windows (PowerShell)install.bat— Windows (Command Prompt)
Quick Install
Linux and macOS
Install the latest release automatically:
curl -sSfL https://raw.githubusercontent.com/JuliaComputing/jh/v0.4.3/install.sh | shOr download and run the script manually:
wget https://raw.githubusercontent.com/JuliaComputing/jh/v0.4.3/install.sh
chmod +x install.sh
./install.shOptions:
--install-dir DIR: Custom installation directory (default:$HOME/.local/bin)--help: Show help message
Custom installation directory example:
curl -sSfL https://raw.githubusercontent.com/JuliaComputing/jh/v0.4.3/install.sh | sh -s -- --install-dir /usr/local/binWindows
Option 1: PowerShell (Recommended)
# Download and run the PowerShell installer
Invoke-WebRequest -Uri "https://raw.githubusercontent.com/JuliaComputing/jh/v0.4.3/install.ps1" -OutFile "install.ps1"; .\install.ps1; Remove-Item install.ps1Or download and run manually:
# Download the installer
Invoke-WebRequest -Uri "https://raw.githubusercontent.com/JuliaComputing/jh/v0.4.3/install.ps1" -OutFile "install.ps1"
# Run the installer
.\install.ps1
# Clean up
Remove-Item install.ps1Option 2: Command Prompt (CMD)
curl -L "https://raw.githubusercontent.com/JuliaComputing/jh/v0.4.3/install.bat" -o install.bat && install.bat && del install.batOr download and run manually:
curl -L "https://raw.githubusercontent.com/JuliaComputing/jh/v0.4.3/install.bat" -o install.bat
install.bat
del install.batWindows Installation Notes:
- PowerShell script supports custom install directory:
.\install.ps1 -InstallDir "C:\tools\bin" - PowerShell script can automatically add to PATH: will prompt unless you use
-NoPrompt - For automated installs:
.\install.ps1 -NoPrompt(won't add to PATH automatically) - Default install location:
%USERPROFILE%\.local\bin - CMD script requires curl (available in Windows 10 1803+ and Windows 11)
- After installation, restart your terminal or run
refreshenvto usejhcommand
Download Binary Manually
Download the latest release from the GitHub releases page.
Available for:
- Linux (amd64, arm64)
- macOS (amd64, arm64)
- Windows (amd64, arm64)
Build from Source
git clone https://github.com/JuliaComputing/jh
cd jh
go build -o jh .Quick Start
Authenticate with JuliaHub:
jh auth loginList your datasets:
jh dataset listList your projects:
jh project listClone a project:
jh clone username/project-nameSetup Git credential helper (recommended for seamless Git operations):
jh git-credential setup # Now you can use standard Git commands with JuliaHub repositories git clone https://juliahub.com/git/projects/uuid.git
Commands
Authentication (jh auth)
jh auth login- Login to JuliaHub using OAuth2 device flowjh auth login -s yourinstallto login to yourinstall.juliahub.com
jh auth refresh- Refresh authentication tokenjh auth status- Show authentication statusjh auth env- Print environment variables for authentication
Dataset Management (jh dataset)
jh dataset list- List all accessible datasetsjh dataset download <dataset-id> [version] [local-path]- Download a datasetjh dataset upload [dataset-id] <file-path>- Upload a datasetjh dataset status <dataset-id> [version]- Show dataset status
Job Results (jh job result)
jh job result list <job-name>- List a job's result files (--allfor every job file,--jsonfor scripts)jh job result download <job-name> [file-name]- Download one or all result files (-odestination,--forceto overwrite,--typefor other job file types)
Package Management (jh package)
jh package search [search-term]- Search for Julia packages- Default: Shows Name, Registry, Owner, Version, and Description
jh package search --verbose- Show detailed package information including UUID, repository, tags, stars, docs, and license--registries <names>- Filter by registry names (comma-separated, e.g.General,MyRegistry)--limit <n>- Maximum results to return (default: 10)--offset <n>- Number of results to skip--json- Print only{"results": [...], "total": N}on stdout (also available asjh search packages)
jh package info <package-name>- Get detailed information about a specific package (exact name match, case-insensitive): the listing fields (owner, stars, license, latest version, downloads over the last 30 days, app/Dyad type) plus the stable version's homepage, release date, dependency and dependent counts, contributors and docs build typejh package info --registries General- Search in specific registries onlyjh package info --json- Print only{"results": [...], "total": N}on stdout
jh package dependency <package-name>- List package dependencies- Default: Shows up to 10 direct dependencies (NAME, REGISTRY, UUID, VERSIONS)
jh package dependency --indirect- Include both direct and indirect dependenciesjh package dependency --registry General- Specify registry to usejh package dependency --short- Print one line:JuMP v1.32.1 · General: 9 direct · 40 indirect · 49 total dependenciesjh package dependency --json- Print only{"name", "version", "registry", "dependencies": [...]}on stdout (--indirectadds the indirect ones)
jh package dependents <package-name>- List packages that depend on a package (reverse dependencies)- Default: Prints direct/indirect/total counts and lists the direct dependents (NAME, REGISTRY, UUID)
jh package dependents --indirect- Also list indirect dependentsjh package dependents --registry General- Specify registry to usejh package dependents --short- Print one line:JuMP v1.32.1 · General: 335 direct · 94 indirect · 429 total dependentsjh package dependents --json- Print only{"name", "version", "registry", "direct", "indirect", "total", "dependents": [...]}on stdout; the counts always cover every dependent,dependentslists the indirect ones only with--indirect
Registry Management (jh registry)
jh registry list- List all package registries on JuliaHub- Default: Shows only UUID and Name
jh registry list --verbose- Show detailed registry information including owner, creation date, package count, and description
jh registry config <name>- Show the full JSON configuration for a registryjh registry config add- Add a new registry (JSON payload via stdin or--file)jh registry config update- Update an existing registry (same JSON schema as add, same flags)jh registry permission list <registry>- List permissions for a registryjh registry permission set <registry> --user|--group <name> --privilege download|register- Add or update a permissionjh registry permission remove <registry> --user|--group <name>- Remove a permission
Project Management (jh project)
jh project list- List all accessible projectsjh project list --user- List only your projectsjh project list --user <username>- List specific user's projects
Git Credential Helper (Recommended)
jh git-credential setup- Configure Git to use JuliaHub authentication- After setup, use standard Git commands:
git clone,git push,git pull
Git Operations
jh clone <username/project> [local-path]- Clone a JuliaHub project by username/project namejh push [git-args...]- Push with authenticationjh fetch [git-args...]- Fetch with authenticationjh pull [git-args...]- Pull with authentication
Julia Integration
jh julia install- Install Julia programming languagejh run [-- julia-args...]- Run Julia with JuliaHub configurationjh run setup- Setup JuliaHub credentials for Julia without starting Julia
User Information (jh user)
jh user info- Show detailed information about the logged-in userjh user list- List all users (<name> (<username>)format, via GraphQL)
Group Information (jh group)
jh group list- List all groups (one per line, via GraphQL)
Administrative Commands (jh admin)
User Management
jh admin user list- List all users (requires appropriate permissions)- Default: Shows
<name> (<email>)per line jh admin user list --verbose- Show detailed user information including UUID, groups, and features
- Default: Shows
Group Management
jh admin group list- List all groups via REST API (requires appropriate permissions)
Token Management
jh admin token list- List all tokens (requires appropriate permissions)- Default: Shows only Subject, Created By, and Expired status
jh admin token list --verbose- Show detailed token information including signature, creation date, expiration date (with estimate indicator)
Credential Management
jh admin credential list- List all credentials (tokens, SSH keys, GitHub Apps)jh admin credential list --verbose- Show detailed info including token metadata (account, expiry, scopes, rate limit) and SSH host keys
jh admin credential add token <JSON>- Add a token credentialjh admin credential add ssh <JSON>- Add SSH key credentialsjh admin credential add github-app <JSON>- Add a GitHub App credentialjh admin credential update token <JSON>- Update an existing token credentialjh admin credential update ssh <JSON>- Update an SSH credential by 1-based indexjh admin credential update github-app <JSON>- Update an existing GitHub App credentialjh admin credential delete token <name>- Delete a token credentialjh admin credential delete ssh <index>- Delete an SSH credential by 1-based indexjh admin credential delete github-app <app-id>- Delete a GitHub App credential
All add and update commands accept JSON as a positional argument or from stdin:
jh admin credential add token '{"name":"MyToken","url":"https://github.com","value":"ghp_xxxx"}'
echo '{"name":"MyToken","url":"https://github.com","value":"ghp_xxxx"}' | jh admin credential add tokenLanding Page Management
The landing page is the markdown "Welcome" (greeter) card of the home page layout, the one edited under Administrator → Settings → Custom Landing Page. These commands edit only that card via the homepage layout API (/api/v1/ui/layout/homepage) and leave the rest of the layout untouched.
jh admin landing-page show- Print the current landing page markdown (reports "No custom content set" when the layout has no Welcome card)jh admin landing-page update <markdown-content>- Set the landing page markdown (adds a Welcome card as the first row if the layout has none)jh admin landing-page update --file landing.md- Read content from a filecat landing.md | jh admin landing-page update- Read content from stdin
jh admin landing-page remove- Remove the Welcome card from the home page layout
Vulnerability Scanning (jh vuln)
jh vuln <package-name>- Show known vulnerabilities for a Julia package- Defaults to the latest stable version (fetched from the registry); only shows advisories where that version is affected
--version <ver>- Check a specific version instead of the latest--registry <name>- Registry to use for version lookup (default:General)--advisory <id>- Filter to a specific advisory ID (e.g. a CVE or GHSA identifier)--all- Show all advisories regardless of whether the queried version is affected--verbose/-v- Show additional details: aliases, published/modified dates, and references- Advisory IDs are clickable links to the JuliaLang SecurityAdvisories repository
- Each advisory shows: severity scores, affected status, full summary, affected versions, and version ranges
Manifest Scanning (jh scan)
jh scan [path]- Upload aManifest.toml(and the siblingProject.tomlwhen present), queue a Trivy vulnerability scan, and (by default) poll until it finishespathmay be a directory (looks forManifest.tomlandProject.tomlinside) or a manifest file; defaults to the current directory--project <path>- Use an explicitProject.tomlinstead of the auto-detected sibling--no-project- Skip theProject.tomleven if a sibling exists--tool <id>- Static analysis tool id (default:juliahub-trivy)--no-wait- Submit and return immediately, printing only therun_uuid--csv- Request results as CSV (negotiated via theAcceptheader; ignored with--no-wait)--output <file>/-o- Write the results to a file instead of stdout--poll-interval <sec>- Poll cadence while waiting (default: 3)--timeout <sec>- Max seconds to wait for the scan (default: 600)- The
run_uuidis printed up front, so Ctrl+C during polling leaves the scan running on the server; resume withjh scan status/jh scan results
jh scan status <run-uuid>- Show lifecycle status (staging,initiated,queued,completed,failed) plus tool/timing info and any failure reasonjh scan results <run-uuid>- Fetch results for a finished scan--csv- CSV output instead of JSON--output <file>/-o- Write to a file instead of stdout
Search (jh search)
Search the Julia packages indexed on JuliaHub. Every subcommand takes --json, which prints only a JSON document on stdout (notes and errors go to stderr), so the output can be consumed directly by scripts and by tool-calling agents.
jh search code <pattern>- Regular-expression (RE2) search over package source files; one result per matching line with package, registry,file:lineand the line text--package <name|uuid>- Restrict to a package (repeatable; names are resolved to UUIDs via the package catalogue)--registry <name>- Restrict to a registry (repeatable)--path <regex>- Only search files whose path matches--ignore-case- Case-insensitive match--limit <n>- Maximum number of results (default: the server's)--json-{"results": [...], "truncated": bool}
jh search symbols <name>- Find where a function, type, macro or module is defined and used--type <kind>-function,type,macroormodule(repeatable)--usage <kind>-defineoruse(repeatable)--package,--registry,--limit,--jsonas forcode
jh search docs <query>- Natural-language search over rendered package documentation; results are packages ranked by score with their matching sections--threshold <x>- Keep results scoring at leastx(0-1) times the best result's score--strict-phrase/--strict-phrase=false- Require the query as a phrase / match its words separately (default: the server's setting, strict on a default install)--package,--registry,--limit,--jsonas forcode
jh search packages [search-term]- The package catalogue search (same asjh package search), with--registries,--limit,--offset,--verboseand--json({"results": [...], "total": N})--server/-saccepts a JuliaHub host as elsewhere, or a full URL such as--server http://localhost:4446to pointcode/symbols/docsat a locally running search service (no stored login required; the request is sent unauthenticated with a note on stderr, and--packagemust then be given as a UUID). The stored token is only ever sent overhttps://, or overhttp://to a loopback host; a plain-http URL on any other host gets an unauthenticated request and a note- Older JuliaHub installs expose only the legacy search routes; the CLI detects this and falls back to them automatically. In human-readable mode a
note: results truncated (search stopped early)line on stderr means the server stopped before exhausting the index
Update (jh update)
jh update- Check for updates and automatically install the latest versionjh update --force- Force update even if current version is newer than latest release
Configuration
Configuration is stored in ~/.juliahub with 0600 permissions. The file contains:
- Server configuration
- Authentication tokens (access, refresh, ID tokens)
- User information (name, email)
Default server: juliahub.com
Currently, you will only be logged in one server at a time.
Examples
Dataset Operations
# List datasets
jh dataset list
# Download latest version of a dataset
jh dataset download my-dataset
# Download specific version
jh dataset download username/dataset-name v2
# Upload new dataset
jh dataset upload --new ./my-data.tar.gz
# Upload new version to existing dataset
jh dataset upload my-dataset ./updated-data.tar.gzJob Result Operations
A job produces a result file by setting ENV["RESULTS_FILE"] to a file path; JuliaHub uploads it when the job finishes.
# List a job's result files
jh job result list jr-abc123xyz
# List every file attached to the job, with its type
jh job result list --all jr-abc123xyz
# Download all result files into the current directory
jh job result download jr-abc123xyz
# Download one result file to a specific path (e.g. to reuse a previous run's output)
jh job result download jr-abc123xyz results.tar.gz -o previous-run.tar.gz
# Download into a directory, overwriting existing files
jh job result download jr-abc123xyz -o results/ --forcePackage Operations
# Search for packages by name
jh package search dataframes
# Search with verbose output
jh package search --verbose plots
# Filter by registry
jh package search --registries General optimization
# Limit and paginate results
jh package search --limit 20 --offset 0 ml
# Get detailed info about a specific package
jh package info DataFrames
jh package info Plots --registries General
# List package dependencies
jh package dependency DataFrames # Shows up to 10 direct dependencies
jh package dependency DataFrames --indirect # Includes indirect dependencies
jh package dependency CSV --registry General # Use specific registry
# List reverse dependencies (dependents)
jh package dependents JuMP # Counts, plus the direct dependents
jh package dependents JuMP --indirect # Also lists indirect dependentsRegistry Operations
# List all registries (UUID and Name only)
jh registry list
# List registries with detailed information
jh registry list --verbose
# List registries on custom server
jh registry list -s yourinstall
# Show full configuration for a registry
jh registry config JuliaSimRegistry
jh registry config JuliaSimRegistry -s nightly.juliahub.dev
# Add a registry (JSON via stdin or --file)
echo '{
"name": "MyRegistry",
"license_detect": true,
"artifact": {"download": true},
"docs": {"download": true, "docgen_check_installable": false, "html_size_threshold_bytes": null},
"metadata": {"download": true},
"pkg": {"download": true, "static_analysis_runs": []},
"enabled": true, "display_apps": true, "owner": "", "sync_schedule": null,
"download_providers": [{
"type": "cacheserver", "host": "https://pkg.juliahub.com",
"credential_key": "JC Auth Token"
}]
}' | jh registry config add
# Or use a file
jh registry config add --file registry.json
# Update an existing registry (same JSON schema, registry identified by "name" field)
jh registry config update --file registry.jsonProject Operations
# List all projects you have access to
jh project list
# List only your projects
jh project list --user
# List projects by specific user
jh project list --user aliceUser and Group Operations
# List users (GraphQL)
jh user list
# List groups (GraphQL)
jh group listAdministrative Operations
# List all users (requires admin permissions)
jh admin user list
# List users with detailed information
jh admin user list --verbose
# List all groups via REST (requires admin permissions)
jh admin group list
# List all tokens (requires admin permissions)
jh admin token list
# List tokens with detailed information including signatures and dates
jh admin token list --verbose
# List tokens on custom server
jh admin token list -s yourinstall
# Use specific timezone for date display
TZ=America/New_York jh admin token list --verbose
# List credentials
jh admin credential list
jh admin credential list --verbose
# Add a token credential (JSON as argument or via stdin)
jh admin credential add token '{"name":"MyGHToken","url":"https://github.com","value":"ghp_xxxx"}'
# Add SSH credentials (private key from file)
jh admin credential add ssh '{"host_key":"github.com ssh-ed25519 AAAA...","private_key_file":"/home/user/.ssh/id_ed25519"}'
# Add a GitHub App credential
jh admin credential add github-app '{"app_id":"12345","url":"https://github.com/my-org","private_key_file":"app.pem"}'
# Update a token's URL (partial update — only supply fields to change)
jh admin credential update token '{"name":"MyGHToken","url":"https://github.com/new-org"}'
# Update an SSH key by index (use list to find the index)
jh admin credential update ssh '{"index":1,"private_key_file":"/home/user/.ssh/new_key"}'
# Delete credentials
jh admin credential delete token MyGHToken
jh admin credential delete ssh 1
jh admin credential delete github-app 12345Landing Page Operations
# Show current custom landing page
jh admin landing-page show
# Set landing page from inline markdown
jh admin landing-page update '# Welcome to JuliaHub'
# Set landing page from a file
jh admin landing-page update --file landing.md
# Set landing page from stdin
cat landing.md | jh admin landing-page update
# Remove the custom landing page (drops the Welcome card from the home page layout)
jh admin landing-page removeVulnerability Scanning
# Scan latest stable version (only shows advisories where it is affected)
jh vuln MbedTLS_jll
# Scan a specific version
jh vuln MbedTLS_jll --version 2.28.1010+0
# Show all advisories regardless of affected status
jh vuln MbedTLS_jll --all
# Filter to a specific advisory
jh vuln MbedTLS_jll --advisory JLSEC-2025-232
# Show extra details (aliases, dates, references)
jh vuln MbedTLS_jll --verbose
# Use a non-General registry for version lookup
jh vuln MyPkg --registry MyRegistry
# Scan against a custom server
jh vuln SomePackage -s nightly.juliahub.devManifest Scanning
# Scan the Manifest.toml + Project.toml in the current directory; polls until done
jh scan
# Scan the manifest from a specific project directory
jh scan ./my-project
# Use an explicit manifest file and override the Project.toml path
jh scan Manifest.toml --project=Project.toml
# Write CSV results to a file instead of JSON on stdout
jh scan --csv --output results.csv
# Submit the scan and return immediately (prints just the run_uuid)
jh scan --no-wait
# Check the status of an earlier scan (e.g. after Ctrl+C or --no-wait)
jh scan status <run-uuid>
# Pull results for a finished scan
jh scan results <run-uuid>
jh scan results <run-uuid> --csv --output results.csvSearch
# Regex search over package source; restrict to two packages and a registry
jh search code "@kwdef" --package DataFrames --package CSV --registry General
# Only files under src/, case-insensitive, at most 20 hits
jh search code "todo" --path "^src/" --ignore-case --limit 20
# Where is the DataFrame type defined?
jh search symbols DataFrame --type type --usage define
# Every use of the @time macro
jh search symbols @time --type macro --usage use --limit 50
# Documentation search, five best packages
jh search docs "read a CSV file into a DataFrame" --limit 5
# Package catalogue search under the search group
jh search packages dataframes --registries General
# Machine-readable output for scripts and agents: only JSON on stdout
jh search code "function innerjoin" --json | jq '.results[] | .packagename + " " + .file'
jh search packages plots --json | jq '.results[0].uuid'
# Point the code/symbols/docs commands at a local search service
jh search code "foo" --server http://localhost:4446 --package a93c6f00-e57d-5684-b7b6-d8193f3e46c0Git Workflow
# Option 1: Use JuliaHub CLI wrapper commands (resolves uuids for you)
jh clone alice/my-project
cd my-project
# Make changes...
jh push
# Option 2: Use Git credential helper (recommended)
jh git-credential setup
git clone https://juliahub.com/git/projects/uuid
cd my-project
# Make changes...
git pushNote: It's recommended to use the git-credential helper, but you can still clone using jh clone username/project-name; otherwise you need the project's uuid
Julia Workflow
# Install Julia (if not already installed)
jh julia install
# Setup JuliaHub credentials only
jh run setup
# Start Julia REPL with JuliaHub configuration
jh run
# Run a Julia script
jh run -- script.jl
# Execute Julia code directly
jh run -- -e "println(\"Hello from JuliaHub!\")"
# Run Julia with project and multiple threads
jh run -- --project=. --threads=4 script.jlNote: Arguments after -- are passed directly to Julia. The jh run command:
- Sets up JuliaHub credentials in
$JULIA_DEPOT_PATH/servers/<server>/auth.toml(or~/.julia/servers/<server>/auth.tomlifJULIA_DEPOT_PATHis not set) - Configures
JULIA_PKG_SERVERenvironment variable - Starts Julia with your specified arguments