Skip to main content

Minimal ML experiment platform wrapping Azure ML, Vertex AI, and Vercel Sandbox

Project description

NUCL

Minimal ML experiment platform. 2,000 lines of code.

NUCL wraps Azure ML, Vertex AI, and Vercel Sandbox behind a unified CLI and web dashboard. No servers to manage, no databases to maintain, no collectors to deploy. Every feature delegates to a managed service.

nucl run --name "vision/resnet-50-v2" --script train.py --gpu-type t4
nucl ps vision/
nucl log vision/resnet-50-v2 -f
nucl pull vision/resnet-50-v2

Architecture

graph LR
    subgraph Clients
        CLI["CLI (Python)"]
        Web["Web Dashboard"]
    end

    subgraph Vercel
        API["Next.js API Routes"]
        Auth["Clerk (auth + API keys)"]
    end

    subgraph Sandbox["Vercel Sandbox (Python 3.13)"]
        AzureSDK["azure-ai-ml SDK"]
        VertexSDK["vertex AI SDK"]
    end

    subgraph Platforms
        AzureML["Azure ML"]
        VertexAI["Vertex AI"]
        SandboxRun["Sandbox (CPU)"]
    end

    CLI -- HTTP --> API
    Web -- HTTP --> API
    API --> Auth
    API -- "job submission" --> Sandbox
    API -. "read ops (list, logs, cancel)" .-> Platforms
    AzureSDK --> AzureML
    VertexSDK --> VertexAI
    Sandbox --> SandboxRun

Job submission spins up a short-lived Vercel Sandbox with Python 3.13 and uses the official cloud SDKs to upload code and create training jobs. Read operations (list, logs, cancel) use direct REST API calls.

Three platforms:

Platform GPU Use case
Azure ML Yes Production training on Azure
Vertex AI Yes Production training on GCP
Sandbox No (CPU) Quick tests, no cloud account needed

Setup

Web (Vercel)

cd web
bun install
cp .env.example .env.local  # fill in values
bun dev

Required environment variables:

NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_...
CLERK_SECRET_KEY=sk_...
NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in
NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up
ENCRYPTION_KEY=<openssl rand -hex 32>
VERCEL_TOKEN=...

CLI

cd cli
uv sync
uv run nucl --help

Or install globally:

uv tool install .
nucl --help

CLI Commands

Auth

nucl auth login                    # Browser-based sign-in
nucl auth logout
nucl auth status

Teams (Clerk Organizations)

nucl team show                     # Current team info
nucl team set <org-id>             # Switch team
nucl team config azure             # Set Azure credentials for team
nucl team config vertex            # Set Vertex credentials for team

Jobs

nucl run --name "project/experiment" --script train.py --gpu-type t4
nucl ps                            # List all experiments
nucl ps project/                   # Filter by folder
nucl log <job-id> -f               # Stream logs
nucl stop <job-id>
nucl pull <job-id> ./outputs       # Download results

Models

nucl model ls
nucl model pull <name>

HPO

nucl hpo run config.yaml

Experiment Organization

Experiments use path-based naming with / as the folder separator:

lung-cancer/detection/yolov9-baseline
lung-cancer/detection/yolov9-augmented
lung-cancer/segmentation/unet-v1
breast-cancer/screening/resnet-50

Filter by prefix with nucl ps lung-cancer/detection/. The web dashboard renders folder paths with a muted prefix and bold experiment name.

Cloud Credentials

Credentials are stored per-team using Clerk Organization privateMetadata, encrypted with AES-256-GCM. They never touch the CLI or browser -- only the server-side API routes decrypt them to submit jobs.

An org admin configures credentials once via the Team Settings page or nucl team config. All team members use them.

In-Job Logging

NUCL does not ship a custom SDK. Use MLflow directly in your training scripts:

import mlflow

mlflow.log_param("learning_rate", 0.001)
mlflow.log_metric("accuracy", 0.95)
mlflow.log_artifact("model.pth")

Both Azure ML and Vertex AI natively support MLflow.

Tech Stack

Layer Technology
CLI Python 3.11+, Click, httpx
Web Next.js 16, React 19, TypeScript 6
UI shadcn, Tailwind CSS 4, TanStack Table
Data fetching TanStack Query 5
Auth Clerk 7 (Organizations, API keys)
Job submission Vercel Sandbox (Python 3.13)
Encryption AES-256-GCM
Package management uv (Python), Bun (JS)

Tests

# Web (158 tests)
cd web && bunx vitest run

# CLI (94 tests)
cd cli && uv run pytest -v

What NUCL Does Not Do

NUCL delegates everything it can. It does not:

  • Provision VMs (cloud platforms do this)
  • Collect logs (cloud platforms do this)
  • Manage GPU quotas (cloud platforms do this)
  • Handle preemption (cloud platforms do this)
  • Build Docker images (use platform environments)
  • Provide an in-job SDK (use MLflow)
  • Run a backend server (Vercel handles this)
  • Manage a database (Clerk handles credentials, no DB needed)

License

Internal use only.

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

nucl-0.8.0.tar.gz (20.0 kB view details)

Uploaded Source

Built Distribution

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

nucl-0.8.0-py3-none-any.whl (13.9 kB view details)

Uploaded Python 3

File details

Details for the file nucl-0.8.0.tar.gz.

File metadata

  • Download URL: nucl-0.8.0.tar.gz
  • Upload date:
  • Size: 20.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for nucl-0.8.0.tar.gz
Algorithm Hash digest
SHA256 07617d27fac35aae68d2a5a25a4f55ad16447d357d00603af92adc02d4f5e249
MD5 aec631c9433c8ee21e4b8296148482a6
BLAKE2b-256 462730b61528f3c37ad4a76012c2a537c25916f6415f6e93ef4d6bfd2637a1ce

See more details on using hashes here.

Provenance

The following attestation bundles were made for nucl-0.8.0.tar.gz:

Publisher: publish-cli.yml on lunit-io/nucl

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file nucl-0.8.0-py3-none-any.whl.

File metadata

  • Download URL: nucl-0.8.0-py3-none-any.whl
  • Upload date:
  • Size: 13.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for nucl-0.8.0-py3-none-any.whl
Algorithm Hash digest
SHA256 1a64124f8b51478f42d5808601ccaec8888c970b54644956fdf09ae70f4c9f76
MD5 5c306ae97e4839eecbed662c3f6272dd
BLAKE2b-256 f0c59b108b514730f95599089eeb9d3e29c218092d7b1924700cd54ee40f3965

See more details on using hashes here.

Provenance

The following attestation bundles were made for nucl-0.8.0-py3-none-any.whl:

Publisher: publish-cli.yml on lunit-io/nucl

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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