Skip to main content

Official Python SDK and CLI for KeyNode — AI compute on distributed GPUs

Project description

KeyNode Python SDK & CLI

Official Python SDK and CLI for KeyNode — the AI compute platform that connects your workloads to underutilized GPUs from distributed providers. Run training jobs and inference cheaper and faster than traditional cloud.

Requirements

  • Python 3.10+

Installation

pip install keynode

Or install from source:

git clone <repo_url>
cd keynode-python
pip install .

# Development (editable) install
pip install -e .

Authentication

Option 1 — CLI login (recommended)

keynode auth login

This prompts for your API key and saves it to ~/.keynode/config.json.

Option 2 — Environment variables

export KEYNODE_API_KEY="kn_xxx"
export KEYNODE_BASE_URL="https://api.keynode.es"  # optional, this is the default

Option 3 — Direct SDK initialization

from keynode import KeyNodeClient

client = KeyNodeClient(api_key="kn_xxx", base_url="https://api.keynode.es")

CLI Usage

Auth

keynode auth login     # Save API key to config
keynode auth whoami    # Verify authentication

GPU Catalog

keynode gpu list                                    # List all available GPUs
keynode gpu list --min-vram 24                      # Filter by minimum VRAM
keynode gpu list --max-price 1.5 --region eu-west   # Filter by price and region
keynode gpu list --model "RTX 4090"                 # Search by model name
keynode gpu stats                                   # Platform-wide GPU stats
keynode gpu detail "NVIDIA A100" --vram 80          # Detailed info for a GPU SKU

Runs

keynode run list                                    # List all runs
keynode run get <run_id>                            # Get run details
keynode run create -f payload.json                  # Create run from JSON file
keynode run cancel <run_id>                         # Cancel a run
keynode run retry <run_id>                          # Retry a run immediately
keynode run clone-retry <run_id>                    # Clone and retry a run
keynode run resume <run_id>                         # Resume a paused run
keynode run wait <run_id>                           # Block until run finishes
keynode run wait <run_id> --timeout 3600            # Wait with timeout (seconds)
keynode run metrics <run_id>                        # GPU/CPU metrics time-series
keynode run manifest <run_id>                       # Show run manifest
keynode run download-manifest <run_id> -o out.json  # Download manifest as JSON
keynode run artifacts <run_id>                      # List artifacts
keynode run download-artifacts <run_id> -o out.tar.gz  # Download artifacts tarball

Backups

keynode backup list                                 # List all backups
keynode backup list --run-id 365                    # Filter by run
keynode backup list --status completed              # Filter by status
keynode backup delete <backup_id>                   # Delete a backup

Datasets

keynode dataset list                                # List datasets
keynode dataset upload ./train.csv --name my-train  # Upload a dataset
keynode dataset download <dataset_id> -o data.csv   # Download a dataset
keynode dataset delete <dataset_id>                 # Delete a dataset

Sources

keynode source list                                 # List sources
keynode source upload ./my_code.tar.gz              # Upload a source archive
keynode source delete <source_id>                   # Delete a source

Secrets

keynode secret list                                 # List secrets
keynode secret create --name HF_TOKEN               # Create a secret (prompts for value)
keynode secret delete <secret_id>                   # Delete a secret

API Keys

keynode apikey list                                 # List your API keys
keynode apikey create --name "ci-pipeline"          # Create a new API key
keynode apikey create --name "tmp" --expires-in-days 30  # Key with expiry
keynode apikey revoke <api_key_id>                  # Revoke an API key

Python SDK Usage

Initialize the client

from keynode import KeyNodeClient

# From environment variables or ~/.keynode/config.json
client = KeyNodeClient.from_env()

# Or explicitly
client = KeyNodeClient(api_key="kn_xxx", base_url="https://api.keynode.es")

Browse the GPU catalog

with KeyNodeClient.from_env() as client:
    # List available GPUs
    gpus = client.gpu.list(min_vram=24, max_price=2.0)
    for g in gpus:
        print(f"{g['model']} {g['vram_gb']}GB — €{g['min_price_per_hour']:.3f}/hr ({g['units_available']} available)")

    # Platform stats
    stats = client.gpu.stats()
    print(f"{stats['gpus_available']} GPUs available across {stats['regions_active']} regions")

    # Detailed SKU info
    detail = client.gpu.detail("NVIDIA A100", vram_gb=80)
    print(detail["region_breakdown"])

Create a training run and wait for completion

from keynode import KeyNodeClient

payload = {
    "name": "my-training-job",
    "image": "registry.keynode.es/keynode-jupyter-scipy-ssh:v1",
    "cmd": "python train.py",
    "cpus": 4,
    "memory_gb": 16,
    "gpu_count": 1,
}

with KeyNodeClient.from_env() as client:
    run = client.runs.create(payload)
    run_id = run["run_id"]

    # Block until finished (polls every 5s)
    result = client.runs.wait(run_id, timeout=7200)
    print(f"Status: {result['status']}")

    # Download results
    client.runs.download_artifacts(run_id, output_path="./results.tar.gz")

List runs

with KeyNodeClient.from_env() as client:
    runs = client.runs.list()
    print(runs)

Get GPU/CPU metrics for a run

with KeyNodeClient.from_env() as client:
    metrics = client.runs.metrics(run_id=365, step_s=10)
    for point in metrics["items"]:
        print(f"{point['ts']}  GPU {point['gpu_util']}%  VRAM {point['gpu_mem_mb']}MB")

Work with backups

with KeyNodeClient.from_env() as client:
    # List all backups
    backups = client.backups.list()

    # Filter by run
    run_backups = client.backups.list(run_id=365, status="completed")

    # Delete a backup
    client.backups.delete(backups[0]["id"])

Work with datasets

with KeyNodeClient.from_env() as client:
    # Upload
    dataset = client.datasets.upload("./data/train.csv", dataset_name="train-v1")

    # Download
    client.datasets.download(dataset["id"], output_path="./train_downloaded.csv")

    # Delete
    client.datasets.delete(dataset["id"])

Manage API keys

with KeyNodeClient.from_env() as client:
    # Create a new key (raw key shown only once)
    result = client.api_keys.create(name="ci-pipeline", expires_in_days=90)
    print(result["api_key"])  # save this immediately

    # List existing keys
    keys = client.api_keys.list()

    # Revoke a key
    client.api_keys.revoke(keys[0]["api_key_id"])

Manage secrets

with KeyNodeClient.from_env() as client:
    client.secrets.create(name="HF_TOKEN", value="hf_xxx", description="HuggingFace token")
    secrets = client.secrets.list()
    client.secrets.delete(secrets[0]["id"])

Download run artifacts

with KeyNodeClient.from_env() as client:
    # List artifacts
    artifacts = client.runs.artifacts(run_id=365)

    # Download as tarball
    client.runs.download_artifacts(run_id=365, output_path="./results.tar.gz")

    # Download manifest
    client.runs.download_manifest(run_id=365, output_path="./manifest.json")

Error handling

from keynode import KeyNodeClient
from keynode.exceptions import KeynodeAuthError, KeynodeApiError

try:
    with KeyNodeClient.from_env() as client:
        run = client.runs.get(999)
except KeynodeAuthError:
    print("Invalid or missing API key")
except KeynodeApiError as e:
    print(f"API error {e.status_code}: {e.message}")

Package Structure

keynode       → Python SDK (client, resources, config, exceptions)
keynode_cli   → CLI application

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

keynode-0.1.1.tar.gz (22.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

keynode-0.1.1-py3-none-any.whl (25.2 kB view details)

Uploaded Python 3

File details

Details for the file keynode-0.1.1.tar.gz.

File metadata

  • Download URL: keynode-0.1.1.tar.gz
  • Upload date:
  • Size: 22.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.12

File hashes

Hashes for keynode-0.1.1.tar.gz
Algorithm Hash digest
SHA256 ad82bb2cb969ed75ca149a9711636e4e8596b9353aebe9f44e386f3095fad576
MD5 8794d9696812f6ac75b2c942f71819ad
BLAKE2b-256 d43ee7df1257ab49931c13a42b84ab7f643b060a0ef07a956ab05c23eef06b08

See more details on using hashes here.

File details

Details for the file keynode-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: keynode-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 25.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.12

File hashes

Hashes for keynode-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 47c15dfad7e40a3f44c5a016bd41ffefcf92de04abd2e070c73a478eded43e4c
MD5 ef2d1c0c4ae50d54717e742a2690d9f2
BLAKE2b-256 7418198926985de21a9bb3bffeed092405adf4965c344358e1b71b615b646864

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page