client/media/skills/sap-system-personality-report/SKILL.md
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.
npx skillsauth add marcellourbani/vscode_abap_remote_fs sap-system-personality-reportInstall 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.
Generate a rich, structured report that characterizes an SAP system in human-readable terms. You will collect data by running SQL queries, then present the results in a webview table AND provide a narrative AI summary.
CRITICAL: Before running ANY query, call get_abap_sql_syntax to understand ABAP SQL syntax. Use get_object_lines to check table structures before running SQL queries.
CRITICAL: All queries must use ABAP SQL syntax (e.g., ORDER BY field DESCENDING not DESC). Use the execute_data_query tool with displayMode: "internal" to collect data, then assemble final results into a displayMode: "ui" call.
Get basic system information first. Use the get_sap_system_info tool — it returns system type (S/4HANA vs ECC), release, timezone, and client details. No SQL needed for this step.
Run these queries to count custom objects. Use displayMode: "internal" with rowRange: {start: 0, end: 5} since we only need counts.
Run all of these in parallel (they are independent):
SELECT COUNT(*) AS CNT FROM SEOCLASS WHERE CLSNAME LIKE 'Z%' OR CLSNAME LIKE 'Y%'
NOTE: The SEOINTERF table does NOT exist in S/4HANA. Use TADIR instead:
SELECT COUNT(*) AS CNT FROM TADIR WHERE PGMID = 'R3TR' AND OBJECT = 'INTF' AND OBJ_NAME LIKE 'Z%'
Then separately for Y:
SELECT COUNT(*) AS CNT FROM TADIR WHERE PGMID = 'R3TR' AND OBJECT = 'INTF' AND OBJ_NAME LIKE 'Y%'
Sum both counts.
CRITICAL: The TRDIR table contains ALL program types (reports, includes, class pools, etc.). Using a raw count is very misleading since includes (SUBC='I') dominate the count. Always break down by SUBC field:
SELECT SUBC, COUNT(*) AS CNT FROM TRDIR WHERE NAME LIKE 'Z%' OR NAME LIKE 'Y%' GROUP BY SUBC ORDER BY CNT DESCENDING
SUBC values: '1'=Executable Reports, 'I'=Includes, 'M'=Module Pools, 'S'=Subroutine Pools, 'K'=Class Pools, 'J'=Interface Pools, 'X'=XSLT Programs.
In the final report, present these as separate line items:
Omit class pools (K) and interface pools (J) from the report since those are already counted under Classes and Interfaces.
SELECT COUNT(*) AS CNT FROM TFDIR WHERE FUNCNAME LIKE 'Z%' OR FUNCNAME LIKE 'Y%'
SELECT COUNT(*) AS CNT FROM TLIBG WHERE AREA LIKE 'Z%' OR AREA LIKE 'Y%'
SELECT COUNT(*) AS CNT FROM DD02L WHERE TABNAME LIKE 'Z%' AND TABCLASS = 'TRANSP' AND AS4LOCAL = 'A'
Then separately for Y:
SELECT COUNT(*) AS CNT FROM DD02L WHERE TABNAME LIKE 'Y%' AND TABCLASS = 'TRANSP' AND AS4LOCAL = 'A'
Sum both counts.
SELECT COUNT(*) AS CNT FROM DD02L WHERE TABNAME LIKE 'Z%' AND TABCLASS = 'INTTAB' AND AS4LOCAL = 'A'
Then separately for Y and sum.
SELECT COUNT(*) AS CNT FROM DD04L WHERE ROLLNAME LIKE 'Z%' AND AS4LOCAL = 'A'
Then separately for Y and sum.
SELECT COUNT(*) AS CNT FROM DD01L WHERE DOMNAME LIKE 'Z%' AND AS4LOCAL = 'A'
Then separately for Y and sum.
SELECT COUNT(*) AS CNT FROM DD40L WHERE TYPENAME LIKE 'Z%' AND AS4LOCAL = 'A'
Then separately for Y and sum.
SELECT COUNT(*) AS CNT FROM DDDDLSRC WHERE DDLNAME LIKE 'Z%'
Then separately for Y and sum.
SELECT COUNT(*) AS CNT FROM T100A WHERE ARBGB LIKE 'Z%' OR ARBGB LIKE 'Y%'
SELECT COUNT(*) AS CNT FROM TSTC WHERE TCODE LIKE 'Z%' OR TCODE LIKE 'Y%'
Shows how heavily the system extends SAP standard:
SELECT COUNT(*) AS CNT FROM TADIR WHERE PGMID = 'R3TR' AND OBJECT = 'ENHO' AND (OBJ_NAME LIKE 'Z%' OR OBJ_NAME LIKE 'Y%')
SELECT COUNT(*) AS CNT FROM TADIR WHERE PGMID = 'R3TR' AND OBJECT = 'NROB' AND (OBJ_NAME LIKE 'Z%' OR OBJ_NAME LIKE 'Y%')
NOTE: Some queries may fail on specific systems (missing tables, authorization). If a query fails, record the count as "N/A" and continue with the rest.
This is the most valuable section. Get object counts per custom package.
CRITICAL: The column OBJECT is a reserved keyword in ABAP SQL. Do NOT alias it (e.g., OBJECT AS OBJ_TYPE will cause a parser error Unknown column name "O"). Use the column name OBJECT directly without alias.
SELECT DEVCLASS, OBJECT, COUNT(*) AS OBJ_COUNT
FROM TADIR
WHERE DEVCLASS LIKE 'Z%'
AND PGMID = 'R3TR'
GROUP BY DEVCLASS, OBJECT
ORDER BY DEVCLASS ASCENDING
Use displayMode: "internal" with a large enough rowRange (start: 0, end: 1000) and maxRows: 5000.
Note: We no longer filter by specific OBJECT types in the WHERE clause — instead retrieve all R3TR objects and filter/pivot in post-processing. This avoids issues with long IN() lists and captures all object types.
Then run the same for Y packages:
SELECT DEVCLASS, OBJECT, COUNT(*) AS OBJ_COUNT
FROM TADIR
WHERE DEVCLASS LIKE 'Y%'
AND PGMID = 'R3TR'
GROUP BY DEVCLASS, OBJECT
ORDER BY DEVCLASS ASCENDING
Pivot the results into a table with columns: | Package | Classes | FMs | Reports | DD Objects | CDS | Interfaces | Other | Total |
Where "DD Objects" = sum of TABL + DTEL + DOMA + TTYP + VIEW + ENQU + SHLP for that package.
Sort by Total descending. Show top 30 packages.
Shows when custom development started and when the most recent object was created:
SELECT MIN( CREATED_ON ) AS OLDEST, MAX( CREATED_ON ) AS NEWEST
FROM TADIR
WHERE (OBJ_NAME LIKE 'Z%' OR OBJ_NAME LIKE 'Y%')
AND PGMID = 'R3TR'
AND CREATED_ON <> '00000000'
Objects changed but never activated — a code quality smell:
SELECT COUNT(*) AS CNT FROM DD02L WHERE (TABNAME LIKE 'Z%' OR TABNAME LIKE 'Y%') AND AS4LOCAL = 'M'
SELECT COUNT(*) AS CNT FROM DD04L WHERE (ROLLNAME LIKE 'Z%' OR ROLLNAME LIKE 'Y%') AND AS4LOCAL = 'M'
AS4LOCAL = 'M' means modified/inactive. Sum the counts across DD02L and DD04L for a rough inactive object count. If the count is high relative to active objects, it's a quality concern worth noting.
SELECT AS4USER, COUNT(*) AS TR_COUNT
FROM E070
WHERE AS4DATE >= '<CALCULATE: today minus 90 days, format YYYYMMDD>'
AND STRKORR <> ''
GROUP BY AS4USER
ORDER BY TR_COUNT DESCENDING
Date calculation: You must compute the date yourself. Today's date minus 90 days, formatted as YYYYMMDD (e.g., 20251205 for Dec 5, 2025). ABAP SQL dates are stored as YYYYMMDD strings.
Use maxRows: 100, rowRange: {start: 0, end: 50}.
SELECT COUNT(*) AS TOTAL
FROM E070
WHERE AS4DATE >= '<90 days ago YYYYMMDD>'
AND STRKORR <> ''
SELECT DATUM, COUNT(*) AS DUMP_COUNT
FROM SNAP
WHERE DATUM >= '<CALCULATE: today minus 30 days, format YYYYMMDD>'
GROUP BY DATUM
ORDER BY DATUM ASCENDING
CRITICAL: The SNAP table in S/4HANA does NOT have a FESSION (or SEESSION) field for error type. The S/4HANA SNAP table only contains: DATUM, UZEIT, AHOST, UNAME, MANDT, MODNO, SEQNO, XHOLD, and FLIST01-08 (text blobs).
Use the SNAP_ADT table instead — it has a structured RUNTIME_ERROR field with the error type name:
SELECT RUNTIME_ERROR, COUNT(*) AS CNT
FROM SNAP_ADT
WHERE DATUM >= '<30 days ago YYYYMMDD>'
GROUP BY RUNTIME_ERROR
ORDER BY CNT DESCENDING
Use maxRows: 20, rowRange: {start: 0, end: 10}.
SELECT COUNT(*) AS CNT FROM SEOCLASS WHERE CLSNAME LIKE 'Z%TEST%' OR CLSNAME LIKE 'Y%TEST%' OR CLSNAME LIKE 'ZCL%TEST%' OR CLSNAME LIKE 'ZCL_TEST%'
NOTE: SNAP table may not be accessible due to authorization. On S/4HANA, the SNAP table has a simplified structure — use SNAP_ADT for error type breakdowns instead. If both SNAP and SNAP_ADT queries fail, skip the health section and note "Dump data unavailable — likely authorization restriction."
From the package breakdown data collected in Step 3, categorize packages by SAP functional area.
Use your own knowledge to categorize: Look at package names, their descriptions (if available), and the types of objects they contain. Common patterns:
Group packages into these areas and calculate percentages.
Use execute_data_query with displayMode: "ui" and data parameter (direct data input) to create the final report as a structured table.
Create ONE comprehensive display with these sections as a data table:
Title: "System Personality Report: {connectionId}"
Build a summary data table with columns: | Category | Metric | Value | |----------|--------|-------|
Rows should include:
After collecting all data, write a 5-20 sentence narrative paragraph summarizing the system's personality. Include:
Present this narrative to the user as part of your response text, alongside the data table.
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).
data-ai
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.
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.