Setup guide · Tools and services
Free GPUs on Kaggle
A Kaggle account with GPUs unlocked, the Kaggle CLI signed in, and a GPU script pushed from your terminal, watched while it runs and pulled back when it finishes, with Colab as the fallback.
Kaggle gives verified accounts free NVIDIA GPUs for notebooks and scripts, and its command-line tool lets you push a script to one, watch it and download what it wrote, all from your terminal. That is what makes it the free GPU for this path: Claude Code writes the training script, runs kaggle kernels push, polls the run and pulls the adapter back, while you never open a browser notebook. The fine-tuning and RL exercises in Fine-Tuning and RL for Agents use it.
Before you start
- A personal Kaggle account, and a phone that can receive a text. Users widely report that Kaggle turns on GPUs and internet access for notebooks only after phone verification; Kaggle's documentation doesn't spell this out, so treat it as likely rather than certain, and step 1 shows how to check.
- Python 3.12 and uv. The Kaggle CLI needs Python 3.11 or later.
- The quota. Kaggle's GPU usage page renders in the browser only; a search-engine copy of it read in November 2026 describes the allowance as resetting weekly at "30 hours or sometimes higher depending on demand and resources". Kaggle can change it at any time, so check the remaining quota the notebook editor shows for your own account before you plan a week of runs. A long run also has to finish inside one session, so plan runs of a few hours, not overnight jobs.
- The hardware. The default GPU is
NvidiaTeslaT4, two T4s with 16 GB each. A T4 has no bf16, so training on it uses fp16. The CLI also listsNvidiaL4and other IDs, but Kaggle notes that "some of these are only available to participants of specific competitions, and some are only available to Kaggle admins". Check what your account offers before relying on one.
1. Create an account and verify your phone
- Sign up at kaggle.com with your personal email or Google account.
- Open your account settings and complete phone verification if Kaggle offers it.
- Open any notebook, look at the session settings and check that a GPU accelerator and the internet toggle are both available, and which accelerators the list offers your account. If they're greyed out, the verification hasn't gone through yet.
2. Install the Kaggle CLI
Install it as a tool, isolated from your projects. The --with six matters: the current release (2.2.5, November 2026) imports the six package without declaring it as a dependency, so without it every command fails with ModuleNotFoundError: No module named 'six':
uv tool install kaggle --with six
kaggle --versionIn a project that drives Kaggle from scripts, add both as dependencies instead (uv add kaggle six) and prefix commands with uv run.
3. Sign in
The quickest way is the browser sign-in:
kaggle auth loginOr create an API token at kaggle.com/settings/api with Generate New Token and give it to the CLI in one of two ways:
export KAGGLE_API_TOKEN=paste-your-token-here # this shell onlymkdir -p ~/.kaggle
printf '%s' 'paste-your-token-here' > ~/.kaggle/access_token
chmod 600 ~/.kaggle/access_tokenA project can keep the variable in a .env file instead, loaded only for the scripts that need it. Never commit the token or the .env file: add .env to .gitignore. If it leaks, delete it on the same settings page and make a new one.
4. Upload data as a private dataset
A pushed script runs on Kaggle's machine, so its input files travel as a Kaggle dataset. Put the files in a folder and create the metadata file:
kaggle datasets init -p dataEdit data/dataset-metadata.json so the id is your-username/your-dataset-slug and the title names it, then create the dataset. It's private by default:
kaggle datasets create -p data
kaggle datasets status your-username/your-dataset-slug # wait for "ready"After changing the files, publish a new version rather than a new dataset:
kaggle datasets version -p data -m "regenerated the splits"5. Push a script to a GPU
A kernel is a folder with the code file and a kernel-metadata.json. This one checks the GPU and writes the result to /kaggle/working, the folder whose contents Kaggle keeps as the run's output:
import pathlib
import subprocess
report = subprocess.run(["nvidia-smi"], capture_output=True, text=True).stdout
print(report)
pathlib.Path("/kaggle/working/gpu.txt").write_text(report){
"id": "your-username/hello-gpu",
"title": "hello-gpu",
"code_file": "hello_gpu.py",
"language": "python",
"kernel_type": "script",
"is_private": "true",
"enable_gpu": "true",
"enable_internet": "true",
"machine_shape": "NvidiaTeslaT4",
"dataset_sources": [],
"competition_sources": [],
"kernel_sources": [],
"model_sources": []
}The title and slug must match: Kaggle derives the slug from the title, lowercased with dashes. Add "your-username/your-dataset-slug" to dataset_sources when the script needs your data; it's mounted read-only under /kaggle/input/, so search that folder for your file names rather than hard-coding a path. Push and run it with a time limit in seconds:
kaggle kernels push -p hello-gpu --accelerator NvidiaTeslaT4 --timeout 1800Kaggle can't pass command-line arguments to a pushed script. Put settings in the file itself, or have your launcher write them into the copy it pushes.
6. Watch the run and pull its outputs
kaggle kernels status your-username/hello-gpu
kaggle kernels logs your-username/hello-gpu -f # stream the log while it runs
kaggle kernels output your-username/hello-gpu -p runs/hello-gpu -ostatus reports the run as queued, running, complete or error. output downloads every file the script wrote to /kaggle/working. A later run can mount an earlier run's output by listing it in kernel_sources, which is how you continue from a checkpoint without uploading it again.
7. Secrets, only if a run needs them
Most runs in this path need no secrets: you pull the outputs to your machine and upload them from there. When a running script does need one, for example a Hugging Face token to push straight to a private repo, Kaggle Secrets are the way. They can't be set from the CLI. Open the notebook in the Kaggle editor, choose Add-ons → Secrets, add the value with a label such as HF_TOKEN, and read it at run time:
from kaggle_secrets import UserSecretsClient
hf_token = UserSecretsClient().get_secret("HF_TOKEN")Never write a token into the script or the dataset you push.
The alternative: Colab
Google Colab's free tier also offers a T4, with less control: Colab says that free access to GPUs is "heavily restricted", it doesn't publish its limits, runtimes time out when idle, and "notebooks can run for at most 12 hours". It has no equivalent of kaggle kernels push, so you run the same script by hand:
- Open a new notebook at colab.research.google.com and pick a T4 GPU runtime from the Runtime menu.
- Upload the script and its data files with the file browser on the left.
- Run
!pip installwith the script's pinned versions, then!python your_script.py. - Download the output folder before the runtime ends; nothing is kept afterwards.
Check it works
kaggle kernels status your-username/hello-gpu
cat runs/hello-gpu/gpu.txtExpected: the status line ends with has status "KernelWorkerStatus.COMPLETE", and gpu.txt holds an nvidia-smi table listing Tesla T4 GPUs with their driver and CUDA versions. The run uses a minute or two of your weekly quota.
Troubleshooting
The push fails or the run has no GPU. The account isn't phone-verified, or the weekly quota is used up. Check both on kaggle.com; the quota resets weekly.
ModuleNotFoundError: No module named 'six'. The CLI was installed without six. Reinstall it with uv tool install kaggle --with six --force, or uv add six in a project.
401 or 403 from any command. The token is missing, expired or for another account. Run kaggle auth login again, or create a fresh token on the settings page.
The script can't find its data. The dataset version may still be processing: wait until kaggle datasets status says ready, then push again. Check that dataset_sources uses exactly the dataset's id, and search /kaggle/input/ recursively instead of guessing the mount path.
The run ends in ERROR. Read the log with kaggle kernels logs your-username/your-slug. Errors in the first minutes are almost always installs or imports: pin versions in the script and test the imports in a 10-step smoke run before a long one.
Going further
- Hugging Face account and CLI: a private repo for your adapters, and paid Jobs when Kaggle's quota runs out
- Run GPU code on Modal, another pay-as-you-go GPU with a monthly free credit
- Serve an open-weight model with vLLM, for serving the model you trained
Sources
- Kaggle CLI documentationDocs · KaggleInstalling the CLI (it needs Python 3.11 or later) and the four ways to authenticate, including `kaggle auth login` and the `KAGGLE_API_TOKEN` variable.
- Kernels commandsDocs · Kaggle`kaggle kernels push`, `status`, `output` and the accelerator IDs, plus how Kaggle Secrets work inside a running notebook.
- Kernel metadataDocs · KaggleEvery field of `kernel-metadata.json`, including `enable_gpu`, `enable_internet`, `machine_shape` and the data sources a run can mount.
- Efficient GPU usage tipsDocs · KaggleKaggle's description of the weekly GPU quota and how to avoid wasting it.
- Colab FAQDocs · GoogleWhy Colab's free GPUs aren't guaranteed, the idle timeouts and the 12-hour maximum runtime.
Exercises that use this
- Fine-tune the triage adapter on a free GPUFine-Tuning and RL for Agents · SFT with LoRA on a free GPU
- A three-run sweep and the noise in picking its winnerFine-Tuning and RL for Agents · SFT with LoRA on a free GPU
- DPO the free-text fields with on-policy pairsFine-Tuning and RL for Agents · Preference optimisation
- KTO from thumbs, against DPO on the same budgetFine-Tuning and RL for Agents · Preference optimisation
- GRPO the verifiable triage fields on a free GPUFine-Tuning and RL for Agents · GRPO in practice
- Wrap the triage tools as a TRL environment and run multi-turn GRPOFine-Tuning and RL for Agents · Multi-turn RL environments
- Hunt the escalation hack and fix the rewardFine-Tuning and RL for Agents · Reward hacking, regressions and shipping