PullMD Teil 8: Vom Tool für mich zum OSS-Projekt – Einfach erklärt
Am Vormittag des 25. April hatte ich den Trafilatura-Sidecar eingebaut und einen Fehler behoben, der wochenlang im Code schlummerte. Beides Thema von Teil 5. Nachmittags stand dann die Sache an, die ich seit Wochen vor mir herschob: das Tool öffentlich machen. Der Code war so weit. Nur der Name stimmte noch nicht, und eine Lizenz fehlte auch.
Der alte Name passte nicht mehr (Grund 1)
Das Tool hatte einen internen Codenamen. Claude hatte ihn im allerersten Konzept-Chat vorgeschlagen, weil das Ding damals nur Reddit-Inhalte verarbeitete und der Name kurz genug für ein App-Icon war. Ich habe ihn übernommen, ohne groß nachzudenken. Der Service lief nur bei mir, nicht unter einer Marke.
Inzwischen war das Tool etwas ganz anderes. Drei verschiedene Wege, Webseiten in sauberen Text zu verwandeln. Eine Schnittstelle für KI-Agenten. Ein Skill-Paket. Eine Mini-App fürs Handy. Reddit war nur noch einer von vielen Wegen, jeder davon funktioniert für jede beliebige Webadresse.
Ein Name, der nach “Reddit-Tool” klingt, obwohl das Ding längst universell ist, weckt sofort eine falsche Erwartung. Das ist weniger ein Marketing-Problem als eine Support-Frage, die nur noch keiner gestellt hat.
Der alte Name war juristisch grenzwertig (Grund 2)
Da war noch etwas, und das war eigentlich der wichtigere Grund. Wenige Tage nach dem Konzept-Chat war mir klargeworden, dass der Codename phonetisch einer bekannten Marke aus einer ganz anderen Branche ähnelte. Die Firma dahinter ist dafür bekannt, auch gegen kleine Projekte vorzugehen, wenn ein Name zu ähnlich klingt. Dokumentierte Praxis, keine Spekulation.
Schon am 8. März hatte ich deshalb das Verzeichnis auf dem Server unter dem neuen Namen angelegt. Damit war für mich faktisch entschieden: der Codename bleibt intern, nach draußen kommt was anderes. Nur im Quellcode selbst stand der alte Name noch, weil es bis dahin egal war. Ein Nutzer, ein Server, niemand sonst schaut da rein.
Vor dem öffentlichen Release wurde aus “intern egal” jetzt “muss aufgeräumt werden”. Die Wahl war einfach: 30 Minuten gründliches Aufräumen oder das Risiko eines Briefes von einer Markenrecht-Kanzlei. Die 30 Minuten schienen sinnvoller.
PullMD: beschreibend, langweilig, gut
“Pull” wie ziehen, der Service zieht Inhalte von Webseiten herunter. “MD” wie Markdown, das einfache Textformat, in dem er die Inhalte zurückliefert. Kein Wortspiel. Keine Anspielung. Keine phonetische Nähe zu irgendeiner Marke.
Manchmal ist der langweilige Name der beste: man liest ihn und weiß sofort, was man bekommt.
Den alten Namen überall rauslösen
Auf dem Server, wo das Tool tatsächlich lief, war nichts zu tun. Dort hatte es seit dem 8. März schon den neuen Namen. Was blieb: der Quellcode und alle internen Verweise darin. Plus die gesamte Änderungshistorie, in der überall noch der alte Name stand.
Claude Code hat die Bereinigung übernommen. Ehrlich gesagt habe ich erst beim Schreiben dieses Artikels nachgeschaut, was dabei eigentlich gelaufen ist. Es gibt ein spezielles Werkzeug namens git filter-repo, das durch die gesamte Änderungshistorie geht und dort den alten Namen gegen den neuen austauscht. Auch die Autorangaben wurden vereinheitlicht, damit die öffentliche Geschichte unter einer einzigen Identität läuft. Das Werkzeug ist der offizielle Nachfolger eines älteren Programms, das so viele Stolpersteine hatte, dass die Betreuer selbst davon abraten.
Jetzt weiß ich’s. Damals: zugesehen, gewartet, weitergemacht.
Vor dem ersten öffentlichen Push ist so ein Umschreiben der Geschichte harmlos, weil noch niemand eine Kopie hat, die davon betroffen wäre. Bei einem bereits öffentlichen Projekt wäre es deutlich riskanter.
Das kritischere Stück war das Sitzungs-Archiv. Claude Code legt Gesprächsprotokolle in einem Verzeichnis ab, dessen Name vom Projektnamen abhängt. Dieses Archiv ist die Quelle, aus der diese Blogserie überhaupt entsteht. Die Zitate aus den frühen Gesprächen wären ohne ein Backup davon nicht mehr auffindbar gewesen.
Die Lizenz: was dürfen andere damit?
Wenn man Code öffentlich auf GitHub stellt, muss man festlegen, was andere damit machen dürfen. Eine Lizenz ist wie ein Aushang neben einer Pinnwand: “Du darfst dir das hier nehmen, aber unter diesen Bedingungen.” Ohne so einen Aushang darf rechtlich gesehen niemand etwas damit anfangen.
Die zwei Enden des Spektrums:
MIT-Lizenz (benannt nach der Hochschule, an der sie entstanden ist): sehr freizügig. Nimm den Code, mach was du willst, du musst nichts zurückgeben. Ideal für kleine Helferlein und Bibliotheken, die möglichst weit verbreitet werden sollen.
AGPL (Affero General Public License): strenger, auf eine bestimmte Weise. Wenn jemand das Tool nimmt, Verbesserungen einbaut und das Ganze als Online-Dienst betreibt, muss er diese Verbesserungen ebenfalls offen veröffentlichen.
PullMD ist kein passiv genutztes Paket, sondern ein laufender Dienst, der Anfragen beantwortet. Wenn jemand das im Hintergrund verbessert und als eigenen Dienst anbietet, erfahre ich nie, was die eigentlichen Schwachstellen meines Codes sind. AGPL sorgt dafür, dass Verbesserungen zurückfließen müssen.
Das ist keine ideologische Aussage über freie Software. Es ist eine ganz pragmatische Überlegung: wer hat einen Anreiz, Fehler zu melden, wenn er sie schon selbst behoben hat?
Mehr Nuancen zu den verschiedenen Lizenzen gibt’s auf choosealicense.com.
Damit auch andere das Tool bei sich betreiben können
Bis dahin lief das Tool nur bei mir, mit meinen Server-Adressen fest im Code. Wer es bei sich installieren wollte, hätte überall meine Adressen gesehen. Eine einzige einstellbare Variable sorgt jetzt dafür, dass das Tool auf jeder beliebigen Domain läuft, ohne dass man im Code herumändern muss. Wer es bei sich aufsetzt, setzt diese eine Variable, und der Rest fügt sich von allein.
Die Anleitung wurde komplett für die Außenwelt neu geschrieben. Kein internes Kauderwelsch mehr, keine Notizen, die nur für mich Sinn ergaben.
Der Push
Ein Befehl, und das Repo war öffentlich. Naja, fast. Zwischen “lokal fertig” und “wirklich draußen” lagen noch zwei Tage Feinschliff. Ein kleiner Fehler im Kommentar-Zwischenspeicher musste erst auf dem Server behoben werden, bevor das Ganze nach draußen durfte.
Am 27. April lief der eigentliche Push dann durch. In den Tagen danach kamen noch ein paar Nachbesserungen: ein Footer hier, ein Layout-Detail da. Die Art von Sachen, die einem erst auffallen, wenn man das erste Mal mit echtem Abstand auf das eigene Werk schaut.
Das Tool liegt seitdem offen auf GitHub, unter github.com/AeternaLabsHQ/pullmd.
Was danach lief
Der Dienst läuft seitdem auf eigener Domain, und ich benutze ihn jeden Tag. Für Reddit-Posts, für Artikel, für Dokumentationsseiten. Für alles, was ich als sauberen Text in einen Chat-Kontext bringen will.
Darunter steckt alles, was seit März dazugekommen ist: die drei Extraktionswege mit Qualitätsbewertung, der MCP-Server (Model Context Protocol) für Claude Code, das Skill-Paket, die Mini-App für den Android-Teilen-Workflow.
JavaScript-Seiten: der unsichtbare Browser
Seit dem 25. April sammelt das Tool nebenbei Daten in einer kleinen Statistik-Datenbank: welche Webseite wurde abgerufen, welcher Extraktionsweg hat funktioniert, wie gut war das Ergebnis. Der Plan war, eine Woche lang zuzuschauen und dann zu entscheiden, ob sich ein zusätzlicher Schritt lohnt.
Das Problem: Manche Webseiten liefern ihren eigentlichen Inhalt erst, wenn ein Browser die Seite öffnet und das JavaScript darin ausführt. JavaScript ist die Programmiersprache, die Webseiten interaktiv macht: Menüs aufklappen, Preise nachladen, Tabellen zusammenbauen. Ohne Browser kommt bei solchen Seiten nur eine leere Hülle zurück.
Der Anlass, doch nicht eine Woche zu warten, war eine einzelne Seite. Die Preisliste von Mistral (einem KI-Anbieter) kam als 452 Kilobyte HTML zurück, in denen die Preise selbst gar nicht standen, weil der Browser sie erst beim Anzeigen zusammenbaut. Readability (eine der Extraktions-Bibliotheken aus Teil 5) holte daraus 19 Überschriften und drei Absätze. Trafilatura (die andere) ganze 283 Zeichen.
Dazu kam die Zahl aus dem Statistik-Log. Von 29 Web-Abrufen war die statische Extraktion bei vieren durchgefallen: 14 Prozent. Die Grenze, ab der sich der Aufwand laut Briefing lohnt, lag bei zehn.
Daraus entstand der zweite Sidecar, nach Trafilatura aus Teil 5. Ein Sidecar ist ein eigenständiger Hilfsdienst, der in einem eigenen Container neben dem Hauptdienst läuft. Ein Container ist eine Art versiegelte Box mit dem Programm und allem, was es zum Laufen braucht.
Dieser Sidecar enthält einen Browser ohne Fenster: ein Chromium, das Seiten vollständig aufbaut, als würde ein Mensch sie öffnen, nur eben unsichtbar. Es nimmt eine Adresse entgegen und gibt das fertig zusammengebaute HTML zurück. Daraus machen Readability und Trafilatura dann ihr Bestes.
Wann der unsichtbare Browser ran muss, entscheidet eine kleine Regel im Code. Drei Fälle: Readability hat fast nichts gefunden (weniger als 500 Zeichen), es gibt viele Überschriften aber kaum Absätze, oder die Qualitätsbewertung liegt unter der Hälfte des Maximums. Trifft nichts davon zu, bleibt es bei der normalen Extraktion. Antwortet der Sidecar nicht oder braucht er länger als 20 Sekunden, kommt das schwächere Ergebnis zurück, mit einem Hinweis, woran es lag.
Rendern dauert spürbar länger als ein normaler Abruf. Deshalb kam in derselben Version eine Statuszeile dazu, die anzeigt, was gerade passiert.
Der Plan, eine Woche zu warten, hat keine zwei Tage gehalten. Der Sidecar stand schon am 27. April, ein paar Stunden nach dem öffentlichen Push, und ging als Version 1.1.0 raus.
Und dann: zeigen
Was dann noch fehlte, war das Naheliegendste: das Ding mal jemandem zeigen. Einen Tag nach dem Push habe ich einen Post auf r/ClaudeAI geschrieben.
Was der ausgelöst hat, steht in Teil 9.
Teil 8 von 15 der PullMD Serie.
← PullMD Teil 7: Der MCP-Server | PullMD Teil 9: Reddit-Tag und die ersten Issues →