platform-cli skill
Use when operating Ultralytics Platform from a terminal or script with the ul cloud CLI (ul cloud RESOURCE OPERATION key=value, PyPI package ultralytics-platform) — listing, creating, updating, cloning, or moving projects, datasets, and models; inspecting dataset images, statistics, metadata, duplicates, and similar images; starting and monitoring cloud training runs; per-image model validation analysis; downloading weights; exports, deployments, uploads, trash and restore, storage integrations, and account usage, storage, and billing; and building Agents (YOLO, LLM, gate, and alert workflows). For the Platform web UI or local yolo commands, see yolo; for choosing what to train and how to improve it, see yolo-training and yolo-tuning.
- GitHub stars
- 38
- Files
- 2
- Last commit
- Nov 8, 2026
- License
- AGPL-3.0
- Allowed tools
- —
What does the platform-cli skill do?
platform-cli uses when operating Ultralytics Platform from a terminal or script with the ul cloud CLI (ul cloud RESOURCE OPERATION key=value, PyPI package ultralytics-platform) — listing, creating, updating, cloning, or moving projects, datasets, and models; inspecting dataset images, statistics, metadata, duplicates, and similar images; starting and monitoring cloud training runs; per-image model validation analysis; downloading weights; exports, deployments, uploads, trash and restore, storage integrations, and account usage, storage, and billing; and building Agents (YOLO, LLM, gate, and alert workflows). For the Platform web UI or local yolo commands, see yolo; for choosing what to train and how to improve it, see yolo-training and yolo-tuning.
How to install the platform-cli skill
Each command copies the skill folder into the client's skills directory. Restart the client or start a new session to load it.Install the platform-cli skill in Plugin
/plugin marketplace add ultralytics/skills /plugin install yolo@ultralytics
Install the platform-cli skill in Claude Code
~/.claude/skills/platform-cli/SKILL.md
$ npx degit ultralytics/skills/skills/platform-cli ~/.claude/skills/platform-cliInstall the platform-cli skill in Claude Code (project)
.claude/skills/platform-cli/SKILL.md
$ npx degit ultralytics/skills/skills/platform-cli .claude/skills/platform-cliInstall the platform-cli skill in Codex
~/.agents/skills/platform-cli/SKILL.md
$ npx degit ultralytics/skills/skills/platform-cli ~/.agents/skills/platform-cliInstall the platform-cli skill in Gemini CLI
~/.gemini/skills/platform-cli/SKILL.md
$ npx degit ultralytics/skills/skills/platform-cli ~/.gemini/skills/platform-cliInstall the platform-cli skill in Claude.ai
npx degit ultralytics/skills/skills/platform-cli platform-cli && zip -r platform-cli.zip platform-cli # claude.ai → Customize → Skills → + → Create skill → Upload a skill → platform-cli.zip
SKILL.md
View on GitHubPlatform CLI (ul cloud)
ul needs Python 3.11+ and comes with pip install ultralytics or pip install ultralytics-platform. ul cloud <resource> <operation> calls the Platform API through the generated SDK; ul login, ul train, ul predict, the ul cloud train|predict|export|download shortcuts (see yolo), and the other local commands delegate to the ultralytics package. This skill covers Platform operations, not model selection or hyperparameter tuning.
pip install ultralytics # or `pip install ultralytics-platform`
export ULTRALYTICS_API_KEY="YOUR_API_KEY" # or `ul login API_KEY`
ul cloud --help # every resource and operation
ul cloud training start --help # one operation's arguments, types, and choices
Canonical command shapes
ul cloud account summary # plan, credits, counts; `username` is your workspace
ul cloud datasets list owner=WS # owner=TEAM for a team
ul cloud projects create owner=WS project=helmets name="Helmet Detection" visibility=private
ul cloud models create body='{"owner":"WS","project":"helmets","model":"exp1","name":"Experiment 1"}'
ul cloud training start model_id=MODEL_ID gpu_type=l4 \
train_args='{"model":"yolo26n.pt","data":"ul://WS/datasets/helmets","epochs":50}'
ul cloud models training owner=WS project=helmets model=exp1 # live status, epoch progress, metrics
ul cloud models files owner=WS project=helmets model=exp1 # short-lived weights download URL
Argument rules:
- Use the command shapes shown here without a preliminary
--helpcall. Check operation help when a needed argument is missing or after an argument error. - Arguments are SDK Python names as
key=value(gpu_type,project_id), never--key value. A boolean key given without=valuemeanstrue. Quote JSON for the shell. - An operation takes one
body=JSON object exactly when its help listsbody (dict[str, Any]). These are the operations whose API request is a union of shapes:models create,deployments update,images update,lifecycle delete-trash,datasets ingest,datasets create-batch,upload signed-url,storage-integrations create/discover, andmodels predict/deployments predict. Every other operation takes flat fields; nested objects such astrain_args,metadata, andargsare still JSON values. - Object and array values accept
@file.jsonor@-for stdin. Multipart binaries such as the predictfilefield accept@pathonly. - For body keys and value types, read only the operation's request schema, such as
paths["/api/models"].post.requestBody, from the production contract athttps://platform.ultralytics.com/openapi.json, instead of guessing or loading the whole file.
Behavior rules:
- Output is the complete API response on stdout, printed as JSON, text, or bytes according to its content type.
omit=key1,key2drops those keys from JSON at any depth when the question does not need them, such asomit=trainArgsonprojects retrievewhen run configurations are not compared, oromit=labels,scatterSampleonmodels retrieve ... analysis=1(addexamplesto drop the per-image rows and keep the summary, cohort metrics, and comparisons). Download operations return expiring signed URLs, not bytes:datasets export,datasets create-export,models files, and a completedexports retrieve. Preserve them verbatim and fetch them separately. - Failures go to stderr: exit 1 for API/connection errors, 2 for argument/file errors, 130 when interrupted. Interrupting does not cancel a submitted job; use its cancel operation (
models delete-training,exports delete,datasets delete-batch). - There is no
--json,--fields,--dry-run, or automatic pagination.datasets list(limit,include_samples,include_image_urls) andprojects list(limit) take nooffsetorsearch; passinclude_samples=falseto keep dataset listings small.models listrequiresproject=, returns the 20 most recently updated models by default and at most 100 withlimit=, and takes nooffset. Operations that page exposepage,offset,cursor, orpage_token. Follow returned continuation fields until exhausted. A limit-only listing may still be incomplete. - Pass
owner=on every command that takes it: the signed-in username for the caller's own resources,owner=TEAMfor team workspaces, and the resource's own owner for public or shared resources. An omitted pathownerdefaults to the logged-in username but costs an extra account lookup on every call. Account, billing, trash, storage-integration, and Roboflow commands act on the credential's own account, andaccount summarydoes not list teams for API keys. - Display names, URL slugs, database IDs, and URIs are distinct. Training data is
ul://OWNER/datasets/DATASET; starting weights are a checkpoint name orul://OWNER/PROJECT/MODEL. Carry returned IDs and slugs into the next command; retrieve missing identifiers instead of inferring them from names or URLs;dataset=takes a dataset slug, never adatasetId(a model's dataset ismodel.dataset.ownerandmodel.dataset.datasetfrommodels retrieve). Take a named dataset's or project's slug from its listing before retrieving it.
Working method
- Resolve the requested outcome and target. Use exact supplied identifiers; otherwise list and pick one unambiguous match. For several matches, inspect distinguishing metadata and ask when the target or consequence stays ambiguous. When a named resource is not found, say so and offer the closest matches; never substitute another one. A bounded listing does not prove absence; broaden discovery or report what was searched. Look up datasets the user names in their own workspace; find new public datasets with
explore search q=... type=datasets, one short keyword at a time (aerial, thenUAV), narrowed withtask,min_images, ormax_images. Explore dataset search ranks exact and whole-word name, tag, class, and description matches first, then datasets whose images match the term by content; project search matches the term at the start of a word. Before recommending a public dataset for training, verify clone eligibility, labels, and splits. If none match or search fails, say so. - Read current state when it affects the change (visibility, status, existing children).
- Execute the smallest requested change, then verify from the response. Retrieve again when the response omits needed state, the write is uncertain, or the job is asynchronous.
- Report what actually changed, current status, warnings, and a verified resource link when one exists. Creating an entry, accepting a job, and completing it are separate outcomes.
Execute clearly requested actions without repeated confirmation. For spending, sharing, or irreversible changes, resolve ambiguity about target or consequence first. A request for advice is not authorization to act; "clean things up" is not permission for account-wide deletion. Do not invent commands, flags, or status edits to simulate operations the CLI does not expose; point the user to the Platform UI for those.
Workflows
Commands below omit the ul cloud prefix and owner=; add owner= as described above.
| Goal | Commands |
|---|---|
| Inventory | projects list, datasets list, models list project=P. explore search q=... type=datasets searches public content, which is not private inventory; public models appear under type=projects. Retrieve a dataset to check task, classes, splits, and readiness. |
| Create | projects create project=slug name="Display", datasets create dataset=slug name="Display" task=detect. Set visibility= deliberately. |
| Copy | datasets clone dataset=D owner_body=DEST_OWNER, projects clone project=P owner_body=DEST_OWNER, models clone project=P model=M owner_body=DEST_OWNER project_body=DEST_PROJECT. Path fields name the source; *_body fields name the destination. A model's destination project must exist. |
| Rename, edit, move | <resource> update with the changed fields only; a new name also changes the URL slug, so use the returned slug afterwards. Move a model with models update project=P model=M project_id=DEST_ID as the only changed field. |
| Compare runs | projects retrieve project=P omit=trainArgs lists every model in the project with its status and metrics (datasets models dataset=D for runs on a dataset); large outputs can still be clipped, so never claim a complete ranking from a clipped or capped listing. Rank by the requested metric before naming a leader. Use models retrieve project=P model=M for evidence the summary lacks: configuration, dataset/version, or plots. Tabulate status, dataset/version, configuration, and requested metrics with links. Missing metrics are unknown, not zero. There is no compare command. |
| Analyze model | models retrieve project=P model=M analysis=1, then models find-similar-training-images project=P model=M when needed. See Model analysis and similarity for coverage and hash selection. |
| Weights | models files project=P model=M returns a temporary checkpoint URL. No training or export is needed. |
| Convert | exports create project=P model=M format=onnx, then exports retrieve project=P model=M export_id=ID for progress and the download URL. format=engine needs gpu_type. Exporting does not deploy. |
| Dataset versions | datasets create-export dataset=D saves an immutable numbered snapshot with a signed NDJSON URL; datasets export dataset=D (v=N for a saved version) returns a download URL; datasets restore dataset=D version=N rolls the dataset back; datasets update-export dataset=D version=N description="TEXT" updates a saved version's description. |
| Deploy | deployments create project=P model=M deployment=slug name="Display" region=us-central1. deployments update deployment=D body='{"action":"replace","project":"P","model":"M"}' swaps the model on the same URL; body='{"action":"stop"}' and {"action":"start"} pause and resume it. deployments health deployment=D warms it. |
| Usage, services | account storage, billing usage-summary, and billing transactions inspect the credential's own account usage; deployments list, retrieve, logs, and metrics inspect endpoints. See Usage and billing and Compute for filters and pagination. |
| Inference | models predict project=P model=M body='{"file":"@image.jpg"}' or deployments predict deployment=D body='{"file":"@image.jpg"}'. images predict image_id=ID model_id=ul://... predicts on a dataset image without saving labels. |
| Agents | agents save name="Display" graph='{...}' version=0 creates a canvas Agent; read agents save --help for blocks first. Use real datasets, models, deployments, and detectable classes; fix returned errors. Edit: read the current graph and version with agents list id=ID, then agents save id=ID name=N version=V graph='{...}' with the full edited graph. |
| Import data | datasets create dataset=D name="Display", then upload signed-url body= (assetType, assetId, filename, contentType, totalBytes) for one .zip, .tar, .tar.gz, .tgz, or .ndjson file, PUT the bytes with the returned headers, datasets ingest dataset=D body='{"sessionId":"S"}' (completes the upload; or {"sourceUrl":...}), then retrieve until ready. Queued is not imported. |
| Trash | projects delete project=P, datasets delete dataset=D, and models delete project=P model=M move them to 30-day trash. lifecycle trash lists it, lifecycle restore id=ID type=model undeletes, lifecycle delete-trash body='{"id":"ID","type":"model"}' purges one item, and body='{"all":true}' permanently empties all workspace trash. |
Platform exports a dataset only as NDJSON that links its images; there is no YOLO-format or ZIP export. For local training, pass the file, or ul://OWNER/datasets/DATASET with ULTRALYTICS_API_KEY set, straight to model.train(data=...), which downloads the images and builds the YOLO folders; for the folders alone, run asyncio.run(convert_ndjson_to_yolo("dataset.ndjson", output_path="datasets")) after import asyncio and from ultralytics.data.converter import convert_ndjson_to_yolo.
Cloud training
- Resolve the workspace, project, a ready dataset, starting weights, and requested settings. Check
training gpu-availabilitybefore choosinggpu_type; cloud training spends credits.datamust use the dataset's actual owner, which may differ from the model's. models create body=...withowner,project, themodelslug, andnamefor a new experiment. Reuse a pending entry from a failed start after checking its state.training start model_id=ID gpu_type=... train_args=...with a freshtrain_argsholdingmodel,data, and numericepochsplus requested settings. Omitdevice. Do not copy stored worker arguments wholesale; saved data paths may be worker-local.models trainingormodels retrievefor progress. Return the run link and actual status without waiting for completion unless asked.models delete-trainingcancels a run and keeps its entry; never calltraining starton a model whose run is still active.
Recover
- 401: check the credential source without exposing secrets.
ULTRALYTICS_API_KEYoverrides the saved login key, so logging in again does not replace a stale environment value. If the execution environment injects credentials, use its flow. Verify with a read afterwards. - 403: read the error for workspace access, permissions, or operation constraints; do not assume an expired login.
- Fix clear validation errors within the requested action. After a timeout or uncertain write, inspect state before retrying. Stop on unresolved inputs, permissions, or repeated failure; report partial results and remaining work instead of duplicating writes.
Resource links
Resource links use https://platform.ultralytics.com: projects /{owner}/{project}, datasets /{owner}/datasets/{dataset}, models and training /{owner}/{project}/{model}, and deployments /{owner}/deploy/{deployment} with the returned deployment slug. After status is ready, report the exact serviceUrl returned by deployments retrieve for inference; never construct a service URL.
Operation gotchas
Operation help already says what each command does. These are the side effects and constraints it omits; --help and the error text still win when they disagree.
Clone
- Project, dataset, and model clones need a different destination workspace. Cloning is not how to create a same-workspace experiment; use
models create. - Model sources need usable weights and must not be training. Project clones carry completed models with weights but not datasets, deployments, exports, or unfinished runs.
Visibility
- Creation may default to public and clones may keep the source's visibility, so set
visibility=explicitly. Public projects expose their models. Public visibility is not collaborator edit access.
Update
- Arrays and
metadataobjects replace prior values. Send the complete array or object, including unchanged entries. - An update that includes
starredignores every other field; send it alone. - Starting training again on an existing model clears its prior run metrics and results. Create a new model to keep them. Fine-tuning from existing weights does not resume the optimizer or epoch count.
capture_dataset_version=truesaves a new snapshot; it does not select an existing one.
Delete, trash, restore
lifecycle delete-trashis irreversible. Run it only when the user explicitly requests permanent deletion of the specified items;body='{"all":true}'requires an explicit request to empty all workspace trash. Otherwise, leave purging to the user in the UI.projects update archived=trueonly organizes; it frees nothing.- Trashing a project also trashes its models and cancels their training. Both
projects deleteandmodels deletepermanently delete attached deployments during the trash operation; restoring the project or model does not restore deployments. If deployments are attached (lifecycle trash id=ID type=projectortype=modelpreviews them), explain this consequence and obtain explicit authorization before trashing, unless the user's request already covers their permanent deletion. A 502 response means cleanup is incomplete; inspect deployments before reporting them deleted. - Restore a parent before its children; independently trashed children need their own restore. Dataset version restore is separate:
datasets restore dataset=D version=Nreplaces the current images, splits, classes, and annotations with the selected snapshot. It cannot be undone unless the current state was first versioned. When preservation matters, first rundatasets create-export dataset=D. Stop active annotation before restoring, then wait for the dataset to return toready. images deleteandimages delete-bulkare permanent and bypass trash.datasets create-exportreuses an identical existing snapshot instead of creating a duplicate.
Files in this skill
2platform-cli skill questions
How do I install the platform-cli skill in Claude Code?
Run npx degit ultralytics/skills/skills/platform-cli ~/.claude/skills/platform-cli. Claude Code loads skills from ~/.claude/skills (all projects) or .claude/skills (one project) and uses a skill when its description matches the task.
Which clients can use the platform-cli skill?
Any client that reads the Agent Skills format: Claude Code, Codex, Gemini CLI and claude.ai (upload as a ZIP). Scripts in the skill run only where the client allows code execution.