Push your app to inference shell.
Deploy
1belt app deployUseful flags
| Flag | Description |
|---|---|
--dry-run | Run validation, packaging, and upload checks without registering a new version |
--meta | Update listing fields from inf.yml only (no new version): title, description, category, and non-empty images (card, thumbnail, banner) |
--stage | Deploy as a staged version (not current) |
After inf.yml is loaded, deploy prints a warning (not a hard error) when description is longer than the listing limit (200 characters). belt app deploy --dry-run shows the same warning; a dry run still builds and uploads the package and skips only registering the version (POST /apps). The API still rejects a new or changed description over the limit; an unchanged long description on an already-deployed app is kept until you edit the field.
Namespace
An app deploys into the namespace from inf.yml.
Namespace in inf.yml | Result |
|---|---|
| Empty, or your active workspace | Deploys into your workspace |
| Another namespace, and you are a member | Deploys into your own workspace (a copied inf.yml keeps its author's namespace) |
| Another namespace, and you are platform staff | Needs admin access. From the CLI, run belt admin elevate and approve it in the browser first; without it the deploy is refused with Deploying into namespace "…" needs admin access |
Warnings
After the version is registered, the API can return warnings about the app's credentials and annotations. The CLI prints each one with ! after the deployment summary. The deploy still succeeds.
| Code | When |
|---|---|
readonly_broad_credential | A function marked readOnlyHint: true requires a capability that has a narrower read-only counterpart |
unused_credential | Every function declares its own credentials, and an inf.yml entry is used by none of them |
missing_annotations | The app uses credentials and a function sets neither readOnlyHint nor destructiveHint |
JSON output
belt app deploy --json prints one result object (one per app with --all):
1{2 "success": true,3 "namespace": "myteam",4 "app": "my-app",5 "version": "2df033wcb89a83z8wq3hw2mkm3",6 "short_id": "2df033wc",7 "warnings": [8 { "code": "missing_annotations", "function": "delete_file", "message": "delete_file has no annotations; clients will treat it as destructive" }9 ]10}warnings is [] when there are none. error is present only when the deploy failed.
Use --meta after editing store listing fields in Configuration, for example title, description, category, or images. Only non-empty values in your local inf.yml are sent. The app must already be deployed once.
What happens
- Validation — Checks required files and runs
belt app doctordiagnostics (errors block deploy; warnings are shown but do not stop the build) - Credential keys — For each
credentials:entry with akey, the CLI checks that the capability exists (belt app credentials list). Provider-only entries (providerwithsecrets, nokey) are not capabilities; the API validates those when the version is registered - Dependencies — Installs packages locally
- Packaging — Bundles everything
- Upload — Sends to inference shell
- Registration — Makes it available
Run diagnostics manually before deploy:
1belt app doctor # list issues (exits 0 — report only)2belt app doctor fix # auto-fix what it can (relative imports, missing __init__.py, GPU deps, ESM config, …)3belt app doctor --check # exit 10 (config) when errors are found (CI gate)Use --json with --check for machine-readable output in scripts. → CLI setup — App health
Output
1┌──────────────────────────────────────┐2│ deployment summary │3├──────────────────────────────────────┤4│ │5│ final status: success │6│ duration: 45s │7│ app: my-app │8│ link: https://app.inference.sh/... │9│ │10└──────────────────────────────────────┘View your app
After deploy:
- Find it in the Grid
- Run it from the workspace
- Add it to agents
Update
Make changes, then deploy again:
1belt app deployNew version is created and becomes the active version unless you used --stage.
Staged deploys and promotion
belt app deploy --stage uploads a new version without making it current. Tasks and the store listing keep using the previous current version until you promote the staged one.
When you are ready to go live:
- Workspace — open the app and set the active version under Versions
- REST API (requires
apps:write):
1curl -X PUT "https://api.inference.sh/apps/{appId}/versions/{versionId}/current" \2 -H "Authorization: Bearer inf_your_api_key"Returns the updated app object. appId and versionId are server IDs (from belt app my -l or the deploy response), not namespace/name refs.
JavaScript SDK:
1await client.apps.setCurrentVersion('app_xyz', 'ver_abc');The Python SDK does not yet expose this helper; use the REST call above.
Runs and agent tools resolve namespace/name without a version pin to the current version.
List your apps
1belt app my2belt app my -l # Detailed listNext
If you want programmatic access: