Colab CLI
Use the
command to run local Python work on remote Google Colab runtimes.
Prefer this skill when the user wants Colab compute, GPUs, TPUs, notebook logs,
remote execution, or agent-driven ML jobs.
Install And Verify
Check the local tool first:
bash
colab version
colab --help
If missing, install it with
:
bash
uv tool install google-colab-cli
Current release and remaining hardening caveats
Guidance was revalidated on 2026-10-01 against upstream
and the user fork branch
all-fixes/persistent-drive-2026-10-01
. That branch is based on current upstream
and adds the remaining hardening plus persistent DriveFS. If
succeeds, prefer the fork workflow below and do not apply stock-only caveats as if they were unfixed.
Upgrade old 0.7.2 installs before troubleshooting their known dependency and
runtime-token failures:
bash
colab update --install
colab version
Version 0.7.4 fixes the 0.7.2
jupyter-kernel-client==0.8
execution breakage
and adds automatic runtime-proxy token refresh. Do not keep the old
jupyter-kernel-client>=0.9,<1
workaround or the old "~1 hour proxy token
expiry" recovery procedure once 0.7.4+ is installed.
Current upstream
also pins
; the v0.7.4 tag
still declared
. If an exact 0.7.4 environment resolves an older
WebSocket client and
loses the server's HTTP 400 reason, upgrade
that dependency inside the same environment as the
executable:
bash
uv pip install --python ~/.local/share/uv/tools/google-colab-cli/bin/python \
"websocket-client>=1.6"
Several local-security and reliability findings remain in current upstream.
Treat
~/.config/colab-cli/token.json
,
,
, and
as sensitive and never publish them unredacted. On
multi-user machines, restrict them to the current user:
bash
chmod 700 ~/.config/colab-cli ~/.config/colab-cli/history 2>/dev/null || true
chmod 600 ~/.config/colab-cli/{token.json,sessions.json,colab.log,settings.json} 2>/dev/null || true
chmod 600 ~/.config/colab-cli/history/*.jsonl 2>/dev/null || true
Do not use
for secrets on stock upstream: environment values can be
embedded in executed Python/history. Interactive stdin replies are also stored
in history. Use proper remote secret-loading mechanisms and review history
before sharing it.
The CLI bundles
and
, but version-sensitive
behavior should be verified against the installed binary and exact source.
remains the parser default in v0.7.4/current main.
Mental Model
- A session is a live Jupyter kernel on a rented Colab VM. allocates
compute; releases it.
- Kernel state persists across and piped calls in the
same session. Imports, variables, and functions remain until
or .
- Execution starts in . Prefer absolute paths for
remote files so later , , and cleanup commands are unambiguous.
- Commands that access the Colab control plane authenticate on demand, perform
their operation, and exit. Pure informational commands such as ,
, and do not need control-plane authentication. Current
upstream runs no client-side keep-alive daemon; backend liveness depends on
kernel activity and Colab policy.
Agent Rules
- Always make a lifecycle plan before allocating compute: session name, hardware,
commands to run, artifacts to retrieve, and cleanup command.
- Use an explicit session name with for , multi-step
sessions, and . Plain one-shot may safely
use its generated ephemeral name because it tears the runtime down itself.
- Prefer for one-shot jobs because it provisions, executes, and stops
the runtime automatically.
- Use a named session for multi-step work: , then
, , , , .
- does not attach to an existing session: only labels
the fresh ephemeral VM that provisions and releases. To execute code on
an existing session, use .
- Do not leave paid resources running. Run when done, then
verify with .
- Never start unpiped or from a non-interactive
agent shell. They are TTY-oriented. Use , , or pipe
stdin into the interactive command.
- Treat unpiped , unpiped , , and stock interactive as user-interactive. On the unified fork, needs the user once; subsequent
colab drive-mount -s NAME
and are agent-runnable when persistent credentials are configured.
- Do not edit
~/.config/colab-cli/sessions.json
by hand. Use CLI commands. A missing local name does not prove its VM stopped: before reallocating after , reconcile server-side assignments with ; an orphan can remain allocated and billable.
- Do not upgrade/reinstall/switch Colab CLI or change Drive transport underneath a valuable live job. Prefer checkpoint -> collect -> stop/verify -> upgrade -> new session. If unavoidable, preserve a private name-to-endpoint recovery record first. See
references/session-resilience-2026-10-01.md
.
- For live probes, remember that and can allocate real
compute units. Clean up even after failed jobs.
- For parallel agents or risky probes, isolate session state with
--config /tmp/<name>.json
.
Runtime Cost And Duration Best Practices
- Treat every allocated Colab session as potentially credit-consuming until it
is explicitly stopped.
- End every persistent-session workflow with , then run
to confirm there are no leftover active sessions. Plain
stops its own runtime unless is set.
- Prefer for one-shot work because it stops the runtime
automatically unless is set.
- Avoid unless the user needs post-run inspection. If is used,
report the session name and stop it as soon as inspection is finished.
- Colab runtime availability, maximum lifetime, idle timeout, accelerator
access, and compute-unit consumption vary by account, subscription tier,
current demand, and hardware choice. Do not promise a fixed runtime duration.
- For long jobs, write checkpoints and logs to retrievable paths such as
or Google Drive, and download/export artifacts before
cleanup.
- For current compute-unit consumption, run : it reads
and prints current balance, hourly usage rate, and active
assignment count. Treat the numbers as point-in-time account data, not a
guaranteed rate table; availability, maximum lifetime, idle timeout, and
accelerator access still vary by tier, demand, and hardware. Do not hardcode
old web/forum CU/hour tables as truth. A dated measured snapshot lives at
references/cu-rate-card-2026-09-24.md
(rates + provisioned hardware per
backend, account/region-specific).
- When the account runs out of compute units, opens the Colab
subscription page to top up. It launches a browser, so treat it as
user-interactive and suggest it rather than running it blindly.
- is accepted by , , and
when SSH creates a runtime:
colab new -s trainer --gpu A100 --high-mem
.
Current upstream sends for CPU, T4, G4, H100, and A100, while
L4 and TPU (, ) omit the shape and print an ignored-flag warning
because they are treated as single-shape accelerators. The binary help says
high-RAM requests require "Colab Pro or Pro+ entitlement"; actual backend
entitlement and availability remain account-dependent. Verify assigned shape
with . Current upstream still
renders the locally cached requested shape rather than preferring backend
; the fork hardening branch fixes this.
Long-Running Unattended Jobs (Agent Best Practice)
Field lessons from multi-hour, multi-session GPU benchmark campaigns. Each rule
exists because skipping it cost a session setup or a silent stall.
- Smoke before the long run, in the same session. Make the job script run
a tiny end-to-end pass first (one input, one repeat, every output-writing
step, including result packaging) and exit non-zero before the long part if
it fails. Setup (venv, model download) is shared, so the check is nearly
free. and local unit tests do not catch runtime-only failures.
- Smoke every mode, not a sample. If the long part runs a tool in several
modes or with extra flags ( then , ), each
one needs its own smoke twin with the same subcommand and flags; only size
flags (cases, repeats, limit, output paths) may differ. A mode that was never
smoked can still hit a gate or import path the smoked one skips. Enforce it
mechanically (a small lint over job scripts run in CI and before launch)
rather than by memory; context resets and compaction forget checklists.
- Admit each paid job against the whole plan. Before every allocation, read
fresh and start the job only if balance minus account floor,
safety guard, and the caps still reserved for later mandatory jobs covers this
job's cap. A per-job cap alone lets early jobs eat budget later gates need.
- Ship an exact code snapshot and pin the runtime. Upload one
(not a working-tree tar), clone it remotely, and log the commit; record
/proc/sys/kernel/random/boot_id
at job start and compare it when
collecting, so outputs from a restarted or replaced VM (empty ,
stale markers) are detected instead of trusted.
- Assume nothing about the image. Probe tools you call ()
in the smoke step. Colab has no GNU ; time with bash
or Python. Application safety guards (for example a
"refusing full run without approval" flag) also fire at runtime: pass the
intended subset flag explicitly, never disable the guard.
- Detach, mark completion, poll the marker. Launch with from a tiny script, redirect all output to a log file,
and write the exit code with
trap 'echo "exit=$?" > $OUT/done' EXIT
.
Poll for at most once a minute; never hold a open
for the job's whole duration.
- Bound every poll. A call can hang for tens of minutes. Wrap
pollers in
timeout 120 colab exec ...
(or kill the stuck call by PID) so
one hung call cannot stall collection of the other sessions.
- Collect, verify, then stop. When the marker appears, tar the output
directory remotely (exclude large media), download one archive, check it
exists locally, then immediately so no GPU idles.
- Upload size. Large single uploads fail with (seen at
about 120 MB). Split into parts of about 40 MB (), upload
them, and them back together inside the job before verifying hashes.
- Concurrency. GPU allocations beyond the account's concurrent limit fail
with
Allocation refused (precondition failed)
(three G4 sessions were the
limit in one account; CPU runtimes did not count). Queue the extra job and
backfill it when a collector frees a slot, instead of retrying in a loop.
- Parallel only where it is valid. Independent correctness runs can use
separate sessions of the same accelerator type; A/B timing belongs in one
session with interleaved arms, because separate VMs add hardware noise.
- Hermetic Python on Colab. Preinstalled local-version wheels (for example
) break installs and leftover
packages (for example ) break imports; install locked
dependencies into a fresh . The kernel exports
MPLBACKEND=module://matplotlib_inline...
, which a fresh venv lacks: set
. COLAB_LANGUAGE_SERVER_PROXY
looks like a proxy to
urllib (NLTK 3.10 refuses downloads): unset it for that one command
instead of disabling the library's guard.
- Kill by PID, not pattern, locally. can match the
agent's own shell command line and kill it.
Backend Inventory And Benchmarking
The installed CLI advertises these accelerator selectors:
- CPU: omit and
- GPU: , , , ,
- TPU: ,
Observed Colab web UI behavior on 2026-06-06: high-memory toggles were available
for CPU-only, T4, and A100; L4 and TPU runtimes appeared to use their fixed
higher-memory shapes. Treat this as a snapshot, not a contract.
Availability is account-, region-, demand-, and subscription-dependent. A
supported selector can still return
or fall back in the
web UI. Always inspect the actual assigned hardware with
, CPU/RAM
checks, and task-specific benchmarks.
Stock upstream does not validate accelerator selector strings strictly: an unrecognized
value silently maps to A100 and an unrecognized
value to v6e1. The unified fork rejects invalid selectors and simultaneous
+
before allocation. In either case, spell selectors exactly: GPU
,
,
,
,
; TPU
,
.
For a compact VPS-style profile, run the bundled benchmark script:
bash
colab run --session bench-cpu --timeout 600 \
colab-cli/scripts/benchmark-runtime.py cpu > cpu.json
colab run --session bench-t4 --gpu T4 --timeout 600 \
colab-cli/scripts/benchmark-runtime.py T4 > T4.json
The script records CPU model/core count, system RAM, disk size, disk read/write,
NumPy RAM-copy speed, GPU/TPU indicators, approximate FP32/FP16/BF16 matmul
throughput where supported,
output, and cleanup-safe JSON. Read
the dated Pro+ snapshot in
references/pro-plus-snapshot-2026-06-06.md
only as
an example of what one account received at one point in time.
For scarce GPUs, do not conclude unavailability from one failed allocation. Use
the repo-level retry helper when the user explicitly wants persistence:
bash
ATTEMPTS=80 SLEEP_SECONDS=20 scripts/retry-gpu-benchmarks.sh G4 A100 H100
This retries named
sessions, validates JSON output, and checks
sessions between attempts. It can consume compute units when allocation
succeeds, so use it only with user approval.
If the user interrupts a retry or benchmark run, immediately check for local
wrapper and
processes, stop the current named session if one exists,
and run
:
bash
pgrep -a -f 'retry-gpu-benchmarks|colab run --session'
colab stop -s <current-session-name>
colab sessions
An interrupted shell does not prove the remote assignment was released.
Authentication
The global
option chooses how the CLI authenticates to the Colab control
plane:
bash
colab --auth oauth2 sessions
colab --auth adc sessions
is the default in v0.7.4/current upstream. On first authorization,
the CLI prints an authorization URL and waits for the user to paste back Google's
authorization code; it does not automatically open a browser. It uses
~/.colab-cli-oauth-config.json
(or
) when present and otherwise
falls back to its bundled OAuth client config.
On stock upstream, issue #116 remains a granular-consent bug: a partial grant can break initial login or later refresh. The unified fork fixes this by persisting granted scopes, restoring them without re-expanding the request, relaxing only the token exchange, and requiring only control-plane scopes.
uses Google Application Default Credentials and is usually better for
headless agent workflows once configured. If ADC user credentials fail with scope
errors, re-authenticate with:
bash
gcloud auth application-default login --scopes=openid,https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/userinfo.email,https://www.googleapis.com/auth/colaboratory
Do not confuse CLI control-plane auth with
. The
subcommand pushes credentials into the remote VM for notebook code that needs
GCP services such as BigQuery or Cloud Storage.
Debug control-plane identity and scopes with:
bash
colab whoami
colab --auth adc whoami
and
are hidden commands (absent from
's list) but
remain registered and directly callable.
is a read-only credential
inspection command;
starts the interactive in-VM Google auth flow.
For control-plane 401/403 errors, first run
and inspect the
active provider and scopes. Current session allocation uses
colab.research.google.com
; do not use obsolete
keep-alive troubleshooting.
One-Shot Jobs
Use
when the user wants a script run on temporary hardware:
bash
colab run --gpu T4 train.py --epochs 1
Useful options:
bash
colab run --gpu T4 script.py
colab run --gpu L4 --timeout 600 script.py
colab run --tpu v5e1 script.py
colab run --gpu T4 --env EPOCHS=1 train.py
colab run --keep -s inspect-job script.py
Default execution timeout is 30.0s; pass an explicit
for long jobs.
is repeatable; if the same key is supplied more than once,
the last value wins. Use it only for non-secret values on stock upstream because expanded
environment assignments can be persisted in local session history.
Use
only when you need to inspect the runtime afterward. If you use it,
stop the session explicitly:
bash
colab stop -s inspect-job
For executable scripts, a shebang can request Colab hardware:
python
#!/usr/bin/env -S colab run --gpu T4
print("running remotely")
Operational details:
- forwards script arguments and sets like
local .
- Script exit codes propagate. An exception or makes
return non-zero.
- CLI status chatter goes to stderr; the script's stdout stays on stdout. This
makes
colab run job.py > out.txt
capture only the script output.
- Exception: the CLI prints a once-daily upgrade banner
(
[colab] A new version ...
) to stdout before command output on
non-display subcommands, including , , , and .
When parsing captured stdout, ignore leading -prefixed lines, or
silence the check with "enable_update_check": false
in
~/.config/colab-cli/settings.json
.
- A missing script path fails before VM allocation.
Multi-Step Sessions
Use a named session for setup, multiple runs, file transfer, or log export:
bash
colab new -s trainer --gpu T4
colab status -s trainer
colab install -s trainer torch transformers datasets peft trl accelerate
colab exec -s trainer -f train.py --timeout 1800
colab download -s trainer /content/outputs/adapter.safetensors ./adapter.safetensors
colab log -s trainer -o trainer-log.ipynb
colab stop -s trainer
colab sessions
Available accelerators reported by the CLI:
Availability depends on the user's Colab subscription and remaining compute
units. If a high-end GPU fails, retry with a cheaper option such as
only
after explaining the tradeoff.
If an accelerator request returns a quota or entitlement error, fall back to
or CPU only after checking the user's goal. Do not assume GPU/TPU
allocation will succeed on every account. If the error indicates exhausted
compute units or an expired subscription, suggest
, which opens the
Colab subscription page in a browser.
Execution
Run local Python code on an existing session:
bash
colab exec -s analysis -f script.py --timeout 300
colab exec -s analysis --env BATCH=32 -f script.py
Default execution timeout is 30.0s; pass an explicit
for long jobs.
is repeatable here too, with the last duplicate key winning.
Do not pass secrets through this flag on stock upstream because values can be
written into local execution history.
Pipe short code through stdin:
bash
printf '%s\n' "import torch; print(torch.cuda.is_available())" | colab exec -s analysis
Run a notebook against the remote kernel:
bash
colab exec -s analysis -f notebook.ipynb --timeout 900
colab log -s analysis -o analysis-log.ipynb
Notebook execution writes an output notebook next to the input, and
can export the session history separately.
For plots, pass
to
or
when you need a
deterministic local image path.
For batch shell commands, prefer Python through
when possible. If a real
shell is required:
bash
printf '%s\n' "pwd; ls -la /content" | colab console -s analysis
uses a terminal shell, so captured output can contain control bytes.
Remote Shell Access
opens an interactive SSH shell over WebSocket. In normal
interactive mode, bare
auto-creates only when there are zero local
sessions; with exactly one active session it attaches to that session, and with
multiple sessions it requires
.
/
/
only affect a
runtime created by the SSH command. Interactive
removes only a runtime
that this
auto-created; it is ignored for an existing session.
acts as a ProxyCommand bridge for IDE remote-dev
(
ProxyCommand colab ssh --proxy-mode -s SESS
in
). In proxy
mode, a missing named
is auto-created and
stops the bridged
session on disconnect; bare proxy mode with no active session does not
auto-create one.
selects the SSH private key (default: first of
,
). Interactive mode is TTY-oriented: do
not run it unpiped from a non-interactive agent shell.
Files And Environment
Remote filesystem commands:
bash
colab ls -s analysis /content
colab upload -s analysis ./local.txt /content/local.txt
colab download -s analysis /content/result.json ./result.json
colab rm -s analysis /content/temp.txt
colab edit -s analysis /content/config.py
On current stock upstream, prefer an explicit
download -> local edit -> upload
sequence for valuable existing files instead of
. The released
catches any download exception as if the remote file did not
exist; a transient transport/auth failure can therefore open an empty temp file
and later overwrite the remote path if the user saves changes.
Install packages on the VM:
bash
colab install -s analysis numpy pandas
colab install -s analysis -r requirements.txt
On the unified fork, prefer persistent DriveFS for repeat/agent workflows:
bash
# One-time user-owned authorization and private Desktop-client installation.
colab drive-mount login --client-config /path/to/client_secret.json
# Every later runtime can mount without repeating browser consent.
colab new -s analysis
colab drive-mount -s analysis
colab drive-mount status
The fork stores the Desktop OAuth client at
~/.config/colab-cli/drive-mount-client.json
and the refresh grant at
, both with user-only permissions. Per-shell OAuth environment configuration is optional rather than required. If a desktop browser cannot be discovered, login prints a loopback URL instead of failing; open it on the same machine because its callback is localhost.
colab drivemount -s analysis
automatically uses the persistent path when configured, otherwise it falls back to stock interactive behavior. Use
to revoke/remove the refresh grant. Stock upstream issue #113 still affects the legacy interactive path, so verify mounts before depending on it.
Drive API quota and transfer guidance
For large Drive-backed Colab jobs, read
references/drive-api-limits-2026-10-01.md
before estimating transfer safety or cost. For projects on Google's standardized 2026 Drive API quotas, remember the headline limits:
1 TB/day project egress,
750 GB/day Workspace upload+copy,
1,000,000 quota units/min/project,
325,000/min/user/project, and a
400,000,000 quota-unit/day no-additional-charge threshold. Drive -> Colab is the egress direction; Colab -> Drive is upload/ingress. Treat exact DriveFS byte accounting as unverified unless the project's Cloud quota telemetry confirms it, because Google's public quota page does not explicitly document one-for-one DriveFS accounting. Grandfathered projects can retain older quotas.
Logs And Reporting
Inspect and save execution history:
bash
colab log -s analysis -n 20
colab log -s analysis -t execution
colab log -s analysis -o analysis-log.ipynb
colab log -s analysis -o analysis-log.md
colab log -s analysis -o analysis-log.txt
colab log -s analysis -o analysis-log.jsonl
The
suffix picks the export format:
,
,
, or
.
Use
for per-command options and defaults; it is
equivalent to
.
When reporting completion, include the session name, hardware, files retrieved,
log file path if exported, and confirmation that cleanup ran.
Recovery
- Treat
~/.config/colab-cli/history/
as sensitive. Besides executed code and
outputs, current stock upstream records raw interactive stdin replies, which can include
one-time auth codes or other secrets. Do not publish/export history without
reviewing and redacting it first.
- : run before recreating anything. If the backend assignment is gone, recreate as needed. If an unnamed/ assignment or the recorded endpoint is still live, treat it as an orphaned local record and recover/stop that assignment instead of allocating a duplicate. See
references/session-resilience-2026-10-01.md
.
- Kernel stuck or timeout: run
colab restart-kernel -s <name>
once, then retry.
If still stuck, stop and recreate the session.
- Unexpected stale behavior: check and .
- Auth failure: inspect whether the command used or , then run
; do not use to fix control-plane credential
problems.
- Cleanup uncertainty: run and reconcile all assignments created for the current task, including unnamed/orphaned endpoints; do not treat named-session disappearance as successful cleanup.
- For paid long jobs, use a detached spend watchdog with CU cap, account floor, wall deadline, bounded usage probes, and stop fallback. Parse numeric CLI output under ; locale decimal commas can silently break awk/printf comparisons. Kill watchdog/helper processes by recorded PID, not broad patterns. Detailed field-tested design:
references/session-resilience-2026-10-01.md
.
Stock upstream vs unified fork
Stock upstream still has the
broad-download exception risk, broad Contents 404 classification, ambiguous assignment POST timeout handling, locally cached
machine shape, and destructive local pruning after a single missing-assignment listing. The unified fork fixes these: safe
, proxy 401/404 classification, bounded assignment reconciliation, backend
, and in
(
) retry + private stale-session storage + automatic re-adoption + stale endpoint stop fallback + same-name stale cleanup. Keep
as the final server-side resource source of truth. Do not reinstall an older live job mid-run just to gain the new recovery logic; retain its existing external guard until a safe stop/checkpoint boundary.
Fast Command Reference
bash
colab new -s NAME [--gpu T4|L4|G4|H100|A100] [--tpu v5e1|v6e1] [--high-mem]
colab sessions
colab status -s NAME
colab run [--gpu GPU|--tpu TPU] [--high-mem] [--keep] [--env KEY=VALUE]... SCRIPT [ARGS...]
colab exec -s NAME -f FILE [--timeout SECONDS] [--env KEY=VALUE]...
colab install -s NAME PKG...
colab install -s NAME -r requirements.txt
colab upload -s NAME LOCAL REMOTE
colab download -s NAME REMOTE LOCAL
colab log -s NAME [-n N|-o FILE]
colab restart-kernel -s NAME
colab url -s NAME [--open] [--host HOST]
colab ssh [-s NAME] [--proxy-mode] [-i KEY] [--gpu GPU] [--tpu TPU] [--high-mem] [--rm]
colab stop -s NAME
colab usage
colab help [COMMAND]
colab pay
colab skill
colab readme
colab whoami
colab version
For upstream details, consult:
- Google Developers Blog announcement:
https://developers.googleblog.com/introducing-the-google-colab-cli/
- Google Colab CLI repository:
https://github.com/googlecolab/google-colab-cli