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 (including long detached runs with live progress tracking), 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". Also load it before launching or resuming any detached run on a Studio, even one driven by your own helper scripts, a handoff note or the summary of a compacted conversation, and load it again after a compaction; every such run needs the live progress bar from lightning-jobs/progress.py.

Quellinformationen

Repository
Lightning-AI/skills
Letzte Quellaktivität
6. Oktober 2026 um 14:27
Erkannte Sprache von SKILL.md
Englisch
Sterne
9
Forks
0

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
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 (including long detached runs with live progress tracking), 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". Also load it before launching or resuming any detached run on a Studio, even one driven by your own helper scripts, a handoff note or the summary of a compacted conversation, and load it again after a compaction; every such run needs the live progress bar from lightning-jobs/progress.py.
license
Apache-2.0
compatibility
Requires Python with uv or pip, the lightning CLI from the lightning-sdk package (installed on demand), network access to lightning.ai, and a Lightning AI account.
# 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 export DEBUG=0 LIGHTNING_DEBUG=0 # an inherited DEBUG=1 logs the Authorization header; set this in every new shell # 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 ``` **Signed in as the wrong account.** A saved teamspace can belong to a different login, and `lightning login` reuses the current identity. To sign in separately, give the new login its own credentials file and no inherited key, then check who you are and what you can see: ```bash D=$(mktemp -d "${TMPDIR:-/tmp}/lightning-login.XXXXXX") && chmod 700 "$D" && echo "env file: $D/env" printf '%s\n' 'unset LIGHTNING_API_KEY LIGHTNING_USER_ID LIGHTNING_AUTH_TOKEN' \ "export LIGHTNING_CREDENTIAL_PATH='$D/credentials.json' DEBUG=0 LIGHTNING_DEBUG=0" > "$D/env" . "$D/env" && lightning login && lightning auth whoami \ && lightning api /v1/memberships | jq -r '.memberships[] | [.ownerType, .name, .projectId] | @tsv' ``` Shell variables don't carry over between agent commands, so start every later command with `. "$D/env" &&` (the path printed above) and pass `--teamspace` explicitly. ## 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 OWN = {"lightning-baremetal", "lightning-public-prod"} # Lightning's own accounts sort first # 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] # then real waits before missing or placeholder ones (300 s, 10800 s), then fastest, then cheapest key = lambda r: (r[2] not in OWN, r[0] in (None, 300, 10800), r[0] or 0, r[1] or 0) for wait, cost, acct, m in sorted(rows, key=key)[:15]: 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: the head of the sorted list, never the tail, and check its first row against the request before anything else. **Prefer Lightning's own accounts (`lightning-baremetal`, `lightning-public-prod`).** Dev and test accounts can list GPUs they can't start: a broken region, a bare HTTP 500, `no price available`, or a Studio that boots without its GPU. A `wait_time` of exactly 300 or 10800 s is a placeholder, not an estimate. When an account fails to start, take the next row instead of retrying it. **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
Auf GitHub ansehen
Diese SKILL.md ist sehr gross, daher zeigt SkillsMP hier nur den ersten Abschnitt. Auf GitHub ansehen