client/media/skills/sap-customizing/SKILL.md
Navigate and understand SAP Customizing (SPRO/IMG). Use when the user asks about customizing settings, SPRO activities, configuration tables, maintenance views, view clusters, or needs to read/understand any customizing data. This skill teaches how to systematically trace from an SPRO activity to the actual tables where config data is stored, and how to find the SPRO menu path for any activity. Load this skill whenever customizing, SPRO, IMG, configuration, or settings maintenance is involved.
npx skillsauth add marcellourbani/vscode_abap_remote_fs sap-customizingInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Your training data about SAP customizing is almost certainly wrong. Do NOT guess which tables store which customizing data. Follow the lookup procedures below to discover the truth from the system itself.
Always read table structures with get_object_lines before querying. Never hardcode field names from memory.
Text fields are case-sensitive. Use aggressive wildcards: %aterial%ype% finds "Material Types", "material type", etc.
Minimize SQL round-trips. Use JOINs to combine lookups into single queries.
Present only useful information to the user. Internal IDs like activity IDs (SIMG_CFMENUOLMSOMS2), tree GUIDs (368DDFAB...), and node IDs are technical plumbing — never include them in your answer. Only show the user: SPRO menu path, table names, view/cluster names, transaction codes, and descriptions.
| Table | Purpose | Key Fields |
|-------|---------|------------|
| CUS_IMGACH | IMG activity header | activity, c_activity (links to CUS_ACTH), tcode |
| CUS_IMGACT | IMG activity texts (language-dependent) | spras, activity, text |
| Table | Purpose | Key Fields |
|-------|---------|------------|
| CUS_ACTH | Activity header | act_id, act_type, tcode |
| CUS_ACTT | Activity texts (language-dependent) | spras, act_id, text |
| CUS_ACTOBJ | Core — links activities to maintenance objects | act_id, objecttype, objectname, tcode |
CUS_ACTH.act_type: C = customizing (most common), E = BAdI definition, I = BAdI implementation. Note: filtering by act_type = 'E' is unreliable — many BAdI activities use act_type = 'C'. To find BAdIs, search CUS_IMGACT text for %BAdI% or %Business Add-In%. This mainly works for IS solutions (IS-Retail, IS-Utilities, HR). Core modules (MM, FI, SD, PP) often do not register BAdIs in the IMG at all — for those, use SE18 directly with patterns like MB_*, ME_*, MM_*.
CUS_ACTOBJ.objecttype (domain OB_TYP):
| Value | Meaning | What objectname contains |
|-------|---------|---------------------------|
| V | View | Maintenance view name (e.g., V_T001W). Via SM30 or dedicated tcode |
| C | View Cluster | Cluster name (e.g., MTART). Via SM34 or dedicated tcode |
| S | Table with Text Table | Table name directly. Via SM30 |
| T | Individual Transaction | Logical object (often SNUM). The tcode field has the transaction |
| L | Logical Transport Object | Transport object type. The tcode field has the transaction |
| D | Dummy Object | Usually IMGDUMMY. The tcode field has the transaction |
| Table | Purpose | Key Fields |
|-------|---------|------------|
| VCLDIR | Cluster directory | vclname, exitprog |
| VCLSTRUC | Cluster structure — views inside a cluster | vclname, object, objpos, dependency, startobj |
VCLSTRUC.dependency (domain OBJDEP): R = root/header, S = dependent on one parent, M = dependent on multiple parents. startobj X = initial object shown.
| Table | Purpose | Key Fields |
|-------|---------|------------|
| DD26S | View base tables | viewname, tabname, as4local (use A), tabpos (1 = primary) |
ABAP FS cannot read view structures, but can read tables. Always resolve views to their base tables via DD26S, then use get_object_lines on the table.
| Table | Purpose | Key Fields |
|-------|---------|------------|
| TSTC | Tcode → program | tcode, pgmna |
| TSTCT | Tcode descriptions | sprsl, tcode, ttext |
| TSTCP | Tcode parameters | tcode, param |
TSTCP.param for SM30 wrappers: /*SM30 VIEWNAME=<view>;UPDATE=X; — extract VIEWNAME to find the maintained view.
The SPRO tree is stored across multiple linked sub-trees:
| Table | Purpose | Key Fields |
|-------|---------|------------|
| TNODEIMG | Tree nodes (folders + activity leaves) | tree_id, node_id, parent_id, node_type, reftree_id |
| TNODEIMGT | Node texts — holds folder/section names, NOT activity names | tree_id, node_id, spras, text |
| TNODEIMGR | Node references — links leaf nodes to IMG activities | node_id, ext_key, ref_type, ref_object |
CRITICAL: TNODEIMGR has NO tree_id column — it only has node_id, ext_key, ref_type, ref_object. Never try to JOIN it with TNODEIMG/TNODEIMGT on tree_id.
CRITICAL: TNODEIMGT contains folder labels ("Material Types", "Basic Settings"), NOT activity names ("Define Attributes of Material Types"). Activity names live in CUS_IMGACT. To find a leaf node for a known activity, use TNODEIMGR (see Procedure 3).
node_type values: IMG0 = folder node, IMG = activity leaf (text in CUS_IMGACT, not TNODEIMGT), REF = reference to a sub-tree (follow reftree_id).
TNODEIMGR.ref_type: COBJ = customizing activity ID (matches CUS_ACTOBJ.act_id), ACTI = IMG activity ID (matches CUS_IMGACH.activity, prefixed with SIMG).
Main SPRO tree ID is 368DDFAB3AB96CCFE10000009B38F976 ("SAP Customizing Implementation Guide") — this is SAP-delivered and consistent across systems. If unsure, look it up:
SELECT t~id FROM ttree AS t INNER JOIN ttreet AS n ON t~id = n~id
WHERE n~spras = 'E' AND t~type = 'IMG' AND n~text LIKE '%AP Customizing Implementation Guide'
Its top-level children (Logistics - General, Materials Management, FI, etc.) are REF nodes pointing to component sub-trees via reftree_id.
DD07T decodes any coded field: query with domname, ddlanguage = 'E', as4local = 'A' to get domvalue_l → ddtext.
SELECT a~activity, t~text, a~c_activity, o~objecttype, o~objectname, o~tcode
FROM cus_imgach AS a
INNER JOIN cus_imgact AS t ON a~activity = t~activity
INNER JOIN cus_actobj AS o ON a~c_activity = o~act_id
WHERE t~spras = 'E'
AND t~text LIKE '%your search%'
Then branch by objecttype:
V (View) → resolve to base table:
SELECT d~viewname, d~tabname, d~tabpos FROM dd26s AS d
WHERE d~viewname = '<objectname>' AND d~as4local = 'A'
ORDER BY d~tabpos ASCENDING
The tabpos = 1 row is the primary base table. Run get_object_lines on it and query directly.
C (View Cluster) → get constituent views, then resolve each:
SELECT v~vclname, v~exitprog, s~object, s~objpos, s~dependency, s~startobj
FROM vcldir AS v
INNER JOIN vclstruc AS s ON v~vclname = s~vclname
WHERE v~vclname = '<objectname>'
ORDER BY s~objpos ASCENDING
Each s~object is a view — resolve via DD26S as above.
S (Table with Text Table) → objectname IS the table. Read with get_object_lines directly. Text table is usually <table>T.
T / D / L → the tcode is key. When objectname = 'SNUM', this is a number range activity — data is in table NRIV (number range intervals), not a normal config table. The tcode (e.g., OMH6, MMNR) opens the number range maintenance screen. For other standalone tcodes, check TSTCP to see if it wraps SM30:
SELECT t~tcode, t~param FROM tstcp AS t WHERE t~tcode = '<tcode>'
If param contains VIEWNAME=, extract it and resolve via DD26S. If TSTCP has no entry (standalone transaction), look up the tcode in TSTC for its program — but note that for standalone transactions (objecttype T/D), the underlying table often cannot be determined from metadata alone. You may need to search the program's source code or ask the user.
Often faster than forward text search (Procedure 1) when you know the table/view name, especially when forward search returns noisy results from many modules.
SELECT o~act_id, o~objecttype, o~objectname, o~tcode, t~text
FROM cus_actobj AS o
INNER JOIN cus_actt AS t ON o~act_id = t~act_id
WHERE t~spras = 'E'
AND o~objectname LIKE '%<table_or_view>%'
If this returns 0 rows, the table may be a secondary member inside a view cluster (CUS_ACTOBJ stores only the cluster name, not individual member tables). Find the cluster via VCLSTRUC + DD26S:
SELECT s~vclname, s~object FROM vclstruc AS s
INNER JOIN dd26s AS d ON d~viewname = s~object
WHERE d~tabname = '<your_table>' AND d~as4local = 'A'
Then search CUS_ACTOBJ for the vclname value with objecttype = 'C'.
The SPRO tree is split into sub-trees linked by REF nodes. Building the full path requires walking upward through multiple sub-trees. Expect 3-4 queries per tree level, and 3-5 tree levels — so roughly 10-15 queries total.
Step A — Find the tree node for a known activity ID (from Procedure 1). Use TNODEIMGR — do NOT search TNODEIMGT by activity name (it only has folder labels).
Step A.1 — Get all node_ids for the activity from TNODEIMGR:
SELECT r~node_id FROM tnodeimgr AS r
WHERE r~ref_type = 'COBJ' AND r~ref_object = '<activity_id>'
This often returns multiple rows — the same activity appears in several SPRO locations.
Step A.2 — For each node_id, look it up in TNODEIMG to get tree_id and parent_id. Some node_ids from TNODEIMGR are orphans (they exist in TNODEIMGR but not TNODEIMG) — skip any that return 0 rows:
SELECT n~node_id, n~parent_id, n~tree_id, n~node_type
FROM tnodeimg AS n WHERE n~node_id = '<node_id_from_A1>'
Pick the node that resolves successfully and belongs to a module-relevant sub-tree. If unsure which, try each until one produces a complete path to the SPRO root.
To search by folder name instead (not activity name), search TNODEIMGT:
SELECT n~node_id, n~parent_id, n~tree_id, t~text
FROM tnodeimg AS n
INNER JOIN tnodeimgt AS t ON n~node_id = t~node_id AND n~tree_id = t~tree_id
WHERE t~spras = 'E' AND t~text LIKE '%folder name%'
Step B — Walk up parent_id within the same tree_id, collecting folder texts from TNODEIMGT:
SELECT n~node_id, n~parent_id, t~text
FROM tnodeimg AS n
INNER JOIN tnodeimgt AS t ON n~node_id = t~node_id AND n~tree_id = t~tree_id
WHERE t~spras = 'E' AND n~tree_id = '<tree_id>' AND n~node_id = '<parent_id>'
Repeat until parent_id is empty (you've hit the sub-tree root).
Step C — Jump to the parent tree. Find which REF node references this sub-tree. First try without text JOIN (some REF nodes lack TNODEIMGT text):
SELECT n~node_id, n~parent_id, n~tree_id
FROM tnodeimg AS n
WHERE n~reftree_id = '<current_tree_id>' AND n~node_type = 'REF'
If this returns multiple rows, they are different SPRO locations linking to the same sub-tree — pick the one whose tree_id traces back to the main SPRO root. If this returns 0 rows, the sub-tree is an orphaned copy with no parent link — go back to Step A and try a different node_id for the same activity.
Once you have the REF node, continue walking up parent_id in THAT tree (Step B again). Get the REF node's parent folder text from TNODEIMGT to add to your path.
Step D — Repeat Steps B-C until you reach the main SPRO tree root (368DDFAB3AB96CCFE10000009B38F976).
Assemble the collected texts in reverse order: SAP Customizing Implementation Guide > Logistics - General > Material Master > Basic Settings > Material Types > Define Attributes of Material Types.
SELECT d~domvalue_l, d~ddtext FROM dd07t AS d
WHERE d~domname = '<DOMAIN_NAME>' AND d~ddlanguage = 'E' AND d~as4local = 'A'
User asks: "Where is material type customizing stored?"
Find activity + storage:
SELECT a~activity, a~c_activity, t~text, o~objecttype, o~objectname, o~tcode
FROM cus_imgach AS a
INNER JOIN cus_imgact AS t ON a~activity = t~activity
INNER JOIN cus_actobj AS o ON a~c_activity = o~act_id
WHERE t~spras = 'E' AND t~text LIKE '%aterial%ype%'
Result: objecttype=C, objectname=MTART — a view cluster.
Get cluster views:
SELECT v~vclname, v~exitprog, s~object, s~objpos, s~dependency, s~startobj
FROM vcldir AS v INNER JOIN vclstruc AS s ON v~vclname = s~vclname
WHERE v~vclname = 'MTART' ORDER BY s~objpos ASCENDING
Result: T134 (R=root, Material types) and VT134M (S=child, Quantity/value updating). Exit program: MMMTARTEXIT.
Resolve to base tables:
SELECT d~viewname, d~tabname, d~tabpos FROM dd26s AS d
WHERE d~viewname IN ('VT134M', 'T134') AND d~as4local = 'A'
Result: T134 → T134 (tabpos=1), VT134M → T134M (tabpos=1). Read with get_object_lines and query directly.
Note: a reverse lookup on CUS_ACTOBJ for objectname LIKE '%T134M%' returns 0 rows — because CUS_ACTOBJ stores the cluster name MTART, not individual member tables. To find T134M's SPRO entry, search VCLSTRUC+DD26S as shown in Procedure 2.
tcode = SM30 in CUS_ACTOBJ, it's generic. A different tcode may be an SM30 wrapper (check TSTCP) or standalone.objecttype = S, text tables conventionally follow <table>T (e.g., T134 → T134T), but verify.development
Create SAP Data Workbooks (.sapwb) for SAP data analysis. Use when the user asks to analyze SAP data, create data quality checks, build reports, compare tables, profile data, or any multi-step SAP data exploration. Workbooks have ABAP SQL cells (queries against SAP) and JavaScript cells (process results). They save as files and can be re-run.
tools
Investigate SAP ADT REST API endpoints. Use when the user asks about ADT API endpoints, request/response XML formats, content types, or how a specific ADT feature works under the hood. Teaches how to trace from discovery documents → RES_APP classes → handler classes → Simple Transformations → XML schemas. Requires the adt_discovery_export tool output files and standard ABAP tools (get_abap_object_lines, search_abap_objects, search_abap_object_lines).
development
Generate a comprehensive SAP System Personality Report. Analyzes custom code landscape, functional footprint, development activity, health metrics, and package breakdown. Use when a user asks to characterize a system, understand a system, get a system overview, system report, system personality, or "what does this system do?" Collects data via SQL queries and presents results in a structured webview.
development
Clean ABAP coding standards and best practices. Use when writing ABAP code, reviewing ABAP code, or refactoring ABAP code to ensure it follows SAP's official Clean ABAP style guide. Covers naming conventions, modern language constructs, class/method design, error handling, formatting, comments, and unit testing patterns.