« Back to Applications

Kodama

PowerPC Mac (Tiger) 向け Source Available

An ultra-lightweight 3-pane web reader for PowerPC Macs (G3/G4/G5) running Mac OS X 10.4 Tiger. Modern web pages are full of JavaScript, ads, and huge images that hardware from the mid-2000s simply can't handle. Kodama loads none of that — it parses raw HTML with libxml2, keeps only the headings, body text, and image links, and draws them directly with stock Cocoa components. No JavaScript, no CSS engine. The goal is to stay usable even on a 450MHz G3.

Download Kodama.dmg
Downloads so far: 60
Last updated: 2026-08-29 (v0.2.1)
Note: Tiger's stock Safari/curl can't verify today's HTTPS certificates, so downloading here directly can fail. We recommend Aquafox — the PowerPC-era browser we make a Japanese language pack for — which handles modern HTTPS fine. Failing that, fetch the file on a modern machine and copy it over, or use a modern curl via Tigerbrew/MacPorts.

Changelog

  • 2026-08-29 — v0.2.1: Now bundles a curl capable of modern HTTPS directly in the app, so installing an external curl via MacPorts/Tigerbrew is no longer needed. Use v0.2.1 unless you have a specific reason not to.

Features

  • Left pane — a list of headings (h1–h3). Click to jump to that spot in the body, or straight to another article if the heading is itself a link.
  • Center pane — the article body. Images are replaced with [ Show image N ] links and only fetched on click.
  • Right pane — a preview of whichever image you clicked. Hidden by default, a "hidden third pane" layout that keeps the reading area wide on small screens.
  • A collapsible bookmark bar under the address bar, with per-bookmark rename/delete.
  • Back/forward history, including a right-click history menu on the Back button.
  • Japanese/English UI switch, live at runtime.
  • Typing a non-URL string into the address bar falls back to DuckDuckGo's HTML search endpoint.
  • File downloads (.dmg/.zip/.pdf/etc.) are detected from the actual response headers and saved via a normal save dialog, instead of being (mis)rendered as a page.

Requirements

  • Mac OS X 10.4 Tiger, PowerPC G3/G4/G5
  • Nothing else, as of v0.2.1 — a modern, TLS 1.2/1.3-capable curl now ships inside the app itself, so Tiger's ancient system curl is never used. (Older versions needed a separate curl installed via Tigerbrew or MacPorts — that's no longer necessary, though Kodama will still fall back to one if present.)

Installation

  1. Download Kodama.dmg and open it.
  2. Drag Kodama.app to /Applications or wherever you like on the target PowerPC Mac.
  3. That's it — open it and start browsing. No separate curl install needed.

Known Limitations

  • No HTML form support (e.g. search boxes on a page) — the address bar's search fallback is the only workaround for now.
  • Per-site navigation stripping is a simple heuristic, so ads/menus can still leak into the article body depending on how a given site is marked up.

Supported Environments

EnvironmentPowerPC Mac / Mac OS X 10.4.11 (Tiger)
Verified hardwareiBook G4

A personal hobby project provided with no warranty, MIT licensed. See GitHub for source code and technical details.

Kodama is basically just a lightweight parser that turns raw HTML into structure using libxml2. No WebKit, no JavaScript, no CSS engine at all. The goal from day one was staying usable on a 450MHz G3. Here's how it actually came together, and some of the real-site landmines along the way.

Why not WebKit

Modern web pages are full of JS, ads, and huge images that a G3-era CPU just can't render. So Kodama skips WebKit entirely — it parses HTML with libxml2, pulls out just the headings, body text, and image links, and draws them with plain Cocoa components. No JS, no CSS to execute, so there's nothing there to be slow.

Hitting Tiger's limits over and over

Even in the first pass at the parser, real-hardware testing turned up one old-environment wall after another. The libxml2 that ships here (2.6.16) doesn't even have the HTML_PARSE_RECOVER constant. Foundation on 10.4 doesn't have componentsSeparatedByCharactersInSet:, so that had to be rewritten around NSScanner instead. The most annoying one was gcc 4.0.0's Objective-C string literals — an @"..." literal containing multi-byte characters like Japanese just doesn't encode correctly and comes out garbled. Ran into that enough times that a small macro, PWRJPStr, was born — it builds strings from a plain C literal via stringWithUTF8String: instead, and every UI string uses it from then on.

Async networking before blocks or GCD existed

Tiger has neither GCD nor blocks, so even calling curl asynchronously took some doing. CurlTaskRunner waits on both NSTaskDidTerminateNotification and NSFileHandleReadCompletionNotification at once and reports back through a delegate — the old-school way. On real hardware it pulled off actual HTTPS fetches using a portable curl from Tigerbrew (7.58.0 + OpenSSL 1.0.2l), which is what proved the core idea of the whole project: dodging the TLS 1.2/1.3 handshake problem was actually possible.

Bundling curl instead of requiring one

v0.2's requirement for a Tigerbrew/MacPorts curl worked, but it meant a plain Tiger install with neither of those was dead in the water — confirmed by an actual user hitting exactly that on a real Power Mac G4. v0.2.1 bundles a static PPC build of curl 8.9.1 (against LibreSSL 3.8.4) plus a current cacert.pem straight inside Kodama.app/Contents/Resources. CurlTaskRunner's path detection now checks for that bundled copy first, before falling back to the old search order (/opt/local/usr/local/bin → a portable curl on the user's PATH) for anyone who still has one installed. The --cacert flag only gets passed when the bundled curl is the one actually running — fall back to a system-installed curl and it keeps trusting whatever CA store that one already trusts, rather than overriding it.

Building the "hidden third pane"

The right pane (image preview) sits at zero width by default and only opens when you click an image link. Except Tiger's NSSplitView (10.4) doesn't have setPosition:ofDividerAtIndex:, so the modern approach was off the table. Had to fall back to the old way: calculating subview frames by hand inside splitView:resizeSubviewsWithOldSize: to collapse and expand it.

An endless fight with real websites

This is probably where most of the actual time went.

Garbled Shift_JIS. libxml2 2.6.16's automatic encoding detection turned out to be unreliable — real sites declaring charset=shift_jis (like ITmedia) came out garbled. Fixed it by no longer handing NULL to htmlReadMemory and letting it guess; instead, Kodama reads the meta charset declaration near the top of the HTML itself and passes the encoding explicitly.
JavaScript leaking into the article body. The same libxml2 doesn't treat everything inside a script tag as raw text the way the HTML5 spec says it should — a tag-like string inside a JS template literal (seen on FNN News, for example) fooled it into thinking it had exited the script tag, and the raw JS code ended up rendered as body text. Fixed by stripping out script/style contents at the raw-byte level before the parser ever sees them.
Global nav menus leaking into the article. On sites like FNN News, a div-based global menu (class="m-gnav" and similar) would show up whole at the top of the article body since it's not an actual nav tag. Added a heuristic that excludes elements whose class/id contains telltale words — but deliberately avoided generic words like "nav" or "header," since those show up in legitimate article class names too and would cause false positives. Stuck to specific, low-false-positive words instead: gnav, globalnav, breadcrumb, pankuzu, drawer, hamburger.

Traps in the Japanese/English switch

Someone reported that switching to English left the window title stuck on "コダマ" and the Edit menu items still in Japanese. Turned out part of the window title was hardcoded to that literal string instead of going through the localization system, and the Edit menu items were built as plain local variables that never got added to the list of things the switch updates — just an oversight from when they were first added. Fixed both, confirmed on real hardware. One thing that can't be switched at runtime at all: the app name shown at the far left of the menu bar comes straight from CFBundleName, which macOS controls itself. Since that's unreadable to non-Japanese speakers no matter what, it's set to the Latin "Kodama" from the start — the "コダマ" identity still lives on in the window title, the About panel, and this site.

What's next

No HTML form support yet (search boxes, etc.) — the address bar's DuckDuckGo fallback is the only workaround for now, still thinking about the right way to handle it.

Full source code is on GitHub.