Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Rent, manage, and destroy GPU instances on vast.ai. Use when user says "rent gpu", "vast.ai", "rent a server", "cloud gpu", or needs on-demand GPU without owning hardware.
.claude/skills/aris-vast-gpu/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-07 | ✗→✓ | ▲ Improved | 146% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 97% | 0% |
| case-12 | ✗→✓ | ▲ Improved | 177% | 0% |
| case-13 | ✗→✓ | ▲ Improved | 148% | 0% |
| case-14 | ✗→✓ | ▲ Improved | 332% | 0% |
Manage vast.ai GPU instance: $ARGUMENTS
Rent cheap, capable GPUs from vast.ai on demand. This skill analyzes the training task to determine GPU requirements, searches for the best-value offers, presents options with estimated total cost, and handles the full lifecycle: rent → setup → run → destroy.
Users do NOT specify GPU models or hardware. They describe the task — the skill figures out what to rent.
Prerequisites: The vastai CLI must be installed (requires Python ≥ 3.10) and authenticated:
bashpip install vastai vastai set api-key YOUR_API_KEY
> If your system Python is < 3.10, create a virtual environment with Python ≥ 3.10 (e.g., conda create, pyenv, uv venv, etc.) and install vastai there.
SSH public key must be uploaded at https://cloud.vast.ai/manage-keys/ BEFORE creating any instance. Keys are baked into instances at creation time — if you add a key after renting, you must destroy and re-create the instance.
All active vast.ai instances are tracked in vast-instances.json at the project root:
json[ { "instance_id": 33799165, "offer_id": 25831376, "gpu_name": "RTX_3060", "num_gpus": 1, "dph": 0.0414, "ssh_url": "ssh://root@1.208.108.242:58955", "ssh_host": "1.208.108.242", "ssh_port": 58955, "created_at": "2026-03-29T21:12:00Z", "status": "running", "experiment": "exp01_baseline", "estimated_hours": 4.0, "estimated_cost": 0.17 } ]
This file is the source of truth for /aris-run-experiment and /aris-monitor-experiment to connect to vast.ai instances.
Analyze the task, find the best GPU, and present cost-optimized options. This is the main entry point — called directly or automatically by /aris-run-experiment when gpu: vast is set.
Step 1: Analyze Task Requirements
Read available context to determine what the task needs:
refine-logs/EXPERIMENT_PLAN.md):num_parameters, config filesDataParallel, DistributedDataParallel, accelerate, deepspeedStep 2: Determine GPU Requirements
Based on the task analysis, determine:
| Factor | How to estimate | |--------|----------------| | Min VRAM | Model params × 4 bytes (fp32) or × 2 (fp16/bf16) + optimizer states + activations. Rules of thumb: 7B model ≈ 16 GB (fp16), 13B ≈ 28 GB, 70B ≈ 140 GB (needs multi-GPU). ResNet/ViT ≈ 4-8 GB. Add 20% headroom. | | Num GPUs | 1 unless: model doesn't fit in single GPU VRAM, or scripts use DDP/FSDP/DeepSpeed, or plan specifies multi-GPU | | Est. hours | From experiment plan's cost column, or: (dataset_size × epochs) / (throughput × batch_size). Default to user estimate if available. Add 30% buffer for setup + unexpected slowdowns | | Min disk | 20 GB base + model checkpoint size + dataset size. Default: 50 GB | | CUDA version | Match PyTorch version. PyTorch 2.x needs CUDA ≥ 11.8. Default: 12.1 |
Step 3: Search Offers
Search across multiple GPU tiers to find the best value. Always search broadly — do NOT limit to one GPU model:
bash# Tier 1: Budget GPUs (good for small models, fine-tuning, ablations) vastai search offers "gpu_ram>=<MIN_VRAM> num_gpus>=<N> reliability>0.95 inet_down>100" -o 'dph+' --storage <DISK> --limit 10 # Tier 2: If VRAM > 24 GB, also search high-VRAM cards specifically vastai search offers "gpu_ram>=48 num_gpus>=<N> reliability>0.95" -o 'dph+' --storage <DISK> --limit 5
The output is a table with columns: ID, CUDA, N (GPU count), Model, PCIE, cpu_ghz, vCPUs, RAM, Disk, $/hr, DLP (deep learning perf), score, NV Driver, Net_up, Net_down, R (reliability %), Max_Days, mach_id, status, host_id, ports, country.
The first column (ID) is the offer ID needed for vastai create instance.
Step 4: Present Cost-Optimized Options
Present 3 options to the user, ranked by estimated total cost:
Task analysis:
- Model: [model name/size] → estimated VRAM: ~[X] GB
- Training: ~[Y] hours estimated
- Requirements: [N] GPU(s), ≥[X] GB VRAM, ~[Z] GB disk
Recommended options (sorted by estimated total cost):
| # | GPU | VRAM | $/hr | Est. Hours | Est. Total | Reliability | Offer ID |
|---|-------------|-------|--------|------------|------------|-------------|-----------|
| 1 | RTX 3060 | 12 GB | $0.04 | ~6h | ~$0.25 | 99.4% | 25831376 | ← cheapest
| 2 | RTX 4090 | 24 GB | $0.28 | ~4h | ~$1.12 | 99.2% | 6995713 | ← best value
| 3 | A100 SXM | 80 GB | $0.95 | ~2h | ~$1.90 | 99.5% | 7023456 | ← fastest
Option 1 is cheapest overall. Option 3 finishes fastest.
Pick a number (or type a different offer ID):Key presentation rules:
Relative speed scaling (approximate, for estimating hours across GPU tiers):
| GPU | Relative Speed (FP16) | |-----|-----------------------:| | RTX 3060 | 0.5× | | RTX 3090 | 1.0× | | RTX 4090 | 1.6× | | A5000 | 0.9× | | A6000 | 1.1× | | L40S | 1.5× | | A100 SXM | 2.0× | | H100 SXM | 3.3× |
Use these to scale the base estimated hours across offers.
Create an instance from a user-selected offer.
Step 1: Create Instance
bashvastai create instance <OFFER_ID> \ --image <DOCKER_IMAGE> \ --disk <DISK_GB> \ --ssh \ --direct \ --onstart-cmd "apt-get update && apt-get install -y git screen rsync"
Default Docker image: pytorch/pytorch:2.1.0-cuda12.1-cudnn8-devel (override via CLAUDE.md image: field if set).
The output looks like:
Started. {'success': True, 'new_contract': 33799165, 'instance_api_key': '...'}The new_contract value is the instance ID — save this for all subsequent commands.
Step 2: Wait for Instance Ready
Poll instance status every 20 seconds until it's running (typically takes 30-60 seconds, max ~5 minutes):
bashvastai show instances --raw | python3 -c " import sys, json instances = json.load(sys.stdin) for inst in instances: if inst['id'] == <INSTANCE_ID>: print(inst['actual_status']) "
Wait states: loading → running. If stuck in loading for >5 minutes, warn the user — the host may be slow or the image may be large.
Step 3: Get SSH Connection Details
bashvastai ssh-url <INSTANCE_ID>
This returns a URL in the format: ssh://root@<HOST>:<PORT>
Parse out host and port from this URL. Example:
ssh://root@1.208.108.242:589551.208.108.242, Port: 58955> Important: Always use vastai ssh-url to get connection details — do NOT rely on ssh_host/ssh_port from vastai show instances, as those may point to proxy servers that differ from the direct connection endpoint.
Step 4: Verify SSH Connectivity
bashssh -o StrictHostKeyChecking=no -o ConnectTimeout=15 -p <PORT> root@<HOST> "nvidia-smi && echo 'CONNECTION_OK'"
If SSH fails with "Permission denied (publickey)":
If SSH fails with "Connection refused":
Step 5: Update State File
Write/update vast-instances.json with the new instance details including the ssh_url from Step 3, estimated hours and cost.
Step 6: Report
Vast.ai instance ready:
- Instance ID: <ID>
- GPU: <GPU_NAME> x <NUM_GPUS>
- Cost: $<DPH>/hr (estimated total: ~$<TOTAL>)
- SSH: ssh -p <PORT> root@<HOST>
- Docker: <IMAGE>
To deploy: /aris-run-experiment (will auto-detect this instance)
To destroy when done: /aris-vast-gpu destroy <ID>Set up the rented instance for a specific experiment. Called automatically by /aris-run-experiment when targeting a vast.ai instance.
Step 1: Install Dependencies
bashssh -p <PORT> root@<HOST> "pip install -q wandb tensorboard scipy scikit-learn pandas"
If a requirements.txt exists in the project, install that instead:
bashscp -P <PORT> requirements.txt root@<HOST>:/workspace/ ssh -p <PORT> root@<HOST> "pip install -q -r /workspace/requirements.txt"
> Note: scp uses uppercase -P for port, while ssh uses lowercase -p.
Step 2: Sync Code
bashrsync -avz -e "ssh -p <PORT>" \ --include='*.py' --include='*.yaml' --include='*.yml' --include='*.json' \ --include='*.txt' --include='*.sh' --include='*/' \ --exclude='*.pt' --exclude='*.pth' --exclude='*.ckpt' \ --exclude='__pycache__' --exclude='.git' --exclude='data/' \ --exclude='wandb/' --exclude='outputs/' \ ./ root@<HOST>:/workspace/project/
Step 3: Verify Setup
bashssh -p <PORT> root@<HOST> "cd /workspace/project && python -c 'import torch; print(f\"PyTorch {torch.__version__}, CUDA: {torch.cuda.is_available()}, GPUs: {torch.cuda.device_count()}\")'"
Expected output: PyTorch 2.1.0, CUDA: True, GPUs: 1 (or more GPUs if multi-GPU instance).
Tear down a vast.ai instance to stop billing.
Step 1: Confirm Results Collected
Before destroying, check if there are experiment results to download:
bashssh -p <PORT> root@<HOST> "ls /workspace/project/results/ 2>/dev/null || echo 'NO_RESULTS_DIR'"
If results exist, download them first:
bashrsync -avz -e "ssh -p <PORT>" root@<HOST>:/workspace/project/results/ ./results/
Also download logs:
bashscp -P <PORT> root@<HOST>:/workspace/*.log ./logs/ 2>/dev/null
Step 2: Destroy Instance
bashvastai destroy instance <INSTANCE_ID>
Output: destroying instance <INSTANCE_ID>.
> Destruction is irreversible — all data on the instance is permanently deleted.
Step 3: Update State File
Remove the instance from vast-instances.json or mark its status as destroyed.
Step 4: Report Cost
Calculate actual cost based on creation time and $/hr:
Instance <ID> destroyed.
- Duration: ~X.X hours
- Actual cost: ~$X.XX (estimated was $Y.YY)
- Results downloaded to: ./results/Show all active vast.ai instances:
bashvastai show instances
Cross-reference with vast-instances.json for experiment associations.
Tear down all active instances (use after all experiments complete):
vast-instances.json--direct SSH when creating instances — faster than proxy SSHvastai ssh-url <ID> to get connection details — the host/port from show instances may differpytorch/pytorch:2.1.0-cuda12.1-cudnn8-devel unless user specifies otherwise/workspace/ (Docker default). Code syncs to /workspace/project/vast-instances.json must stay up to date — other skills depend on itvastai CLI requires Python ≥ 3.10 — if system Python is older, use a conda envUsers only need to set gpu: vast — no hardware preferences required:
markdown## Vast.ai - gpu: vast # tells run-experiment to use vast.ai - auto_destroy: true # auto-destroy after experiment completes (default: true) - max_budget: 5.00 # optional: max total $ to spend (skill warns if estimate exceeds this) - image: pytorch/pytorch:2.1.0-cuda12.1-cudnn8-devel # optional: override Docker image
The skill analyzes experiment scripts and plans to determine what GPU to rent. No need to specify GPU model, VRAM, or instance count.
/aris-run-experiment "train model" ← detects gpu: vast, calls /aris-vast-gpu provision
↳ /aris-vast-gpu provision ← analyzes task, presents options with cost
↳ user picks option ← rent + setup + deploy
↳ /aris-vast-gpu destroy ← auto-destroy when done (if auto_destroy: true)
/aris-vast-gpu provision ← manual: analyze task + show options
/aris-vast-gpu rent <offer_id> ← manual: rent a specific offer
/aris-vast-gpu list ← show active instances
/aris-vast-gpu destroy <instance_id> ← tear down, stop billing
/aris-vast-gpu destroy-all ← tear down everything| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→fail | 5,723 | 22,349 | +291% | 1 | 1 | 0% | 886 | 6,446 | +628% | 0 | 0 | — |
case-02 | fail→fail | 18,473 | 24,268 | +31% | 1 | 1 | 0% | 3,978 | 10,324 | +160% | 0 | 0 | — |
case-03 | fail→fail | 11,184 | 6,305 | -44% | 1 | 1 | 0% | 2,180 | 6,104 | +180% | 0 | 0 | — |
case-04 | fail→fail | 15,263 | 7,531 | -51% | 1 | 1 | 0% | 3,121 | 5,146 | +65% | 0 | 0 | — |
case-05 | fail→fail | 6,406 | 6,491 | +1% | 1 | 1 | 0% | 561 | 4,846 | +764% | 0 | 0 | — |
case-06 | fail→fail | 12,735 | 5,702 | -55% | 1 | 1 | 0% | 2,391 | 4,817 | +101% | 0 | 0 | — |
case-07 | fail→pass | 14,847 | 7,287 | -51% | 1 | 1 | 0% | 2,432 | 5,981 | +146% | 0 | 0 | — |
case-08 | fail→pass | 14,178 | 3,001 | -79% | 1 | 1 | 0% | 2,588 | 5,097 | +97% | 0 | 0 | — |
case-09 | pass→pass | 10,375 | 6,725 | -35% | 1 | 1 | 0% | 1,780 | 5,916 | +232% | 0 | 0 | — |
case-10 | fail→fail | 15,257 | 10,165 | -33% | 1 | 1 | 0% | 3,035 | 6,501 | +114% | 0 | 0 | — |
case-11 | pass→pass | 7,979 | 2,746 | -66% | 1 | 1 | 0% | 1,326 | 5,086 | +284% | 0 | 0 | — |
case-12 | fail→pass | 11,418 | 4,906 | -57% | 1 | 1 | 0% | 2,027 | 5,606 | +177% | 0 | 0 | — |
case-13 | fail→pass | 9,984 | 2,359 | -76% | 1 | 1 | 0% | 1,956 | 4,845 | +148% | 0 | 0 | — |
case-14 | fail→pass | 19,759 | 5,236 | -74% | 1 | 1 | 0% | 1,265 | 5,465 | +332% | 0 | 0 | — |
case-15 | fail→fail | 3,793 | 3,053 | -20% | 1 | 1 | 0% | 851 | 5,090 | +498% | 0 | 0 | — |
case-16 | fail→fail | 3,162 | 1,890 | -40% | 1 | 1 | 0% | 715 | 4,842 | +577% | 0 | 0 | — |
case-17 | fail→pass | 10,573 | 3,221 | -70% | 1 | 1 | 0% | 1,845 | 5,004 | +171% | 0 | 0 | — |
case-18 | pass→pass | 11,032 | 2,804 | -75% | 1 | 1 | 0% | 2,213 | 4,976 | +125% | 0 | 0 | — |
case-19 | fail→pass | 14,031 | 2,673 | -81% | 1 | 1 | 0% | 2,677 | 4,973 | +86% | 0 | 0 | — |
case-20 | fail→pass | 12,416 | 4,160 | -66% | 1 | 1 | 0% | 2,239 | 5,166 | +131% | 0 | 0 | — |
case-21 | fail→fail | 13,288 | 7,733 | -42% | 1 | 1 | 0% | 2,284 | 5,832 | +155% | 0 | 0 | — |
case-22 | fail→fail | 16,100 | 7,271 | -55% | 1 | 1 | 0% | 2,875 | 5,741 | +100% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted, and 18 counted toward the lift figure. The other 4 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +36 percentage points is the difference between those two pass rates over the 18 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.