Skip to main content

lightning-studios

Manage Lightning AI Studios (cloud dev machines with CPUs/GPUs) - create, start, stop, delete studios, switch machine types, run commands in them, upload/download files, and SSH in. Use when the user wants to work with lightning.ai Studios, needs a cloud GPU dev box, or asks to run something "on a studio".

معلومات المصدر

المستودع
Lightning-AI/skills
آخر نشاط في المصدر
٢٨ سبتمبر ٢٠٢٦ في ٠٩:٤١
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
٧
التفرعات
٠

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
name
lightning-studios
description
Manage Lightning AI Studios (cloud dev machines with CPUs/GPUs) - create, start, stop, delete studios, switch machine types, run commands in them, upload/download files, and SSH in. Use when the user wants to work with lightning.ai Studios, needs a cloud GPU dev box, or asks to run something "on a studio".
# Lightning AI Studios A Studio is a persistent cloud development machine on [lightning.ai](https://lightning.ai). Its filesystem persists across sessions; compute (CPU/GPU) attaches on start and detaches on stop. Everything below uses the `lightning` CLI and `lightning_sdk` Python package. ## Setup & auth ```bash # Use the Lightning AI CLI from the current env; install or upgrade it there if it's missing or older than 2026.9.18 v=$(lightning --version 2>/dev/null | sed -n 's/^Lightning CLI version //p') [ -n "$v" ] && [ "$(printf '%s\n' 2026.9.18 "$v" | sort -V | head -1)" = 2026.9.18 ] \ || uv pip install -U lightning-sdk || python3 -m pip install -U lightning-sdk lightning --version # must print "Lightning CLI version …"; if not, see the table below lightning login # browser flow; or set env vars for headless use: export LIGHTNING_API_KEY=... LIGHTNING_USER_ID=... # USER_ID optional: with it Basic auth, without it the key is a Bearer token ``` This uses, and if needed installs into, the agent's current environment (project venv, conda env, …); then call plain `lightning …` everywhere. If setup doesn't go cleanly: | Symptom | Fix | |---|---| | No active env, `externally-managed-environment`, or a conflict with the project's own pins | Install it on its own: `uv tool install lightning-sdk` (or `pipx install lightning-sdk`), and call `"$(uv tool dir --bin)/lightning"` if that isn't on `PATH` | | Still no `Lightning CLI version` line after installing | Another `lightning` (PyTorch Lightning's) or an inactive env comes first: check `command -v lightning`, then activate the env or call its `bin/lightning` | | `No such command`, `No such option` or `unexpected extra argument` | The CLI is too old: upgrade it where `command -v lightning` points (`uv pip install -U lightning-sdk`, or `uv tool upgrade lightning-sdk`) | | Installing is blocked (read-only env or home, agent sandbox) | Run each command as `UV_CACHE_DIR="${TMPDIR:-/tmp}/uv" UV_TOOL_DIR="${TMPDIR:-/tmp}/uv-tools" uvx lightning-sdk …` | | SSL/CA errors on every call, even `lightning --version`, only inside an agent sandbox | A `**/*.pem` read-deny rule hides certifi's `cacert.pem`: allow that one path; don't disable the sandbox | | `NameResolutionError`, only inside an agent sandbox | If `lightning api` fails too, ask the user to allow `lightning.ai` and `*.lightning.ai` (`/sandbox`). If only `studio`/`job` commands or the SDK fail, they bypass the sandbox proxy: run just those outside it. Background pollers fail the same way, silently | Credentials are stored in `~/.lightning/credentials.json`. The install above also makes `lightning_sdk` importable in that env, so Python snippets run with its `python`. If the CLI came from a uv tool or `uvx` fallback instead, run one-off scripts with `uv run --with lightning-sdk python script.py`. For code that stays in the user's project, ask, then declare `lightning-sdk` as a dependency with the project's own tool (`uv add`, `poetry add`). ## Resolving org and teamspace (do this first) Every studio lives in a teamspace owned by either an organization or a user. **Never guess.** Resolve in this order: 1. Explicit `--teamspace owner/teamspace` flag (owner = org or user name) / `Teamspace("owner/teamspace")` in Python (the separate `org=`/`user=` arguments are deprecated). 2. Env vars `LIGHTNING_ORG`, `LIGHTNING_TEAMSPACE`, `LIGHTNING_USERNAME`, or config defaults in `~/.lightning/config.yaml` (`lightning config get teamspace`). 3. Otherwise list the options and **ask the user which org/teamspace to use**: ```bash lightning api /v1/memberships | jq -r '.memberships[] | [.ownerType, .name, .projectId] | @tsv' ``` Persist the user's choice so they aren't asked again: `lightning config set teamspace <owner>/<teamspace>`. **From a scoped API key** (an agent with no user to ask): `--teamspace` needs the owner's *slug*, while `/v1/memberships` only gives the owner's id, and the same teamspace can appear twice (an `organization` row and a `user` row with one `projectId`). Continue only if a single teamspace is listed, prefer its organization row, and resolve the owner by `ownerType` (needs `jq`): ```bash M=$(lightning api /v1/memberships) if [ "$(printf "%s" "$M" | jq '[.memberships[].projectId] | unique | length')" != 1 ]; then echo "several teamspaces: ask the user which one" >&2 else ROW=$(printf "%s" "$M" | jq -c '(.memberships | map(select(.ownerType=="organization"))) + .memberships | .[0]') TS=$(printf "%s" "$ROW" | jq -r .name); OID=$(printf "%s" "$ROW" | jq -r .ownerId) if [ "$(printf "%s" "$ROW" | jq -r .ownerType)" = organization ]; then OWNER=$(lightning api "/v1/orgs/$OID" | jq -r .name) else # a personal teamspace; the search is fuzzy, so match the id exactly OWNER=$(lightning api /v1/users/search -X GET -f "query=$OID" \ | jq -r --arg id "$OID" '.users[] | select(.id==$id) | .username') fi lightning config set teamspace "$OWNER/$TS" # or pass --teamspace "$OWNER/$TS" each time fi ``` ## CLI reference `--teamspace` always takes `owner/teamspace`. Omitting `--name`/`--teamspace` in an interactive terminal opens a picker menu; in scripts always pass them explicitly. ```bash # create (registers the studio, does NOT attach compute) lightning studio create --name my-studio --teamspace owner/teamspace [--cloud PROVIDER] [--studio-type TEMPLATE] # start compute (blocking; --create makes it if missing) lightning studio start --name my-studio --teamspace owner/teamspace --machine CPU [--create] [--interruptible] lightning studio start --name my-studio --teamspace owner/teamspace --gpus L4:4 # --gpus and --machine are mutually exclusive # manage lightning studio list --teamspace owner/teamspace [--all] [--sort-by status] # default lists only your studios lightning studio switch --name my-studio --teamspace owner/teamspace --machine A100 # requires Running studio lightning studio stop --name my-studio --teamspace owner/teamspace lightning studio delete my-studio --teamspace owner/teamspace -y # NAME is positional here; -y/--yes: required non-interactively # ssh / one-shot connect (create + start + ssh) lightning studio ssh --name my-studio --teamspace owner/teamspace lightning studio connect my-studio --teamspace owner/teamspace --machine CPU # machine names the CLI accepts (offline list; says nothing about availability) lightning machine list [--json] ``` ### Files: `lit://` paths Studio paths use `lit://<owner>/<teamspace>/studios/<studio-name>/<path>`. Exactly one side of a copy must be `lit://`; directories need `-r`. ```bash lightning cp ./train.py lit://owner/teamspace/studios/my-studio/train.py # upload lightning cp -r lit://owner/teamspace/studios/my-studio/logs/ ./logs # download dir lightning ls lit://owner/teamspace/studios/my-studio # list files (-r recursive, --json) lightning rm lit://owner/teamspace/studios/my-studio/old.txt [-r] [-f] ``` **`cp -r` copies a folder's contents, not the folder.** `lightning cp -r ./proj lit://…/studios/my-studio/` puts `proj`'s files straight into the Studio's home, whether or not either path ends in `/`. To keep the folder, name it in the destination: `lightning cp -r ./proj lit://…/studios/my-studio/proj/`. Check the result with `lightning ls -r` before running anything that expects the files in place. **Uploads reach the machine late, even on a ready Studio.** `lightning cp` and `studio.upload_file` / `upload_folder` go through storage and return before the file is on the Studio's disk, so a command launched right after can fail with `No such file or directory`. Wait until the file is there before running anything that needs it: `upload_landed` in *Example workflows* does this. ## Python SDK ```python from lightning_sdk import Machine, Studio, Teamspace ts = Teamspace("my-org/my-teamspace") # owner/teamspace; org=/user= are deprecated studio = Studio(name="my-studio", teamspace=ts, create_ok=True) # create_ok=False -> error if missing studio.start(machine=Machine.CPU) # blocking; interruptible=True for spot pricing print(studio.status) # NotCreated|Pending|Running|Stopping|Stopped|Completed|Failed # run commands — studio must be Running out = studio.run("nvidia-smi") # raises RuntimeError on non-zero exit out, code = studio.run_with_exit_code("pytest -q") # no raise on non-zero out, code = studio.run_and_detach("python train.py", timeout=30) # keeps running in background studio.upload_file("train.py", remote_path="train.py") # remote path relative to studio home studio.download_file("outputs/model.ckpt", "model.ckpt") studio.upload_folder("./src"); studio.download_folder("outputs/") studio.switch_machine(Machine.A100) # change machine while running studio.set_env({"WANDB_API_KEY": "..."}) # env vars; partial=True merges studio.stop() # releases compute, keeps filesystem studio.delete() ``` ### Machine types Pass as `Machine.<NAME>` or string (`Machine.from_str("A100")` accepts name or slug): - CPU: `CPU_SMALL`, `CPU` (default, 4 cores), `CPU_X_2/4/8/16`; big-disk: `DATA_PREP`, `DATA_PREP_MAX`, `DATA_PREP_ULTRA` - GPU: `T4_SMALL`, `T4`, `T4_X_2/4/8`, `L4`, `L4_X_2/4/8`, `L40S`, `L40S_X_2/4/8`, `RTXP_6000` (+`_X_2/4/8`), `A100` (+`_X_2/4/8`), `H100` (+`_X_2/4/8`), `H200` (+`_X_2/4/8`), `B200`, `B200_X_8` - `A100_40GB*`/`A100_80GB*` variants exist in the SDK but are hidden from CLI `--machine` (usable with `studio switch` and in Python). SKUs get added, so treat this list as a starting point, not a closed set. `lightning machine list` shows the names your CLI accepts, not what a teamspace can launch. **Pick the machine from live data, per cloud account.** A teamspace can launch on several cloud accounts, and the same GPU differs between them in name, price and wait. List what each account can start right now, fastest first: ```python from lightning_sdk import Teamspace ts = Teamspace("my-org/my-teamspace") FAMILY = "H100" # the GPU family the workload needs # Accounts go by id: ts.cloud_accounts holds display names, and list_machines() returns [] for a name rows = [(m.wait_time, m.cost, a.cluster_id, m) for a in ts.cloud_account_objs for m in ts.list_machines(cloud_account=a.cluster_id) if m.family == FAMILY] for wait, cost, acct, m in sorted(rows, key=lambda r: (r[0] is None, r[0] or 0, r[1] or 0)): print(f"{acct:34} {m.name:28} x{m.accelerator_count} ${cost}/h wait ~{wait}s") ``` `cost` is USD per hour and `wait_time` the expected seconds until a machine is free. `list_machines()` with no argument merges several accounts without saying which row belongs to which. Show the user the top rows with price and wait. **Ask before starting any GPU, and wait for a yes.** Show the machine, its account, the price per hour and the most the run can cost under its deadline. Ask even when the user named the GPU or gave a budget: a budget is a limit, not approval to spend it. **A Studio's cloud account is fixed at creation (`studio switch` can't move it), so create it on the chosen row's account** and start or switch it to that row's machine. What matters is that the account sells that GPU at that count, not its name: the SDK maps `H200`, `lit-h200-1` and `lit-h200-141gb-1` to one machine. **`cloud=` / `--cloud` takes the account id (`cluster_id`), not a display name.** `Studio(..., cloud="Lightning Cloud")` fails with `400 clusterID Lightning Cloud is invalid`. For quotes before login, `GET /v1/core/accelerators?cloudProvider=<PROVIDER>` needs no auth (the `lightning-cost-estimation` skill has the provider values and the costing recipes). Don't invent a catalog endpoint: `/v1/accelerators`, `/v1/accelerator-catalog`, `/v1/pricing` and `/v1/compute/accelerators` all return `code: 5`. Interruptible (spot) is a flag, not a machine type: `--interruptible` / `interruptible=True`. ### Launching on a GPU <!-- TODO: remove this workaround once the backend rejects a GPU request it can't fill instead of starting a CPU machine (Task Board: "CLI silently downgrades to CPU when a GPU SKU isn't available"). --> **Ask for a GPU the Studio's cloud doesn't sell and `studio start` comes up on CPU with only a "hasn't been vetted" warning.** The default cloud doesn't sell every GPU at every count (e.g. 1× H200 isn't on AWS). The first workflow below guards against this: 1. **Create the Studio on an account that sells the GPU at your count** (listing above). A reused Studio keeps its old cloud: check it in `lightning studio list`, and create a new one if wrong. 2. **Do setup on CPU on that account, because installs, model downloads and CUDA source builds bill at GPU rates otherwise.** Builds need their target set, e.g. `TORCH_CUDA_ARCH_LIST=9.0` for H100/H200. 3. **After switching to that row's `Machine`, wait until the Studio can run commands and check the hardware.** No GPU means stop the Studio and go back to step 1; don't retry. ## Example workflows Prompts this skill handles: *"spin up a GPU studio and run my training script"*, *"copy this repo to my studio and start a long run"*, *"SSH into exp-studio"*, *"my studio is idle, stop it"*. **Set up on CPU, switch to a GPU, run, collect results, stop.** `Running` comes before a Studio can run commands, and `studio.start()` / `lightning studio start` can keep blocking after it can, or never return. So start in the background and poll for readiness with a deadline (see Gotchas). Other SDK calls (`run*`, `switch_machine`, `stop`) poll with no time limit of their own, so every call below goes through `bounded`: a stalled call raises instead of billing forever, and the `except` stops the Studio. The `lightning-jobs` skill reuses the helpers below, with their imports: ```python import hashlib, os, re, shlex, threading, time
عرض على GitHub
ملف SKILL.md هذا كبير جدا، لذلك يعرض SkillsMP القسم الاول فقط هنا. عرض على GitHub