Moves a released transport request through the landscape (DEV → QAS → PRD) and reads its import status / return code via STMS. Four modes: status (default, READ-ONLY — a target's import queue, or where a TR sits on the route); logs (READ-ONLY — import log + step RC mapped to OK / WARN / ERROR / FATAL); import (WRITE, gated — import one released TR; a PRODUCTION target needs a typed-SID echo + second confirmation, the most outward-facing action in the toolset; never imports an unreleased/NO-GO...
Scanned 9/5/2026
Install to Claude Code
npx -y skills add sapdev-ai/sap-dev --skill sap-stms --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Sap Stms?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/sapdev-ai-sap-stms)More formats (shields.io, HTML) on the badges page.
---
name: sap-stms
description: |
Moves a released transport request through the landscape (DEV → QAS → PRD) and
reads its import status / return code via STMS. Four modes: status (default,
READ-ONLY — a target's import queue, or where a TR sits on the route); logs
(READ-ONLY — import log + step RC mapped to OK / WARN / ERROR / FATAL); import
(WRITE, gated — import one released TR; a PRODUCTION target needs a typed-SID
echo + second confirmation, the most outward-facing action in the toolset; never
imports an unreleased/NO-GO TR without --force); import-all (WRITE, double-gated,
off without --all). Missing import authorization → COULD_NOT_IMPORT (never a
faked success); RC 8/12 = failure even if the queue row looks "done". The import
VBS is a recording-gated scaffold that fails SAFE — run /sap-gui-probe --record on
STMS_IMPORT once per release first.
Prerequisites: active /sap-login GUI session; QA/PROD imports need TMS import
authorization (status/logs work without it).
argument-hint: "[status] [<TR>] [--system SID] [--route] | logs <TR> --system SID | import <TR> --to SID [--client NNN] [--immediate] [--leave-in-queue] [--force] | import-all --to SID --all [--connection PROFILE] [--report] [--out PATH]"
---
# SAP STMS - Transport Landscape Movement Skill
You move a **released** transport request through the transport landscape and
read its import status. You are READ-ONLY by default; any import is opt-in,
gated, and — for a production target — the most strongly-guarded action in the
whole toolset. You never import an unreleased or NO-GO TR without `--force`, and
you report return codes truthfully (RC 8/12 = failure, even if the row looks
done).
Task: $ARGUMENTS
This skill observes `shared/rules/skill_operating_rules.md` (Rule 2 — no
unsolicited write). It is the downstream of the release chain:
`/sap-transport-readiness` (GO/NO-GO) -> `/sap-se01 release` -> **`/sap-stms`**.
`/sap-fix-incident` hands off here after a DEV fix.
---
## Shared Resources
| File / token | Path | Purpose |
|---|---|---|
| `skill_operating_rules.md` | `<SAP_DEV_CORE_SHARED_DIR>\rules\skill_operating_rules.md` | Rule 2 confirmation gate |
| `language_independence_rules.md` | `<SAP_DEV_CORE_SHARED_DIR>\rules\language_independence_rules.md` | IDs + `MessageType`, never displayed text |
| `settings_lookup.md` | `<SAP_DEV_CORE_SHARED_DIR>\rules\settings_lookup.md` | per-key settings merge; per-connection pin |
| `sap_settings_lib.ps1` + `sap_connection_lib.ps1` | `<SAP_DEV_CORE_SHARED_DIR>\scripts\` | `Get-SapWorkDir`, `Get-SapCurrentSessionPath` |
| `sap_rfc_lib.ps1` (`%%RFC_LIB_PS1%%`) | `<SAP_DEV_CORE_SHARED_DIR>\scripts\sap_rfc_lib.ps1` | E070 released-status read (RFC) |
| `sap_attach_lib.vbs` (`%%ATTACH_LIB_VBS%%`) | `<SAP_DEV_CORE_SHARED_DIR>\scripts\sap_attach_lib.vbs` | `AttachSapSession` for every VBS |
| `sap_session_lock.vbs` (`%%SESSION_LOCK_VBS%%`) | `<SAP_DEV_CORE_SHARED_DIR>\scripts\sap_session_lock.vbs` | lock the session around the import write |
| `<SKILL_DIR>\references\sap_stms_queue_read.vbs` | *(reader)* | STMS import-queue scrape (read-only) |
| `<SKILL_DIR>\references\sap_stms_log_read.vbs` | *(reader)* | import log + RC scrape (read-only) |
| `<SKILL_DIR>\references\sap_stms_import.vbs` | *(writer)* | import one TR into a target (gated; recording-calibrated) |
| `sap_log_helper.ps1` | `<SAP_DEV_CORE_SHARED_DIR>\scripts\sap_log_helper.ps1` | structured logging |
**Skills referenced**: `/sap-transport-readiness` (optional pre-flight gate),
`/sap-se01` (release — the step before import), `/sap-se16n` (manual E070 check).
`<SAP_DEV_CORE_SHARED_DIR>` = `plugins/sap-dev-core/shared` — 3 levels up from
`<SKILL_DIR>`, then into `sap-dev-core\shared`.
---
## Step 0 — Resolve Work Directory and Settings
```bash
powershell -NoProfile -ExecutionPolicy Bypass -Command ". '<SAP_DEV_CORE_SHARED_DIR>\scripts\sap_settings_lib.ps1'; . '<SAP_DEV_CORE_SHARED_DIR>\scripts\sap_connection_lib.ps1'; Write-Output ('WORK_DIR=' + (Get-SapWorkDir)); Write-Output ('PROD_IDS=' + (Get-SapSettingValue 'prod_system_ids' ''))"
```
Settings reads follow `settings_lookup.md`. Read `prod_system_ids` (optional
comma-separated allow-list of production SIDs — see PROD detection in Step 3);
saved profiles in `connections.json` whose `environment=PRD` (Rule 0
classification, `safety_policy.md`) count as a PROD signal for their
`system_name` too.
Set `{WORK_TEMP}` = `{work_dir}\temp`; `{RUN}` = `{WORK_TEMP}\stms\<run>`:
```bash
cmd /c if not exist "{WORK_TEMP}\stms" mkdir "{WORK_TEMP}\stms"
```
Set `{RUN_TEMP}` = the per-run scratch dir (`Get-SapRunTemp` mints + creates `{work_dir}\temp\run_<id>`):
```bash
powershell -NoProfile -ExecutionPolicy Bypass -Command ". '<SAP_DEV_CORE_SHARED_DIR>\scripts\sap_connection_lib.ps1'; Write-Output ('RUN_TEMP=' + (Get-SapRunTemp))"
```
Per the CLAUDE.md "Two-bucket temp model" write this skill's `_run.json` log state under `{RUN_TEMP}` (the working files already live in the per-run `{RUN}`); keep `{WORK_TEMP}` (base) only for `Get-SapCurrentSessionPath -WorkTemp`.
## Step 0.5 — Start Logging (best-effort)
```bash
powershell -ExecutionPolicy Bypass -File "<SAP_DEV_CORE_SHARED_DIR>\scripts\sap_log_helper.ps1" -Action start -StateFile "{RUN_TEMP}\sap_stms_run.json" -Skill sap-stms -ParamsJson "{}"
```
---
## Step 1 — Mode Dispatch
| First token / flags | Mode | Section |
|---|---|---|
| `import-all --all` | IMPORT-ALL | Import-All Mode |
| `import <TR> --to <SID>` | IMPORT | Import Mode |
| `logs <TR> --system <SID>` | LOGS | Logs Mode |
| `status` / none | STATUS | Status Mode (default) |
`--to` / `--system` is **mandatory for any write** — there is no default target.
Validate the TR format (`<SID>K<digits>`).
---
# Status Mode (default, read-only)
## S1 — Resolve target(s)
`--system <SID>` for one system; `--route` to walk every system on the TR's
transport route. If a `<TR>` is given, also locate where it sits.
## S2 — Read the queue (GUI)
Substitute + run `sap_stms_queue_read.vbs` (32-bit cscript; attach tokens as in
Step W3 below). Tokens: `%%TARGET_SID%%`, `%%TR%%` (or empty), `%%OUTPUT_FILE%%`.
It navigates `/nSTMS_IMPORT`, opens the target queue, and scrapes each row
(`TRKORR`, owner, short text, status, RC if shown) to `{RUN}\queue.json`.
> **RFC alternative (preferred when available).** `TMS_MGR_READ_TRANSPORT_QUEUE`
> reads the queue over RFC without GUI; it needs the target's TMS RFC + auth.
> v1 ships the GUI reader (universally available to a dialog user); the RFC path
> is a documented Phase-2 optimization.
## S3 — Report
Print the queue (or the TR's position) and whether the TR is already imported.
`STATUS: QUEUE system=<SID> rows=<n> tr=<TR?> position=<n|not-in-queue|imported>`.
> **TMS-down outcome.** When the reader exits 1 with
> `QUEUE: status=error reason=STMS_TMS_RFC_DOWN alert=<exception> function=<FM> destination=<TMSADM@...>`,
> the TMS communication layer itself is broken on that system (the alert
> fields carry the technical exception, e.g. `RFC_COMMUNICATION_FAILURE`).
> Report `STATUS: COULD_NOT_READ reason=STMS_TMS_RFC_DOWN` with those details
> and point the operator at Basis (repair the `TMSADM@<SID>.DOMAIN_<SID>`
> destination) — do NOT suggest re-recording control IDs for this outcome.
---
# Logs Mode (read-only)
## L1 — Read the import log
Substitute + run `sap_stms_log_read.vbs`. Tokens: `%%TARGET_SID%%`, `%%TR%%`,
`%%OUTPUT_FILE%%`. It **navigates into the named target system's import queue**
(double-clicks the `%%TARGET_SID%%` row on the STMS_IMPORT overview) before
reading, so the RC is read from the RIGHT system — not whatever queue
`/nSTMS_IMPORT` happened to land on. Then it reads the **return code**.
## L2 — Map RC -> verdict and report
| RC | Verdict |
|---|---|
| `0` | OK |
| `4` | OK_WITH_WARNINGS |
| `8` | ERROR (import errors — activation / generation failures) |
| `12` | FATAL (cancelled / system error) |
| (none / not found) | NOT_IMPORTED |
| (target queue not reachable) | QUEUE_NOT_REACHED |
| (TMS communication down) | TMS_RFC_DOWN |
`STATUS: LOG tr=<TR> system=<SID> rc=<0|4|8|12|-> verdict=<...>`. **RC 8/12 is a
failure even if the queue row shows "done"** — say so plainly. A
`verdict=QUEUE_NOT_REACHED` means the reader could **not** open the
`%%TARGET_SID%%` queue (system not in the overview, or the queue view differs on
this release) — it deliberately did **not** read another queue's RC and did not
stamp the SID as verified. Re-record `OpenTargetQueue` candidate IDs via
`/sap-gui-probe --record` on STMS_IMPORT; do not treat it as a successful import.
---
# Import Mode (WRITE — gated)
## W1 — Parse + resolve the route
`import <TR> --to <SID> [--client NNN] [--immediate] [--leave-in-queue]
[--force]`. Read the TMS route so the target can be classified DEV / QA / PROD
(route position + the `prod_system_ids` allow-list + any `connections.json`
profile for that SID carrying `environment=PRD`; any one PROD signal wins —
stricter always wins, per `safety_policy.md` 0.1/0.4).
## W2 — Pre-flight gate (each a hard stop unless noted)
| Check | How | Stop unless |
|---|---|---|
| TR is **released** | RFC read `E070-TRSTATUS = R` (via `sap_rfc_lib.ps1`; or `/sap-se16n E070`) | not `R` -> "release it first via `/sap-se01 release <TR>`" |
| Already imported in target | Logs Mode read (RC present) | already imported -> report + stop (no double import) |
| Readiness verdict | optional `/sap-transport-readiness <TR>` | `NO_GO` -> stop unless `--force` (and say `--force` was used) |
| Target is PROD? | route position / `prod_system_ids` / a `connections.json` profile with `environment=PRD` | escalate to the PROD gate in W3 |
| PROD target allowed by policy? | `userConfig.prod_write_policy` (settings chain) | **Rule 0 (`safety_policy.md` 0.2):** when `target_class=PROD` and the policy is `BLOCK` (or blank — the default), STOP: `SAFETY: REFUSED class=SAFETY_PROD_REFUSED` — end the run `FAILED` with that error class. No `--force`, no override. Only `TYPED_CONFIRM` lets a PROD import continue into W3. |
Echo each: `PREFLIGHT: released=<Y/N> imported=<Y/N> readiness=<GO|NO_GO|skipped> target_class=<DEV|QA|PROD>`.
## W3 — Confirmation (tiered, mandatory)
- **QA / test target**: ask once — *"Import `<TR>` into `<SID>`/`<client>`?
(yes / no)"*. Proceed only on `yes`.
- **PRODUCTION target**: show the TR's object inventory summary, then require
**two** signals: (1) the user **types the target SID back**, and (2) confirms
*"yes, import to production"*. Anything else aborts. Log the confirmation
explicitly. This is irreversible-in-effect — you cannot un-import.
Never skip W3. There is no `--apply`-style bypass for a production import.
## W4 — Run the import (GUI, recording-calibrated)
> **Calibration gate.** `sap_stms_import.vbs` ships with PLACEHOLDER control IDs
> for the destructive Import-Request + import-options dialog (the STMS queue/tree
> + dialog IDs vary by release and were NOT recorded against a live system). On
> first use per release, run `/sap-gui-probe --record` on the `STMS_IMPORT` import flow
> and replace the `PLACEHOLDER_*` constants. Until then the VBS **fails loud**
> (`ERROR: import controls not calibrated`) rather than clicking anything — a
> safe no-op, never a mis-import.
Substitute the VBS and run it (32-bit cscript). It locks the session
(`%%SESSION_LOCK_VBS%%`), navigates to the target queue, and — **only after
positively verifying the selected row's `TRKORR` equals `<TR>` and the screen is
the intended target's queue** — presses Import Request, fills the target
`--client`, and confirms. If it cannot verify the row == `<TR>`, it ABORTS
without importing (exit 1).
> **`--immediate` / `--leave-in-queue` are not yet wired.** The import-options
> checkboxes are release-specific and have **no recorded control IDs** in the VBS.
> If either `%%IMMEDIATE%%` or `%%LEAVE_IN_QUEUE%%` is passed as a truthy value
> (`1`/`X`/`true`), the VBS **fails loud** with `ERROR: STMS_OPTION_UNSUPPORTED`
> (exit 1) rather than silently importing with the queue default. Leave both `0`
> (the example below) until you record the checkbox IDs via `/sap-gui-probe --record` on
> the STMS_IMPORT options dialog and wire them in. **All abort/error paths now
> exit 1** (were exit 0) so the caller never reads a failed import as success.
```powershell
$shared = '<SAP_DEV_CORE_SHARED_DIR>\scripts'
. "$shared\sap_connection_lib.ps1"
# BAKE the path into %%SESSION_PATH%% (attach Strategy 1) rather than exporting
# $env:SAPDEV_SESSION_PATH here: this generator is a SEPARATE process from the one
# that runs cscript, so the env var would already be gone and the attach lib would
# silently fall through to its sole-connection default (2026-08-06). NOTE: this
# pins the DOMAIN CONTROLLER session STMS is driven from -- the import's *target*
# system is a separate concern, guarded by this skill's own TARGET-based PROD gate
# (W2/W3), which is why sap-stms is deliberately off SAFETY_GATE_SKILLS.
$sessionPath = Get-SapCurrentSessionPath -WorkTemp '{WORK_TEMP}' # or the --session value
$vbs = [IO.File]::ReadAllText('<SKILL_DIR>\references\sap_stms_import.vbs', [Text.Encoding]::UTF8)
$vbs = $vbs.Replace('%%ATTACH_LIB_VBS%%', "$shared\sap_attach_lib.vbs")
$vbs = $vbs.Replace('%%SESSION_LOCK_VBS%%',"$shared\sap_session_lock.vbs")
$vbs = $vbs.Replace('%%SESSION_PATH%%', $sessionPath)
$vbs = $vbs.Replace('%%TR%%', 'THE_TR')
$vbs = $vbs.Replace('%%TARGET_SID%%', 'THE_SID')
$vbs = $vbs.Replace('%%TARGET_CLIENT%%', 'THE_CLIENT')
$vbs = $vbs.Replace('%%IMMEDIATE%%', '0') # MUST be 0 until the options checkboxes are calibrated (a truthy value -> STMS_OPTION_UNSUPPORTED)
$vbs = $vbs.Replace('%%LEAVE_IN_QUEUE%%', '0') # MUST be 0 until calibrated (see note above)
$vbs = $vbs.Replace('%%OUTPUT_FILE%%', '{RUN}\import.json')
[IO.File]::WriteAllText('{RUN}\stms_import_run.vbs', $vbs, [System.Text.UnicodeEncoding]::new($false, $true))
```
```bash
C:\Windows\SysWOW64\cscript.exe //NoLogo "{RUN}\stms_import_run.vbs"
```
## W5 — Verify (RC) and report
After the import, read the RC via Logs Mode (`sap_stms_log_read.vbs`) — do NOT
trust the queue row. Map RC -> verdict (Logs Mode table). Register an import
evidence artifact for `/sap-evidence-pack` if the artifact lib is in use.
Report the TR, target, RC, verdict, and the next route hop (e.g. "imported to
QAS RC 4; next hop is PRD — re-run `/sap-stms import <TR> --to PRD` after QA
sign-off").
### Status line
```
STATUS: IMPORTED tr=<TR> target=<SID>/<client> rc=<0|4|8|12> verdict=<OK|OK_WITH_WARNINGS|ERROR|FATAL>
STATUS: QUEUED tr=<TR> target=<SID> (scheduled, not yet run)
STATUS: ALREADY_IMPORTED tr=<TR> target=<SID>
STATUS: COULD_NOT_IMPORT reason=<no-auth|not-released|no-go|not-in-queue|not-calibrated|STMS_OPTION_UNSUPPORTED|STMS_TMS_RFC_DOWN|verify-failed|queue-not-found>
STATUS: BLOCKED reason=<prod-not-confirmed|tr-not-released>
```
The import VBS exits **1** on every abort/error (`ABORTED` / `IMPORT_ERROR` in
`import.json`) and **0** only on `IMPORT_SUBMITTED`. Treat a non-zero exit (or an
`import.json` `result` other than `IMPORT_SUBMITTED`) as `COULD_NOT_IMPORT` — the
`detail` field carries the reason code (e.g. `STMS_OPTION_UNSUPPORTED`,
`verify-failed`, `not-in-queue`, `not-calibrated`).
---
# Import-All Mode (WRITE — double-gated)
Off unless `import-all --to <SID> --all` is given **and** the user double-confirms
(and types the SID for a PROD target). Imports the whole queue into the target.
Reuses W1–W5 over every queued TR; reports per-TR RC. Recommended only for
DEV/QA refresh — discourage for production (import individual TRs there).
---
## Final — Log End
```bash
powershell -ExecutionPolicy Bypass -File "<SAP_DEV_CORE_SHARED_DIR>\scripts\sap_log_helper.ps1" -Action end -StateFile "{RUN_TEMP}\sap_stms_run.json" -Status SUCCESS -ExitCode 0
```
| Outcome | Status / ExitCode / ErrorClass |
|---|---|
| Imported, RC 0/4 | `-Status SUCCESS -ExitCode 0` |
| Status / logs read | `-Status SUCCESS -ExitCode 0` |
| Imported, RC 8/12 | `-Status FAILED -ExitCode 1 -ErrorClass STMS_IMPORT_RC_ERROR -ErrorMsg "rc=<n>"` |
| Blocked (not released / prod not confirmed) | `-Status SKIPPED -ExitCode 1 -ErrorClass STMS_BLOCKED` |
| No import authorization | `-Status SKIPPED -ExitCode 1 -ErrorClass STMS_NO_AUTH` |
| Import controls not calibrated | `-Status SKIPPED -ExitCode 1 -ErrorClass STMS_NOT_CALIBRATED` |
| TMS communication down (alert viewer) | `-Status SKIPPED -ExitCode 1 -ErrorClass STMS_TMS_RFC_DOWN -ErrorMsg "<alert=... function=... destination=...>"` |
---
## Component IDs (for reference / recording)
| Element | Candidate ID | Note |
|---|---|---|
| OK code | `wnd[0]/tbar[0]/okcd` | stable |
| STMS Import Overview | okcd `/nSTMS_IMPORT` | system-overview list |
| Import queue grid/tree | `wnd[0]/usr/cntlCTRL_IMPORT_QUEUE/shellcont/shell` (candidate) | **RECORD** — varies by release |
| TMS Alert Viewer (TMS down) | program `SAPLTMSU_ALT` + popup fields `wnd[1]/usr/txtGS_DYN100-S_ALOG-ERROR` / `-FUNCTION` / `MSG_LINE2` | **captured live 2026-07-11** on S/4HANA 2022 + ECC — identical IDs; drives the `STMS_TMS_RFC_DOWN` guard |
| Import Request button | `PLACEHOLDER_IMPORT_BTN` | **RECORD** — destructive; PLACEHOLDER until calibrated |
| Import-options dialog | `PLACEHOLDER_OPTS_DIALOG` (target client / date tab / options tab) | **RECORD** |
| Confirm import | `PLACEHOLDER_OPTS_CONFIRM` | **RECORD** |
| Status bar | `wnd[0]/sbar` | `MessageType` for S/W/E |
## Known Issues / Failure Modes
| Symptom | Cause | Recovery |
|---|---|---|
| `COULD_NOT_IMPORT not-calibrated` | the import VBS PLACEHOLDER IDs are not yet recorded for this release | `/sap-gui-probe --record` the STMS_IMPORT flow; replace `PLACEHOLDER_*` in `sap_stms_import.vbs` |
| `STMS_TMS_RFC_DOWN` (any mode) | TMS communication layer broken — STMS_IMPORT opens the TMS Alert Viewer (`SAPLTMSU_ALT` + `GS_DYN100-S_ALOG-*` popup) instead of the queue. Observed live 2026-07-11 on BOTH S/4HANA 2022 (CPIC `ThSAPOCMINIT` gateway failure on `TMSADM@S4H.DOMAIN_S4H`) and ECC (secure-storage logon-data retrieval failure on `TMSADM@ER1.DOMAIN_ER1`) | Basis: repair/regenerate the `TMSADM@<SID>.DOMAIN_<SID>` RFC destination (SM59 / STMS reconfiguration; for the secure-storage variant see SAP Note 1568362 — `TMS_UPDATE_PWD_OF_TMSADM` on the domain controller, client 000). NOT a control-ID recording issue — calibration is impossible until the queue renders |
| `COULD_NOT_IMPORT no-auth` | dialog user lacks TMS import authorization (often Basis-gated) | run status/logs only, or have Basis import; this is expected in many shops |
| `BLOCKED tr-not-released` | TR is still modifiable (`E070-TRSTATUS != R`) | `/sap-se01 release <TR>` first |
| queue grid not found | STMS queue control ID drift | `/sap-gui-probe --record` STMS_IMPORT; update the candidate in `sap_stms_queue_read.vbs` |
| row "done" but failures | RC 8/12 not surfaced in the row | always confirm via Logs Mode RC, never the row |
## Limitations
- **Read-first.** Status/logs are the most-used (and universally authorized)
modes; import requires TMS auth that is frequently Basis-only.
- **Import VBS is recording-gated.** It ships as a fail-safe scaffold (PLACEHOLDER
destructive IDs + mandatory row==TR verification); it does nothing until
`/sap-gui-probe --record`-calibrated. By design it cannot mis-import on an uncalibrated
system.
- **Production import** is the most outward-facing action in the toolset — typed
SID echo + second confirmation, always; no bypass flag.
- **RC is truth.** Verdicts come from the import RC (0/4/8/12), never the queue
row's appearance.
- **No scheduling windows** in v1 (immediate / next-run only).
- **RFC queue read** (`TMS_MGR_READ_TRANSPORT_QUEUE`) is a documented Phase-2
path; v1 reads the queue via GUI.
---
## Pipeline Integration
```
/sap-fix-incident (DEV fix) ─┐
├─► /sap-transport-readiness <TR> (GO/NO-GO)
└─► └─► /sap-se01 release <TR> (irreversible)
└─► /sap-stms import <TR> --to QAS ─► test ─► --to PRD
```
The skill that finally moves a change to QA / production — the last link in the
delivery chain. Release stays a deliberate `/sap-se01` step; this skill never
releases, and never imports without its gates.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!