- 332→148 lines, restructured for AI scanning not human reading - Added triggers array in YAML frontmatter - Consolidated command reference into single table - Consolidated constraints to 6 hard rules (inline) - Consolidated error patterns to quick-reference table + escape flow - Removed installation/distribution/prose (belongs in README)
153 lines
8.6 KiB
Markdown
153 lines
8.6 KiB
Markdown
---
|
|
name: sap-cli
|
|
description: "SAP ABAP ADT CLI for AI agents. Trigger when: operating ABAP objects, syncing code to/from SAP, managing transports, querying DDIC, running ABAP programs, reading SAP tables, or any SAP development task via terminal."
|
|
version: "2.2.1"
|
|
author: WuRangyu
|
|
license: MIT
|
|
triggers:
|
|
- "ABAP development"
|
|
- "sync to SAP"
|
|
- "download from SAP"
|
|
- "SAP transport request"
|
|
- "DDIC/SE11/SE16N/SE38/SE80"
|
|
- "SAP ADT REST API"
|
|
---
|
|
|
|
# sap-cli — SAP ABAP Development Object Management
|
|
|
|
Python CLI wrapping the SAP ADT REST API. Manages the full lifecycle of ABAP development objects from the terminal. Core loop: **download → local edit → sync back to SAP**.
|
|
|
|
## Quick Start
|
|
|
|
```bash
|
|
# 1. Single object: download → edit → sync
|
|
python main.py download --name ZMY_CLASS --type class --path ./src
|
|
# edit ./src/zmy_class.abap
|
|
python main.py sync --name ZMY_CLASS --type class --path ./src/zmy_class.abap --corr_nr DEVK901XXX
|
|
|
|
# 2. Batch project sync (auto dependency-ordered)
|
|
python main.py init --path ./my_project # add objects under src/
|
|
python main.py sync --all --path ./my_project --corr_nr DEVK901XXX
|
|
|
|
# 3. Table query: structure (SE11) + data (SE16N)
|
|
python main.py show-table --name ZMY_TABLE
|
|
python main.py read-table --name ZMY_TABLE --fields "F1,F2" --where "F1 = 'X'" --max-rows 50
|
|
```
|
|
|
|
## Command Reference
|
|
|
|
Global params (before command): `--profile <name>`, `--verify-ssl`. Optional params in `[ ]`.
|
|
|
|
| Category | Command | Key Parameters |
|
|
|----------|---------|----------------|
|
|
| CRUD | `create` | `--name --type [--description --source <.abap> --definition <.json> --package <$TMP> --corr_nr]` |
|
|
| CRUD | `info` | `--name --type` |
|
|
| CRUD | `download` | `--name --type --path` |
|
|
| CRUD | `sync` | `--name --type --path --corr_nr` **(REQUIRED)** |
|
|
| CRUD | `delete` | `--name --type` |
|
|
| CRUD | `activate` | `--name --type --corr_nr` (built-in NW 7.40 double-activate) |
|
|
| CRUD | `upload` | `--name --type --path --corr_nr` (lock→write→unlock only; no check/activate) |
|
|
| CRUD | `syntax-check` | `--name --type` (remote object; no upload/activate) |
|
|
| Batch | `init` | `--path` |
|
|
| Batch | `refresh` | `--path` |
|
|
| Batch | `sync --all` | `--path --corr_nr [--dry-run]` |
|
|
| Batch | `analyze` | `--path` (dependency analysis) |
|
|
| Query | `show-table` | `--name` (SE11 structure) |
|
|
| Query | `read-table` | `--name [--fields --where --max-rows]` (SE16N data) |
|
|
| Query | `list` | `--type [--package --prefix]` |
|
|
| Query | `whereused` | `--name --type` |
|
|
| Query | `search` | `--query` |
|
|
| Query | `diff` | `--name --type --path` (local vs SAP) |
|
|
| Transport | `transport list` | — |
|
|
| Transport | `transport info` | `--corr_nr` |
|
|
| Transport | `transport release` | `--corr_nr` |
|
|
| Transport | `transport objects` | `--corr_nr` |
|
|
| Config | `config show` | — |
|
|
| Config | `config list-profiles` | — |
|
|
| Config | `config set` | `<key> <val>` |
|
|
| Config | `auth login` / `auth status` | password stored in keyring |
|
|
| Other | `run-program` | `--name` (SA38) |
|
|
| Other | `check` | `--name --type` (ATC) |
|
|
| Other | `format` | `--name --type` (Pretty Printer) |
|
|
| Other | `package create` | `--name` |
|
|
| Other | `cds download` | `--name --path` |
|
|
| Other | `scaffold` | `--name --template <t>` — alv-report, bapi-wrapper, interface-class, data-model |
|
|
|
|
Batch sync dependency order: `domain(10) → dataelement(20) → table(30) → tabletype(40) → interface(50) → class(60) → function(70) → report(80)`.
|
|
|
|
Step-wise sync for lock-heavy automation — split the atomic `sync` when lock conflicts are frequent; upload now, verify, activate later:
|
|
```bash
|
|
python main.py upload --name ZMY_CLASS --type class --path ./src/zmy_class.abap --corr_nr DEVK901XXX # lock→write→unlock only
|
|
python main.py syntax-check --name ZDEPENDENT_REPORT --type report # verify dependents (no upload)
|
|
python main.py activate --name ZMY_CLASS --type class --corr_nr DEVK901XXX # activate once clean
|
|
```
|
|
|
|
### Supported Object Types (16)
|
|
|
|
| Category | Types | Has source |
|
|
|----------|-------|------------|
|
|
| Programs | `report`, `include` | ✅ |
|
|
| OOP | `class`, `interface` | ✅ |
|
|
| Functions | `function` | ✅ |
|
|
| DDIC base | `domain`, `dataelement`, `table`, `structure` | ✅ |
|
|
| DDIC ext | `cdsview`, `view` | ✅ |
|
|
| DDIC no-source | `tabletype`, `messageclass`, `searchhelp`, `lockobject` | ❌ |
|
|
| Groups | `functiongroup` | ❌ |
|
|
|
|
**Function naming**: must use `group/module`, e.g. `ZMY_FGROUP/Z_MY_FUNC`.
|
|
|
|
## ⚠️ Constraints (HARD RULES — DO NOT VIOLATE)
|
|
|
|
Full rules: `references/sap-tool-constraints.md`. Violations are intercepted by hooks.
|
|
|
|
1. **Only `python main.py <cmd>` touches SAP** — no `requests`/`urllib`, no curl to ADT/SOAP/RFC, no `python -c` inline, no importing `ADTClient` internals, no hand-built ADT XML. Exceptions: `run-program` custom reports, explicit user request, or developing sap-cli itself.
|
|
2. **Never modify SAP standard objects** (`CL_*`, `CX_*`, `IF_*`, `SAPL*`, or any non-user original system) — read-only only: download/info/list/search/whereused/show-table/read-table/diff. When unsure, ask the user.
|
|
3. **Never write system tables** (TADIR, E071, SEOCLASS, REPOSRC, D010SINF, T000, TDEVC, TSTC) — read-only SELECT is fine; any write needs explicit authorization.
|
|
4. **`sync` must carry `--corr_nr`** — otherwise it triggers an interactive transport-request prompt.
|
|
5. **Non-interactive `delete` needs piped confirm** — `echo "yes" | python main.py delete ...` (else EOFError).
|
|
6. **DDIC `sync` failure on NW 7.40 (HTTP 406) is a system limit** — do not retry; report to the user for SE09.
|
|
|
|
## Error Handling (Quick Reference)
|
|
|
|
Full flow: `references/error-handling.md`.
|
|
|
|
| Error Pattern | Action |
|
|
|---|---|
|
|
| HTTP 406 (DDIC Lock) | System limit — report to user → SE09 manual DDIC sync |
|
|
| HTTP 403 (Locked) | Residual enqueue lock — try `run-program` clear-locks report, then SM12 |
|
|
| HTTP 400 (SaveFailure) | Class DEFINITION mismatch — diff local vs SAP source |
|
|
| HTTP 404 (DDIC download/sync) | NW 7.40 has no `/source/main` endpoint (7.50+) — DDIC objects only create/info/delete |
|
|
| HTTP 423 (Transport lock) | Object bound to transport — report to user → SE09 |
|
|
| Activate fails, still inactive | double-activate built-in; still fails → report → SE09 |
|
|
| `WITH EMPTY KEY` dump | NW 7.40 unsupported — use `WITH NON-UNIQUE KEY` / `WITH DEFAULT KEY` |
|
|
| Function name error | Missing `/` separator — use `ZGROUP/Z_FUNC` |
|
|
| EOFError on delete | Non-interactive — prepend `echo "yes" \|` |
|
|
|
|
General flow: **diagnose** (params / file / transport / network / object existence) → **usage error**: fix & retry → **sap-cli limit**: report, never bypass → **SAP limit**: exhaust automation below → **confirmed un-automatable**: request SAP GUI op.
|
|
|
|
Automation fallbacks — exhaust in order before requesting any SAP GUI action:
|
|
1. **Adjust params** — different `--corr_nr`, or `--dry-run` to preview a batch before committing.
|
|
2. **`run-program` workaround** — sync + run a helper report (e.g. `ZSAPILOT_CLEAR_LOCKS`) to clear residual enqueue locks.
|
|
3. **`delete` + recreate** — only if the object needs a full rewrite; `delete` may fail with HTTP 423 (transport-bound) → then it is SE09.
|
|
4. **`activate` retry** — double-activate is built in; if it still fails, stop retrying and report — do not chase other activation strategies.
|
|
|
|
- **Never bypass sap-cli** (no requests / curl / ADTClient) — report the failure and its cause.
|
|
- **Give the complete change checklist at once** — do the full comparison first (`show-table` vs code field refs); never surface issues incrementally.
|
|
- **System-table writes** — 4-step authorization: explain reason → list exact statements → state risks & alternatives → await explicit approval.
|
|
|
|
## NW 7.40 Compatibility (E2E verified — v2.2.1)
|
|
|
|
Full matrix: `docs/NW740-COMPATIBILITY.md`.
|
|
|
|
| Availability | Types |
|
|
|---|---|
|
|
| Full (download → edit → sync closed loop) | `report`, `class`, `interface`, `function`, `functiongroup`, `include` |
|
|
| CRUD only (create/info/delete, no source edit) | `domain`, `dataelement` — DDIC stored as XML at object URI, no `/source/main` endpoint (7.50+ feature) |
|
|
| Endpoint missing (404/415) | `table`, `structure`, `tabletype`, `view`, `messageclass`, `searchhelp`, `lockobject`, `cdsview` |
|
|
|
|
NW 7.40 specifics:
|
|
- **DDIC Lock** — `delete` fixed (dedicated Accept header); `sync` still 406.
|
|
- **Activation false-negative** — first activate may report failure but actually succeed; double-activate is built in.
|
|
- **ABAP syntax limits** — no string templates `\|...\|`, no inline `DATA(...)`, no `WITH EMPTY KEY`.
|
|
- **CSRF token** — all writes require it; sap-cli handles automatically.
|