SAP ADT CLI Skill
Read ABAP source code and metadata from SAP via scripts/sap_adt_cli.py.
CLI Location
The CLI is scripts/sap_adt_cli.py inside this skill's directory.
Resolve the skill directory at runtime using the skill tool's path, then build the CLI path:
SKILL_DIR="$(dirname "$(realpath "${BASH_SOURCE[0]:-$0}")")"
SAP_CLI="$SKILL_DIR/scripts/sap_adt_cli.py"
python3 "$SAP_CLI" <command> [args]
If you already know the absolute path to the skill directory (e.g. from the skill loader), use it directly:
# Linux / macOS — skill installed via clone + symlink
SAP_CLI="$HOME/.agents/skills/sap-adt-cli/scripts/sap_adt_cli.py"
python3 "$SAP_CLI" <command> [args]
# Windows — skill installed via setup-opencode-abap-cli.bat (Junction)
$SAP_CLI = "$env:USERPROFILE\.agents\skills\sap-adt-cli\scripts\sap_adt_cli.py"
python "$SAP_CLI" <command> [args]
First run auto-installs click, requests, and urllib3. All source code output goes to stdout. Errors go to stderr with exit code 1.
CRITICAL: Credential Check Before First Command
Always run this before the first ABAP query in a session:
python3 "$SAP_CLI" status
Credentials configured → proceed
Output example:
URL: https://my-sap.example.com:8000
Username: DEVELOPER
Client: 100
Language: EN
SSL: verify
Write mode: DISABLED
Transport write: DISABLED
Config source: /home/user/.sap-adt-cli/config.json
Credentials NOT configured → collect and save non-interactively
You will see:
Not configured. Run: python3 sap_adt_cli.py configure
Or any ABAP command will print to stderr:
SAP credentials not configured.
...
Collect all credentials in a SINGLE question tool call — pass all fields as one array.
Do NOT ask one field at a time; multiple sequential calls create separate UI tabs that can
cause earlier answers to be overwritten before all values are saved.
Fields to ask (all at once):
1. SAP System URL — e.g. https://my-sap.example.com:8000 (include port)
2. SAP Username — dialog user, e.g. DEVELOPER
3. SAP Password — SAP logon password
4. SAP Client — 3-digit number, e.g. 100
5. Skip SSL check? — yes/no (yes = self-signed / internal systems, no = production with valid cert)
After receiving all answers from the single question call, save with one configure command:
python3 "$SAP_CLI" configure \
--url "https://my-sap.example.com:8000" \
--username "DEVELOPER" \
--client "100" \
--language "EN"
# add --no-verify-ssl if user said yes to skipping SSL
Pass the password via environment variable to avoid shell history exposure:
SAP_PASSWORD="mysecret" python3 "$SAP_CLI" configure \
--url "https://my-sap.example.com:8000" \
--username "DEVELOPER" \
--client "100"
Then verify:
python3 "$SAP_CLI" status
Credentials are saved to ~/.sap-adt-cli/config.json (permissions 0600) and reused in all future sessions.
To enable write or transport capabilities:
# Interactive — answer prompts for write/transport flags
python3 "$SAP_CLI" configure
# Non-interactive — pass flags explicitly
SAP_PASSWORD="mysecret" python3 "$SAP_CLI" configure \
--url "https://sap-dev.example.com:44300" \
--username "DEVELOPER" \
--client "400" \
--allow-write \
--no-allow-transport
| Flag | Default | Controls |
|---|---|---|
--allow-write / --no-allow-write |
disabled | write-source, activate |
--allow-transport / --no-allow-transport |
disabled | create-transport, release-transport |
One-time confirmation rule (CRITICAL for agent workflows): Even when capability flags are enabled, every write/create/release operation requires an interactive change preview and explicit
[y/N]confirmation. This confirmation applies to the current operation only and is immediately discarded after use — it is NEVER stored, cached, or reused. In the same conversation, if the user asks for another write/create/release operation, confirmation must be obtained again from scratch. Use--yesonly when the caller has explicit out-of-band authorization (e.g. a trusted CI pipeline). Never pass--yeson behalf of the user based on a previous confirmation in the same conversation.
Security note: inform the user that credentials stored in SKILL-local
.envor~/.sap-adt-cli/config.jsonare plain text. The JSON config file is protected with0600permissions but is not encrypted.
Alternative A — SKILL-local .env (recommended for per-skill isolation):
cp "$(dirname "$SAP_CLI")/../.env.example" "$(dirname "$SAP_CLI")/../.env"
# edit .env and fill SAP_URL, SAP_USERNAME, SAP_PASSWORD, SAP_CLIENT
python3 "$SAP_CLI" status
Alternative B — env vars per invocation (no file written, useful for one-off sessions):
SAP_URL="https://..." SAP_USERNAME="USER" SAP_PASSWORD="pass" SAP_CLIENT="100" python3 "$SAP_CLI" status
Credential precedence is: process env vars > SKILL-local .env > ~/.sap-adt-cli/config.json.
Capability flags map to SAP_ALLOW_WRITE and SAP_ALLOW_TRANSPORT; keep both 0
unless the user explicitly authorizes write or transport operations.
Commands Quick Reference
| Command | Usage | Description |
|---|---|---|
configure |
configure |
Interactive credential setup wizard |
status |
status |
Show current connection config |
get-program |
get-program <NAME> |
ABAP program (report) source code |
get-class |
get-class <NAME> |
ABAP class source code |
get-function-group |
get-function-group <NAME> |
Function group top-include source |
get-function |
get-function <NAME> --group <FG> |
Function module source code |
get-include |
get-include <NAME> |
ABAP include source code |
get-interface |
get-interface <NAME> |
ABAP interface source code |
get-table |
get-table <NAME> |
DDIC table field definitions |
get-structure |
get-structure <NAME> |
DDIC structure definition |
get-type-info |
get-type-info <NAME> |
Domain or data element (tries domain first) |
get-package |
get-package <NAME> |
Package object list → JSON array |
get-transaction |
get-transaction <NAME> |
Transaction properties/package info |
search-object |
search-object <QUERY> [--max-results N] |
Quick object search (* wildcard) |
syntax-check |
syntax-check <TYPE> <NAME> [--group <FG>] |
ABAP syntax check — no system change |
get-cds-view |
get-cds-view <NAME> |
CDS View DDL source code |
get-type-group |
get-type-group <NAME> |
ABAP type group (TYPE POOL) source |
write-source |
write-source <TYPE> <NAME> --file <PATH> |
Write source code (allow_write + confirm each time) |
activate |
activate <TYPE> <NAME> |
Activate ABAP object (allow_write + confirm each time) |
where-used |
where-used <TYPE> <NAME> [--max-results N] |
Where-used list → JSON array |
run-sql |
run-sql "<SQL>" [--max-rows N] |
Open SQL SELECT → JSON; DML statements are blocked |
list-transports |
list-transports [--user U] [--status D|R] |
List transport requests → JSON |
create-transport |
create-transport --description "<DESC>" |
Create transport request (allow_transport + confirm each time) |
release-transport |
release-transport <TRKORR> [--yes] |
Release transport — irreversible (allow_transport + confirm each time) |
Usage Examples
SAP_CLI="<skill_dir>/scripts/sap_adt_cli.py"
# Source code
python3 "$SAP_CLI" get-program SAPMV45A
python3 "$SAP_CLI" get-class ZCL_MY_CLASS
python3 "$SAP_CLI" get-function BAPI_SALESORDER_CREATEFROMDAT2 --group BAPI_SD_SALESORDER
python3 "$SAP_CLI" get-include MV45AFZZ
python3 "$SAP_CLI" get-interface ZIF_MY_INTERFACE
# Dictionary
python3 "$SAP_CLI" get-table VBAK
python3 "$SAP_CLI" get-structure VBAKKOM
python3 "$SAP_CLI" get-type-info MATNR
# Discovery
python3 "$SAP_CLI" search-object "ZCL_*" --max-results 20
python3 "$SAP_CLI" get-package ZMYPACKAGE
python3 "$SAP_CLI" get-transaction VA01
# CDS View & Type Group (read-only)
python3 "$SAP_CLI" get-cds-view ZI_INVENTORY_POSITION
python3 "$SAP_CLI" get-type-group ICON
# Write & activate (requires allow_write + confirmation each time)
python3 "$SAP_CLI" write-source class ZCL_MY_CLASS --file /tmp/zcl.abap
python3 "$SAP_CLI" write-source class ZCL_MY_CLASS --file /tmp/zcl.abap --activate
cat updated.abap | python3 "$SAP_CLI" write-source class ZCL_MY_CLASS --file -
python3 "$SAP_CLI" write-source class ZCL_MY_CLASS --file /tmp/zcl.abap --yes # skip confirm (trusted automation only)
python3 "$SAP_CLI" activate class ZCL_MY_CLASS
# Where-used (read-only)
python3 "$SAP_CLI" where-used class ZCL_PAYMENT_PROCESSOR --max-results 50
python3 "$SAP_CLI" where-used interface ZIF_MY_INTERFACE
# Open SQL via Data Preview (read-only)
python3 "$SAP_CLI" run-sql "SELECT * FROM t001 UP TO 10 ROWS"
python3 "$SAP_CLI" run-sql "SELECT bukrs, butxt FROM t001 WHERE spras = 'EN'" --max-rows 200
# Transport management
python3 "$SAP_CLI" list-transports # read-only — no flag needed
python3 "$SAP_CLI" list-transports --user SHREK --status D
python3 "$SAP_CLI" create-transport --description "Fix rounding issue" # allow_transport + confirm
python3 "$SAP_CLI" release-transport DEVK900001 # allow_transport + confirm (irreversible warning)
python3 "$SAP_CLI" release-transport DEVK900001 --yes # skip confirm (trusted automation only)
Key Behaviors & Gotchas
- Object names: SAP names are case-insensitive but always use UPPERCASE for reliability (e.g.
VBAK,ZCL_MY_CLASS, notvbak) - Source output:
get-program,get-class,get-function, etc. return raw ABAP source text - XML output:
get-table,get-structure,get-type-info,get-transaction,search-objectreturn raw XML from ADT — parse it or read it as-is - JSON output:
get-packageis the only command that returns a parsed JSON array get-type-infofallback: tries domain first; if not found, falls back to data element- SSL: for internal SAP systems with self-signed certs, configure with SSL disabled (
SAP_VERIFY_SSL=0or answer "n" in wizard) - Session reuse: the HTTP session is reused within a single script invocation; each
python3 "$SAP_CLI" ...call starts fresh - Credentials precedence: process env vars > SKILL-local
.env>~/.sap-adt-cli/config.json - Capability flags — config layer:
write-sourceandactivaterequireallow_write: true;create-transportandrelease-transportrequireallow_transport: true. Runconfigureto enable.list-transportsis read-only and has no flag requirement. - One-time confirmation — execution layer: every write/create/release operation
shows a change preview and requires
[y/N]confirmation before executing. This confirmation is scoped to the current operation only — it is immediately discarded after use and never cached or reused within the same session. The next write/create/release in the same session requires a fresh confirmation. - Agent rule — never reuse confirmation: when operating as an AI agent,
do not infer that a previous confirmation covers subsequent operations.
Every invocation of a write-capable command is independent.
Pass
--yesonly with explicit user instruction for that specific call. write-sourcelock protocol: flow is lock → PUT → unlock; unlock runs infinallyso objects are never left locked after an error.release-transportis irreversible: once released, a transport cannot be recalled. The confirmation preview explicitly calls this out.run-sqlOpen SQL only: uses ADT Data Preview; accepts SAP Open SQL syntax (e.g.UP TO N ROWS), not Native SQL or JDBC-style syntax.run-sqlDML blocked: statements starting withINSERT,UPDATE,DELETE,MODIFY, orTRUNCATEare unconditionally rejected in this version. OnlySELECTstatements are permitted. Detection is by first keyword, case-insensitive —SELECTcontaining write keywords in values is safe.where-usedempty result: returns[]— not an error (exit 0).get-cds-viewname: use the CDS entity name (e.g.ZI_INVENTORY_POSITION), not the underlying database table name.syntax-checkwith function: requires--group <FG>(same asget-function).
Output Format
| Command | Output Format |
|---|---|
Source code commands (get-program, get-class, get-function, get-include, get-interface, get-cds-view, get-type-group) |
Plain text ABAP source |
get-table, get-structure, get-type-info, get-transaction, search-object |
Raw XML |
get-package, where-used, list-transports, run-sql |
JSON array |
syntax-check |
Plain text messages ([ERROR], [WARNING], [INFO] prefixed); "Syntax OK" if clean |
status |
Plain text key-value pairs |
Error Handling
| Error Output | Cause | Action |
|---|---|---|
Not configured |
No saved credentials | Guide user through configure |
HTTP 401 |
Wrong username/password | Ask user to re-run configure |
HTTP 403 |
Missing ADT authorization | User needs SAP_ADT_BASE role or equivalent |
HTTP 404 |
Object name not found | Try search-object to find the correct name |
HTTP 503 |
ADT service not active | SAP Basis must activate /sap/bc/adt in transaction SICF |
| SSL error | Certificate issue | Re-configure with SAP_VERIFY_SSL=0 |
Workflows
Read an unknown class:
python3 "$SAP_CLI" search-object "ZCL_ORDER*"
python3 "$SAP_CLI" get-class ZCL_ORDER_HANDLER
Explore a package:
python3 "$SAP_CLI" get-package ZMYPACKAGE
# → JSON list of all objects; pick the ones you need
python3 "$SAP_CLI" get-program ZMYREPORT
python3 "$SAP_CLI" get-class ZCL_MYCLASS
Look up a BAPI signature:
python3 "$SAP_CLI" get-function BAPI_SALESORDER_CREATEFROMDAT2 --group BAPI_SD_SALESORDER
Understand a table structure:
python3 "$SAP_CLI" get-table VBAK
python3 "$SAP_CLI" get-type-info VBELN # look up field type
Find a transaction's package/application:
python3 "$SAP_CLI" get-transaction VA01
Safe write workflow — syntax-check before writing:
python3 "$SAP_CLI" syntax-check class ZCL_MY_CLASS
# → fix any errors locally, then:
python3 "$SAP_CLI" write-source class ZCL_MY_CLASS --file ./zcl_my_class.abap --activate
# → preview shown, confirmation required; confirmation discarded after use
Find all usages of an interface:
python3 "$SAP_CLI" where-used interface ZIF_MY_INTERFACE --max-results 100
# → JSON list of all implementing/using objects
Quick data check without SE16N:
python3 "$SAP_CLI" run-sql "SELECT COUNT(*) AS CNT FROM ekko WHERE bstyp = 'F'"
Create and release a transport (two separate confirmations):
python3 "$SAP_CLI" create-transport --description "Sprint 12 — invoice fix"
# → preview shown, confirmation #1 required → Created transport: DEVK900042
python3 "$SAP_CLI" list-transports --status D
# → JSON list (read-only, no confirmation)
python3 "$SAP_CLI" release-transport DEVK900042
# → irreversible-warning preview shown, confirmation #2 required (fresh, not reused)
SAP Prerequisites
- ADT services active: transaction
SICF→ path/sap/bc/adt→ Activate - User authorization: role
SAP_ADT_BASEor objectsS_ADT_RES,S_RFC - Write & activate (
write-source,activate): requiresallow_write: truein config. SAP user additionally needsS_DEVELOPwithACTVT=02on relevant object types. - Transport management (
create/release-transport): requiresallow_transport: truein config. SAP user needsS_CTS_ADMIor equivalent transport authorization.list-transportsis read-only and needs no additional flag. - Data Preview (
run-sql): requires/sap/bc/adt/datapreviewactive in transaction SICF.