I cloned my Debian 13 libvirt template VM and named the clone “occ”. This’ll be where I run weird OBD-II code without careful analysis.
You see, I decided to pivot away from SocketCAN/raw CAN and toward ELM327-based
OBD-II diagnostics. Seems a bit easier to accomplish within the timebox.
Besides, this way I can run ELM327-emulator in the VM, and run the DOS QEMU
guest nested within the same VM. Keeps life simple. Once I’m done with OCC I
just stop the VM. Libvirt rocks; just gotta read a lot of docs and books about
it to fully understand its capabilities. It has a great Python API too, if
shelling out to virsh won’t suffice.
I did eventually installed ELM327-emulator with some unforseen speed bumps. It
needed an old version of setuptools because setup.py expects pkg_resources
to exist, and that module was no longer present in pre-installed setuptools.
ELM327-emulator runs runs, and I was able to connect to the ELM327
pseudoterminal via minicom or screen. Next I need to work out what the
heck ELM327 commands look like. Stay tuned.

Figure 1: ELM327-emulator runs
Updates from other OCC participants began trickling in. Some post on Gopher.
Others post on Gemini. And of course some use plain old HTTP/HTTPS and HTML.
Didn’t know of a Gopher or Gemini client off the top of my head. Then I
recalled lynx. It does Gopher - yay! No Gemini support, however. But the
good thing is this Gemini proxy portal exists and works with lynx:
https://portal.mozz.us/. For example:
http://portal.mozz.us/gemini/pv.smol.pub/occ-2026-day-3#old-computer-challenge-2026-day-3

Figure 2: Lynx viewing Gemini content via portal.mozz.us
Discussed possibly adding Gemini support to lynx. Funnily enough everyone
assumed that I intended to upstream the code changes and go through all the
gymnastics. Nah. I was just thinking I could vibecode it and circumvent the
need for a Gemini portal. It is a means to an end. But for now, that
portal.mozz.us seems to do the trick! ChatGPT came up with a couple things to
check into, if I do choose to run a local dirty lynx tree. Any upstream
contributions would not be vibecoded. The idea is to get this less-important
code change done yesterday, not begin a multi-month upstreaming pilgrimage.
I’ve been busy too; can’t be bothered to plug leaks in the van, and it’s storming hard tonight. So I spent a bit of time cleaning up camp, wrapping the entire van in a tarp using tensioning knots that I recently learned. Then I drove up to Klondike to buy a large clothes trunk. Nice people. I appreciated the “God bless you” code switch experienced farther north. More neighborly, less adversarial to outsiders. They were super appreciative and gave me a bunch of other equipment (free of charge) which I have already put to use.
On my way back to camp, I stopped at a coffee shop, got distracted reading my localhost-hosted Wikipedia mirror, and spied a 3D-printed “check engine” light (CEL) keychain doodad. It seemed only fitting to obtain this trinket as an OCC keepsake.

Figure 3: Check engine light trinket
Next up, prepare a FreeDOS image using virt-install or manually loading up a
libvirt XML document to teach libvirt about the new VM. Then I’ll configure
the libvirt VM to hook the local ELM327-emulator pseudoterminal in as a serial
console. Finally I’ll code up something in DOS. I’m thinking a C-based DOS
program that speaks ELM327’s higher-level OBD-II commands over the serial
connection.
As a reminder, it’ll look like this:
DOS in QEMU ⬌ virtual serial/PTY plumbing ⬌ ELM327 emulator or device
Some OBD-II software tools to try with an ELM327 (excerpted from the ELM327-emulator readme):
- https://github.com/brendan-w/python-OBD
- https://www.obdautodoctor.com/
- https://www.scantool.net/ (https://github.com/kees/scantool)
I’m gassed. I’m going to take a nap.