Say local RPG development and most teams mean VS Code with Code for IBM i, or RDi where the seats are already paid for. Your source lives in git on your own machine. You edit it there, press Deploy, and the members go up to the IFS so the partition can run CRTSQLRPGI on them.

Only the editing is local. The compile is a job on the IBM i, the program runs on the IBM i, and the compile errors come back in a spool file, so every developer needs a profile, a library list, and a partition that is up. Change one bucket boundary in an aging program and you are queued behind whatever else the machine is doing that afternoon.

Compiling RPG Without the IBM i

The same source compiles on the developer's own machine, unchanged, DDS included. Triton RPG reads the display file, the subfile, and the embedded SQL as they sit in your library and compiles it to a class you run on the JVM, with the 5250 front end wired into it, so your team goes on maintaining the RPG they already maintain.

An aging inquiry, compiled and run:

rpgc ARINQUIRY.rpgle -o out --dds-path .

java -cp out:triton-rpg.jar:jline.jar:h2.jar ARINQUIRY
                        AR Aging Inquiry

 As of:  08/10/2026                              Open items:  11
  InvNo   Customer Name         Due Date      Balance   Days Aging
  1001    Acme Corporation      2025-11-15  2500.00    268   Over 90
  1002    Baker Industries      2025-12-20  3200.00    233   Over 90
  1003    Acme Corporation      2026-02-01  1300.00    190   Over 90
  1004    Central Services      2026-02-15  3100.00    176   Over 90
  1005    Baker Industries      2026-03-15  750.00     148   Over 90
  1006    Central Services      2026-04-01  2250.00    131   Over 90
  1007    Delta Electronics     2026-04-15  1500.00    117   Over 90
  1008    Central Services      2026-04-25  890.00     107   Over 90
  1009    Delta Electronics     2026-05-15  3000.00    87    61-90
  1010    Eagle Supplies        2026-05-30  975.00     72    61-90
  1011    Eagle Supplies        2026-06-15  5500.00    56    31-60


 Aging Summary
 Current:  0.00          1-30:     0.00          31-60:  5500.00
 61-90:    3975.00       Over 90:  15490.00      Total:  24965.00


 F3=Exit   F5=Refresh

That is the aging inquiry your users know, running on a laptop with no IBM i behind it: the subfile scrolls, F5 reloads, and F3 exits, all from the display file already in your library:

ARINQUIRY.rpgle

DCL-F ARINQUIRY WORKSTN SFILE(SFLREC:wRRN);

That compile takes a third of a second. Move a bucket boundary, run those two commands again, and the new totals are on the screen.

The compiler reads the source file you name and the DDS directory you point it at, so the size of the library the program came out of never enters into it.

Pointing It at Db2 for i

Those rows came out of an in-memory database on the same machine, loaded from a file of INSERT statements, with no change to the RPG. QSYS2.GENERATE_SQL writes the CREATE TABLE statements for your own files straight off the partition, and a SELECT gets you as many rows as a developer needs to work with. The JDBC URL decides which database answers, so the same compiled program reads your Db2 for i once you give it four environment variables:

export JDBC_URL="jdbc:as400://myhost/WHITEHORN1"
export JDBC_DRIVER="com.ibm.as400.access.AS400JDBCDriver"
export JDBC_USER="MYUSER"
export JDBC_PASSWORD="MYPASS"

On a developer's machine those four point at a test database and are set by hand. Anywhere shared, they come from the same credential store your other applications use rather than from a file in the repository.

Your team gets two places to run one program: an in-memory copy while the code is changing, with data they can reload at will, and your Db2 for i when they want real volumes. The same arrangement is how a JUnit suite tests RPG on a build server with no partition in the pipeline.

The Error Comes Back Where You Typed It

Misspell a variable and the compile says so, with the line and the column:

[ERROR] ARINQUIRY.rpgle:168:19 — TRN2135: Undefined variable 'wDuDate'

The same diagnostics run in the editor as you type, through a language server that installs beside the compiler, so an undeclared field is underlined before you save. A copy member you have open is read from the editor rather than from disk, which means adding a field to it clears the errors in every program that includes it before anything is written.

Start With One Program

Nothing has to move for you to try this. Put one program in a directory with its display file and compile it. Copy members and anything it CALLs come along the same way, a directory at a time. Neither the source nor the green screen changes, and the copy on the partition keeps running for the people who use it every day.

The object you ship still comes off the partition, compiled by IBM's compiler, the way your auditors expect; every compile before that one happens on the developer's machine. A new hire can read your code and run it against a throwaway copy of the data on their first day, with no profile and no library list. Pick the program you are already dreading a change to, and start there.

Want RPG development off the partition?

Start a Conversation