From sap-dev-core
Activates an inactive SAP repository object via SAP GUI Scripting. Routes to the correct transaction by object type: SE38 for reports/programs/function- group main programs, SE37 for function modules, SE24 for classes/interfaces /methods, SE11 for DDIC objects (table, view, dataelement, structure, tabletype, typegroup, domain, searchhelp, lockobject). Handles the "inactive objects worklist" popup that SAP shows when there are multiple inactive objects of the same locality (transportable vs. local — SAP filters the popup by package locality of the triggering object). Verifies activation via PROGDIR (programs/FMs include) and DWINACTIV. Prerequisites: Active SAP GUI session (use /sap-login first).
How this skill is triggered — by the user, by Claude, or both
Slash command
/sap-dev-core:sap-activate-object <OBJECT_TYPE> <OBJECT_NAME><OBJECT_TYPE> <OBJECT_NAME>The summary Claude sees in its skill listing — used to decide when to auto-load this skill
You activate an inactive SAP repository object via SAP GUI Scripting,
You activate an inactive SAP repository object via SAP GUI Scripting, routing to the appropriate transaction based on the object type and verifying the result via DDIC tables.
Task: $ARGUMENTS
| File | Purpose |
|---|---|
<SAP_DEV_CORE_SHARED_DIR>/rules/skill_operating_rules.md | Mandatory operating rules |
Settings reads/writes follow shared/rules/settings_lookup.md — merge settings.local.json over settings.json per-key on the .value field; writes always go to settings.local.json. Resolve sap-dev-core paths: 2 levels up from <SKILL_DIR> to the plugin root, then settings.json and (if present) settings.local.json. Read work_dir, sap_user.
| Setting | Default if blank |
|---|---|
work_dir | C:\sap_dev_work |
Set {WORK_TEMP} = {work_dir}\temp. Ensure it exists:
cmd /c if not exist "{WORK_TEMP}" mkdir "{WORK_TEMP}"
sap_user is needed for the DWINACTIV pre/post checks. If blank, ask the
user.
Start a structured log run. The shared helper persists run_id to a state
file so subsequent steps and Step 7 can append to the same run. Logging is
best-effort — if userConfig.log_enabled=false or the lib can't load, the
helper silently no-ops.
<SAP_DEV_CORE_SHARED_DIR> resolves to plugins/sap-dev-core/shared/.
State file: {WORK_TEMP}\sap_activate_object_run.json
powershell -ExecutionPolicy Bypass -File "<SAP_DEV_CORE_SHARED_DIR>\scripts\sap_log_helper.ps1" -Action start -StateFile "{WORK_TEMP}\sap_activate_object_run.json" -Skill sap-activate-object -ParamsJson "{\"object_type\":\"<TYPE>\",\"object_name\":\"<NAME>\"}"
Required:
| Arg | Description | Example |
|---|---|---|
OBJECT_TYPE | One of the keys below | REPORT |
OBJECT_NAME | Object name in Z/Y namespace | ZHKTEST003 |
If $ARGUMENTS is missing the type or name, ask:
Which object should I activate? Provide
<OBJECT_TYPE> <OBJECT_NAME>(e.g.REPORT ZHKTEST003).
| OBJECT_TYPE | Transaction | DWINACTIV OBJECT value | TADIR OBJECT value |
|---|---|---|---|
REPORT / PROGRAM | SE38 | REPS (source include) | PROG |
TEXT_ELEMENTS | SE38 (Goto > Text elements) | TEXT | PROG |
FUGR (function group main pgm) | SE38 | REPS | FUGR |
FM (function module) | SE37 | FUNC | FUGR (registered under group) |
CLASS | SE24 | CLAS | CLAS |
INTERFACE | SE24 | INTF | INTF |
METHOD | SE24 (open class) | METH | CLAS |
TABLE | SE11 (radRSRD1-TBMA) | TABL | TABL |
VIEW | SE11 (radRSRD1-VIMA) | VIEW | VIEW |
DTEL (data element) | SE11 (radRSRD1-DDTYPE) | DTEL | DTEL |
STRUCTURE | SE11 (radRSRD1-DDTYPE) | TABL (structures = TABL) | TABL |
TABLETYPE | SE11 (radRSRD1-DDTYPE) | TTYP | TTYP |
TYPEGROUP | SE11 (radRSRD1-TYMA) | TYPE | TYPE |
DOMAIN | SE11 (radRSRD1-DOMA) | DOMA | DOMA |
SEARCHHELP | SE11 (radRSRD1-SHMA) | SHLP | SHLP |
LOCKOBJECT | SE11 (radRSRD1-ENQU) | ENQU | ENQU |
If the user supplies an unknown type → list the allowed values and ask.
Query TADIR via /sap-se16n to read DEVCLASS for the object:
SELECT
PGMID
OBJECT
OBJ_NAME
DEVCLASS
FILTER
PGMID EQ R3TR
OBJECT EQ <TADIR_OBJECT_FROM_TABLE_ABOVE>
OBJ_NAME EQ <OBJECT_NAME>
Read DEVCLASS:
$ (e.g. $TMP) → local object (no TR association).Store as LOCALITY = LOCAL | TRANSPORT. If TADIR has no row, the object does
not exist — report and stop.
This step is optional but recommended; LOCALITY is used to anticipate the "inactive objects worklist" popup behaviour described in Step 3.
Query DWINACTIV via /sap-se16n filtering by the logged-in user:
SELECT
OBJECT
OBJ_NAME
UNAME
FILTER
UNAME EQ <sap_user>
This lists all inactive repository objects locked to this user. SAP's "inactive objects worklist" popup appears on activate when there are multiple inactive objects of the same locality as the object being activated:
Use this list to inform the user: "There are N other inactive objects under your user; the activation popup will let you pick which to activate."
The VBS templates handle the popup automatically (Select All + Continue, matching the recordings).
This skill requires an active SAP GUI session. If not already logged in, run
/sap-login.
Pick the template by transaction:
| Transaction | Template | Tokens |
|---|---|---|
| SE38 | ./references/sap_activate_se38.vbs | %%OBJECT_NAME%% |
| SE37 | ./references/sap_activate_se37.vbs | %%OBJECT_NAME%% |
| SE24 | ./references/sap_activate_se24.vbs | %%OBJECT_NAME%% |
| SE11 | ./references/sap_activate_se11.vbs | %%OBJECT_NAME%%, %%OBJECT_TYPE%%, %%ACTIVATION_LOG_VBS%%, %%TEMP_DIR%% |
Token-replace into {WORK_TEMP}\sap_activate_<txn>_run.ps1:
$content = Get-Content '<SKILL_DIR>\references\sap_activate_<TXN>.vbs' -Raw
$content = $content -replace '%%OBJECT_NAME%%','THE_NAME'
$content = $content -replace '%%OBJECT_TYPE%%','THE_TYPE' # SE11 only
$content = $content -replace '%%ACTIVATION_LOG_VBS%%','<SAP_DEV_CORE_SHARED_DIR>\scripts\sap_activation_log.vbs' # SE11 only
$content = $content -replace '%%TEMP_DIR%%','{WORK_TEMP}' # SE11 only
Set-Content '{WORK_TEMP}\sap_activate_<TXN>_run.vbs' $content -Encoding Unicode
Write-Host 'Done'
Activation-log capture (SE11 only, by design): when SE11 activation reports an error (
STATUS_TYPE = EorA), the helper writes{WORK_TEMP}\<OBJECT>.activation_log.txtand the script echoesACTIVATION_LOG: <path>andACTIVATION_ERROR: <top error line>. This turns the opaque "refer to log" SAP popup into actionable output.Not applicable to SE38 / SE37 / SE24 / SE91. The
Utilities > Activation Logmenu is a DDIC-worklist concept that exists only in SE11. Other transactions surface activation errors directly in the source-code editor (inline error markers + clickable error list) and in the status bar — the existingSTATUS_TYPE/STATUS_TEXTcapture in those VBS templates is the right surfacing mechanism. Do NOT propagate this helper to non-SE11 activate scripts.
Run via 32-bit cscript:
powershell -ExecutionPolicy Bypass -File "{WORK_TEMP}\sap_activate_<TXN>_run.ps1"
cmd /c C:\Windows\SysWOW64\cscript.exe //NoLogo {WORK_TEMP}\sap_activate_<TXN>_run.vbs
Each VBS emits:
INFO: ... — progressSTATUS_TYPE: <S|W|E|A|I> — final status bar message typeSTATUS_TEXT: <text> — final status bar message textDONE on success or ERROR: ... on failure.The status bar text should be Object(s) activated (S-type message). If
the VBS reports an E/A status type, surface the text to the user and treat
as failure.
For programs and FMs, query PROGDIR via /sap-se16n:
For REPORT/PROGRAM/FUGR (SE38):
SELECT
NAME
STATE
FILTER
NAME EQ <OBJECT_NAME>
STATE EQ A
Expect at least one row — STATE = A means the active version exists.
For FM (SE37):
TFDIR via /sap-se16n:
SELECT
FUNCNAME
PNAME
INCLUDE
FILTER
FUNCNAME EQ <OBJECT_NAME>
Build the include name. PNAME is the function group main program; INCLUDE
is the FM's source include number. The conventional include name format is
L<group>U<include> where <group> = the 4-char part after SAPL of
PNAME, and <include> = INCLUDE (zero-padded, with the literal letter
prefix). Or simply: read PNAME-INCLUDE text directly if SAP returns it
as a column.PROGDIR with NAME EQ <include_name> and check STATE = A.Re-query DWINACTIV filtering by user + the specific object:
SELECT
OBJECT
OBJ_NAME
UNAME
FILTER
UNAME EQ <sap_user>
OBJECT EQ <DWINACTIV_OBJECT_FROM_TABLE_ABOVE>
OBJ_NAME EQ <OBJECT_NAME>
Expect NO rows. Any row means the object is still inactive for this user (activation failed or was skipped).
Report the result to the user:
Activated <OBJECT_TYPE> <OBJECT_NAME> via <TXN>.
Locality : <LOCAL | TRANSPORT>
Status bar : [<TYPE>] <TEXT>
PROGDIR check : <STATE=A | n/a>
DWINACTIV : <not found ✓ | still present ✗>
If the object still appears in DWINACTIV, recommend re-activating manually or checking dependencies (inactive nested objects).
Log the run-end record. Best-effort: silently no-ops if logging disabled. On success:
powershell -ExecutionPolicy Bypass -File "<SAP_DEV_CORE_SHARED_DIR>\scripts\sap_log_helper.ps1" -Action end -StateFile "{WORK_TEMP}\sap_activate_object_run.json" -Status SUCCESS -ExitCode 0
On failure (substitute <CLASS> and short message):
powershell -ExecutionPolicy Bypass -File "<SAP_DEV_CORE_SHARED_DIR>\scripts\sap_log_helper.ps1" -Action end -StateFile "{WORK_TEMP}\sap_activate_object_run.json" -Status FAILED -ExitCode 1 -ErrorClass <CLASS> -ErrorMsg "<short>"
Suggested <CLASS>: ACTIVATE_FAILED, GUI_TIMEOUT.
| Element | ID |
|---|---|
| OK code | wnd[0]/tbar[0]/okcd |
| Program name field | wnd[0]/usr/ctxtRS38M-PROGRAMM |
| Activate (initial screen) | sendVKey 21 (Shift+F9) on wnd[0] |
| Inactive worklist popup | wnd[1] — Select All tbar[0]/btn[9], Continue tbar[0]/btn[0] |
| Element | ID |
|---|---|
| FM name field | wnd[0]/usr/ctxtRS38L-NAME |
| Activate | sendVKey 27 (Ctrl+F3) on wnd[0] |
| Inactive worklist popup | wnd[1] — Continue tbar[0]/btn[0] (FMs typically don't show Select All; the popup is for "activate dependent includes") |
| Element | ID |
|---|---|
| Class name field | wnd[0]/usr/ctxtSEOCLASS-CLSNAME |
| Display (Enter) | sendVKey 0 |
| Activate | sendVKey 27 (Ctrl+F3) on wnd[0] |
| Inactive worklist popup | wnd[1] — Select All tbar[0]/btn[9], Continue tbar[0]/btn[0] |
| Element | ID |
|---|---|
| Object type radios | radRSRD1-TBMA / VIMA / DDTYPE / TYMA / DOMA / SHMA / ENQU |
| Name field | ctxtRSRD1-<key>_VAL (matching radio key) |
| Display (Enter) | sendVKey 0 |
| Activate | sendVKey 27 (Ctrl+F3) on wnd[0] |
| Inactive worklist popup | wnd[1] — Select All tbar[0]/btn[9], Continue tbar[0]/btn[0] |
| Field | Meaning |
|---|---|
OBJECT | DDIC object type code (e.g. REPS, PROG, FUNC, CLAS, TABL, DOMA) |
OBJ_NAME | Object name |
UNAME | User who locked the inactive version |
| Field | Meaning |
|---|---|
PGMID | R3TR for repository objects |
OBJECT | TADIR object type (e.g. PROG, CLAS, TABL) |
OBJ_NAME | Object name |
DEVCLASS | Package — $* = local, otherwise transportable |
| Field | Meaning |
|---|---|
NAME | Program / include name |
STATE | A = active, S = saved (inactive) |
The current popup-handling presses Select All (tbar[0]/btn[9]) then Continue
(tbar[0]/btn[0]). When the worklist contains transportable inactive objects
that DID NOT come from the current activate call (leftover from prior failed
runs in the same user's namespace), Select-All activates them too. If any of
those leftover objects has a non-recoverable activation error, the worklist
re-appears in a loop and the activate never completes.
Mitigation today: before invoking this skill, query DWINACTIV filtered by
the logged-in user and delete or fix any leftover transportable inactive
objects unrelated to the current target. The /sap-dev-clean skill handles
the sap-dev-init artefacts; other leftovers must be cleaned manually.
Proper fix (not yet implemented — needs a recording session per SAP release):
selectively uncheck rows in the worklist grid whose OBJ_NAME differs from
the current OBJECT_NAME, then press Continue. The pseudocode:
' Find the worklist grid (S/4HANA 1909 commonly uses cntlGRID1 or similar)
Dim oGrid : Set oGrid = oSession.findById("wnd[1]/usr/cntlGRID1/shellcont/shell")
Dim r, sName
For r = 0 To oGrid.RowCount - 1
sName = oGrid.GetCellValue(r, "OBJ_NAME")
If UCase(sName) <> UCase(TARGET_OBJECT_NAME) Then
oGrid.ModifyCheckbox r, "DEACTI", False ' or whatever the select column is named
End If
Next
oSession.findById("wnd[1]/tbar[0]/btn[0]").press ' Continue
The grid path (cntlGRID1...) and select-column ID (DEACTI?) need to be
captured on the target SAP release via /sap-gui-record. The grid behaviour
differs between S/4HANA 1909, 2020, and 2023; the recording must be re-done
per system if needed.
Until then, the Select-All path remains the documented default — it works cleanly on systems where the user's worklist contains only the current target.
npx claudepluginhub sapdev-ai/sap-dev --plugin sap-dev-coreGuides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.