with one click
btp-cli-reference
// Reference skill for all BTP CLI operations — session management, command taxonomy, JSON output patterns, and scope boundaries. Intended to be read by other skills before issuing BTP CLI commands.
// Reference skill for all BTP CLI operations — session management, command taxonomy, JSON output patterns, and scope boundaries. Intended to be read by other skills before issuing BTP CLI commands.
Invoke this skill to migrate destination and keystore DATA (configuration entries, certificates, credentials) that are stored at subaccount level or app level in a SAP BTP Neo environment to Cloud Foundry — this transfers platform-level configuration, NOT application source code. Use when the user wants to transfer existing Neo destination configurations or keystore entries to CF (e.g. 'migrate my BTP destinations to CF', 'copy Neo keystores to Cloud Foundry', 'transfer destination configs from Neo account', 'upload keystores to CF'). Do NOT invoke for source code changes that replace ConnectivityConfiguration/DestinationConfiguration Java API usage with SAP Cloud SDK — use the destinations skill for that instead.
Invoke this skill to orchestrate complete Neo to Cloud Foundry migration. Analyzes the Neo app, creates a migration plan, and INVOKES other skills in correct order. Use when user says 'migrate Neo app', 'convert to CF', or 'Neo to Cloud Foundry migration'.
Orchestrate complete Neo subaccount configuration migration to Cloud Foundry. Collects all required inputs upfront, then invokes the subaccount migration skills in sequence: trust export/import and roles export. Destinations and keystores migration is deferred to neo-destinations-keystores-migrator (run after all CF apps are deployed). Produces a consolidated migration report. Use when you want a single command to migrate all platform-level configuration from a Neo subaccount to CF. Individual skills can also be invoked standalone for partial migrations.
Invoke this skill to set up the SAP Application Router (approuter) for Cloud Foundry. Detects web-facing applications with webapp/ directory, web.xml, or HTML content. Creates the approuter directory with package.json, xs-app.json, and optional extended middleware for SAML2/Basic Auth handling.
Invoke this skill to set up XSUAA authentication and Application Router. Detects <auth-method>FORM</auth-method> in web.xml, security-constraint definitions, or UserProvider usage in Java code. Replaces Neo built-in auth with CF XSUAA.
Reference skill for all CF CLI operations — session management, full command taxonomy (apps, services, routes, orgs/spaces, admin, quotas), MultiApps plugin (cf deploy/mta), JSON output patterns, and scope boundaries. Intended to be read by other skills before issuing CF CLI commands.
| name | btp-cli-reference |
| description | Reference skill for all BTP CLI operations — session management, command taxonomy, JSON output patterns, and scope boundaries. Intended to be read by other skills before issuing BTP CLI commands. |
| disable-model-invocation | false |
| allowed-tools | Read, Bash |
Complete reference for the SAP BTP CLI (btp) — session management, full command taxonomy, JSON output patterns, and scope boundaries. Use this skill as a toolset when other skills need to issue BTP CLI commands.
btp --version
# Example: SAP BTP command line interface (client v2.x.x)
The BTP CLI operates against the BTP Account API — it manages the account layer (subaccounts, entitlements, security, service manager). It does NOT manage Cloud Foundry runtime objects (apps, CF service instances, CF spaces) — those require the cf CLI.
The CLI uses a session file stored in ~/.btp/ that caches the login token. A session is valid for a limited time (roughly 12 hours for SSO, longer for some flows). Commands fail silently with "Authorization failed" or "Unknown session" when expired.
btp login --sso
# Opens browser → SAP ID Service login → returns to CLI
btp login --user <email> --password <password>
# Not recommended for CI/CD — prefer service key + REST APIs
btp login --sso --idp <custom-idp-origin>
# Use when your user is managed by a custom IdP (not SAP ID Service)
IMPORTANT: There is NO client-credentials login for the BTP CLI. For headless/automated workflows, use the underlying BTP REST APIs directly with OAuth2 service keys instead.
After login, set the default subaccount scope so you don't need --subaccount on every command:
btp target --subaccount <subaccount-id>
# e.g. btp target --subaccount 2f964175-0856-47b2-b77a-469c74df0cca
Check current target:
btp target
# Shows: global account, subaccount, org, space
Clear target:
btp target --reset
# Set JSON as default for all commands
btp set config --format json
# Or per-command
btp --format json list security/role-collection
Before running commands in a script, verify the session is active:
btp --format json list accounts/subaccount 2>&1 | grep -q '"subaccounts"' \
&& echo "Session OK" || echo "Session expired — run: btp login"
--subaccount is optional when targeted — if you ran btp target --subaccount <id>, omit it. If targeting a different subaccount, pass it explicitly.btp vs cf — BTP CLI manages the account layer; cf CLI manages the CF runtime layer. Neither can substitute for the other.btp login requires a browser or interactive terminal; cannot be used in CI pipelines with stored credentials. Use REST APIs with service keys instead.--global-account or --subaccount to specify.--of-idp vs --origin — when assigning role collections to users from a custom IdP, use --of-idp <idp-origin> (not --origin). Example: btp assign security/role-collection "MyRC" --to-user user@example.com --of-idp sap.default.btp update security/trust --set-default does not exist — setting the default IdP in a CF subaccount must be done manually in BTP Cockpit → Security → Trust Configuration.jq keys on first use.--format json placement — must come right after btp, before the verb: btp --format json list ... (not btp list ... --format json).See references/command-quick-reference.md for a single-table quick reference of all 70+ commands.
Commands for managing the global account, subaccounts, directories, and environment instances.
# Global Account
btp get accounts/global-account
btp update accounts/global-account --display-name <name>
# Subaccounts
btp list accounts/subaccount
btp get accounts/subaccount <id>
btp create accounts/subaccount \
--display-name <name> \
--region <region> \
--subdomain <subdomain>
btp update accounts/subaccount <id> --display-name <name>
btp delete accounts/subaccount <id>
btp move accounts/subaccount <id> --to-directory <dir-id>
# Directories
btp list accounts/directory
btp get accounts/directory <id>
btp create accounts/directory --display-name <name>
btp update accounts/directory <id> --display-name <name>
btp delete accounts/directory <id>
btp enable accounts/directory <id> --for entitlements
btp enable accounts/directory <id> --for authorizations
# Environment Instances (CF Org provisioning)
btp list accounts/environment-instance [--subaccount <id>]
btp get accounts/environment-instance <id> [--subaccount <id>]
btp create accounts/environment-instance \
--environment cloudfoundry \
--service cloudfoundry \
--plan standard \
--subaccount <id> \
--display-name <name> \
--parameters '{"instance_name":"<org-name>"}'
btp update accounts/environment-instance <id> \
--subaccount <id> \
--parameters '{"memory":<MB>}'
btp delete accounts/environment-instance <id> [--subaccount <id>]
# Labels
btp list accounts/label [--subaccount <id>]
btp set accounts/label --key <key> --value <val> [--subaccount <id>]
btp delete accounts/label --key <key> [--subaccount <id>]
# Resource providers
btp list accounts/resource-provider
btp get accounts/resource-provider <provider>/<key>
btp create accounts/resource-provider \
--provider <AWS|AZURE|GCP> \
--technical-name <key>
btp delete accounts/resource-provider <provider>/<key>
# Custom Properties
btp list accounts/custom-property [--subaccount <id>]
btp set accounts/custom-property --key <key> --value <val>
# List what's available and assigned
btp list accounts/entitlement [--subaccount <id>]
btp list accounts/entitlement --show-technical-info
# Assign entitlement quota to a subaccount
btp assign accounts/entitlement \
--service-name <service> \
--plan-name <plan> \
--subaccount <id> \
--amount <N>
# For CF Runtime (unlocks memory/routes quota):
btp assign accounts/entitlement \
--service-name APPLICATION_RUNTIME \
--plan-name MEMORY \
--subaccount <id> \
--amount <MB>
# Assign entitlement to a directory
btp assign accounts/entitlement \
--service-name <service> \
--plan-name <plan> \
--directory <id> \
--amount <N> \
--distribute
# Subscriptions (SaaS applications)
btp list accounts/subscription [--subaccount <id>]
btp subscribe accounts/subaccount \
--app-name <app> \
--plan <plan> \
[--subaccount <id>]
btp unsubscribe accounts/subaccount \
--app-name <app> \
[--subaccount <id>]
Commands for managing roles, role collections, users, and trust.
# Role Collections
btp list security/role-collection [--subaccount <id>]
btp get security/role-collection "<name>" [--subaccount <id>]
btp create security/role-collection "<name>" \
--description "<desc>" \
[--subaccount <id>]
btp update security/role-collection "<name>" \
--description "<new-desc>" \
[--subaccount <id>]
btp delete security/role-collection "<name>" [--subaccount <id>]
# Adding roles to a role collection
btp add security/role \
--role-collection "<rc-name>" \
--role-name "<role-name>" \
--app-id "<appid>" \
--role-template "<template-name>" \
[--subaccount <id>]
# Note: --app-id is the XSUAA xsappname!application suffix, e.g. "nonosgi-auth!t12345"
# Get it from: btp --format json list security/app | jq '.[] | select(.name=="<appname>") | .appId'
# Removing roles from a role collection
btp remove security/role \
--role-collection "<rc-name>" \
--role-name "<role-name>" \
--app-id "<appid>" \
--role-template "<template-name>" \
[--subaccount <id>]
# Users
btp list security/user [--subaccount <id>]
btp get security/user <email> [--of-idp <idp-origin>] [--subaccount <id>]
btp create security/user <email> [--of-idp <idp-origin>] [--subaccount <id>]
btp delete security/user <email> [--of-idp <idp-origin>] [--subaccount <id>]
# Assign/unassign role collections to users
btp assign security/role-collection "<rc-name>" \
--to-user <email> \
[--of-idp <idp-origin>] \
[--subaccount <id>]
btp unassign security/role-collection "<rc-name>" \
--from-user <email> \
[--of-idp <idp-origin>] \
[--subaccount <id>]
# Assign/unassign role collections to user groups
btp assign security/role-collection "<rc-name>" \
--to-group <group-name> \
[--of-idp <idp-origin>] \
[--subaccount <id>]
# XSUAA Applications (inspect app scopes/roles deployed by MTA)
btp list security/app [--subaccount <id>]
btp get security/app <appid> [--subaccount <id>]
# Lists all scopes and role-templates available from a deployed XSUAA app
# Trust Configuration
btp list security/trust [--subaccount <id>]
btp get security/trust <origin> [--subaccount <id>]
btp create security/trust \
--idp <ias-tenant-id-or-host> \
[--subaccount <id>]
btp update security/trust <origin> \
--description "<desc>" \
[--subaccount <id>]
btp delete security/trust <origin> [--subaccount <id>]
btp migrate security/trust "<origin>" [--subaccount <id>]
# migrate: convert a SAML trust to OIDC (for IAS tenants only)
# Settings
btp list security/setting [--subaccount <id>]
btp get security/setting <key> [--subaccount <id>]
btp set security/setting <key>=<value> [--subaccount <id>]
btp unset security/setting <key> [--subaccount <id>]
Commands for managing services via Service Manager.
# Service Offerings and Plans
btp list services/offering [--subaccount <id>]
btp get services/offering <id> [--subaccount <id>]
btp list services/plan [--subaccount <id>]
btp get services/plan <id> [--subaccount <id>]
# Service Instances
btp list services/instance [--subaccount <id>]
btp get services/instance <id> [--subaccount <id>]
btp create services/instance \
--offering-name <svc> \
--plan-name <plan> \
--display-name <name> \
[--parameters '{"key":"value"}'] \
[--subaccount <id>]
btp update services/instance <id> \
--display-name <new-name> \
[--parameters '{"key":"value"}'] \
[--subaccount <id>]
btp delete services/instance <id> [--subaccount <id>]
# Service Bindings (service keys)
btp list services/binding [--subaccount <id>]
btp get services/binding <id> [--subaccount <id>]
btp create services/binding \
--instance-id <instance-id> \
--display-name <binding-name> \
[--parameters '{"key":"value"}'] \
[--subaccount <id>]
btp delete services/binding <id> [--subaccount <id>]
# Brokers
btp list services/broker [--subaccount <id>]
btp get services/broker <id> [--subaccount <id>]
btp create services/broker \
--name <name> \
--url <url> \
--user <user> \
--password <password> \
[--subaccount <id>]
btp update services/broker <id> \
--url <new-url> \
[--subaccount <id>]
btp delete services/broker <id> [--subaccount <id>]
# Platforms (service manager platforms)
btp list services/platform [--subaccount <id>]
btp get services/platform <id> [--subaccount <id>]
btp register services/platform \
--name <name> \
--type <type> \
[--subaccount <id>]
btp unregister services/platform <id> [--subaccount <id>]
btp list connectivity/destination [--subaccount <id>]
btp get connectivity/destination <name> [--subaccount <id>]
# Note: these are early commands, do NOT rely on them for production automation
# Use the Destination Service REST API for reliable destination management
btp list accounts/backup-configuration
btp get accounts/backup-configuration <id>
btp update accounts/backup-configuration <id> --enable
See references/json-output-schemas.md for full schema examples.
# List all role collection names
btp --format json list security/role-collection | jq '.[].name'
# Get appId for a specific XSUAA app by display name
btp --format json list security/app | \
jq '.[] | select(.name | startswith("nonosgi-auth")) | {name, appId}'
# List all role-templates available for an app
btp --format json get security/app "<appid>" | \
jq '.roleTemplates[] | {name, description}'
# Check if a role collection exists
btp --format json list security/role-collection | \
jq 'any(.[]; .name == "MyRoleCollection")'
# Get CF org details from environment instance
btp --format json list accounts/environment-instance | \
jq '.environmentInstances[] | select(.environmentType == "cloudfoundry") | {displayName, labels}'
# List users in a role collection
btp --format json get security/role-collection "MyRC" | \
jq '.userReferences[] | .value'
# Extract subaccount ID by display name
btp --format json list accounts/subaccount | \
jq '.value[] | select(.displayName == "MySubaccount") | .guid'
# Get binding credentials (service key)
btp --format json get services/binding <binding-id> | \
jq '.credentials'
#!/bin/bash
set -e
# 1. Verify session is active
if ! btp --format json list accounts/global-account &>/dev/null; then
echo "ERROR: BTP CLI session expired. Run: btp login"
exit 1
fi
# 2. Target subaccount
SUBACCOUNT_ID="2f964175-0856-47b2-b77a-469c74df0cca"
btp target --subaccount "$SUBACCOUNT_ID"
# 3. Check if role collection already exists before creating
RC_NAME="MyApp-Users"
EXISTS=$(btp --format json list security/role-collection | jq --arg name "$RC_NAME" 'any(.[]; .name == $name)')
if [ "$EXISTS" = "false" ]; then
btp create security/role-collection "$RC_NAME" --description "Users of MyApp"
echo "Created role collection: $RC_NAME"
else
echo "Role collection already exists: $RC_NAME"
fi
After deploying an MTA with XSUAA, get the appId (needed for btp add security/role):
# List all XSUAA apps — appId has the format "<xsappname>!t<number>"
btp --format json list security/app | jq '.[] | {name, appId}'
Role collections created before XSUAA app deployment have no roles. After deploying, add them:
# 1. Get the appId
APP_ID=$(btp --format json list security/app | \
jq -r '.[] | select(.name | startswith("nonosgi-auth")) | .appId')
# 2. List available role-templates from the app
btp --format json get security/app "$APP_ID" | jq '.roleTemplates[] | .name'
# 3. Add each role-template to the appropriate role collection
btp add security/role \
--role-collection "nonosgi-auth-Everyone" \
--role-name "Everyone" \
--app-id "$APP_ID" \
--role-template "Everyone"
# List existing trust configurations
btp list security/trust
# Create OIDC trust with IAS tenant
btp create security/trust \
--idp <ias-tenant-hostname-or-id> \
--subaccount <subaccount-id>
# e.g. --idp nss.accounts.ondemand.com
# After creation, set it as default in BTP Cockpit manually
# (btp update security/trust --set-default does NOT exist)
When cf push or cf deploy fails with SUBSCRIPTION_QUOTA — total memory: 0, routes: 0:
# Check current entitlements
btp list accounts/entitlement --subaccount <id>
# Assign CF Runtime memory — triggers BTP to create and apply a new org quota
btp assign accounts/entitlement \
--service-name APPLICATION_RUNTIME \
--plan-name MEMORY \
--subaccount <id> \
--amount 3072 # MB — 3 GB minimum for typical apps
# After assignment, BTP automatically:
# 1. Creates a new org quota named "<guid>-t-<subaccount-guid>"
# 2. Applies it to the CF org (replaces SUBSCRIPTION_QUOTA)
# Note: btp assign can take 30-60 seconds to propagate to CF
Gotcha: Space quotas (
cf create-space-quota) do NOT override org-level route limits. The org quota must be fixed. Only BTP Cockpit entitlement assignment (or thebtp assign accounts/entitlementcommand above) creates the correct org quota automatically.
# Check if CF environment already exists
btp --format json list accounts/environment-instance --subaccount <id> | \
jq '.environmentInstances[] | select(.environmentType == "cloudfoundry")'
# Create CF environment (provisions a CF org)
btp create accounts/environment-instance \
--environment cloudfoundry \
--service cloudfoundry \
--plan standard \
--subaccount <id> \
--display-name "My CF Org" \
--parameters '{"instance_name":"my-org-name"}'
After any BTP CLI operation, verify with:
# Verify role collection was created
btp --format json list security/role-collection | jq '.[].name'
# Verify role was added to collection
btp --format json get security/role-collection "<rc-name>" | \
jq '.roleReferences[] | {roleTemplateName, roleTemplateAppId}'
# Verify user assignment
btp --format json get security/role-collection "<rc-name>" | \
jq '.userReferences[] | .value'
# Verify trust created
btp list security/trust
# Verify entitlement applied
btp --format json list accounts/entitlement | \
jq '.[] | select(.serviceName == "APPLICATION_RUNTIME")'
# Verify service instance created
btp --format json list services/instance | jq '.[] | {name, offering, plan, state}'
| Symptom | Cause | Solution |
|---|---|---|
Authorization failed. Unknown session | BTP CLI session expired | Run btp login (browser SSO) |
btp add security/role fails with "app not found" | Wrong --app-id format | Use full XSUAA appId (xsappname!tXXXX), get from btp list security/app |
btp assign with --of-idp fails | Wrong flag name | Use --of-idp (not --origin) for custom IdP users |
Role collection shows empty after btp add security/role | Race condition or targeting wrong subaccount | Verify with btp get security/role-collection <name>, check --subaccount param |
btp create security/trust fails | IAS tenant not yet connected | Use IAS tenant hostname (not GUID), verify IAS tenant exists |
btp assign accounts/entitlement appears to do nothing | BTP Cockpit hasn't reflected the change yet | Wait 60 seconds; then check btp list accounts/entitlement |
| CF quota still 0 after entitlement assignment | BTP creates quota async | Wait 1-2 minutes, then run cf quotas to see new quota appear |
--set-default flag not recognized by btp update security/trust | This subcommand does not exist | Set default IdP manually in BTP Cockpit → Security → Trust Configuration |
| Task | Reason | Alternative |
|---|---|---|
| Manage CF apps, spaces, routes, services | These are CF runtime layer objects | cf CLI |
| Create CF service instances | CF service instances live in CF org/space | cf create-service |
| Manage destinations (create, update, delete) | No reliable BTP CLI support for destinations | Destination Service REST API |
| Headless/CI login with client credentials | Login is always interactive (browser/password) | BTP REST APIs with service keys |
| Set default IdP in trust configuration | No --set-default flag exists | BTP Cockpit → Security → Trust |
| Abort stuck MTA operations | MTA operations run in CF layer | cf mta-ops, cf deploy -i -a abort |
| Access Neo subaccount resources | BTP CLI targets CF subaccounts only | Neo CLI (neo.sh) or Neo REST APIs |