Author Topic: claude-os2-toolkit — a verified OS/2 reference + tooling kit for AI coding  (Read 247 times)

phaelonimaire

  • Newbie
  • *
  • Posts: 15
  • Karma: +2/-0
If you have ever asked ChatGPT or Claude an OS/2 question, you already know the problem: it answers instantly, fluently, and often wrongly. It will invent a WinSetWindowPos parameter order, hand you a DosOpen flag that does not exist, or confidently describe PM's coordinate origin as top-left. OS/2's APIs and internals are essentially absent from these models' training data, so what comes out is plausible-shaped noise — and the failure mode is confidence, not hesitation, which makes it worse than useless if you do not already know the answer.

I have been building OS/2 software with an AI assistant anyway, because when it is given real references it is genuinely useful. This is the scaffolding that makes that work, cleaned up and published:
github.com/phaelonimaire/claude-os2-toolkit — MIT licensed

What it is

A documentation-and-tooling kit you drop next to your project and point the assistant at.

  • os2ref/ — 42 reference documents covering OS/2 internals and the application API surface: file/memory/process/IPC/exceptions, PM windows, controls, dialogs and GPI, VIO, clipboard and DDE,  drag-drop, printing, profiles, EAs, SOM, WPS, REXX, sockets, MMPM/2, DART audio, thunking, and the LX/NE executable formats.

    Every claim carries a provenance tag saying how it was established, and names the header, book or file:line so you can re-check it yourself:
Code: [Select]
[DOC-IBM]     IBM's own word - a Toolkit/DDK header, an IBM book, a redbook
[OBS-RE]      observed by reverse-engineering a binary or a debugger session
[DOC]         community/secondary - EDM2, osFree, period references
[SRC]         read out of the source of something that runs on OS/2
[unverified]  could not be pinned down - said so rather than guessed
  • A document on kLIBC / LIBC Next — how the POSIX layer actually implements fds, fork/exec/spawn, signals, malloc and BSD sockets on top of the native Dos* APIs. Verified against the bitwiseworks source, with file:line citations throughout. If you have ever wondered why fork() behaves the way it does on OS/2, or why a ported shell hangs on every external command, that is the document.
  • tools/ — Python utilities that inspect what you build: LX/NE object tables, exports and imports (including forwarders, and the ordinals a module actually references through its fixup records), per-ordinal parameter word counts read out of the entry table, symbol-annotated disassembly, .SYM parsing, a duplicate-menu-mnemonic checker, and scripted control of the kernel debugger over a VM serial pipe.
  • corpus/ — scripts that turn IBM .INF books into greppable text, mirror the redbooks and EDM2 locally, and extract PDF books with page numbers preserved so a fact stays citable. Plus a search tool that queries everything in provenance order.
  • recipes/ and scaffolds/ — install, build, test, debug and port, with working minimal PM, console and menu/dialog programs.

What it is not

It ships no IBM material. No headers, no DDK, no Developer Connection books, no toolchain. What it contains is facts restated in my own words with citations, plus pointers to where the originals actually live — Hobbes (now hobbesarchive.com), EDM2, komh.github.io/os2books, archive.org.

If you download those and cite them, that is exactly the intended use. In fact I think the "finding aid" half is the more valuable half: there is a verified list of where the Developer Connection sets, the DDK, and all four volumes of the OS/2 Debugging Handbook can be found — most copies in the wild are Volume I only, and Volume II is the one that documents the debug kernel and dump formatter.

Caveats, honestly
A lot of this is observed rather than documented, and some of it is explicitly marked unverified because I could not source it. There will be errors. The provenance tags exist precisely so you can tell how much weight any given line deserves, and so a wrong claim can be tracked back and fixed rather than quietly propagating.

It is also not magic. A model with this kit still gets things wrong; it just gets them wrong less often, and it can be made to show its work. The single most useful discipline in the whole thing is never originate an ABI fact — look it up, cite it, or say you do not know.

Corrections and contributions welcome
This community knows things that are not written down anywhere, and that is exactly what the kit is short of. If you spot something wrong, or know the answer to something marked unverified, I would genuinely rather be corrected than politely left alone. CONTRIBUTING.md explains the format — facts restated with citations, never pasted copyrighted text, provenance tagged.

Happy to answer questions here.

Dave Yeo

  • Hero Member
  • *****
  • Posts: 6052
  • Karma: +167/-1
Looks good on a quick view, well other then the em-dashes :) Lot to digest, especially for someone like me who has never used Claude, which I guess could be another topic. Something like how to get Claude to write a PM hello world app might be a good start.

JPM

  • Jr. Member
  • **
  • Posts: 72
  • Karma: +10/-0
Thank you for putting this together and sharing it with the OS/2 community. The focus on verified sources and clear provenance is especially valuable. Great work!

Dave Yeo

  • Hero Member
  • *****
  • Posts: 6052
  • Karma: +167/-1
Looking at CONTRIBUTING.md does raise questions. I looked at recipes\rebuild-a-netlabs-package.md, something I know a bit.
First it seems that you're talking about doing this on Linux, which is fine but does need to be qualified. And I would have to boot to Linux to check on some of this stuff, which is fine.
Now I look at,
Code: [Select]
**b. `PATH` is `;`-separated with drive letters; configure splits on `:`.** So it finds *nothing* —
first `no acceptable C compiler`, then `no acceptable grep`. Name every tool absolutely:

```sh
export CC=/@unixroot/usr/bin/gcc.exe AR=/@unixroot/usr/bin/ar.exe RANLIB=/@unixroot/usr/bin/ranlib.exe
export GREP=/@unixroot/usr/bin/grep.exe SED=/@unixroot/usr/bin/sed.exe AWK=/@unixroot/usr/bin/gawk.exe
export EGREP="/@unixroot/usr/bin/grep.exe -E" FGREP="/@unixroot/usr/bin/grep.exe -F"
```
Which brings up two points. These exports could be put in a config.site file, especially as it is an expanding list. Config.site must be documented in the autoconf docs, so I guess I would need to read them, reword and use them as a citation. These exports might also be replaced with an "export exeext=.exe" which I would have to test and, not being sure of a citation, citate how? Learned this a long time back.
Next is,
Code: [Select]
**c. `-Zomf` resolves `-lfoo` to `foo_s.a`, which many devel packages don't ship.** They ship OMF
**import libraries** (`.lib`) instead:

```
weakld: cannot open library file '\@unixroot\usr\lib\curses_s.a'
```

`ls /@unixroot/usr/lib | grep -i <name>` to see what exists, then either drop the flag (if the
package doesn't actually use that library) or override the make variable with the real path —
e.g. readline's link libs come from `SHLIB_LIBS`:

Which once again seems wrong, or rather incomplete.
I'd write it perhaps as "**c. `LDFLAGS=-Zomf`implies using emxomfld which resolves"...
And then, looking, I see locally in G:\usr\doc\GCC-3.3.5\ReleaseNotes.os2,
Code: [Select]
Changed library search algorithms for the linkers (emxomfld
 and ld). Three variations, static, shared and shared+dll.
 (The options indicated corresponds to what binutils 2.12.x
 documents.)
 static: (-Bstatic, -non_shared, -dn, -static)
   1. libfoo_s.a
   2. foo_s.a
   3. libfoo.a
   4. foo.a
 shared: (default, -Bshared, -call_shared, -dy)
   1. libfoo_dll.a
   2. foo_dll.a
   3. libfoo.a
   4. foo.a
   5. libfoo_s.a
   6. foo_s.a
 shared+dll: (-Zdll-search with -Bshared, -call_shared, -dy)
   1. libfoo_dll.a
   2. foo_dll.a
   3. libfoo.a
   4. foo.a
   5. foo.dll
   6. libfoo_s.a
   7. foo_s.a
Now this is probably in the subversion history and not sure where else. I take it I would have to reword this list and find the citation on the internet? Perhaps best to look at the source for a citation but there is still the problem of rewriting a simple list.
Plus in my experience something like "LDFLAGS=-Zomf -lmmpm2" does work, assuming the os2tk45-libs rpm package is installed. The system libs such as mmpm2.lib are obviously OMF and ld isn't going to find them.
Hopefully I make sense here, had a couple of drinks, it's the wives birthday :)

phaelonimaire

  • Newbie
  • *
  • Posts: 15
  • Karma: +2/-0
Quote from: Dave Yeo
Which once again seems wrong, or rather incomplete.

Wrong, not just incomplete — and you supplied the counterexample yourself. Fixed and pushed; the long version is in the commit messages: github.com/phaelonimaire/claude-os2-toolkit

-Zomf and .lib. Your -lmmpm2 datum was right. emxomfld tries .lib third of six, ahead of _s.lib and _s.a — so .lib was never the problem. What fooled us was the diagnostic: on failure find_lib() leaves the last candidate it built in the buffer, and weakld prints that. Proof in two lines:

Code: [Select]
$ gcc -Zomf t.c -L. -lzznothing          -> weakld: cannot open ... zznothing_s.a
$ gcc -Zomf -static t.c -L. -lzznothing  -> weakld: cannot open ... zznothing.a

Nothing called zznothing exists either way — different mode, different reported name. Your "implies using emxomfld which resolves" wording is the frame the section uses now.

And the readline case was worse than I first wrote. It wasn't just "no curses under that name". ncurses is in netlabs-rel right enough, but it wasn't on my box when that build ran — rpm install dates put the base packages at 2015, readline at 2021, and ncurses at late 2025. And even once installed, -lcurses still fails: ncurses-libs gives you libcurses.dll, but .dll isn't in the default suffix list (that needs -Zdll-search) — what -l wants is the import library from ncurses-devel, a separate package. So the "just ls the directory" advice I was leaning on can show you a curses file and it's still a link failure. Available, present and linkable are three different things.

config.site. Right, and better than the ever-growing CC=/GREP= list. Two caveats: the automatic $prefix/share/config.site only applies when --prefix was passed, and it still needs CONFIG_SHELL — without it every check passes, "creating config.status" prints, and then it dies on /bin/sh: not found with no Makefile.

exeext. Right instinct, wrong variable — it's ac_executable_extensions (EXEEXT is the suffix of what configure builds). autoconf references it and assigns it nowhere, so it's yours to set.

Your citation question. Cite the code, not the note — emxomfld.c, find_lib(), three adjacent arrays anyone can open. That list is stale in the notes anyway, and find_lib()'s own header comment gives a third order matching neither. As for rewording a simple list: you don't have to. A list of names in functional order is a fact, not expression — reproduce it and cite where you read it. CONTRIBUTING.md now says so; that gap was real.

And fair on qualifying "on Linux" — each section is now tagged host or OS/2, with the host a convenience for autoreconf rather than a requirement.

phaelonimaire

  • Newbie
  • *
  • Posts: 15
  • Karma: +2/-0
Looks good on a quick view, well other then the em-dashes :)

Guilty. Not one in this post, I checked.

A PM hello world is exactly what it is for, and it is already in there: scaffolds/hello-pm is a working skeleton, anchor block and message queue, frame and client window, WM_PAINT, and a .def marked WINDOWAPI, with the build lines for both OpenWatcom and GCC next to it. Point Claude at the kit, ask for a PM app, and that is where it starts from instead of inventing Win32 by mistake.

It scales up from there: same kit got Notepad2 from Windows to OS/2. Next is a proper PM terminal to replace VIO windows, xterm or PowerShell class, drag the corner and it reflows instead of being stuck at fixed rows by columns. 

Edit: Em-dashes are in neither CP437 nor CP850, so one in a .c comment makes the file Non-ISO extended-ASCII, and then grep goes silent on it rather than erroring. The whole kit will be plain ASCII on the next push.


« Last Edit: August 02, 2026, 09:52:43 pm by phaelonimaire »

Dave Yeo

  • Hero Member
  • *****
  • Posts: 6052
  • Karma: +167/-1
config.site can be referenced by $CONFIG_SITE. set CONFIG_SITE=x:/foo/config.site.
Looking at old EMX era config.site, I had
Code: [Select]
export ac_exeext=.exe
export ac_cv_exeext=.exe
export ac_executable_extensions=".exe"
Can't remember if the quoting was important, nor what version of autoconf.
Which brings up the odd project that still uses autconf 2.13 such as Mozilla where the only way for it to work on OS/2 was to run autoconf, now autoconf213.
I'll check out the PM app. The PM terminal sounds interesting. There's been a few attempts
Thanks for the work you're putting in.

Dave Yeo

  • Hero Member
  • *****
  • Posts: 6052
  • Karma: +167/-1
Forgot to mention libtool. Bitwise has made some good changes to our port compared to upstream, which did mostly work. Needed --disable-static --enable-shared passed to configure to build a DLL and the opposite for a static lib.