Reference
alter apps
Create, inspect, update, archive, and delete applications.
An app owns API keys, provider configuration, agents, and grants. These commands manage the app objects themselves.
alter apps list [--limit <n>] [--offset <n>] [--include-archived] [--no-include-stats]alter apps create --name <name> [--description ...] [--website-url ...] [--stub]alter apps show <app-id>alter apps update <app-id> [--name ...] [--description ...] [--website-url ...]alter apps legal-profile <app-id> --legal-name ... --privacy-url ... --terms-url ...alter apps archive <app-id>alter apps unarchive <app-id>alter apps delete <app-id> [--confirm <name>]Reads need dashboard_apps:read; create and update need dashboard_apps:write; legal-profile needs dashboard_apps:write and an organization-admin principal; archive / unarchive need dashboard_apps:admin; delete needs dashboard_apps:delete. Every command except delete accepts --output (delete prints only a confirmation line).
List apps in the current organization.
| Flag | Default | Description |
|---|---|---|
--limit <n> | 100 | Page size, from 1 to 1,000. |
--offset <n> | 0 | Non-negative pagination offset. |
--include-archived | off | Include archived (soft-deleted) apps. Default is active-only. |
--no-include-stats | stats on | Skip per-app grant / connection / secret / provider / key / API-call counts (faster). |
The command returns one page as an array. To list every app, keep the same
--limit and increase --offset by that amount until a page has fewer rows
than the limit. Collect all pages before deleting apps; deleting between
pages shifts offsets and can skip rows.
alter apps listalter apps list --include-archived --output jsonalter apps list --limit 200 --offset 200 --no-include-stats --output jsonIn table output the STATUS column combines the archive state with stub
routing: active, archived, active (stub), or archived (stub). JSON and
JSONL output carry the is_stub boolean as its own field.
create
Section titled “create”Create a new app.
| Flag | Required | Description |
|---|---|---|
--name <name> | yes | App name (maximum 100 characters; control characters rejected). |
--description <text> | no | Free-form description (maximum 500 characters; control characters rejected). |
--website-url <url> | no | Full public website URL (http:// or https://; paths allowed; maximum 2,048 characters; embedded credentials rejected). |
--stub | no | Create a stub app — see Stub apps below. Available only on deployments with stub-provider mode enabled. |
alter apps create --name "Acme Production" --description "Customer-facing app"Stub apps
Section titled “Stub apps”A stub app routes its provider traffic to a stub provider instead of to real third-party providers. It exists so integration and functional tests can drive provider-calling flows — OAuth token exchange, managed-secret preflight, and proxied API calls — without real third-party credentials.
alter apps create --name "ci-fixtures" --stubThree properties are worth knowing before using it:
- Stub apps are permanent.
--stubis accepted only at creation. There is noalter apps update --stub, and a stub app can never be converted into a normal app or the reverse. An app that changed stub routing mid-life would silently move where its credentials are exchanged, so the choice is fixed for the life of the app. Create a separate app instead. - Availability is a property of the deployment, not of the token. No scope
or permission grants access to stub apps;
--stubrides the samedashboard_apps:writeverb as any other create. Stub-provider mode is enabled on staging and preview environments only. Production refuses the setting outright, so a stub app cannot be created against production under any credential. - Credential checks against a stub are never reported as verified. Provider
and managed-secret preflights that route to the stub return
inconclusiveorskipped, neverpassed— a stub cannot vouch for a real credential.
Running --stub against a deployment that does not have stub-provider mode
enabled fails with usage code 2 and a message saying so; re-run without
--stub to create a normal app.
Show one app by ID.
alter apps show <app-id>update
Section titled “update”Patch app fields. At least one of --name, --description, or --website-url is required — an empty update is rejected. Names are limited to 100 characters, descriptions to 500, and Website URLs to 2,048. Control characters are rejected in --name and --description; --website-url must be a complete http:// or https:// URL with no embedded credentials.
alter apps update <app-id> --description "Renamed for Q3"Pass an empty --description or --website-url value to clear that optional
field. When Connect sessions omit allowed_origin, Alter derives the browser
origin (scheme, host, and port) from website_url.
Stub routing is not patchable — see Stub apps.
legal-profile
Section titled “legal-profile”Set the Customer identity and policy links Wallet and Connect show to End Users before identity and authorization data is collected. URLs are validated locally and by the backend. Provide at least one support channel.
alter apps legal-profile <app-id> \ --legal-name "Acme, Inc." \ --privacy-url "https://acme.example/privacy" \ --terms-url "https://acme.example/terms" \ --support-email "support@acme.example" \ --agent-purpose "Schedule meetings using the accounts you authorize."| Flag | Required | Description |
|---|---|---|
--legal-name <name> | yes | Customer legal name displayed to End Users. |
--privacy-url <url> | yes | Customer Privacy Policy (http:// or https://). |
--terms-url <url> | yes | Customer Terms of Service (http:// or https://). |
--support-url <url> | one support channel | Customer support URL. |
--support-email <email> | one support channel | Customer support email. |
--agent-purpose <text> | no | Short description of the application/agent purpose. |
archive / unarchive
Section titled “archive / unarchive”Archiving is a reversible soft-delete: the app disappears from the default apps list view but keeps all its keys, grants, providers, and audit history. Because archiving pulls an app out of the default view for the whole organization, both commands require the admin-tier dashboard_apps:admin scope (an organization admin). This is separate from dashboard_apps:delete, which gates the irreversible cascade — :admin does not grant it.
alter apps archive <app-id>alter apps unarchive <app-id> # 409 if the app isn't archiveddelete
Section titled “delete”Because the cascade is permanent, delete is gated behind the separate dashboard_apps:delete scope (not bundled into :admin) and a type-to-confirm check:
- Interactive: the CLI prompts you to type the app’s exact name.
- Non-interactive (CI): pass
--confirm <name>matching the app’s name. There is no--yesshortcut — the name must be surfaced so the audit trail records the intent.
# Interactive — prompts for the namealter apps delete <app-id>
# CI — name supplied explicitlyalter apps delete <app-id> --confirm "Acme Production"A wrong --confirm value exits 2 (USAGE); declining the interactive prompt exits 8 (CANCELLED).
Recipes
Section titled “Recipes”Provision an app in CI and pin it for later steps
APP_ID=$(alter apps create --name "ci-staging" --output json | jq -r '.id')alter link "$APP_ID" # subsequent steps in this directory skip --appReview and clean up archived apps
# List what's archived...alter apps list --include-archived --output json \ | jq -r '.[] | select(.archived_at) | "\(.id)\t\(.name)"'# ...then permanently delete one (name required as confirmation)alter apps delete "$APP_ID" --confirm "ci-staging"Related
Section titled “Related”alter keys,alter providers,alter agents— the resources an app owns- Workspace linking — pin a default app so commands skip
--app - Apps — the underlying concept