open-steamgate
An ABAP application server you clone and run on your own machine: transpiled ABAP serving classic /IWBEP/ OData v2 to Fiori over a local database, with no SAP system attached.
Classic Gateway work needs a system to run on: a SEGW project, a _MPC_EXT and _DPC_EXT pair, and a gateway that calls them. This cross-compiles that ABAP (Gateway classes, CDS views, AMDP methods, reports) and runs it against a local database, serving OData to Fiori elements, letting Eclipse edit it over ADT and answering SAP GUI on the DIAG port. abaplintabaplintStatic analysis for ABAP that runs outside a system on serialised source in a repository, so ABAP checks run in a pull request and in CI before the code ever reaches a system.community org, abap and its transpiler@abaplint/transpilerTranspiles ABAP 7.02 syntax to ES6 JavaScript, so ABAP code and its unit tests run on Node.js in CI without an ABAP system, with optional SQLite, PostgreSQL, Snowflake or SAP HANA drivers.community org, abap turn the ABAP into something that runs, the /IWBEP/ interfaces come from open-abap-odataopen-abap-odataA set of OData and Gateway shims in ABAP that serve services built the SEGW way, from a model provider and a data provider class, on Node.js and in "Steampunk".community org, abap, and Open SQL goes through an eleven-method seam onto sql.js, SQLiteSQLiteAn embedded SQL database engine used as a selectable local cache store by CAP caching plugins., DuckDB, PostgreSQLPostgreSQLA relational database. For CAP it is the production database when the answer is not HANA, reached through an adapter that translates CDS queries into its SQL. or SAP HANASAP HANASAP’s relational database platform, which stores application data and executes SQL and SQLScript in the database, available on-premise and as the managed service SAP HANA Cloud.sap official, btp. It is the layer under an ERP rather than an ERP: the language runtime, the dictionary, Open SQL, the ICF service tree, the OData gateway, CDS, AMDP, the LUW, screens, jobs, daemons. A system is a directory of files, the ABAP a repository and the tables abapGit TABU JSON, so a whole one can be branched and thrown away; it starts from a browser page, a DockerDockerA container engine that packages software with the tools it needs and runs it isolated from the host. Things here that ship as an image need it installed, so the reader installs the engine rather than each of the command line tools inside the container. compose stack, one Bun binary, a VS Code extension or npm start in the clone.
Facts
Where it sits
Who is behind it
In the atlas: maintains 6, contributes to 12@oiseemaintainerCodexContributes to this
In the atlas: contributes to 1@codex1 contributor
Before choosing this
Conditions
PracticalFunctional boundary
Not a system to run a business application on: there is no business application in it, and what it implements of the language, the dictionary and Gateway is a stated subset of each. It is a clean-room reimplementation of the /IWBEP/ interfaces that bundles no SAP source and no standard DDIC, so a service that reads standard objects has nothing to read, and ANORMALIES.md records every place the runtime differs from SAP before any workaround is written.
What it declares
Every artifact
- Type
- App
- Origin
- Independently maintained
- Runtime
- Node.js
As an app
- Where it runs
- On your own server or machine
- Distributed through
- Container imageabapGitBinary download
For OData
- Protocols
- odata-v2
Connections
Running the whole stack on a laptop against real bindings
Exposing data and operations through OData
Testing application logic, with test doubles for its dependencies
Managed PostgreSQL from the hyperscaler via a BTP service binding
SAP's Eclipse plugins for ABAP development over ADT
SAP's relational database platform, on-premise and in HANA Cloud
Transpiles ABAP to JavaScript to run on Node.js
Git client written in ABAP that runs inside the system
A container engine that packages software with the tools it needs and runs it isolated from the host. Things here that ship as an image need it installed, so the reader installs the engine rather than each of the command line tools inside the container.
A relational database. For CAP it is the production database when the answer is not HANA, reached through an adapter that translates CDS queries into its SQL.
SAP's relational database platform, on-premise and in HANA Cloud
An embedded SQL database engine used as a selectable local cache store by CAP caching plugins.
Download
Where it sits in your app
Download
hdbIf STG_DB=hana selects HANA as the backendnpm run transpiler:pin builds the pinned transpiler, CLI, runtime and core for a warm local buildpostgres.yml compose file that starts oneIf the PostgreSQL backend is chosennpm run segw:zip builds an abapGit offline repository to reach a real systemIf objects are moved between this and a real ABAP systemREADME
quoted from oisee/open-steamgate under MIT, readopen-steamgate
An ABAP application server you can clone.
Part of the steampunk family: vsp (ADT ↔ MCP), abapiti (TypeScript and WASM to ABAP), open-rfc-go (RFC) and open-diag-go (SAP GUI DIAG).
TL;DR — run it
| way | do this | then open |
|---|---|---|
| Browser, now | nothing to install | oisee.github.io/open-steamgate/main/app/flp.html |
| Docker | git clone https://github.com/oisee/open-steamgate && cd open-steamgate && docker compose -p osd11 -f docker/compose.sqlite.yml up -d | http://localhost:8011/app/flp.html |
| Portainer | Stacks → Add stack → Web editor, paste one YAML block from docs/spin.md (SQLite, DuckDB, PostgreSQL or HANA Express) | http://<host>:8011/app/flp.html |
| One binary (Bun) | download osd-linux-x64 / osd-linux-arm64 / osd-darwin-arm64 / osd-darwin-x64 / osd-windows-x64.exe / osd-windows-arm64.exe from Releases, then mv osd-linux-x64 osd && chmod +x osd && ./osd up | http://localhost:3030/ |
| VS Code | install open-steamgate: local ABAP server, or the .vsix from Releases via Extensions: Install from VSIX…; then run osd: Start | the OSD tree in VS Code |
| Node, from source | npm ci && npm run bootstrap && npm start (Node 22.18+ or 24) | http://localhost:3030/ |
| Your report as a CLI tool | node tools/gogen/osabap.mjs zmy_report.prog.abap, then tools/gogen/.out/osabap (needs Go 1.26) | a native binary, no server (below) |
Each release also carries sqlite.yml, duckdb.yml and postgres.yml; start one with docker compose -f sqlite.yml up -d. ./osd doctor checks a downloaded binary.
🎉 gogen compiles itself (self-hosting step 4, 2026-10-20)
gogen, the ABAP-to-Go compiler in this tree, is written in JavaScript. abapiti compiled gogen itself into Go, and that Go-built gogen emits the same Go as gogen on Node, byte for byte, for the reference class. The output builds and passes its unit test:
step4: build=ok run=ok cmp=equal ref=b90648781967b2cf out=b90648781967b2cf
PASS: ZCL_GOGEN_T_RUNTIME/LTCL_RUNTIME/ELAPSED
Measured on 0b925177 in main with abapiti 3115e569. About twenty full
runs, about fifteen fixes on each side, Node output unchanged by every one:
the story and both SHAs.
The trap-by-trap log before it is in
docs/self-hosting-step4-traps.md.
What it is
open-steamgate (OSD) cross-compiles real ABAP — _MPC_EXT / _DPC_EXT
Gateway classes, CDS views, AMDP methods, reports — and runs it against a local
database. It serves OData to Fiori Elements, lets Eclipse edit it over ADT, and
answers SAP GUI on the DIAG port. No SAP system is attached.
It is the layer under an ERP, not an ERP. The language runtime, the dictionary, Open SQL, the ICF service tree, the OData gateway, CDS, AMDP, LUW, screens, jobs and daemons are all here. There is no business application: no finance, no logistics. Everything runs as a subset: of the language, of the dictionary, and of Gateway (classic code-based SEGW).
Everything is a file. The ABAP is a repository, the tables are abapGit TABU JSON, a build is an immutable generation addressed by the hash of its inputs, and the database sits behind an eleven-method seam: sql.js, SQLite, DuckDB, PostgreSQL or HANA. So a whole system can be copied, branched, compared and thrown away.
The name: vsp (vibing-steampunk) → steamgate. Gate is the SAP Gateway,
the /IWBEP/ framework whose runtime this project reimplements.
The ways to run it, in a sentence each
- Browser. The transpiled ABAP, the OData runtime and SQLite run in a service worker on your machine; no server answers anything.
- Docker.
ghcr.io/oisee/open-steamgate, tagsshowcase-draft(with the demo packs) anddraft(core), multi-arch amd64 and arm64. The arm64 image also runs on a Raspberry Pi 4 (docs/spin.md). - Binary. One self-contained Bun executable per platform. It copies its
system into your user data directory on first start and layers your own
folders over it with
osd up --layer <folder>. - VS Code. The OSD tree, F8 data preview, ABAP Unit in the Test Explorer,
debugging, and a
.httpCodeLens that finds the DPC method behind a request.
For warm local development (OSD_WARM=1 STG_DEV=1 npm start), run
npm run transpiler:pin after npm ci. It builds the libs.lock.json pin in
$HOME/.cache/osd/transpiler-<ref> and links transpiler, CLI, runtime and core;
a verified build is reused. Override the persistent location with TRANSPILER;
temporary directories and session scratchpads are refused. Startup and
osd doctor print a prominent install hint if warm capabilities are missing.
See warm setup.
The launchpad in the browser build:
| tile | what it is |
|---|---|
| Travels, Bookings | Fiori Elements V2 list report and object page over a SEGW-shaped _MPC_EXT / _DPC_EXT pair |
| Flight analytics | an analytical list page over a CDS cube ($select → GROUP BY) |
| SEGW | the Service Builder as an app, editing the project tree |
| Vivid Vibes · Zork · SAP LSD | pages an ABAP class writes: WebGL and audio over APC, a Z-machine in ABAP, a light-show replayed as SAP GUI screens |
The first visit installs the worker; after that the app works offline. Private windows usually refuse service workers.

What it looks like
Every pixel below is served by transpiled ABAP over SQLite. SAPUI5 1.120 is loaded from SAP's CDN, unchanged.




node scripts/capture-docs-shots.mjs takes these pictures while npm start is running.
Where it stands, 2026-09-30
0.3 beta was released on 2026-09-29 (vscode-v0.2.1307); 0.4 is in progress.
AGENDA.md records every decision, docs/backlog/
is the open list, and ANORMALIES.md records every place the
runtime differs from SAP, written down before any workaround.
| area | what works | docs |
|---|---|---|
| Gateway, OData v2 | URL parser, $filter → SELECT-OPTIONS with every io_tech_request_context facet, $batch with changesets, navigation, $expand, deep insert, function imports, value helps, MERGE, create below a parent, media entities ($value), service-to-service calls. All of it is ABAP behind one if_http_extension | docs/prior-art.md |
| SEGW | IWPR ↔ _MPC/_DPC generation with RFC/BOR and search-help mappings; one YAML → a whole project (stg-compile); the project tree in 53 SEGW-shaped tables with byte-identical export; the generator ported to ABAP; the Service Builder as a Fiori app | docs/stg-compile.md, docs/segw-editor.md |
| SADL and CDS | CDS projections, @OData.publish, writable projections (including through a chain of views), analytical cubes, virtual elements | docs/cds-publish.md, docs/cds-writes.md |
| AMDP and SQLScript | An AMDP body runs where it belongs, on HANA, or portably on DuckDB. The SQLScript front end lowers to three dialects and refuses a silently wrong translation | docs/amdp-in-hana.md, docs/portable-amdp-report.html |
| ADT façade | Eclipse ADT and vsp treat OSD as a system: package tree, edit, save, activate, ABAP Unit, F8 preview, create/delete. Every change lands on the git tree as abapGit files. It works over HTTPS (Cloud Project) and over RFC (Custom Application Server) through the built-in JavaScript bridge | docs/adt-facade.md, docs/adt-over-rfc.md |
| Classic screens | SAP Easy Access, SE16, ST05 and an editor, served by ABAP on the paths the originals use | docs/webgui.md |
| Jobs and daemons | JOB_OPEN/SUBMIT/CLOSE with standard signatures, SUBMIT … VIA JOB … WITH … IN, multi-step jobs, durable keys, tail events, a doctor. ABAP daemons: dialog-step queue, PCP, timers, AMC | docs/abap-daemons.md |
| Files | OPEN / READ / TRANSFER / DELETE DATASET behind a sandbox: deny by default, allowed roots, no escape through .., symlinks or a swapped directory. A streaming zip reader in ABAP (own inflate, bounded memory, CRC-checked) runs the same on a system | docs/dataset.md, docs/zip-stream.md |
| OSGo: ABAP → Go | gogen compiles the system to Go: the whole OSD as one Go binary (841 classes at #251, the demo answers), a report as a native command-line tool with its selection screen (osabap), ABAP Unit on Go compared method by method with Node, and sXML about 27× faster than on Node on a 10 MiB benchmark (#275) | tools/gogen/README.md |
| Databases | sql.js, SQLite file (WAL), DuckDB, PostgreSQL and HANA behind one seam; FOR ALL ENTRIES sent in blocks, similar to the kernel | docs/db-backends.md |
| Instruments | Comparing two systems (responses, SQL at the seam, a branch of a whole system), .http regression cases with a frozen clock, and a frame-by-frame oracle against a real system | docs/regression-http-cases.md, docs/frame-comparison.md |
| Packs and delivery | A pack is a directory (osd-pack.json: ABAP, tables, rows, pages, tiles) layered over the tree. There is one Bun binary (build/osd), a relocatable release directory, Docker for amd64 and arm64, the browser preview on GitHub Pages, and a CI that gates every publication on the tag's tests | docs/using-osd.md, docs/preview-deployments.md |
| Tests | npm test = transpile + abaplint + ABAP Unit + mocha over the wire, plus Playwright for the apps. A unit run fails when a test class in the tree did not run |
ABAP as a language for command-line tools
gogen compiles ABAP to Go (OSGo; building needs Go 1.26). Two hosts come out of it.
A report becomes a native command. osabap takes a classic executable
report and builds one self-contained binary with no server, no database and no
SAP system (npm run osgb -- <report> is the same command: osabap is the
compiler, OSGB the binary it makes). The compiler itself runs on Node; the
binary does not. The selection screen is the command-line contract:
node tools/gogen/osabap.mjs tools/gogen/apps/hello/zhello.prog.abap # -> tools/gogen/.out/osabap
tools/gogen/.out/osabap Alice # parameters in declaration order
tools/gogen/.out/osabap --name Alice --loud --s-tag one --s-tag two # a repeated select-option = I/EQ rows
tools/gogen/.out/osabap -params @arguments.json # or all of it as JSON
tools/gogen/.out/osabap # no arguments, a terminal: the selection screen as a TUI
tools/gogen/.out/osabap -sapgui # the same screen to a real SAP GUI over DIAG, on 127.0.0.1
GOOS=windows GOARCH=arm64 node tools/gogen/osabap.mjs report.prog.abap # cross-compiles
The usual lifecycle runs: INITIALIZATION, the selection-screen events,
START-OF-SELECTION, WRITE to stdout. CL_GUI_FRONTEND_SERVICES maps to the
local file system. OPEN DATASET works inside the roots you allow
(-allow-read ./in -allow-write ./out). Build with --read-params P_FILE,P_CONFIG
to grant reads to the files or directories the user supplies, or --read-lists P_DEPS
to also grant the paths listed in that file (relative to its directory).
Supplying a list means the user vouches for every path in it, including absolute
and ../ entries; a list the report wrote earlier is still the user's choice to pass.
The host grants these reads before ABAP runs; -no-default-reads disables them,
and writes still require explicit permission. A report with tables of its own
(their .tabl.xml beside the report) keeps its rows in the SQLite file
-db notes.db names, created with those tables when missing; 12 of the 18
Open SQL forms of tools/gogen/apps/sql-corpus compile so far. The samples are in
tools/gogen/apps/, and the details are in
docs/osabap-native.md.
The whole system in Go. node tools/gogen/osgo.mjs builds tools/gogen/.out/osgo, the
complete OSD (ICF, Gateway, the apps, SQLite) as one Go binary. The same ABAP
Unit tests run on Node and on Go and are compared method by method; closing
the gap is the work before 0.4.
Generated classes in CI. The same folder of *.clas.abap and
*.clas.testclasses.abap can run on either runtime:
npm run osgo:unit -- ./generated --json --class ZCL_EXAMPLE
npm run osgjs:unit -- ./generated --json --class ZCL_EXAMPLE
Both commands read the immediate directory, stage missing class metadata in a
temporary folder, preserve existing .clas.xml, reject source lines longer than
255 characters with file:line, and report overrides on stderr and in JSON.
--class accepts multiple owner names; omit it to run all owners in the folder.
They work from any cwd when invoked by the checkout's absolute script path.
JSON contains rows (class, testclass, method, status, message),
totals (success, failure, not_compiled, error, tests) and overrides.
Exit codes are 0 for at least one test and all SUCCESS, 1 for assertion FAILURE,
2 for NOT_COMPILED/ERROR/SKIPPED, and 3 when there are no tests.
The JS command requires installed Node dependencies and synced libraries. It
copies the configured checkout layers into a disposable checkout, excluding all
content packs (including OSD_PACKS), runs the generators and transpiles
the whole tree (roughly 20 seconds for transpilation), then runs ABAP Unit
only for the selected owners, including class and instance lifecycle hooks.
This command still builds the whole tree; the local warm path can use the
pinned transpiler's only option.
For large generated folders, use Node with a larger heap and a private SQLite
file instead of in-memory sql.js:
NODE_OPTIONS=--max-old-space-size=12288 npm run osgjs:unit -- ./generated --db file --json
--db sqlite (the default) uses sql.js; --db file creates its database in the
invocation's staging directory and removes it on completion. Inherited
STG_DB_PATH cannot select another database. NODE_OPTIONS reaches the scanner,
transpiler, generators and Unit child; choose a heap limit that fits the host.
ABAPiti's public osd-up.sh
runs the pinned JS binary with a private
STG_DB_PATH, and osd-m1.sh
deploys generated classes through ADT. Its workflow
uses the binary, not a Node heap flag; this checkout runner mirrors that file
isolation and documents the extra heap needed to build a large folder at once.
The recorded measurements use Node v26.9.0, the checkout's existing local
runtime/transpiler 2.13.93 build and its resolved core 2.120.59.
Each invocation owns its output and database; parallel runs leave the input
folder, output/ and build/live untouched. The Go command additionally accepts
--jobs N (default 4) and needs Go 1.26.
The generated support page inventories statements, built-ins,
elementary declarations and conversions, joins per-class results for both runtimes,
and lists kernel compatibility warnings. It is evidence from a corpus, not a specification.
Regenerate from a read-only ABAPiti checkout with the commands below; flatten the
split fixtures as the ABAPiti CI does, and repeat the two runtime commands for
any extra qjs, mono and int8 folders under .local/abapiti. Retain JSON from partial runs so passing and failing classes keep their results.
Declare full-folder runs using --runs <manifest.json>; each array entry has
folder (input basename), runtime (osgo or osgjs) and file (relative to
that manifest), or reason for a crash without class results. Full-folder runs
covering every test owner with all rows SUCCESS credit helper classes as
exercised by their tests; partial
runs with failures leave helpers not measured; missing test owners leave helpers
and omitted owners not measured. Harness crashes, OOM and setup failures before
any class are not measured with a reason; fails applies only to test results.
Manifest entries may include wallSeconds and peakRssKiB (GNU time maximum
resident set size across the command and its children, including the build).
Both runners snapshot provenance into their JSON: backend, heap override,
installed runtime/transpiler and database versions, Node, and Go for osgo.
A manifest's provenance can preserve those settings for a crash without JSON
or an older run; it takes precedence over the result's snapshot. Missing metadata
is printed as "not recorded". Regeneration reads the snapshots, so changes to
installed tools or NODE_OPTIONS cannot rewrite historical provenance.
The file backend uses node:sqlite, not better-sqlite; its SQLite version comes
from the installed Node binary. Harness rows carry source: "harness"; assertion
messages never determine provenance.
Plain --osgo/--osgjs files give per-class
evidence only, which is safe for runs restricted with --class.
Editors can import kernelWarnings and KERNEL_FORMS from
tools/osd-kernel-compat.mjs, then call kernelWarnings([{file, source}]) on
unsaved buffers. Each finding includes file, line, form, message and
supportAnchor, a stable link into this page; KERNEL_FORMS lists the fixed
anchors and titles. Show findings as Error diagnostics by default while allowing
the code to run. osg.kernelStrict: "refuse" opts into refusal, matching the
unit runners' --kernel-strict mode.
mkdir -p .local/support-work/go-cache .local/support-work/go-tmp .local/support-work/go-path
export GOPATH="$PWD/.local/support-work/go-path" GOMODCACHE="$PWD/.local/support-work/go-mod"
export GOTOOLCHAIN=go1.26.0 GOFLAGS=-buildvcs=false
export GOCACHE="$PWD/.local/support-work/go-cache" GOTMPDIR="$PWD/.local/support-work/go-tmp"
export ABAPITI_TEST_OUT="$PWD/.local/support-work/corpus"
OSD_HEAVY_RANGE=50-59 tools/osd-heavy.sh bash -c 'cd .local/abapiti-src && go test ./wasm -run "^TestOSD_EmitUnitClasses$" -count=1'
cp .local/support-work/corpus/TestOSD_EmitUnitClasses/split/*.abap .local/support-work/corpus/TestOSD_EmitUnitClasses/
rm -r .local/support-work/corpus/TestOSD_EmitUnitClasses/split
OSD_HEAVY_RANGE=50-59 tools/osd-heavy.sh bash -c 'timeout 1200 npm run -s osgo:unit -- .local/support-work/corpus/TestOSD_EmitUnitClasses --json > .local/support-work/osgo-corpus.json'
OSD_HEAVY_RANGE=50-59 tools/osd-heavy.sh bash -c '/usr/bin/time -f "wallSeconds=%e peakRssKiB=%M exit=%x" -o .local/support-work/osgjs-corpus.time timeout 1800 env NODE_OPTIONS=--max-old-space-size=12288 node tools/osgjs-unit.mjs .local/support-work/corpus/TestOSD_EmitUnitClasses --db file --json > .local/support-work/osgjs-corpus.json 2> .local/support-work/osgjs-corpus.err'
npm run osg:support -- .local/support-work/corpus/TestOSD_EmitUnitClasses --osgo .local/support-work/osgo-corpus.json --osgjs .local/support-work/osgjs-corpus.json --out docs/osg-support.md --json .local/support-work/support.json
# Append extra input folders and partial or successful --osgo/--osgjs files.
# To credit helpers, create a full-folder manifest (paths relative to this JSON):
# Run each extra folder on both runtimes with the same commands and timeout,
# writing osgo-{int8,mono,qjs}.json and osgjs-{int8,mono,qjs}.json.
# When remeasuring, update wallSeconds/peakRssKiB from each .time file.
# If a run has no JSON or only setup ERROR rows, retain its crash/setup reason.
# The committed page uses the following full-folder result files:
cat > .local/support-work/runs.json <<'JSON'
[
{
"folder": "TestOSD_EmitUnitClasses",
"runtime": "osgo",
"file": "osgo-corpus.json",
"provenance": {
"database": "modernc.org/sqlite",
"heap": "Node default (no --max-old-space-size override)",
"versions": {
"@abaplint/runtime": "2.13.93",
"@abaplint/transpiler": "2.13.93",
"Node": "v26.9.0",
"Go": "go1.26.0"
}
}
},
{
"folder": "TestOSD_EmitUnitClasses",
"runtime": "osgjs",
"file": "osgjs-corpus.json",
"wallSeconds": 96.27,
"peakRssKiB": 2590272,
"provenance": {
"database": "--db file (node:sqlite)",
"heap": "--max-old-space-size=12288 MiB",
"versions": {
"@abaplint/runtime": "2.13.93",
"@abaplint/transpiler": "2.13.93",
"Node": "v26.9.0",
"node:sqlite (SQLite)": "3.53.4"
}
}
},
{
"folder": "int8",
"runtime": "osgo",
"file": "osgo-int8.json",
"provenance": {
"database": "modernc.org/sqlite",
"heap": "Node default (no --max-old-space-size override)",
"versions": {
"@abaplint/runtime": "2.13.93",
"@abaplint/transpiler": "2.13.93",
"Node": "v26.9.0",
"Go": "go1.26.0"
}
}
},
{
"folder": "int8",
"runtime": "osgjs",
"file": "osgjs-int8.json",
"wallSeconds": 23.06,
"peakRssKiB": 1371808,
"provenance": {
"database": "--db file (node:sqlite)",
"heap": "--max-old-space-size=12288 MiB",
"versions": {
"@abaplint/runtime": "2.13.93",
"@abaplint/transpiler": "2.13.93",
"Node": "v26.9.0",
"node:sqlite (SQLite)": "3.53.4"
}
}
},
{
"folder": "mono",
"runtime": "osgo",
"file": "osgo-mono.json",
"provenance": {
"database": "modernc.org/sqlite",
"heap": "Node default (no --max-old-space-size override)",
"versions": {
"@abaplint/runtime": "2.13.93",
"@abaplint/transpiler": "2.13.93",
"Node": "v26.9.0",
"Go": "go1.26.0"
}
}
},
{
"folder": "mono",
"runtime": "osgjs",
"file": "osgjs-mono.json",
"wallSeconds": 511.18,
"peakRssKiB": 1636204,
"provenance": {
"database": "--db file (node:sqlite)",
"heap": "--max-old-space-size=12288 MiB",
"versions": {
"@abaplint/runtime": "2.13.93",
"@abaplint/transpiler": "2.13.93",
"Node": "v26.9.0",
"node:sqlite (SQLite)": "3.53.4"
}
}
},
{
"folder": "qjs",
"runtime": "osgo",
"file": "osgo-qjs.json",
"provenance": {
"database": "modernc.org/sqlite",
"heap": "Node default (no --max-old-space-size override)",
"versions": {
"@abaplint/runtime": "2.13.93",
"@abaplint/transpiler": "2.13.93",
"Node": "v26.9.0",
"Go": "go1.26.0"
}
}
},
{
"folder": "qjs",
"runtime": "osgjs",
"file": "osgjs-qjs.json",
"wallSeconds": 1800.45,
"peakRssKiB": 8879396,
"reason": "30-minute timeout after a successful build with the larger heap and private file-backed SQLite; no class results; exit 124",
"provenance": {
"database": "--db file (node:sqlite)",
"heap": "--max-old-space-size=12288 MiB",
"versions": {
"@abaplint/runtime": "2.13.93",
"@abaplint/transpiler": "2.13.93",
"Node": "v26.9.0",
"node:sqlite (SQLite)": "3.53.4"
}
}
}
]
JSON
# Exact command for the committed page:
npm run osg:support -- .local/support-work/corpus/TestOSD_EmitUnitClasses .local/abapiti/int8 .local/abapiti/mono .local/abapiti/qjs --runs .local/support-work/runs.json --out docs/osg-support.md --json .local/support-work/support.json
# Replace --out with --check docs/osg-support.md to compare without writing.
The header identifies generator content by combining the git blob hashes of
tools/osg-support.mjs and tools/osd-kernel-compat.mjs into a short SHA-256 id,
and lists both files and their blob hashes. The default date comes from the
external ABAPiti commit, which is immutable; rebasing or squash-merging OSG
therefore leaves the page and its exact --check comparison unchanged.
To override metadata explicitly, append --osg-rev <hex-id> --date <yyyy-mm-dd>.
Architecture
A generation is one transpiled system named by the hash of its inputs (the
layers of abap_transpile.json, the packs, and the generated gen/). Moving
the live pointer to another generation recycles the work processes, and moving
it back is a rollback. The browser build bundles the same output into a service
worker. More: docs/generations.md,
docs/architecture-split.md.
Run it
Node 22.18+ (major 22) or Node 24. 22.18 is the first Node 22 that strips TypeScript types without a flag; the gogen typing work moves tools to .ts.
git clone https://github.com/oisee/open-steamgate && cd open-steamgate
npm ci
npm run bootstrap # pinned library clones + packs, then gen/
npm start # http://localhost:3030/ is the launchpad
npm run dev # the same, rebuilding as you edit ABAP
npm test # abaplint + ABAP Unit + mocha over the wire
npm run e2e:install && npm run e2e # Playwright
npm run web:preview && npm run web:serve # the browser-only build on :3031
npm run start:duckdb # on DuckDB (STG_DB_PATH=x.duckdb persists)
npm run unit:hana # on a real HANA
npm run binary && build/osd up # the workbench as one Bun binary
npm run vsix # the VS Code extension
HANA Express: running its image accepts SAP's developer licence, see
docs/amdp-in-hana.md. npm run bootstrap reads libs.lock.json: it clones the pinned libraries into
.local/lars/, fetches the packs and runs the first transpile.
Build on it
docs/using-osd.md is the working guide. In short:
- A service is one YAML file (
npm run stg:compile): SEGW without the GUI. An entity reads from a table, a CDS view, a function module, a search help, another service, or a hand-writtenGET_ENTITYSET. - OData from CDS needs one annotation:
@OData.publish: true. - Content comes as a pack: a directory with
osd-pack.json, dropped intopacks/, layered after the tree. A collision is reported with both files. - A real system is reached with a zip.
npm run segw:zipbuilds an abapGit offline repository, and a Fiori app goes as a BSP application with its ICF node (docs/a4h-deploy.md). - A worked example, as a book: osg-demo — The Airship Fleet / Флот дирижаблей builds one ABAP application on open-steamgate chapter by chapter, from a first class to OData, Fiori, CDS, jobs, osabap and abaplint in ABAP. Every chapter runs against a pinned open-steamgate tag; EPUB and PDF, English and Russian, are on the releases page.
Thanks
This is grown on Lars Hvam's work and would
not exist without it: abaplint and the
transpiler turn the ABAP into
something that runs, open-abap is the runtime
library under it, and abapGit is how code
gets in and out. Fixes go back upstream, one small PR each
(docs/upstream.md).
Family
- vsp / vibing-steampunk: MCP server and CLI for ADT, SAP-LZH decode, abapGit deploy-back.
- open-rfc-go: pure-Go NI / RFC / CPIC transport, used as an external oracle.
- sap-lsd, sap-tui: the DIAG light-show and the terminal viewer behind the LSD tile.
Protocol facts from two private siblings are summarised in
docs/layers-we-own.md.
Prior art
MIT unless noted; the evidence is in docs/prior-art.md.
abaplint/transpiler ·
open-abap/open-abap-odata (the /IWBEP/ interfaces; its licence is still unclear, so we use it as interfaces only) ·
abapGit ·
SAP/open-ux-odata (Apache-2.0, studied as the conformance reference, not a dependency) ·
larshp/hithub (the browser preview's recipe).
License
MIT — see LICENSE. This is a clean-room reimplementation of the
/IWBEP/ interfaces. It bundles no SAP source and no standard DDIC.
History
Other 3
Notes
open-steamgate 0.7.2118 (stable): VS Code extension for desktop and vscode.dev. Upload this file to the Marketplace by hand; it replaces 0.7.2117.
- Commit: dfa44b00fde6ff867a4fff389bd7d7224b8ad1ea (PR #835 head: the gear-gate launchpad logo split one element per line for BSP, and docs)
- Gear-gate icon and launchpad logo. Marked as a web extension (ExtensionKind workspace,ui,web; tag __web_extension). Browser entry, Fiori apps, media, lazy DuckDB-Wasm. No PreRelease property.
- Built locally with the marketplace profile, not through release.yml.
SHA-256 ef566fc43fde9b6c452fa816e2c8ee6e5243c4560845b0714763e3222c0d8388
Upload: Marketplace publisher oisee -> open-steamgate -> Update -> this .vsix.
Other 6
Notes
open-steamgate 0.7.2117: VS Code extension, desktop + vscode.dev (browser entry). Built for a manual Marketplace upload as the stable release.
- Commit: 2ee859c847ccdb834def597891d23da31b754464 (PR #835 head: #828 + #833 on main, plus the gear-gate launchpad logo and docs)
- Gear-gate icon and launchpad logo (2026-10-20)
- Marked as a web extension: ExtensionKind
workspace,ui,web, tag__web_extension - Browser entry
dist/web/extension.js, Fiori apps, media, lazy DuckDB-Wasm; packs: zork - Stable (no PreRelease property)
- Built locally with the marketplace profile (OSD_VSIX_PROFILE=marketplace OSD_VSIX_WEB=1 OSD_VSIX_PRERELEASE=0, pinned transpiler fork), not through release.yml: its tagged tests did not run on this exact commit; CI on #835 is in progress.
SHA-256
64b19f953df0b1768e57f0676b14d50e0405a457a7f972f4282af03fdb1df550Upload: Marketplace publisher page (oisee) -> open-steamgate -> Update -> this .vsix, or
npx @vscode/vsce publish --packagePath open-steamgate-0.7.2117.vsix.
Others providing
- launchpad-kpilaunchpad-kpiAn OData service and a one-method ABAP interface that put a number from an abap2UI5 app on a SAP Fiori launchpad tile.community org, abapPuts a number from an abap2UI5 app on a Fiori launchpad tilefrom ABAP
- com.sap.cds:cds-adapter-odata-v2com.sap.cds:cds-adapter-odata-v2The OData V2 protocol adapter for CAP Java, which the runtime serves natively once this beta module is on the classpath, so a V2 frontend keeps working without a change to the CDS model.sap official, capOData V2 protocol adapter built into the CAP Java runtimefrom CAP
- com.sap.cds:cds-adapter-odata-v4com.sap.cds:cds-adapter-odata-v4The OData V4 protocol adapter for CAP Java, auto-exposing every Application Service in the model at /odata/v4/<Service> without protocol code of its own, active by default in the CDS Maven Archetype.sap official, capOData V4 protocol adapter for CAP Java Application Servicesfrom CAP
- @cap-js-community/odata-v2-adapter@cap-js-community/odata-v2-adapterExposes a CAP service as OData V2 for clients that cannot move to V4.community org, capExposes a CAP service as OData V2from CAP
- odata-fwodata-fwA framework for building OData services in ABAP with each entity implemented as its own class, reusable across services, so a model change no longer forces the SEGW service to be regenerated.independent, abapABAP framework for OData services with one class per entityfrom ABAP
- @odatano/core@odatano/coreA CAP plugin that serves the Cardano blockchain as OData V4, giving enterprise-shaped access to a public chain, funded through Cardano Catalyst.independent, capCAP plugin serving the Cardano blockchain as OData V4from CAP
- @odatano/nightgate@odatano/nightgateIndexes the Midnight blockchain and submits transactions to it from CAP, exposed as OData V4, with command-line tools for schema deltas, key rotation and migration.independent, capCAP plugin indexing the Midnight blockchain, exposed as OData V4from CAP
- open-abap-odataopen-abap-odataA set of OData and Gateway shims in ABAP that serve services built the SEGW way, from a model provider and a data provider class, on Node.js and in "Steampunk".community org, abapOData and Gateway shims serving SEGW-style services on Node.jsfrom ABAP
- @root3287/cap-segw@root3287/cap-segwA CAP build tool that compiles a CDS service into the ABAP Model Provider and Data Provider classes a SAP Gateway SEGW project expects, for OData V4 by default or V2.independent, capCompiler from a CDS service to SEGW model and data provider classesfrom CAP
- @sap/cds@sap/cdsThe CAP Node.js runtime, which compiles the CDS model, serves the services declared in it, answers generic requests before any handler runs, and loads every cds-plugin.sap official, capCAP Node.js runtimefrom CAP
- OData Batch CreatorOData Batch CreatorBuilds the payload for an OData batch request from an uploaded $metadata XML file, generating sample data from the metadata rather than asking for it by hand.independent, abapBuilds OData batch request payloads from an uploaded $metadata filefrom ABAP
- abap2UI5 Playgroundabap2UI5 PlaygroundABAP in the editor on the left and the abap2UI5 app it builds on the right, both inside one browser tab: the framework is transpiled to JavaScript at build time and the class in the editor is compiled when Run is pressed.community org, abapIn-browser ABAP editor beside the abap2UI5 app it buildsfrom ABAP
- web-abap2UI5web-abap2UI5A build pipeline and the page it deploys: the abap2UI5 backend downported, transpiled to JavaScript and webpacked into one script that runs inside a browser tab, with no server and no SAP system behind it.community org, abapabap2UI5 transpiled to JavaScript and run in a browser tabfrom ABAP
- vite-plugin-cdsvite-plugin-cdsA CAP plugin that serves a Vite app from the app folder through cds watch, makes .cds files importable into the frontend build, and can polyfill enough of Node to run @sap/cds in the browser.independent, capServes a Vite app through cds watch and imports .cds filesfrom CAP
- com.sap.cds:cds-feature-dev-dashboardcom.sap.cds:cds-feature-dev-dashboardA browser dashboard for a running CAP Java service that shows and manages its messaging, resilience and multitenancy state while developing, open to users with the cds.Developer role.sap official, capBrowser dashboard for a running CAP Java service during developmentfrom CAP
- com.sap.cds:cds-maven-plugincom.sap.cds:cds-maven-pluginThe Maven plugin that runs CDS build steps in a CAP Java project: compiling the model, generating typed Java accessor interfaces and adding facets to an existing project.sap official, capMaven plugin running CDS build steps in a CAP Java projectfrom CAP
- @cap-js-community/common@cap-js-community/commonSix independent features for CAP services in one package: replication cache, migration check, rate limiting, a Redis client broker, a local HTML5 repository and a CDM builder.community org, capSix CAP features in one package, from replication cache to rate limitsfrom CAP
- abap_trial_dockerabap_trial_dockerShell scripts that build a Docker image from the SAP NetWeaver ABAP Developer Edition 7.52 SP04 installation files and run it as an unprivileged container, setting the stable hostname the installer wants.independent, abapScripts running the ABAP Developer Edition in Dockerfrom ABAP
- @neoimpulse/cap-js-bootstrap@neoimpulse/cap-js-bootstrapA command-line tool that starts a local CAP environment with several services and an AppRouter together from one command, documented in German and requiring Node 22 or newer.independent, capCLI starting several CAP services and an AppRouter locally togetherfrom CAP
- pokrakam/abapDevSysInitpokrakam/abapDevSysInitA single ABAP report that automates setting up a new ABAP Developer Edition or trial system, from the user profile and a GitHub RFC destination to fetching abapGit and pulling repositories.independent, abapABAP report setting up a new ABAP Developer Edition or trial systemfrom ABAP
- @sang2x/captools@sang2x/captoolsA CLI of eight CAP development commands aimed at Cloud Foundry workflows, shipped without a repository or README, whose binding step writes resolved VCAP_SERVICES into default-env.json.independent, capCLI of CAP development tools for Cloud Foundry workflowsfrom CAP
- @sap/ams-dev@sap/ams-devCompiles the DCL authorization policies of SAP's Authorization Management Service to DCN, so an AMS-secured application runs and is tested on a laptop.sap official, capCompiler from AMS DCL policies to DCN for local runs and testsfrom CAP
- @sap/cds-dk@sap/cds-dkThe command line client and development toolkit for CAP projects, with the commands cds build, cds deploy, cds watch and cds add among them.sap official, capCommand line client and development toolkit for CAPfrom CAP
- @sap/cds@sap/cdsThe CAP Node.js runtime, which compiles the CDS model, serves the services declared in it, answers generic requests before any handler runs, and loads every cds-plugin.sap official, capCAP Node.js runtimefrom CAP
- dev-approuterdev-approuterA development-time wrapper for the SAP Application Router that serves UI5 and CDS modules once they are added to the project as dependencies.community org, capDev-time wrapper for the SAP Application Routerfrom CAP
- abap2UI5 headless frontendabap2UI5 headless frontendPlays the frontend's side of the abap2UI5 request/response contract in ABAP, so an app class is driven and asserted on from a plain ABAP Unit test.community org, abapDrives abap2UI5 app classes from ABAP Unit testsfrom ABAP
- @abap2ui5/mcp-server@abap2ui5/mcp-serverAn MCP server that puts the abap2UI5 development loop on the machine an agent runs on: check the view the ABAP builds, photograph it, deploy the class into a sandbox, boot the app headless and read the errors.community org, abapMCP server for the abap2UI5 check, deploy and run loopfrom ABAP
- assertassertA fluent assertion helper for ABAP Unit tests that wraps cl_abap_unit_assert in chained calls such as assert(x)->equals(y), also usable outside tests through ZCL_ASSERTABLE.independent, abapFluent assertion helper for ABAP Unit testsfrom ABAP
- @abaplint/transpiler@abaplint/transpilerTranspiles ABAP 7.02 syntax to ES6 JavaScript, so ABAP code and its unit tests run on Node.js in CI without an ABAP system, with optional SQLite, PostgreSQL, Snowflake or SAP HANA drivers.community org, abapTranspiles ABAP to JavaScript to run on Node.jsfrom ABAP
- Modernization Agents for SAP on AWSModernization Agents for SAP on AWSAWS's suite of agents for SAP modernisation work: custom ABAP converted for S/4HANA, PI/PO interfaces moved to Integration Suite, BW objects moved to SAP Datasphere, deployed into a customer's own AWS account and reached only after registration.partner, abapAWS agents for ABAP, PI/PO and BW modernisation workfrom ABAP
- abap_db_preparatorabap_db_preparatorA wrapper over ABAP's OpenSQL replacement service that exports chosen rows into a stored bundle and, in a unit test's setup, replays it as fake table content in two method calls.independent, abapReplays stored database snapshots in ABAP unit testsfrom ABAP
- cacamber-BDD-for-ABAPcacamber-BDD-for-ABAPA BDD framework for ABAP that turns Gherkin-style Given/When/Then scenarios into ABAP Unit test steps, matching each step against a regular expression and calling the test class method it maps to.independent, abapBDD framework turning Given/When/Then into ABAP Unit stepsfrom ABAP
- abap-utesthelpabap-utesthelpTwo helper classes for ABAP Unit tests: one verifies a domain constant class against its domain's fixed values, the other creates test doubles without naming the interface.independent, abapHelper classes for ABAP Unit tests and test doublesfrom ABAP
- regression_testregression_testA snapshot library for ABAP that records a value once and compares against it on every later run, from either the debugger or a unit test, storing snapshots in eCATT test data containers.independent, abapSnapshot testing library for ABAP, from debugger or unit testfrom ABAP
- abapCovabapCovA report, ZABAPCOV, that uploads ABAP Unit test code coverage results to codecov.io, once the repository is installed through abapGit and codecov.io's certificates through STRUST.independent, abapUploads ABAP Unit code coverage to codecov.iofrom ABAP
- ABAP remote filesystemABAP remote filesystemA Visual Studio Code extension that opens an ABAP system over ADT as an editable filesystem and exposes system tools to GitHub Copilot and external MCP clients.independent, abapVS Code extension editing ABAP systems over ADT as a filesystemfrom ABAP
- express-icf-shimexpress-icf-shimA shim that runs an ABAP ICF handler written against if_http_extension behind an Express 4.x server, for ABAP transpiled to JavaScript and run on Node.js in testing and continuous integration.community org, abapShim running an ABAP ICF handler behind an Express 4.x serverfrom ABAP
- open-abap-coreopen-abap-coreReusable ABAP functionality for code transpiled by @abaplint/transpiler: the core ABAP artifacts that code runs against on Node.js.community org, abapCore ABAP artifacts for code transpiled by @abaplint/transpilerfrom ABAP
- mockup_loadermockup_loaderA tool that loads ABAP unit test data prepared in Excel as TAB-delimited text into ABAP structures and tables, and generates interface stubs that return that mock data.independent, abapLoader of Excel-prepared ABAP unit test data, with stub generationfrom ABAP
- mockAmockAA free mocking framework for ABAP, published under the Apache License 2.0.independent, abapA free mocking framework for ABAP, published under the Apache License 2.0.from ABAP
- Vise_for_ABAPVise_for_ABAPA characterisation-test helper: ZCL_VISE=>GRIP records a field's value once and fails a later run if it has changed.independent, abapA characterisation-test helper: `ZCL_VISE=>GRIP` records a field's value once and fails a later run if it has changed.from ABAP
- abap-senchaabap-senchaA BDD/TDD assertion library for ABAP Unit, styled after the JavaScript library Chai.js, that wraps cl_abap_unit_assert in chainable expect, should and assert styles.independent, abapBDD/TDD assertion library for ABAP Unit, styled after Chai.jsfrom ABAP
- abap-test-containerabap-test-containerA test data container for ABAP Cloud that loads unit test data in JSON, XML or raw formats from GitHub and maps it onto the target structure, filling the platform's missing native one.independent, abapGitHub-hosted test data container for ABAP Cloudfrom ABAP
- abap-unit-runnerabap-unit-runnerAn application job that runs and schedules ABAP Unit tests in SAP's ABAP Environment through the SAP_COM_0735 API, where the on-premise test runner has no SAP GUI to run from.independent, abapApplication job that runs and schedules ABAP Unit tests in the cloudfrom ABAP
- adash-servicesadash-servicesThe backend service behind ADASH Cli, exposing ABAP Unit test runs and coverage as REST and OData services for CI/CD pipelines, with a report scheduled to run tests per package.independent, abapBackend exposing ABAP Unit runs and coverage over REST and ODatafrom ABAP
Details
Sources
Sources are graph entities: the same page may back several entries, and an unreachable source flags every row that rests on it.
Compatibility and provenance
Flavors
“Everything runs as a subset: of the language, of the dictionary, and of Gateway (classic code-based SEGW).” — oisee/open-steamgate — README, What it is
Contributors
History in the atlas
- First seen.
For your agent
- Ref
artifact:oisee-open-steamgate- JSON
- /artifacts/oisee-open-steamgate.json
- MCP
- Connecting an agent