Your team gets a private workspace on an NVIDIA DGX Spark: root access, the GPU, Docker, and internet access. You can also send batch jobs to the compute pool, which spreads them over all 8 Sparks in parallel.
Set me up for YAAD by following https://www.yaadops.com/agents#setup| Sign in | UWM email plus the emailed code. No password. |
|---|---|
| Your team workspace | Create or join a team (with a team code), register up to 3 SSH keys (one per device), see your login line and usage, delete the team |
| Compute pool | Live capacity of all Sparks. Submit a batch job (command, memory, CPUs, minutes, GPU, input folder, image), follow it, cancel it, get the download command. |
| Agent access | Create or revoke personal tokens for your AI agent (Claude, OpenAI agents, any MCP client) |
| Help | Send a problem with screenshots, logs, or a screen recording. Replies from the CSI operator and host appear here. |
| Student guide · Agent guide | This page · how to connect and use AI agents |
nvidia-smi | Shows the GB10 GPU, memory use and the processes using it |
|---|---|
apt · pip · sudo | Install anything. You are root; sudo is accepted so scripts run unchanged. |
docker · docker compose | Run NVIDIA / NGC containers in your team's own engine, GPU included (--gpus all works) |
docker login nvcr.io | Sign in to NGC with your own API key, for NVIDIA images that need it |
yaad-diag | One report of GPU, memory, disk, your containers + logs, ports and versions. Attach it to a Help ticket. |
/workspace | Your team's files. Kept until the event ends. Pool results land in /workspace/results/<job>. |
$YAAD_PORT_BASE | The first of your team's 100 ports for web UIs (Jupyter, Gradio, Isaac Sim stream) |
$ROS_DOMAIN_ID | Your team's own ROS 2 domain, so other teams' topics don't mix with yours |
| FortiClient (CSI VPN) | Puts your device on the CSI network so it can reach the Sparks |
|---|---|
ssh-keygen | Creates the SSH key you register on the website (step 2) |
ssh · VS Code Remote-SSH · Termius / Blink | Log in to your workspace |
scp / sftp | Copy files to /workspace and bring results back |
ssh-add (ssh-agent) | Unlocks a passphrase key once, so your AI agent can use ssh/scp without prompting (step 4) |
scope_job | Works out how much memory, CPU and time to request, and whether the job fits one Spark |
|---|---|
list_resources | Free capacity on every Spark and the queue length |
submit_job · get_job · list_jobs · cancel_job | Run batch jobs on any Spark with room, follow them, stop them |
fetch_results | The command that copies a job's results to your computer |
open_session · whoami | Your SSH login, your team, your home Spark |
report_issue · my_issues | Send a problem to the CSI operator and host, and read the answers |
wait_for_answer | Waits for the reply to a ticket, so your agent can tell you the moment it's answered |
Sign in on the Lab page with your @uwm.edu email. Only UWM addresses can sign in. We email you a sign-in code; type it in.
This is how the Spark knows the device belongs to you. There are no passwords. It takes 1 minute per device: step 2.
The Sparks are on the CSI network. Unless you are plugged into CSI's own network, connect the CSI VPN in FortiClient first. That includes campus Wi-Fi like eduroam and home.
You make a key pair on your device. The private key never leaves the device. The public key (one line starting with
ssh-ed25519) is what you paste on the website. Pick your device:
PS> ssh-keygen -t ed25519
PS> Get-Content $env:USERPROFILE\.ssh\id_ed25519.pub | Set-Clipboard
To see it instead: type $env:USERPROFILE\.ssh\id_ed25519.pubssh-ed25519 AAAA… csi\you@PC.PuTTY can't read this key directly. Open PuTTYgen → Conversions → Import key → choose
C:\Users\<you>\.ssh\id_ed25519 (the file without .pub) → Save private key as id_ed25519.ppk.
In PuTTY: Connection → SSH → Auth → Credentials → Private key file = the .ppk. Register the same public line from step 3.
$ ssh-keygen -t ed25519 -C "you@uwm.edu"$ pbcopy < ~/.ssh/id_ed25519.pubiPhone and iPad have no built-in terminal, so use a free SSH app. Both of these create the key for you.
ssh-ed25519).config → Keys & Certificates → + → Generate New.Menu names can differ slightly between app versions. You are looking for "generate key", type Ed25519, then "copy public key". Then paste it on the website from Safari (step 3). Before connecting, turn on the CSI VPN in the FortiClient app on the iPhone/iPad.
On ChromeOS, turn on the Linux development environment first (Settings → Developers), then open Terminal.
$ ssh-keygen -t ed25519 -C "you@uwm.edu" # press Enter to accept the defaults $ cat ~/.ssh/id_ed25519.pub # copy this one line
Install Termius from Google Play. Then do the same as on iPhone: Keychain → + → Generate Key → ED25519 → Save,
and copy the public key. In Termux, run pkg install openssh and then the Linux commands.
ssh-ed25519 (from the .pub file).
Never paste a block that starts with -----BEGIN OPENSSH PRIVATE KEY-----, here or anywhere else.ssh yt-yourteam@172.30.102.9X.PS> ssh yt-yourteam@172.30.102.9X # exact line is on the website
Answer yes the first time (it remembers the Spark). For PuTTY, see the PuTTY note in step 2.
$ ssh yt-yourteam@172.30.102.9X
Termius: Hosts → + → New Host. Address = the Spark IP, Username = yt-yourteam, Key = the key you generated. Save and tap it.
Blink: ssh yt-yourteam@172.30.102.9X (Blink uses the key you made).
Install the Remote - SSH extension → Connect to Host… → paste yt-yourteam@172.30.102.9X.
You get VS Code running on the Spark, inside your workspace, as root. Open /workspace.
sudo in Terminal (it asks for your computer password).
Use admin mode only for the setup step, not for everyday work. Admin rights on the Spark are never needed: you are already root in your workspace.Permission denied (publickey). Load the key into ssh-agent once:
# once, in PowerShell "Run as administrator" Get-Service ssh-agent | Set-Service -StartupType Automatic Start-Service ssh-agent # then in a normal PowerShell (asks for the passphrase once) ssh-add $env:USERPROFILE\.ssh\id_ed25519
Use Windows' own ssh/scp (C:\Windows\System32\OpenSSH). Git-for-Windows' ssh has a separate agent.
$ ssh-add --apple-use-keychain ~/.ssh/id_ed25519$ eval "$(ssh-agent -s)" && ssh-add ~/.ssh/id_ed25519$ scp data.zip yt-yourteam@172.30.102.9X: # into /workspace $ scp -r yt-yourteam@172.30.102.9X:results/<job_id> . # bring results home
| You are | root in your team's own Ubuntu 24.04 + CUDA container. apt install and pip install work. sudo … works too, so install scripts run unchanged. |
|---|---|
| Your files | /workspace. Kept between logins until the event ends. Other teams can't see them. |
| GPU | nvidia-smi shows the GB10. Every container you start also gets it. |
| Docker | docker and docker compose run in your team's own engine. --gpus all works, and so does -v /workspace/data:/data. |
| Internet | apt, pip, Hugging Face, NGC, GitHub, build.nvidia.com |
| Memory | Up to 100 GB per team. CPU is shared fairly between the teams on a Spark. |
| Set for you | $ROS_DOMAIN_ID (your own ROS 2 domain) and $YAAD_PORT_BASE (100 ports for your web UIs) |
linux/arm64 images and wheels. "exec format error" means an x86 image.
To check an image before pulling it: docker manifest inspect <image> | grep arm64ssh goes straight to your Spark. If the website, the compute pool or the help desk is down, keep working over SSH: run scripts, docker run --gpus all …, train, and copy files with scp. Save your ssh line somewhere. You only need the website to create or join a team, change keys, or use the pool.Keep long runs alive when you disconnect. Closing your laptop or losing the VPN ends your SSH session and anything running in it.
$ apt install -y tmux $ tmux new -s train # start your run here; Ctrl-b then d to detach $ tmux attach -t train # come back later $ nohup python train.py > /workspace/train.log 2>&1 & # or this, then: tail -f /workspace/train.log
Save checkpoints to /workspace. A workspace restart stops running processes but keeps your files.
Install a coding agent in your workspace. It runs as root in your team's container and only sees your team's files. Sign in with your own account.
$ curl -fsSL https://claude.ai/install.sh | bash # Claude Code; run: claude (it prints a sign-in link) $ curl -fsSL https://deb.nodesource.com/setup_22.x | bash - && apt install -y nodejs && npm i -g @openai/codex # Codex CLI
If a browser sign-in can't reach the Spark, use an API key instead (ANTHROPIC_API_KEY or OPENAI_API_KEY). Your teammates can read files in /workspace and /root, so keep keys out of shared folders.
$ echo $YAAD_PORT_BASE # e.g. 20200; your range is +0..+99 $ jupyter lab --no-browser --ip 0.0.0.0 --port $YAAD_PORT_BASE
Open http://<spark-ip>:<port> (CSI network or CSI VPN), or tunnel: ssh -L 8888:localhost:<port> yt-yourteam@<spark-ip> → http://localhost:8888.
Keep tokens and passwords on: other teams on the same Spark can reach open ports.
| arm64 images | nvcr.io/nvidia/isaac-sim:6.0.0 and :5.1.0, nvcr.io/nvidia/isaac-lab:2.3.0.
Isaac Sim 4.5 / 5.0 and Isaac Lab 2.2 are x86 only and fail with "exec format error". |
|---|---|
| License | The image stops unless you set ACCEPT_EULA=Y and PRIVACY_CONSENT=Y. |
| First pull | About 20 GB. It takes several minutes, once per Spark. |
Put your script in a folder of /workspace (e.g. sdg/) and submit it from the Lab page or your agent:
{ "image": "nvcr.io/nvidia/isaac-sim:5.1.0",
"env": { "ACCEPT_EULA": "Y", "PRIVACY_CONSENT": "Y" },
"input_path": "sdg", "memory_gb": 48, "cpus": 8, "max_minutes": 120,
"command": "/isaac-sim/python.sh /job/in/generate.py --out /job/out" }
The output lands in /workspace/results/<job>. Pool jobs run as root, so writing to /job/out works.
Your command always runs as a bash script; the image's own startup (entrypoint) is skipped.
Tested recipes (2026-10-15, as pool jobs):
| Isaac Lab RL | nvcr.io/nvidia/isaac-lab:2.3.0, 56 GB / 12 CPUs, env ACCEPT_EULA=Y PRIVACY_CONSENT=Y OMNI_KIT_ACCEPT_EULA=YES:cd /workspace/isaaclab && ./isaaclab.sh -p scripts/reinforcement_learning/rsl_rl/train.py --task Isaac-Cartpole-v0 --headless --num_envs 512 --max_iterations 30 && cp -r logs /job/out/ |
|---|---|
| ROS 2 Jazzy | docker.io/library/ros:jazzy, 8 GB / 4 CPUs. ROS is already sourced. apt-get install -y ros-jazzy-demo-nodes-cpp for the demos. |
| Cosmos Reason 7B | nvcr.io/nvidia/pytorch:25.01-py3, 40 GB / 8 CPUs, pip install transformers==4.51.3 qwen-vl-utils, bf16.
The first load downloads ~16 GB (about 4 min); about 35 s per image description. |
Run it in your workspace with docker. Use your ports: signalling on $YAAD_PORT_BASE, media on the next port.
$ docker run -d --name isaac --gpus all -u 0 --network host \ -e ACCEPT_EULA=Y -e PRIVACY_CONSENT=Y -v /workspace:/workspace \ nvcr.io/nvidia/isaac-sim:6.0.0 /isaac-sim/runheadless.sh \ --/exts/omni.kit.livestream.app/primaryStream/signalPort=$YAAD_PORT_BASE \ --/exts/omni.kit.livestream.app/primaryStream/streamPort=$((YAAD_PORT_BASE+1)) \ --/exts/omni.kit.livestream.app/primaryStream/publicIp=<spark-ip> $ docker logs -f isaac # wait for "app ready" (first start: a few minutes of shader compiling)
On your computer (CSI VPN on), the Isaac Sim WebRTC Streaming Client always uses signalling port 49100. Tunnel it to your port
and point the client at 127.0.0.1:
PS> ssh -N -o ServerAliveInterval=30 -L 49100:127.0.0.1:<YAAD_PORT_BASE> yt-yourteam@<spark-ip>
127.0.0.1. A forward to the Spark's IP is refused ("administratively prohibited").<spark-ip>:<YAAD_PORT_BASE+1> over the VPN, which works.NVST_R_BUSY)?
Isaac Sim keeps the dead session. Run docker restart isaac. The restart clears what is loaded, so
save the stage to /workspace often (File → Save As → /workspace/scene.usd), and reopen it after the restart.
ServerAliveInterval on the tunnel makes these drops rarer.docker stop isaac) and use pool jobs (A) for long unattended runs.Files: scp from your computer works (step 4). Inside the workspace you are root, so
apt-get install -y python3 openssh-client adds missing tools.
NemoClaw in your workspace. It calls build.nvidia.com APIs (free key) or models served on the Spark.
workspaceThe arm64 container or HF weights. Cache models in /workspace (HF_HOME=/workspace/hf).
NGC TAO/PyTorch arm64 images. Train as a pool job with image set.
Inference fits the GB10. Fine-tuning: Edge with SFT, Nano with LoRA only. Bigger runs: Brev / build.nvidia.com.
workspacepoolHeadless SDG as pool jobs, or stream it from your workspace: Isaac Sim quick start. Emulate3D runs on the Windows CSI workstation.
workspaceLong training runs as pool jobs with the Isaac Lab image. Write checkpoints to /job/out.
docker run --rm -it --network host -e ROS_DOMAIN_ID ros:jazzy. For off-Spark links, use rosbridge/Zenoh on a port in your range.
Python or NVIDIA containers in your workspace. Use pool jobs for training.
workspacepoolNGC images that need a login: docker login nvcr.io -u '$oauthtoken', then paste your NGC API key (from ngc.nvidia.com) as the password.
Your workspace and your pool jobs have internet access, so you can download open models from Hugging Face, NGC, GitHub, Ollama, Kaggle and similar sites. Model weights work on the ARM64 Sparks like anywhere else; only containers and Python wheels have to be ARM64.
$ export HF_HOME=/workspace/hf # Hugging Face cache that survives logins $ pip install -U huggingface_hub $ huggingface-cli download Qwen/Qwen2.5-7B-Instruct --local-dir /workspace/models/qwen7b $ du -sh /workspace/models/qwen7b # how big it really is
huggingface-cli login with your own token./workspace/models and give the job input_path: "models/qwen7b". It's copied in as /job/in.env (HF_TOKEN) is stored with the job record. Use a read-only token there.git clone, wget and docker pull work too. Everything is deleted at the end of the event, so download what you want to keep.The Spark's GPU and CPU share one pool of memory (GB10, about 119 GB). What has to fit is the model while it runs:
| Weights | billions of parameters × bytes per parameter: bf16/fp16 = 2, fp8/int8 = 1, 4-bit (fp4/int4, GGUF Q4, AWQ) ≈ 0.5. An 8B model is ~16 GB in bf16, ~8 GB in fp8, ~4–5 GB in 4-bit. |
|---|---|
| Running it (inference) | about weights × 1.2 + 6 GB (KV cache, activations, runtime). Long contexts (>32k tokens) need noticeably more. |
| LoRA fine-tuning | about weights × 1.25 + 0.4 GB per billion parameters + 10 GB. QLoRA (4-bit base) roughly halves it again. |
| Full fine-tuning | about 16 bytes per parameter (weights + gradients + Adam). Even an 8B model needs ~140 GB: use LoRA instead. |
Your limits: a pool job up to 80 GB · your workspace up to 100 GB · a whole Spark ~119 GB ·
a 2-Spark job (nodes: 2) gives each half its own Spark, if your code splits the model (FSDP, DeepSpeed, tensor/pipeline parallel).
| Running a model | bf16 · fp8 · 4-bit (approximate memory needed) |
|---|---|
| 7–8B | ~26 GB · ~16 GB · ~11 GB, fits anywhere |
| 13–14B | ~40 GB · ~23 GB · ~15 GB, fits anywhere |
| 32B | ~83 GB (workspace only) · ~45 GB · ~26 GB |
| 70B | too big (~174 GB) · ~90 GB (workspace only, quiet Spark) · ~48 GB, pool job OK |
| 100B+ | 4-bit only, or 2 Sparks, or a hosted model on build.nvidia.com |
scope_job do the mathAsk your AI agent, e.g. "Can I fine-tune Llama 3.1 8B with LoRA on YAAD?". It calls scope_job with the task, the model size
and the precision. You get back:
nodes: 2, hosted);submit_job request (memory, CPUs, minutes, image, env) and whether it would start now or queue.scope_job { "task": "fine_tune_lora", "model_params_b": 8, "precision": "bf16" }
→ estimate ~34 GB, 8 CPUs · fits: pool_or_workspace · suggested_submit_job { memory_gb: 34, cpus: 8, ... } · availability_now: 6 Sparks
Estimates are rules of thumb. Ask for enough memory not to be killed for running out, but not so much that you block other teams.
If a job dies with "out of memory", resubmit with a higher memory_gb.
/workspace/results/<job>command | A bash script. It runs as root in /job/in; write outputs to /job/out. |
|---|---|
image | Optional, e.g. an NGC arm64 image. Blank means Ubuntu 24.04 + CUDA. |
nodes | 1 (default) or 2: one rank on each of two cable-linked Sparks (see below). |
env | Optional environment variables, e.g. {"ACCEPT_EULA":"Y","PRIVACY_CONSENT":"Y"} for Isaac Sim. Up to 20 variables. |
input_path | A folder in your /workspace, copied in as /job/in. |
memory_gb · cpus · max_minutes | Reserved for you and enforced. Not sure what to ask for? Your agent's scope_job tool works it out. |
Submit from the Lab page or let your AI agent do it (agent guide). If nothing has room, the job waits and starts by itself.
Each pair of Sparks is joined by a 200G ConnectX-7 cable (RDMA, measured ~195 Gb/s). Set nodes: 2 (or tick
2 Sparks on the Lab page) to run one rank on each end: memory_gb and cpus are per Spark.
Each rank gets RANK, WORLD_SIZE=2, MASTER_ADDR, MASTER_PORT and the NCCL network settings:
{ "nodes": 2, "image": "nvcr.io/nvidia/pytorch:25.10-py3", "memory_gb": 100, "cpus": 16, "input_path": "project",
"command": "torchrun --nnodes 2 --nproc-per-node 1 --node-rank $RANK --master-addr $MASTER_ADDR --master-port $MASTER_PORT train.py" }
Rank 0's results land in /workspace/results/<job>/, rank 1's in results/<job>/rank1/.
If one rank fails, YAAD stops the other. The job waits until both ends of a pair have room (list_resources → two_spark_pairs).
Use a recent image (PyTorch 25.10 or later) so NCCL knows the GB10.
Lab page → Help: describe it, attach screenshots or logs, or click Record my screen. The answer appears there, usually within minutes.
Ask it to "report this to YAAD". It calls report_issue, waits with wait_for_answer, and tells you the answer. A failed pool job opens a ticket by itself.
In your workspace: yaad-diag > /workspace/diag.txt. It covers GPU, memory, disk, your containers and their logs, and ports.
Some fixes need the operator, for example more memory. Those show Waiting for operator approval, and you don't have to ask again.
--privileged, USB cameras, serial/CAN: not on shared Sparks. Use the CSI lab machines for hardware-in-the-loop.