Mitte Juni 2026 wurden über 1500 AUR-Pakete kompromittiert (siehe auch den vorigen Blog-Beitrag zu diesem Thema). Es zeugt natürlich von großer Überheblichkeit, als Mitautor eines Hacking-Buches zu glauben, selbst immun gegen Angriffe zu sein. Ein Update zum falschen Zeitpunkt hat mich auf den Boden der Tatsachen zurückgeholt und mir — einen Tag vor Urlaubsantritt — … Lehren aus dem AUR-Angriff weiterlesen →
Mitte Juni 2026 wurden über 1500 AUR-Pakete kompromittiert (siehe auch den vorigen Blog-Beitrag zu diesem Thema). Es zeugt natürlich von großer Überheblichkeit, als Mitautor eines Hacking-Buches zu glauben, selbst immun gegen Angriffe zu sein. Ein Update zum falschen Zeitpunkt hat mich auf den Boden der Tatsachen zurückgeholt und mir — einen Tag vor Urlaubsantritt — eine Menge sinnloser Arbeit beschert. Ich habe Anthropic- und OpenAI-Keys widerrufen, die SSH-Keys des betroffenen Notebooks von diversen Servern und Dienstleistern gelöscht und unzählige Passwörter geändert. Sch***! Heute habe ich, natürlich ohne das System neuerlich zu booten, eine Analyse gemacht. Im Prinzip: pacman --root /mnt/arch --dbpath /mnt/arch/var/lib/pacman -Qm Ich habe 60 AUR-Pakete gefunden. Nur eines davon (libgdata, eine veraltete GNOME-Bibliothek für den Zugriff auf Google-Dienste) wurde kompromittiert. Ich habe es nur Stunden nach der Manipulation, aber eben noch vor der Berichterstattung über den Hack installiert. Extremes Pech im Timing! Dieser Blog-Beitrag ist der Versuch einer persönlichen Aufarbeitung. Was ist passiert? Warum ist es passiert? Und was kann ich daraus lernen? Eines vorweg. Dieser Artikel ist keine Kritik am Arch-Linux-Projekt. Dieses hat immer klar kommuniziert, dass AUR-Pakete — wie der Name schon sagt (Arch User Repository) — von den Benutzern selbst gepflegt werden und keiner Kontrolle unterliegen. Wer solche Pakete installiert, ist selbst verantwortlich, mit allen — dieses Mal sehr unerfreulichen — Konsequenzen. Auch Updates können gefährlich sein Die Sicherheitsempfehlung schlechthin lautet: »Installieren Sie regelmäßig Updates.« Aber diese Regel gilt nur für Pakete aus offiziellen Quellen. Für extern gepflegte Pakete wäre eine Cool-Down-Phase sinnvoll. Im Prinzip: »Mach ein Update aller offiziellen Pakete sowie eines aller extern gepflegten Pakete, sofern dieses Update zumindest 4 Tage alt ist«. (Über die genaue Zeitspanne kann man streiten.) Ich kenne allerdings keinen Paketmanager, der so eine Funktion bietet. In die richtige Richtung gehen die Auto-Update-Funktionen von Debian und Ubuntu: Unter Debian werden per Default ausschließlich offizielle Debian-Sicherheitsupdates berücksichtigt (Datei /etc/apt/apt.conf.d/50unattended-upgrades). Sonstige Updates werden ignoriert und müssen manuell installiert werden. Ubuntu ist etwas liberaler und installiert alle Updates aus offiziellen Quellen (aber ebenfalls keine aus externen Quellen). Kurz gesagt: Ein blindes Update über alle Pakete ist nur sinnvoll, wenn Sie sich über die Herkunft aller Pakete sicher sind. Vielleicht werde ich in zukünftigen Blog-Artikeln Tipps zusammenfassen, wie Updates feiner gesteuert werden können. Wozu überhaupt nicht-offizielle Pakete? Eine andere Sicherheitsempfehlung lautet: »Verwenden Sie nur offiziell gepflegte Pakete.« Dennoch hat praktisch jede Distribution zusätzliche Paketquellen: Arch Linux: AUR Debian: externe Debian-Repositories Fedora: externe YUM-Paketquellen, COPR RHEL + Klone: EPEL, Remi und andere externe YUM-Paketquellen Ubuntu: externe Debian-Repositories, PPAs Wenn externe Quellen unsicher sind, warum gibt es sie dann überhaupt? Weil sie manchmal der einzige und viel öfter der bequemste Weg sind, um Software zu installieren, die in den offiziellen Quellen fehlt. Für mich als Autor ist es wichtig, neue, nicht so bekannte Programme unkompliziert auszuprobieren. Viele Entwickler nutzen externe Pakete zur Installation von Tools, die nicht oder nur in veralteten Versionen zur Verfügung stehen. Schließlich fehlen kostenlose Programme mit kommerziellem Ursprung (also keine reine Open-Source-Software) wie Google Chrome in den offiziellen Quellen. Für »große« Distributionen gibt es zumeist »halb-offizielle« Pakete, aber für kleinere Distributionen wie Arch Linux sind Sie auf AUR-Pakete angewiesen. Insofern ist der Rat, auf externe Quellen zu verzichten, für fortgeschrittene Benutzer und Software-Entwicklerinnen nur schwer umzusetzen. Alles, worüber ich hier im Kontext von Linux-Paketen schreibe, gilt im Übrigen auch für die Erweiterungen/Bibliotheken aller wichtigen Programmiersprachen, Editoren und anderer Tools: also für Python-Module, NPM-Pakete, VSCode-Plugins etc. Der Überbegriff für Angriffe auf derartige Zusatzpakete lautet Software Supply Chain Attack (Lieferkettenangriff). Weniger ist mehr Für mich persönlich ist das AUR-Debakel ein Grund, die Nutzung externer Pakete viel stärker zu hinterfragen. Vorgenommen habe ich mir folgende Regeln: So wenig externe Pakete wie möglich! (Gibt es geeignete Alternativen in den offiziellen Quellen?) Ungenutzte externe Pakete deinstallieren. (Welche Pakete habe ich zwei, drei Monate nicht mehr gebraucht? Weg damit!) Eine stärkere Differenzierung zwischen Test- und Work-Systemen. Schadensminimierung Der AUR-Angriff hat auf Authentifizierungsdaten abgezielt, also Keys, Tokens, Passwörter etc. aus allen erdenklichen Quellen (.ssh-Verzeichnis, Passwörter diverser Browser usw.) Eine sehr detaillierte Analyse der Malware finden Sie auf ioctl.fail. In meinem Fall war das größte Problem die Passwortsynchronisation von Google Chrome. Ich speichere im Webbrowser viele Passwörter. Die Passwort-Synchronisation ist durch ein zusätzliches, persönliches Passwort geschützt. Bookmarks und Passwörter sollten also für Google unlesbar sein. Wenn ich ein neues System einrichte (Linux, Windows, macOS, iOS oder Android), installiere ich Google Chrome, melde mich bei Google an, gebe das Master-Passwort für Bookmarks und Passwörter ein und synchronisiere die Daten. Das geht blitzschnell und ist komfortabel. Aber es ist eben ein riesiger Single Point of Failure! Das Master-Passwort schützt mich vor einem Passwort-Hack bei Google, aber es hilft nicht, wenn der Angreifer die lokale Passwort-Datenbank (sqlite-Format) auslesen kann. Und genau das war beim AUR-Angriff der Fall. Die Konsequenz: Ich werde in Zukunft die Anzahl der so synchronisierten Passwörter auf ein absolutes Minimum reduzieren und länger nicht benutzte Passwörter löschen bzw. woanders speichern. Der naheliegende Ort wäre natürlich ein Passwort-Manager. Ich muss aber gestehen, dass ich diesen Programmen gegenüber auch skeptisch bin. Sie ersetzen einen Single Point of Failure durch einen anderen. Wer mit plattformübergreifenden Tools positive Erfahrungen gemacht hat, darf seine/ihre Erfahrungen gerne in den Kommentaren teilen :-) Einmal mehr die Distributionsfrage Auf meinem Linux-Notebook werde ich die aktuelle Parallel-Installation von Arch Linux und CachyOS bei nächster Gelegenheit durch Fedora ersetzen. Ich habe das Notebook zuletzt fast nur noch unterwegs verwendet. Im Büro habe ich mit dem Framework Desktop eine attraktivere Alternative. Dort habe ich mich im Rahmen meiner KI-Arbeiten gut an Fedora gewöhnt. Zu glauben, Fedora sei frei von den skizzierten Gefahren, wäre natürlich naiv. Aber vermutlich sind die Risiken bei großen, weit verbreiteten Distributionen mit kommerziellem Hintergrund (Fedora ist ja eine Art offizielle Spielwiese von Red Hat) doch geringer als bei kleineren Distributionen — auch, was weit verbreitete, aber eben inoffizielle Paketquellen für Zusatzpakete angeht. Alleine schon die Trennung über mehrere Einzel-Repos anstelle des zentralen AUR-Verzeichnisses ist schon ein Vorteil. Der Abschied von Arch Linux fällt mir schwer. Ich empfinde das Rolling-Release-Modell äußerst attraktiv. Arch Linux hat über mehrere Jahre sehr gut für mich funktioniert. Aber ich werde auch in Zukunft nicht ganz ohne externe Pakete auskommen. Mit AUR habe ich mir die Finger einmal verbrannt. Diese Art der Verwaltung externer Pakete ist vielleicht doch zu liberal; Paketmanager wie yay oder paru verschleiern das Risiko zu sehr. Ein zweites Mal will ich dieses Risiko nicht eingehen. Quellen, Links https://ioctl.fail/preliminary-analysis-of-aur-malware/ https://github.com/lenucksi/aur-malware-check (Test-Scripts, ob Sie betroffen sind) https://kofler.info/infos-zur-arch-linux-attacke
Am 11.6. 2026 entdeckten Sicherheitsforscher kompromittierte AUR-Pakete in Arch Linux (AUR = Arch User Repository). Zwischenzeitlich waren ca. 1600 AUR-Pakete betroffen. AUR-Pakete sind nicht offizielle Zusatzpakete, die kein dezidiertes Prüfverfahren durchlaufen. Die Installation erfolgt häufig über einsteigerfreundliche Tools wie yay oder paru. Der Angriff erfolgte durch die Modifizierung der PKGBUILD-Dateien von Paketen, die als verwaist … Infos zur Arch-Linux-Attacke weiterlesen →
Am 11.6. 2026 entdeckten Sicherheitsforscher kompromittierte AUR-Pakete in Arch Linux (AUR = Arch User Repository). Zwischenzeitlich waren ca. 1600 AUR-Pakete betroffen. AUR-Pakete sind nicht offizielle Zusatzpakete, die kein dezidiertes Prüfverfahren durchlaufen. Die Installation erfolgt häufig über einsteigerfreundliche Tools wie yay oder paru. Der Angriff erfolgte durch die Modifizierung der PKGBUILD-Dateien von Paketen, die als verwaist (orphaned) galten, für die es also keinen Maintainer mehr gab. Aufgrund der veränderten PKGBUILD-Datei wurde zusätzlich zum Paket Schadsoftware installiert. Ziel des Angriffs ist offensichtlich das Einsammeln von Passwörtern aus Firefox- und Chromium-basierten Browsern sowie von SSH-Keys und anderer sensibler Daten. Die Informationen dazu sind noch spärlich. Ob ich selbst betroffen bin, kann ich aktuell nicht mit Sicherheit sagen; auf meinem Linux-Notebook habe ich zwei oder drei Tage vor Bekanntwerden das letzte Update durchgeführt. Vorerst habe ich das Gerät stillgelegt und den heutigen Morgen damit verbracht, potentiell betroffene SSH-Keys von diversen Server, GitHub- und GitLab-Accounts zu entfernen :-( An einer Neuinstallation wird kein Weg vorbeiführen. Detaillierte Informationen finden Sie hier: https://ioctl.fail/preliminary-analysis-of-aur-malware/ https://www.sonatype.com/blog/atomic-arch-npm-campaign-adds-malicious-dependency https://cybersecuritynews.com/arch-linux-aur-packages-compromised/ https://linuxnews.de/massiver-angriff-auf-das-aur-ueber-400-pakete-kompromittiert/ https://lists.archlinux.org/archives/list/aur-general@lists.archlinux.org/thread/FGXPCB3ZVCJIV7FX323SBAX2JHYB7ZS4/ (Diskussion auf dem Arch-Linux-Forum) https://md.archlinux.org/s/SxbqukK6IA (Liste der betroffenen Pakete, inoffiziell, Stand 13.6.2026) https://github.com/lenucksi/aur-malware-check (Test-Scripts, ob Sie betroffen sind) Weitere Links https://www.heise.de/news/Angriffswelle-auf-Arch-Linux-Hunderte-Paketbeschreibungen-mit-Malware-im-AUR-11330029.html https://www.phoronix.com/news/Arch-Linux-AUR-More-Than-1500 https://www.archlinux.de/news/35807-Aktuelle-Aktivitaeten-schaedlicher-Pakete-im-AUR (spärliche Informationen) https://wiki.archlinux.org/title/Arch_User_Repository (Erklärung, was AUR-Pakete sind)
Im April oder Mai 2026 habe ich einen denkwürdigen Meilenstein erreicht: Laut meinen Aufzeichnungen wurden eine Million meiner Bücher verkauft. Ein guter Anlass für einen beruflichen Rückblick und ein Dankeschön! Die erste Million fällt zufälligerweise mit einem anderen Jubiläum zusammen: Vor 40 Jahren habe ich mit der Arbeit an meinem ersten Buch begonnen, dem Atari … Die erste Million (1.000.000 📚) weiterlesen →
Im April oder Mai 2026 habe ich einen denkwürdigen Meilenstein erreicht: Laut meinen Aufzeichnungen wurden eine Million meiner Bücher verkauft. Ein guter Anlass für einen beruflichen Rückblick und ein Dankeschön! <img fetchpriority="high" decoding="async" src="https://kofler.info/wp-content/uploads/regal-2026-04-1920.jpg" alt="" width="1920" height="842" class="size-full wp-image-9620" srcset="https://kofler.info/wp-content/uploads/regal-2026-04-1920.jpg 1920w, https://kofler.info/wp-content/uploads/regal-2026-04-1920-850x373.jpg 850w, https://kofler.info/wp-content/uploads/regal-2026-04-1920-1280x561.jpg 1280w, https://kofler.info/wp-content/uploads/regal-2026-04-1920-768x337.jpg 768w, https://kofler.info/wp-content/uploads/regal-2026-04-1920-1536x674.jpg 1536w" sizes="(max-width: 1920px) 100vw, 1920px" /> Die gesammelten Werke (Stand Anfang April 2026) Die erste Million fällt zufälligerweise mit einem anderen Jubiläum zusammen: Vor 40 Jahren habe ich mit der Arbeit an meinem ersten Buch begonnen, dem Atari ST Grafikbuch (mehr Details hier). Dieses Buch war ein Mittelding zwischen Abenteuer, Hobby und Ferialjob. Nie hatte ich damals gedacht, dass das Schreiben zu meinem Beruf werden könnte. Das Atari-ST-Grafikbuch (1. Auflage 1987) Während meines Elektrotechnik-Studiums folgten weitere Bücher zu GfA-Basic, Visual Basic und Mathematica (ein Computer-Algebra-Programm). Die Bücher habe ich überwiegend in den Sommerferien geschrieben. Charakteristisch für diese Zeit war meine grenzenlose Begeisterung für die IT: Der erste, zweite, dritte Computer! (1984: Oric 1, 1986: Atari ST, vermutlich 1990: der erste PC von Vobis) Das erste Programm in Maschinencode (6502) bzw. Assembler (Motorola 68000)! GfA-Basic, ein für die damalige Zeit modernes Basic samt vernünftigem Editor. Dann Visual Basic! Mir war sofort klar, welches Potenzial diese (beinahe erste) grafische IDE hatte. Mathematica! Da hatte ich jahrelang Mathematikvorlesungen besucht, integrieren und Differenzialgleichungen lösen gelernt, und plötzlich gab es ein Programm, das symbolisch rechnen konnte! Aus damaliger Perspektive war das so eindrucksvoll wie vor wenigen Jahren das erste Mal ChatGPT auszuprobieren. Ich empfand es großartig, diese Programme erkunden und dokumentieren zu dürfen — und damit auch noch Geld zu verdienen. Software mit all ihren Stärken und Schwächen zu beschreiben, wie sie in der Praxis wirklich funktionierten. (Halten Sie sich die Zeit vor Augen: Es gab damals noch kein öffentlich zugängliches Internet. Die einzige Dokumentation war ein mitgeliefertes, meist miserables Handbuch. Vereinzelt noch Zeitschriftenartikel.) Erst mit Abschluss von Studium und Zivildienst stellte sich die Frage: Weiter schreiben oder einen »richtigen« Beruf ergreifen? Ich entschied mich für die Selbstständigkeit — und hatte Glück: Zwei, drei Jahre später überschritt ich mit Visual Basic 3 zum ersten Mal die 10.000-Stück-Auflage. Aus meiner Sicht begann damals ein goldenes Zeitalter. Das Interesse an der IT war riesig, und ich hatte (zumindest manchmal) einen guten Riecher für die spannendsten Themen. Für wenige Jahre war ich Bestseller-Autor, zumindest im Maßstab von IT-Büchern. <img decoding="async" src="https://kofler.info/wp-content/uploads/kofler-translations.jpg" alt="" width="1920" height="691" class="size-full wp-image-9674" srcset="https://kofler.info/wp-content/uploads/kofler-translations.jpg 1920w, https://kofler.info/wp-content/uploads/kofler-translations-850x306.jpg 850w, https://kofler.info/wp-content/uploads/kofler-translations-1280x461.jpg 1280w, https://kofler.info/wp-content/uploads/kofler-translations-768x276.jpg 768w, https://kofler.info/wp-content/uploads/kofler-translations-1536x553.jpg 1536w" sizes="(max-width: 1920px) 100vw, 1920px" /> Einige Bücher sind auch als Übersetzungen erschienen Eine erste berufliche Zeitenwende war das Internet. Plötzlich gab es kostenlose, stets aktuelle Information — eine gewaltige Konkurrenz zu Büchern. Die Verkaufszahlen sanken, aber der Internet-Hype, stets neue Programmiersprachen, der Durchbruch von Open-Source-Software schufen gleichzeitig neue Möglichkeiten. Die Ausgesetztheit und das Risiko des selbstständigen Arbeitens wurden mir erstmals 2013 vollständig klar. Addison-Wesley, der Verlag, für den ich über 20 Jahre praktisch exklusiv geschrieben hatte, wurde innerhalb von Monaten abgewickelt und geschlossen. Ich hatte damals den Verdacht, dass die Zeit der IT-Bücher vorbei wäre. Erfreulicherweise fand ich beim Rheinwerk Verlag (ehemals Galileo Press) eine neue Heimat und bin dort sehr glücklich (siehe auch hier). Mit ChatGPT & Co. hat ein neuer Umbruch begonnen: KI-Tools stellen die ganze IT-Branche auf den Kopf und verkleinern das Zielpublikum für Coding-Bücher dramatisch. Natürlich ergeben sich auch damit neue Chancen. Unser Buch Coding mit KI steckt ab, was aktuell technisch möglich ist — und das ist absolut faszinierend! In gewisser Weise schließt sich mit dem Thema »Künstliche Intelligenz« der Kreis dieses Rückblicks: Die Faszination, die ich als Jugendlicher für die ersten Computer empfand, ist nach wie vor da. Heute richtet sie sich auf die Möglichkeiten, die KI-Tools bieten. Was wird morgen kommen? Danke! Leserinnen und Leser: Hätten Sie nicht immer wieder meine Bücher gekauft, auf Amazon hoch bewertet und in Ihrem beruflichen und privaten Umfeld weiterempfohlen, wäre mein berufliches Dasein nicht möglich gewesen. Danke, danke, danke! Verlag/Lektorat/Herstellung: Ich schreibe meine Bücher selbst (im KI-Zeitalter ist das ja nicht mehr selbstverständlich), aber ein Buch entsteht doch nie alleine. Einen ganz wesentlichen Einfluss hat der Verlag und dort speziell das Lektorat. Es spricht bei der Planung des Buchs, bei der inhaltlichen Ausrichtung, der Korrektur, dem Layout, dem Titelbild, beim Marketing und der Werbung mit. Ohne die Mithilfe des Verlags sind erfolgreiche Bücher praktisch unmöglich. Im Verlauf von vier Jahrzehnten hatte ich durchwegs großartige und engagierte Lektorinnen und Lektoren, von denen ich die wichtigsten hier namentlich nennen möchte: Norbert Hesselmann (der Lektor meines ersten Buchs, Sybex), Irmgard Wagner und Boris Karnikowski (beide prägten meine Zeit bei Addison-Wesley) sowie Sebastian Kestel und Christoph Meister (beide waren/sind im Rheinwerk Verlag tätig). Eine besondere Rolle im Verlag nimmt die Herstellung ein: Diese Abteilung des Verlags ist verantwortlich dafür, dass Bücher in ordentlichem Layout gesetzt und dann gedruckt werden, dass E-Books in allen erdenklichen Formaten zur Verfügung stehen usw. Aus historischen Gründen setze ich die meisten Bücher selbst, früher mit LaTeX, jetzt mit einem Docker-Setup bestehend aus Markdown, Pandoc und LuaTeX. Dass ich selbst setzen kann und darf, ist ein absoluter Sonderfall; ich bedanke mich ausdrücklich bei Norbert Englert (Rheinwerk Verlag) für seine Unterstützung. Meine Schreibumgebung unter Linux, links ein PDF-Viewer, oben Emacs, unten ein Terminal. Dasselbe Docker-Setup funktioniert eins zu eins auch unter macOS (und theoretisch sogar unter Windows). Co-Autoren: Im Lauf der Zeit habe ich ein halbwegs solides IT-Wissen erworben, aber es gibt doch Grenzen :-) Viele meiner Bücher wären/sind ohne die Team-Arbeit mit Co-Autoren unmöglich. Die zahlreichen Kooperationen waren immer äußerst produktiv und für mich sehr lehrreich. Mit Bernd Öggl (erster gemeinsamer Titel 2004: PHP und MySQL) ist daraus sogar eine langjährige berufliche Zusammenarbeit und private Freundschaft entstanden. Antworten auf Fragen, die Sie nie gestellt haben Kann man vom Bücherschreiben leben? Normalerweise nicht, in meinem Fall schon. Die ersten Jahre war das Schreiben von Computer-Büchern ein Mittelding zwischen Hobby und einem netten Zuverdienst neben dem Studium. Danach wurde das Schreiben mein Beruf; seit über 30 Jahren sind Bücher meine Haupteinnahmequelle. Einige Jahre habe ich (für meine Begriffe) großartig verdient, die restliche Zeit ganz passabel. <img loading="lazy" decoding="async" src="https://kofler.info/wp-content/uploads/kofler-work.jpg" alt="" width="1422" height="1920" class="size-full wp-image-9675" srcset="https://kofler.info/wp-content/uploads/kofler-work.jpg 1422w, https://kofler.info/wp-content/uploads/kofler-work-481x650.jpg 481w, https://kofler.info/wp-content/uploads/kofler-work-711x960.jpg 711w, https://kofler.info/wp-content/uploads/kofler-work-768x1037.jpg 768w, https://kofler.info/wp-content/uploads/kofler-work-1138x1536.jpg 1138w" sizes="auto, (max-width: 1422px) 100vw, 1422px" /> Im frisch renovierten Büro mit neuem Buchregal Macht das wirklich Spaß? Ja! Je neuartiger das Thema, desto besser. (Die zehnte Überarbeitung eines Buchs ist zugegebenermaßen weniger lustig.) Ich bin ja nicht ausschließlich Autor, sondern unterrichte gelegentlich an einer Fachhochschule, entwickle Software und administriere Server. Aber bei weitem die liebste Tätigkeit ist für mich das Konzipieren eines neuen Buchs, das Recherchieren und Ordnen von Informationen, das Verfassen von verständlichen Anleitungen und Erklärungen. Noch ein Argument für das Schreiben: die freie Zeiteinteilung. Kurz und gut: Ich habe es immer als Privileg empfunden, vom Schreiben leben zu können. Stimmt das mit der Million überhaupt? Ich bekomme je nach Verlag viertel-, halb- oder ganzjährig Abrechnungen mit Verkaufszahlen. Diese landen in einer großen LibreOffice-Calc-Datei. 95% der Million sind so belegt. Der Rest entfällt auf E-Books und Übersetzungen, für die ich zwar Geld, aber keine detaillierten Abrechnungen erhalten habe. Ich habe die Zahlen konservativ geschätzt, aber ich gebe zu: Ganz genau kann ich es nicht sagen. Vielleicht habe ich die Million schon im Februar erreicht, vielleicht ist es erst im Juli so weit. Ich denke, es spielt keine Rolle. Welche Bücher haben sich am besten verkauft? Auf Platz eins steht natürlich mein Linux-Buch, dessen zahlreiche Auflagen fast ein Drittel zur Million beitrugen. Andere Bestseller waren Visual Basic, Raspberry Pi, Excel VBA, Hacking & Security und der Python-Grundkurs. Wie geht es weiter? Wenn es nach mir geht: Auf zur nächsten Million! Realistisch gesehen haben IT-Fachbücher aber ihren Zenit überschritten. Speziell Programmiertitel kämpfen gegen die KI-Konkurrenz. IT-Studien leiden unter sinkenden Studentenzahlen. Konkret heißt das: Es wird Neuauflagen bzw. neue Bücher geben, solange Sie sie kaufen :-) PS: Bitte nehmen Sie sich hin und wieder Zeit für eine kurze Rezension! Das ist ein Zeichen der Wertschätzung für mich und eine Orientierungshilfe für andere. Ja, auch wenn die Links zu Amazon von dieser Website verschwunden sind, gerne dort. Auf Amazon werden die Rezensionen nämlich gelesen, selbst von Leuten, die dort nicht bestellen. Quellen/Links https://kofler.info/ueber/bibliografie https://kofler.info/ueber/uebersetzungen https://kofler.info/30-jahre-linux-buch https://kofler.info/10-jahre-beim-rheinwerk-verlag https://kofler.info/20-jahre-linux-buch https://kofler.info/30-jahre-buchautor
Vor gut zweieinhalb Jahren habe ich hier über pip-Probleme berichtet, die unter aktuellen Ubuntu- und Debian-Systemen aufgetreten sind: externally-managed-environment (PEP 668) verhinderte lokale pip-Installationen wegen Konflikten zwischen System-Paketen. Die damals beschriebenen Lösungen, insbesondere das Einrichten eines virtuellen Environments, funktionieren weiterhin. Aber inzwischen gibt es eine bessere Option: uv ist ein schneller, moderner Paketmanager für Python, … Python-Modulmanager uv weiterlesen →
Vor gut zweieinhalb Jahren habe ich hier über pip-Probleme berichtet, die unter aktuellen Ubuntu- und Debian-Systemen aufgetreten sind: externally-managed-environment (PEP 668) verhinderte lokale pip-Installationen wegen Konflikten zwischen System-Paketen. Die damals beschriebenen Lösungen, insbesondere das Einrichten eines virtuellen Environments, funktionieren weiterhin. Aber inzwischen gibt es eine bessere Option: uv ist ein schneller, moderner Paketmanager für Python, der pip, venv, pipx und noch einige andere Tools auf einmal ersetzt. Wer regelmäßig Python-Module installiert, sollte sich die paar Minuten nehmen, uv kennenzulernen. Es lohnt sich. Update 8.6.2026: uv und Cron Das pip-Problem Zuerst eine kurze Wiederholung meines alten Artikels: Bei immer mehr Linux-Distributionen verhindert PEP 668, dass pip install systemweit Pakete installiert. Stattdessen erscheint die Fehlermeldung externally-managed-environment. Es gibt zwei Auswege: entweder installieren Sie das Python-Modul als Distributionspaket (falls verfügbar), oder sie richten ein Virtual Environment, also ein projektspezifisches Verzeichnis mit eigenen, isolierten Modul-Installationen. Das Einrichten eines Virtual Environments mit python3 -m venv .venv ist nicht schwierig, aber umständlich. Man muss es bei jedem neuen Terminal-Fenster aktivieren (source .venv/bin/activate oder eine Variante dieses Kommandos für Zsh, Fish oder PowerShell), eine requirements.txt pflegen und bei der Weitergabe des Projekts dem Empfänger erklären, was er zu tun hat. uv macht das alles einfacher. Was ist uv? uv ist in der Programmiersprache Rust entwickelt worden und stammt von der Firma Astral. Im März 2026 hat OpenAI Astral übernommen; das Team arbeitet seitdem in der Codex-Abteilung. Ob und wie das die Weiterentwicklung von uv beeinflusst, ist noch nicht absehbar. Das Projekt bleibt aber Open Source (https://github.com/astral-sh/uv). Was uv von pip unterscheidet: Es ersetzt pip, venv, pip-tools, pipx und pyenv in einem einzigen Binary. Es ist laut eigenen Benchmarks 10- bis 100-mal schneller als pip. Es verwaltet Abhängigkeiten in pyproject.toml und einer Lock-Datei. Das manuelle Pflegen von requirements.txt ist damit vorbei. Allein im Februar 2026 wurde uv über 126 Millionen Mal heruntergeladen. Es hat sich als De-facto-Standard für neue Python-Projekte etabliert. Auch bei meinen eigenen Python-Projekten ist uv inzwischen eine Selbstverständlichkeit geworden. Das Kommando ist einfach zu bedienen und funktioniert gut. uv installieren uv wird unabhängig von Python installiert. Unter macOS gelingt das am einfachsten mit Homebrew: brew install uv Bei manchen Linux-Distributionen steht uv als Paket zur Verfügung (apt install uv, dnf install uv). Falls nicht, funktioniert dieses Vorgehen: curl -LsSf https://astral.sh/uv/install.sh -o uv_install.sh less uv_install.sh # kurze Kontrolle sh uv_install.sh Das Script gibt am Ende Hinweise, wie .local/bin zur PATH-Variablen hinzuzufügen ist. Unter Windows führen Sie folgende PowerShell-Kommandos aus: powershell -ExecutionPolicy ByPass ` -c "irm https://astral.sh/uv/install.ps1 | iex" $env:Path = "C:\Users\<accountname>\.local\bin;$env:Path" Nach der Installation überzeugen Sie sich kurz davon, dass alles geklappt hat: uv --version uv 0.11.19 (...) Updates führen Sie mit brew upgrade uv (macOS) bzw. durch Wiederholung des Installations-Kommandos durch. Weitere Installationstipps finden Sie auf der GitHub-Seite. Neues Projekt einrichten Nehmen wir an, Sie entwickeln ein Script, das die Module requests und beautifulsoup4 benötigt. Die folgenden Kommandos richten das Projekt ein: uv init my-webscraper # erzeugt das Projektverzeichnis cd my-webscraper # dorthin wechseln uv add requests beautifulsoup4 # Module installieren Falls es schon ein Projektverzeichnis gibt, wechseln Sie mit cd dorthin und führen uv init . aus. uv init erzeugt ein Projektverzeichnis mit folgender Struktur: my-webscraper/ ├── .gitignore ├── .python-version ├── .venv/ ├── main.py ├── pyproject.toml └── README.md uv init kümmert sich also um das Virtual Environment im Verzeichnis .venv. uv add installiert das gewünschte Modul und trägt es in pyproject.toml ein. Hinweis: Die Datei .gitignore wird nicht erzeugt bzw. verändert, wenn das aktuelle Verzeichnis bereits unter Git-Kontrolle steht. In diesem Fall sollten Sie selbst in .gitignore eine Regel einbauen, die das Verzeichnis .venv ignoriert. Ihr Script führen Sie mit uv run aus: uv run main.py uv run sorgt dafür, dass die richtige Python-Version und das Virtual Environment aktiv sind. Sie müssen sich um nichts weiter kümmern. Weitere Module fügen Sie mit uv add hinzu, überflüssige entfernen Sie mit uv remove. Normalerweise verwendet uv einfach die gerade installierte Python-Version. Wenn Sie ausnahmsweise für ein Projekt eine andere Version benötigen, installieren und fixieren Sie diese: uv python install 3.12 uv python pin 3.12 Projektweitergabe uv pflegt mehrere Dateien für die Projektverwaltung: pyproject.toml enthält die Abhängigkeiten des Projekts. uv.lock enthält die exakten Versionsnummern aller installierten Module. .python-version enthält die gewünschte Python-Version. Wenn Sie Ihr Projekt weitergeben oder auf einem anderen Rechner einsetzen möchten, geben Sie neben dem Quellcode die ersten beiden Dateien weiter, falls die Python-Version wichtig ist, auch die dritte. Die Empfängerin kann das Projekt dann sofort ausführen: uv run main.py uv erkennt pyproject.toml und uv.lock, richtet das Virtual Environment ein und installiert alle erforderlichen Module — vollautomatisch, ohne weitere Anweisungen. Ältere Projekte mit requirements.txt Bei bestehenden Projekten, die noch requirements.txt verwenden, bietet uv ebenfalls Unterstützung: uv venv # Virtual Environment einrichten uv pip install -r requirements.txt # Abhängigkeiten installieren Bestehende Projekte auf uv migrieren Wer ein vorhandenes Projekt von pip auf uv umstellen möchte, beginnt mit uv init --bare im Projektverzeichnis. Das Flag --bare verhindert, dass Beispieldateien erzeugt oder vorhandene Dateien überschrieben werden. Als Ergebnis erscheint eine minimale pyproject.toml. Im nächsten Schritt importieren Sie die bisherigen Abhängigkeiten aus requirements.txt: cd my-project uv init --bare uv add -r requirements.txt uv add -r requirements.txt trägt alle Module in pyproject.toml ein und erzeugt gleichzeitig uv.lock mit den exakten Versionsnummern. Mit uv sync installiert uv anschließend alle Module in einem neuen .venv-Verzeichnis — ohne manuelles Aktivieren der Umgebung. Ab jetzt führen Sie Ihr Script mit uv run aus. Nach erfolgreicher Migration geben Sie künftig pyproject.toml und uv.lock weiter — requirements.txt können Sie löschen. Falls CI-Systeme oder Docker-Builds weiterhin eine requirements.txt benötigen, lässt sie sich jederzeit automatisch aus der Lock-Datei erzeugen: uv export --format requirements-txt > requirements.txt Python-Tools global installieren uv ersetzt auch pipx: Mit uv tool install installieren Sie in Python entwickelte Kommandozeilen-Tools direkt auf Ihrem Rechner, außerhalb eines Projektverzeichnisses. Die Tools landen in .local/share/uv/tools, Links dazu werden in .local/bin angelegt: uv tool install httpie httpie --version 3.2.4 Noch praktischer ist uvx: Damit führen Sie ein Tool aus, ohne es permanent zu installieren. uv lädt die erforderlichen Dateien in ein Cache-Verzeichnis und führt das Tool sofort aus — ideal für die gelegentliche Nutzung: uvx ruff check . # überprüft alle Python-Dateien im Verzeichnis Mit uv cache clean löschen Sie bei Bedarf die zwischengespeicherten Dateien. uv und Cron Wer ein Python-Script per Cron automatisch ausführen möchte, stößt auf zwei Probleme: Erstens ist uv häufig lokal installiert, meist in .local/bin/uv. Cron verwendet eine minimale PATH-Variable und findet das Kommando uv daher nicht. Zweitens setzt uv run voraus, dass das aktuelle Verzeichnis das Projektverzeichnis ist — das ist beim Aufruf per Cron ebenfalls nicht der Fall. Theoretisch könnten Sie beide Probleme durch die Angabe absoluter Pfaden in der crontab-Datei lösen. Eleganter ist es aber, ein kleines Wrapper-Script zu schreiben: # Datei /home/user/myproject/run.sh cd /home/user/myproject /home/user/.local/bin/uv run main.py Dieses Script rufen Sie dann aus Cron auf: # /etc/crontab 0 8 * * * user /home/user/myproject/run.sh user ersetzen Sie jeweils durch Ihren Benutzernamen. Vergessen Sie nicht, das Script ausführbar zu machen (chmod +x run.sh). Quellen/Links https://peps.python.org/pep-0668 https://docs.astral.sh/uv https://docs.astral.sh/uv/guides/migration/pip-to-project/ https://github.com/astral-sh/uv https://simonwillison.net/2026/Mar/19/openai-acquiring-astral https://dasroot.net/posts/2026/05/uv-openai-python-supply-chain-acquisition-risks/ https://kofler.info/hilfe-pip-funktioniert-nicht-mehr/
Wer mein Linux-Buch gelesen hat weiß, dass ich nicht im Vi-Lager zuhause bin, sondern zu den Emacs-Fans zähle. Beim Programmieren verwende ich diverse Editoren und IDEs, von VSCode über IntelliJ bis hin zu Xcode. Aber längere Texte (sprich: Bücher) schreibe ich seit Jahrzehnten ausschließlich mit dem Emacs. Ich habe ein paar halbherzige Versuche mit anderen … Emacs als Markdown-Editor weiterlesen →
Wer mein Linux-Buch gelesen hat weiß, dass ich nicht im Vi-Lager zuhause bin, sondern zu den Emacs-Fans zähle. Beim Programmieren verwende ich diverse Editoren und IDEs, von VSCode über IntelliJ bis hin zu Xcode. Aber längere Texte (sprich: Bücher) schreibe ich seit Jahrzehnten ausschließlich mit dem Emacs. Ich habe ein paar halbherzige Versuche mit anderen Editoren gemacht, aber ich bin immer wieder zurückgekommen. Meine Emacs-Liebe hat weniger mit der Großartigkeit dieses Programms zu tun als viel mehr damit, dass ich mir im Laufe der Zeit ein eigenes Setup mit Tastenkürzeln und Zusatzfunktionen gebastelt habe. Davon bin ich jetzt abhängig, meine Finger wollen sich nicht mehr umgewöhnen. <img loading="lazy" decoding="async" src="https://kofler.info/wp-content/uploads/emacs-markdown-1.png" alt="" width="2284" height="1896" class="size-full wp-image-9657" srcset="https://kofler.info/wp-content/uploads/emacs-markdown-1.png 2284w, https://kofler.info/wp-content/uploads/emacs-markdown-1-783x650.png 783w, https://kofler.info/wp-content/uploads/emacs-markdown-1-1156x960.png 1156w, https://kofler.info/wp-content/uploads/emacs-markdown-1-768x638.png 768w, https://kofler.info/wp-content/uploads/emacs-markdown-1-1536x1275.png 1536w, https://kofler.info/wp-content/uploads/emacs-markdown-1-2048x1700.png 2048w" sizes="auto, (max-width: 2284px) 100vw, 2284px" /> Eine Markdown-Datei aus meinem Scripting-Buch im Emacs. Beachten Sie, dass die Listenpunkte intern zwar sehr lange Textzeilen sind, dass diese aber umbrochen und richtig eingerückt angezeigt werden. Der Umbruch ist auf max. 100 Zeichen limitiert, passt sich aber automatisch an eine kleinere Fensterbreite an. Die Motivation für diesen Blogbeitrag ist die immer wiederkehrende Frage, womit ich meine Markdown-Texte verfasse. Vielleicht finden andere Emacs-Fans in der nachfolgenden .emacs-Datei Ideen, die sie noch nicht kennen; vielleicht schreibt mir auch jemand im Forum, welches Feature ich bisher übersehen habe. Dieser Beitrag ist aber keinesfalls ein Versuch, Sie vom Emacs zu überzeugen. Ein Neustart heute bei Null — da würde ich höchstwahrscheinlich bei einem deutlich moderneren Programm landen (möglicherweise bei zed). Dieser Text will Ihnen auch nicht meine Tastenkürzel aufzwingen. Die sind im Laufe der Zeit eher zufällig entstanden. Aber dieser Teil von .emacs lässt sich ja am einfachsten anpassen. Die Datei .emacs Die Konfiguration des Emacs erfolgt in der Datei .emacs. Die Anweisungen dort müssen in der Programmiersprache Elisp formuliert werden. Das ist die Emacs-Variante der heute ansonsten kaum noch gebräuchlichen Sprache Lisp. Früher war Elisp eine Hürde für viele Emacs-Einsteiger, und in einigen frühen Auflagen meines Linux-Buchs hatte ich sogar ein kurzes Elisp-Kapitel untergebracht. Heute sagen Sie Claude oder einem anderen KI-Tool, was Sie erreichen wollen, schon bekommen Sie den erforderlichen Code. (Manchmal klappt es erst im zweiten oder dritten Versuch.) Dank KI ist die Elisp-Syntaxhürde also überwunden. Der Emacs liest .emacs automatisch beim Start. Spätere Änderungen gelten daher erst mit dem nächsten Start oder indem Sie die geänderten Zeilen markieren und mit Alt+X eval-region Return ausführen. Meine Konfiguration Die ersten Zeilen im folgenden Listing aktivieren einige allgemeine Einstellungen. cua-mode erlaubt die vertrauten Tastenkürzel Strg+C, Strg+X und Strg+V für Kopieren, Ausschneiden und Einfügen. Im originalen Emacs gibt es dafür andere Kürzel, die parallel aktiv bleiben. save-place-mode bewirkt, dass der Emacs die letzte Cursor-Position in jeder geöffneten Datei dauerhaft speichert. Damit das Arbeitsverzeichnis nicht mit Backup-Dateien übersät wird, landen Emacs-Backups gesammelt in ~/.emacs.d/backups/. Moderne Emacs-Konfigurationen laden Erweiterungspakete über package.el nach. Das Standard-Repository des Emacs enthält nur wenige Pakete; deshalb binde ich MELPA ein, das mit Abstand größte Community-Repository mit Tausenden von Erweiterungen. Beim ersten Start auf einem neuen Rechner aktualisiert der Emacs automatisch die Paketliste (package-refresh-contents), sodass alle benötigten Pakete sofort installiert werden können. Das Makro use-package bündelt je ein Paket zusammen mit seiner Konfiguration, Hooks und Tastenkürzel-Bindungen in einem einzigen Block. Die Einstellung use-package-always-ensure t sorgt dafür, dass fehlende Pakete automatisch nachinstalliert werden, ohne manuelles Eingreifen. Der markdown-mode aus dem gleichnamigen Paket steht im Zentrum des Setups. Der Modus hebt Markdown-Syntax farbig hervor und aktiviert über Hooks mehrere Begleitmodi: visual-line-mode sorgt für weiche Zeilenumbrüche ohne harte Zeilenenden in der Datei, display-line-numbers-mode blendet Zeilennummern ein, und visual-fill-column-mode begrenzt die Textbreite auf 100 Zeichen. adaptive-wrap ist ein kleines, aber feines Detail: Wenn eine Zeile weich umgebrochen wird, rückt die Folgezeile so ein, dass Listenelemente (* oder -) korrekt untereinander ausgerichtet bleiben. unfill ergänzt den eingebauten Befehl fill-paragraph (bei mir F4): Statt einen Absatz auf mehrere kurze Zeilen zu verteilen, fasst unfill-paragraph alle Zeilen eines Absatzes wieder zu einer einzigen langen Zeile zusammen. Das ist hilfreich, wenn Markdown-Quellen von anderen Tools weiterverarbeitet werden. Das Paket vertico erweitert den Emacs-Minibuffer um eine vertikale Auswahlliste (siehe den folgenden Screenshot). Beim Wechsel zwischen Buffern (F1) sehe ich alle offenen Dateien auf einen Blick inklusive Dateigröße, Modus und Pfad — letzteres dank marginalia, das die Listeneinträge um nützliche Zusatzinformationen ergänzt. orderless macht die Suche komfortabler: Ich kann mehrere Suchbegriffe mit Leerzeichen trennen und in beliebiger Reihenfolge eingeben. <img loading="lazy" decoding="async" src="https://kofler.info/wp-content/uploads/emacs-minibuffer.png" alt="" width="2284" height="1324" class="alignnone size-full wp-image-9658" srcset="https://kofler.info/wp-content/uploads/emacs-minibuffer.png 2284w, https://kofler.info/wp-content/uploads/emacs-minibuffer-850x493.png 850w, https://kofler.info/wp-content/uploads/emacs-minibuffer-1280x742.png 1280w, https://kofler.info/wp-content/uploads/emacs-minibuffer-768x445.png 768w, https://kofler.info/wp-content/uploads/emacs-minibuffer-1536x890.png 1536w, https://kofler.info/wp-content/uploads/emacs-minibuffer-2048x1187.png 2048w" sizes="auto, (max-width: 2284px) 100vw, 2284px" /> Die benutzerdefinierte vertico-sort-override-function ändert die Sortierreihenfolge im Buffer-Switcher: Statt alphabetischer Reihenfolge erscheinen die zuletzt verwendeten Buffer ganz oben in der Liste. Bei vielen Dateien finde ich die zuletzt verwendeten Datei schneller. swap-char (F11) vertauscht die zwei Zeichen an der Cursor-Position. Tippfehler wie getsern statt gestern lassen sich damit sofort korrigieren: Cursor auf das erste falsche Zeichen, einmal F11, fertig. change-case (F12) wechselt die Groß- bzw. Kleinschreibung des Zeichens unter dem Cursor. change-word-case (F9) tut dasselbe für den ersten Buchstaben des aktuellen Worts, unabhängig davon, wo im Wort der Cursor gerade steht. point-to-register-1 (F5) / jump-to-register-1 (F6): Mit F5 speichere ich die aktuelle Position, mit F6 springe ich dorthin zurück. Beim Sprung wird gleichzeitig die neue Position gespeichert, sodass ich mit wiederholten F6-Drücken zwischen zwei weit entfernten Textstellen hin- und herspringen kann. Ich finde das praktisch, wenn ich parallel an zwei Stellen eines langen Dokuments arbeite. expand-abbrev-or-dabbrev (F3) versucht zunächst, eine gespeicherte Abkürzung zu expandieren. In .abbrevs_defs habe ich einige solche Abkürzungen gespeichert, z.B. ms für »Microsoft« oder rhel für »Red Hat Enterprise Linux«. Falls keine passt, greift dabbrev-expand und vervollständigt das angefangene Wort anhand von Vorkommen im selben Buffer. Praktisch für lange Schlüsselwörter. Beim Einlesen der .emacs-Datei lädt der Editor automatisch alle erforderlichen Pakete herunter. Wenn dabei Download-Fehler auftreten, müssen Sie eventuell den MELPA-Cache aktualisieren. Dazu führen Sie Alt+X package-refresh-contents Return aus und starten den Emacs dann neu. ;; Datei ~/.emacs ;; ======== Grundeinstellungen ==================================== (cua-mode 1) ;Cut&Paste mit Strg+C/X/V (setq inhibit-startup-message t) ;kein Emacs-Startbildschirm (setq screen-preserve-screen-position t) ;zurück zur letzten Zeile (setq scroll-step 5) ;bei Scrollen Sprünge von 5 Zeilen (column-number-mode 1) ; ... Spaltennummern in der Statusleiste (abbrev-mode 0) ;kein automatisches expand-abbrev (setq require-final-newline t) ;letzte Zeile automatisch mit Return abschließen (save-place-mode) ;Cursor-Position innerhalb der Datei merken ;; automatische Backups nicht im lokalen Verzeichnis, sondern in ~/.emacs.d/backups/ (setq backup-directory-alist `(("." . ,(concat user-emacs-directory "backups")))) (setq auto-save-file-name-transforms `((".*" ,(concat user-emacs-directory "backups/") t))) ;; Spaltenbreite für Zeilennummern (nur Markdown) (setq-default display-line-numbers-width 4) ;; Abkürzungstabelle automatisch laden und speichern ;; Falls ~/.abbrev_defs nicht existiert, leere Datei anlegen (kein Fehler) (let ((abbrev-file "~/.abbrev_defs")) (unless (file-exists-p abbrev-file) (write-region "" nil abbrev-file)) (read-abbrev-file abbrev-file)) (setq save-abbrevs t) ;automat. speichern ;; ======== Packages ================================================ ;; package.el initialisieren und MELPA-Repo hinzufügen (falls erforderlich) (require 'package) (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t) (package-initialize) ;; Paket-Repo aktualisieren (first run / new machine) (when (not package-archive-contents) (package-refresh-contents)) ;; alle erforderlichen Pakete automatisch laden (unless (package-installed-p 'use-package) (package-install 'use-package)) (require 'use-package) (setq use-package-always-ensure t) ;; scratch-Buffer automatisch speichern (https://github.com/Fanael/persistent-scratch) (use-package persistent-scratch :config (persistent-scratch-setup-default)) ;; weiche Zeilenumbrüche mit Einrückung bei Listen etc. (use-package adaptive-wrap :hook (visual-line-mode . adaptive-wrap-prefix-mode)) ;; Spalte mit Zeilennummern / zentrierter Text (use-package visual-fill-column :hook (markdown-mode . visual-fill-column-mode) :config (setq-default visual-fill-column-width 100) (setq visual-fill-column-width 100)) ;; Markdown-Modus (use-package markdown-mode :mode (("\\.text\\'" . markdown-mode) ("\\.md\\'" . markdown-mode)) :hook ((markdown-mode . visual-line-mode) ; soft-wrap long lines (markdown-mode . display-line-numbers-mode) ; show line numbers (markdown-mode . visual-fill-column-mode) ; center text within column width (markdown-mode . (lambda () (setq fill-column 79))))) ; hard-wrap at 79 chars ;; Unfill: mehrzeilige Absätze zu einer langen Zeile verbinden (Shift+F4) (use-package unfill) ;; mehr Komfort im Minibuffer (use-package vertico :config (vertico-mode 1) ; sort buffer list by 'recently shown' (setq vertico-sort-override-function (lambda (candidates) (if (eq minibuffer-history-variable 'buffer-name-history) (let ((hist (symbol-value minibuffer-history-variable))) (sort candidates (lambda (a b) (let ((pa (or (cl-position a hist :test #'equal) most-positive-fixnum)) (pb (or (cl-position b hist :test #'equal) most-positive-fixnum))) (< pa pb))))) candidates)))) (use-package orderless :config (setq completion-styles '(orderless basic))) (use-package marginalia :config (marginalia-mode 1)) ;; schönere Statuszeile (setzt voraus, dass die JetBrains Nerd Fonts ;; installiert und als Emacs-Font verwendet werden) (use-package nerd-icons :config (setq nerd-icons-font-family "JetBrainsMono Nerd Font")) (use-package doom-modeline :after nerd-icons :config (doom-modeline-mode 1) (setq doom-modeline-height 25) (setq doom-modeline-icon t)) ;; Ligaturen (setzt ebenfalls einen Nerd Font voraus) (use-package ligature :config (ligature-set-ligatures 't '("!=" "!==" "->" "<-" "=>" "<=>" ">=" "<=" "//")) (global-ligature-mode t)) ;; ======== Farben ================================================ (set-face-attribute 'line-number nil :height 0.8 :foreground "#ffffff" :background "#dddddd") (set-face-attribute 'link nil :foreground "RoyalBlue3" :underline nil) ;; für Markdown-Modus (with-eval-after-load 'markdown-mode (set-face-attribute 'markdown-italic-face nil :inherit 'italic :foreground "dark magenta" :slant 'italic) (set-face-attribute 'markdown-pre-face nil :inherit 'font-lock-constant-face)) (with-eval-after-load 'doom-modeline (set-face-attribute 'doom-modeline-buffer-modified nil :foreground "firebrick" :weight 'bold)) ;; ======== eigene Funktionen =================================================== (defun expand-abbrev-or-dabbrev () ;Expansion von Abkürzung: F3 (interactive) (unless (expand-abbrev) ;falls keine Abkürzung existiert (dabbrev-expand nil))) ;dynamische Expansion (defvar my-point-register 1 "Hilfsvariable für jump-to-register-1: merkt sich, welches Register aktiv ist.") (defun point-to-register-1 () ;Position in Reg. 1 speichern: F5 (interactive) (setq my-point-register 1) (point-to-register 1)) (defun jump-to-register-1 () ;Position wechseln: F6 (interactive) ;springt zur Position, die mit F5 (if (= my-point-register 1) ; gespeichert wurde ... (progn (setq my-point-register 2) (point-to-register 2) (jump-to-register 1)) (progn (setq my-point-register 1) (point-to-register 1) (jump-to-register 2)))) (defun swap-char () ;zwei Buchstaben an der Cursor-Position (interactive) ;vertauschen: F11 (save-excursion (forward-char) (transpose-chars 1))) (defun change-case () ;Groß- und Kleinschreibung des Zeichens (interactive) ;an der Cursorposition ändern: F12 (let ((zeichen (char-after (point)))) (if (> zeichen 64) (progn (setq zeichen (logxor zeichen 32)) (insert-char zeichen 1) (delete-char 1)) (forward-char 1)))) (defun change-word-case () ;Groß- und Kleinschreibung des ersten (interactive) ;Zeichens eines Worts verändern: F9 (point-to-register 2) (backward-word 1) (change-case) (jump-to-register 2)) (defun unfill-paragraph-and-advance () ;Absatz zusammenfügen und zum nächsten springen: S-F4 (interactive) (unfill-paragraph) (forward-paragraph) (skip-chars-forward "\n") (recenter)) (defun toggle-fill-column-width () ;Zeilenumbruch zwischen 100 und 1000 Zeichen wechseln (interactive) (setq-local visual-fill-column-width (if (eq visual-fill-column-width 100) 1000 100)) (visual-fill-column-mode 1)) ;; ======== Tastenkürzel ====================================================== (global-set-key [f1] 'switch-to-buffer) ;F1 Buffer wechseln (global-set-key [f2] 'other-window) ;F2 Fenster wechseln (global-set-key [f3] 'expand-abbrev-or-dabbrev) ;F3 Abkürzung erweitern (global-set-key [f4] 'fill-paragraph) ;F4 Absatz umbrechen (global-set-key [S-f4] 'unfill-paragraph-and-advance) ;S-F4 Absatz zusammenfügen + nächster (global-set-key [f5] 'point-to-register-1) ;F5 Position speichern (global-set-key [f6] 'jump-to-register-1) ;F6 zu Position springen (global-set-key [f7] 'goto-line) ;F7 goto line (global-set-key [f8] 'toggle-fill-column-width) ;F8 kurze/lange Zeilen (global-set-key [f9] 'change-word-case) ;F9 Groß/Klein Wort (global-set-key [f10] 'undo) ;F10 Undo (global-set-key [f11] 'swap-char) ;F11 Buchst. vertauschen (global-set-key [f12] 'change-case) ;F12 Groß-/Klein ändern ;; Mac-Tastatur: fn+ctrl+cursor to start/end of buffer (global-set-key [C-prior] 'beginning-of-buffer) (global-set-key [C-next] 'end-of-buffer) ;; Guillemets-Eingabe mit Alt+Q / Shift+Alt+Q (defun insert-guillemot1 () (interactive) (insert "«")) (defun insert-guillemot2 () (interactive) (insert "»")) (global-set-key [?\M-q] 'insert-guillemot1) ;Alt+Q: « (global-set-key [?\M-Q] 'insert-guillemot2) ;Shift+Alt+Q: » ;; macOS: rechte Alt-Taste zur Eingabe von Sonderzeichen wie @ oder € verwenden (when (eq system-type 'darwin) (setq mac-right-option-modifier nil) ; LeftAlt + L -> @ etc. ) Quellen / Links Die oben abgedruckte Datei können Sie als dotemacs.txt herunterladen. https://www.gnu.org/software/emacs/ https://www.gnu.org/software/emacs/documentation.html https://www.gnu.org/software/emacs/manual/html_node/eintr/ https://www.emacswiki.org https://github.com/chrisdone-archive/elisp-guide (Elisp Guide) https://en.wikipedia.org/wiki/Lisp_(programming_language) https://melpa.org/ (Erweiterungspakete) https://github.com/doomemacs/doomemacs (Emacs-Statuszeile) Andere .emacs-Beispiele https://github.com/jackrusher/dotemacs https://sachachua.com/dotemacs/index.html https://protesilaos.com/emacs/dotemacs
Updates zu lokalen Sprachmodelle: MTP, APEX, Qwopus
Adaptive Precision for EXpert Models (APEX)
Unser Buch Coding mit KI ist gerade erst erschienen, schon gibt es spannende Neuigkeiten rund um die Ausführung lokaler Modelle: Multi-Token Prediction (MTP) ist ein ganz neues Feature in llama.cpp. Seit ein paar Tagen steht es auch in LM Studio zur Verfügung. Durch einen »Trick« (Details folgen gleich) kann mit MTP die Output-Token-Geschwindigkeit deutlich vergrößert … Updates zu lokalen Sprachmodelle: MTP, APEX, Qwopus weiterlesen →
Unser Buch Coding mit KI ist gerade erst erschienen, schon gibt es spannende Neuigkeiten rund um die Ausführung lokaler Modelle: Multi-Token Prediction (MTP) ist ein ganz neues Feature in llama.cpp. Seit ein paar Tagen steht es auch in LM Studio zur Verfügung. Durch einen »Trick« (Details folgen gleich) kann mit MTP die Output-Token-Geschwindigkeit deutlich vergrößert werden: laut diversen Benchmarktests im Internet bis auf das Doppelte, in meinen Tests immerhin um ca. 60 bis 70 Prozent. Adaptive Precision for EXpert Models (APEX) ist ein neues Verfahren zur besonders platzsparenden Quantisierung von MoE-Modellen. Der Platzbedarf sinkt je nach Qualitätsstufe auf die Hälfte gegenüber der herkömmlichen 4-Bit-Darstellungen (Q4_x_x). Qwopus ist eine neue Variante zu den Qwen-Modellen, bei denen das Fine Tuning mit Claude Opus verbessert wurde. Von Speculative Decoding zur Multi-Token Prediction In Coding mit KI gehe ich kurz auf das Vorgängerkonzept zu MTP ein, auf Speculative Decoding: Dabei führt die Engine (z.B. llama.cpp) zwei Sprachmodelle aus. Das kleinere (schnellere) dient als Draft Model. Während der Token-Generierung macht das Draft Model Vorschläge für die folgenden Token. Das größere, qualitativ bessere Modell überprüft anschließend eine Sequenz mehrerer vorgeschlagener Token auf einmal. Im Idealfall wird die ganze Sequenz akzeptiert. Der Geschwindigkeitsvorteil ergibt sich durch die parallele Verifizierung eines ganzen Token-Blocks. Dazu sind weniger Speicher-Transfers vom VRAM in die GPU notwendig, als wenn jedes Token für sich generiert wird. (Die Token-Generierung wird durch zwei Faktoren limitiert: die Rechenleistung der GPU und die Speicherbandbreite vom VRAM in die GPU-Cores. Speculative Decoding setzt beim zweiten Punkt ein, der oft der limitierende Faktor ist.) In der Praxis funktioniert das nur mäßig gut: Zum einen ist es schwierig, ein geeignetes Draft Model zu finden. Es muss aus der gleichen »Familie« stammen, aber deutlich kleiner sein, idealerweise etwa um den Faktor zehn. Zum anderen funktioniert Speculative Decoding für Dense Models besser als für Mixture of Experts Models (MoE). Das Problem bei MoE besteht darin, dass bei jedem Token andere »Experten« zum Einsatz kommen können, was den Geschwindigkeitsvorteil von Speculative Decoding teilweise zunichtemacht. Kleinere MoE-Modelle für den Draft-Einsatz haben zudem oft eine andere Experten-Aufteilung, was die Acceptance Rate verringert. Multi-Token Prediction (MTP) greift die Idee des Speculative Decoding auf. Der entscheidende Unterschied besteht darin, dass ein Modell ausreicht. Ein in das Modell integrierter Layer ist dafür zuständig, rasch ein paar Tokens (üblicherweise 2 bis 4) vorherzusagen. Das Gesamtmodell überprüft dann alle Token auf einmal, was nur unwesentlich mehr Zeit kostet, als ein Token zu berechnen. MTP erspart damit das umständliche Handling mit zwei Modellen. Speculative Decoding und Multi-Token Prediction sind mit keinerlei Qualitätsverlust verbunden! Es werden exakt die gleichen Ergebnisse erzielt, weil jede Token-Sequenz vollständig kontrolliert und bei Abweichungen verworfen wird. Werfen Sie diesbezüglich einen Blick in das Video von Donata Capitella, das diesen Umstand anschaulich erklärt. Für den erzielten Geschwindigkeitsgewinn ist der Prozentsatz der akzeptierten Draft Tokens entscheidend. Dieser variiert je Aufgabenstellung: Bei kreativem Text ist die Akzeptanzrate nur mittelmäßig, bei Code hingegen deutlich höher — ganz einfach deswegen, weil Code strengen Regeln folgt und weniger Spielraum als menschliche Sprachen bietet. Leider ist auch MTP mit Nachteilen verbunden: Das Modell muss für MTP konzipiert sein. MTP muss schon beim Training berücksichtigt werden. Das Modell benötigt einen zusätzlichen Layer für die Token Prediction. Aktuell gibt es nur eine einzige »freie« Modellfamilie mit MTP, nämlich Qwen 3.6 und dessen Variante Qwopus. Gemma-4-Modelle sollten demnächst folgen. In Zukunft wird MTP wohl zu einem Standard-Feature für freie Modelle. Natürlich muss auch die Software MTP unterstützen. Weil viele Programme intern llama.cpp verwenden, wird MTP rasch weite Verbreitung finden. Schließlich teilt sich MTP einen Nachteil mit Speculative Decoding: Es funktioniert bei herkömmlichen Dense-Modellen besser als bei MoE-Modellen (Mixture of Experts). Die ohnedies schon schnellen MoE-Modelle werden also nur geringfügig schneller oder, wie bei einigen meiner Tests, sogar langsamer. Bei den Dense-Modellen ist dagegen eine spürbare Verbesserung zu bemerken. Bei meinen Tests ca. +65%, bei einigen Benchmarks im Internet bis zu +100%, also eine Verdoppelung der Output-Token-Rate. MTP ändert nichts an der Input-Verarbeitung (dem Prompt Processing, pp). Schneller wird nur der Output (die Token Generation, tg). Dense versus Mixture of Experts (MoE): MoE ist schneller, kann aber qualitativ bei gleicher Modellgröße nicht ganz mithalten. Während bei Dense-Modellen immer alle Parameter aktiv sind, nutzen MoE-Modelle nur wenige, stets wechselnde »Experten«, also Subsets mit viel weniger Parametern. Das spart Zeit, aber kein »Experte« ist so gut wie das volle Modell. Dementsprechend sinkt die Qualität der Antworten, nicht massiv, aber spürbar.) Praktische Erfahrungen Ich habe MTP mit LM Studio 0.4.14 auf meinem Framework Desktop ausprobiert (AMD Ryzen Max 395 CPU/GPU). Mein Mini-Benchmarktests lautete: »Explain Python dictionaries«. Die getesteten Modelle denken über diese Frage eine Weile nach und produzieren dann einen mehrseitigen, qualitativ sehr hochwertigen Text mit eingebauten Code-Schnipseln. <img loading="lazy" decoding="async" src="https://kofler.info/wp-content/uploads/lmstudio-mtp.png" alt="" width="1920" height="1229" class="size-full wp-image-9602" srcset="https://kofler.info/wp-content/uploads/lmstudio-mtp.png 1920w, https://kofler.info/wp-content/uploads/lmstudio-mtp-850x544.png 850w, https://kofler.info/wp-content/uploads/lmstudio-mtp-1280x819.png 1280w, https://kofler.info/wp-content/uploads/lmstudio-mtp-768x492.png 768w, https://kofler.info/wp-content/uploads/lmstudio-mtp-1536x983.png 1536w" sizes="auto, (max-width: 1920px) 100vw, 1920px" /> LM Studio mit dem Modell Qwen 3.6 und Multi-Token Prediction (MTP) Ich habe alle Tests mit einem Kontextfenster von 128.000 Token ausgeführt. Bei den MTP-Modellen habe ich die Einstellung MTP Max Tokens = 3 verwendet, also immer drei Tokens auf einmal erzeugt. Alle getesteten Modelle weisen eine 4-Bit-Quantisierung auf (Ausnahme: das APEX-Modell, siehe unten). Als Backend kommt llama.cpp mit Vulkan zum Einsatz. Draft Token Modell MoE APEX MTP Output (tg) Acceptance ----------------- ---- ---- ---- ------------ ------------------ qwen-3.6-27b nein nein nein 12,3 Token/s qwen-3.6-27b-mtp nein nein ja 20,1 Token/s 66,3 % qwopus-3.6-27b-v2-mtp nein nein ja 19,0 Token/s 63,7 % qwen-3.6-35b-a3b ja nein nein 69,7 Token/s qwen-3.6-35b-a3b-mtp ja nein ja 67,1 Token/s 66,6 % qwen-3.6-35b-a3b-apex-mtp ja ja ja 71,5 Token/s 63,3 % qwopus-3.6-35b-a3b-mtp ja nein ja 74,2 Token/s 68,2 % Professionellere Benchmark-Tests hat Donata Capitella durchgeführt (siehe die ersten zwei Links in den Übersicht der Quellen am Ende des Artikels). Interessanterweise ist dort auch bei MoE-Modellen ein spürbarer Geschwindigkeitszuwachs von etwa 30% zu sehen, den ich bei meinen Tests aber nicht nachvollziehen kann. Qwopus-Modelle Die neuen Qwopus-Modelle basieren auf Qwen-Modellen, erhalten aber ein zusätzliches Fine-Tuning mit Claude Opus. Dieses soll den Nachdenkprozess beschleunigen und eine bessere Antwortqualität mit sich bringen. Die erste Versprechung trifft definitiv zu, aber ich bin nicht in der Lage, die Qualität des Modells im Detail zu beurteilen. Subjektiv hatte ich den Eindruck, dass die Unterschiede zu den Qwen-Originalen gering sind. Zum Denkprozess: Beim Prompt »write a Sudoku solver in Python« denkt qwen-3.6-27b-mtp ca. 1:30 Minuten nach, qwopus-3.6-27b-v2-mtp aber ca. nur 1:00 Minuten. (Die Denkzeit hat eine relativ starke Varianz, weswegen hier genaue Angaben sinnlos sind.) Die resultierende Antwort samt Code ist mehr oder weniger gleichwertig (Backtracking-Algorithmus). APEX Quantisierung Die Verkleinerung von Modellen bei möglichst geringen Qualitätsverlust ist zu einer eigenen KI-Disziplin geworden. Die Grundidee besteht darin, Milliarden von Parametern (also eigentlich Fließkommazahlen) mit möglichst wenigen Bits darzustellen, ohne dass die Qualität der Ergebnisse allzu sehr leidet. Der geringere Platzbedarf von Modellen ist insbesondere dann wichtig, wenn der Speicher (VRAM) limitiert ist. Mit einer geschickten Quantisierung läuft ein Modell vielleicht gerade noch auf einer GPU mit 16 GiB VRAM. Vor ein paar Monaten machte Google mit dem neuen Turbo-Quant-Verfahren Furore. Bei der Recherche für diesen Artikel bin ich nun auf das neue Verfahren Adaptive Precision for EXpert Models (APEX) gestoßen. Das von Local AI entwickelte Verfahren ist speziell für MoE-Modelle optimiert und kompatibel zu aktuellen llama.cpp-Versionen. Die Grundidee besteht darin, dass für jede Parametergruppe eine andere, für den Wertebereich und die Wichtigkeit angepasste Quantisierung verwendet wird. Insofern ist eine klare Bit-Angabe (4 Bit pro Parameter) unmöglich. Technische Details und Benchmarks finden Sie auf der GitHub-Projektseite. Local AI arbeitet daran, Modelle lokal auf Smartphones auszuführen; da ist die möglichst platzsparende Darstellung natürlich wichtig. Konkret sind APEX-Modelle zum Teil wirklich erheblich kleiner als vergleichbare Modelle mit Q4-Quantisierung, wie sie bei der lokalen Ausführung von Modellen üblich ist. Die folgende Tabelle zeigt lauter Qwen-3.6-Modelle mit jeweils 35 Milliarden Parameter. Das APEX-MTP-Modell benötigt nur halb so viel Platz wie das MTP-Modell mit einer herkömmlichen Q4-Quantisierung. <img loading="lazy" decoding="async" src="https://kofler.info/wp-content/uploads/lmstudio-mtp-apex.png" alt="" width="1920" height="757" class="size-full wp-image-9614" srcset="https://kofler.info/wp-content/uploads/lmstudio-mtp-apex.png 1920w, https://kofler.info/wp-content/uploads/lmstudio-mtp-apex-850x335.png 850w, https://kofler.info/wp-content/uploads/lmstudio-mtp-apex-1280x505.png 1280w, https://kofler.info/wp-content/uploads/lmstudio-mtp-apex-768x303.png 768w, https://kofler.info/wp-content/uploads/lmstudio-mtp-apex-1536x606.png 1536w" sizes="auto, (max-width: 1920px) 100vw, 1920px" /> Überblick der heruntergeladenen Modelle in LM Studio Leider verrät die Huggingface-Seite des Modells nicht, welche Variante der APEX-Quantisierung verwendet wurde. Es existieren verschiedene Qualitätsstufen, z.B. Quality, Balanced, Compact und Mini. Ich würde vermuten, das Modell ist eher bei Mini als bei Quality angesiedelt. Modell Quantisierung Größe (Disk) ------------------------ ------------- ------------ qwen-3.6-35b-a3b Q4_K_M 22,0 GB qwen-3.6-35b-a3b-mtp Q4_K_S 23,0 GB qwen-3.6-35b-a3b-apex-mtp APEX 11,7 GB (!) Bei der Ausführung des Modells waren für mich keine nennenswerten Unterschiede erkennbar, weder in der Geschwindigkeit noch qualitativ. Aber nochmals: Das sind subjektive Feststellungen anhand einiger Tests, keine objektiven Benchmark-Tests. Dazu fehlt mir ganz einfach die Zeit. Quellen/Links https://www.youtube.com/watch?v=MI0Pm1d6YF4 (gutes Video von Donata Capitella) https://kyuz0.github.io/amd-strix-halo-toolboxes/mtp.html (Benchmarks von Donata Capitella) https://sebastianraschka.com/llm-architecture-gallery/mtp/ https://github.com/ggml-org/llama.cpp/pull/22673 (MTP für llama.cpp) https://lmstudio.ai/changelog/lmstudio-v0.4.14 (LM Studio Changelog) https://github.com/localai-org/apex-quant Ausgewählte Modelle mit MTP und/oder APEX https://huggingface.co/unsloth/Qwen3.6-35B-A3B-MTP-GGUF (Qwen MTP) https://huggingface.co/Jackrong/Qwopus3.6-27B-v2-MTP-GGUF (Qwopus MTP) https://huggingface.co/Jackrong/Qwopus3.6-35B-A3B-v1-MTP-GGUF (ebenso) https://huggingface.co/mudler/Qwen3.6-35B-A3B-APEX-MTP-GGUF (APEX) Technisch/Wissenschaftliche Grundlagen https://arxiv.org/abs/2211.17192 (Speculative Decoding) https://arxiv.org/abs/2404.19737 (MTP) https://arxiv.org/abs/2509.18362v1 (FastMTP) https://arxiv.org/abs/2412.19437 (MTP in DeepSeek-Modellen) https://blog.google/innovation-and-ai/technology/developers-tools/multi-token-prediction-gemma-4/ (MTP in Gemma-Modellen)
Wenn Sie Ihre Domains bei Hetzner verwalten, wurden Sie in den vergangenen Monaten dazu aufgefordert, die Domains in ein neues DNS-Verwaltungstool zu migrieren. Das gelingt zumeist problemlos (zumindest in meinen Fällen). Allerdings hat Hetzner nun auch die alte API zur DNS-Administration abgeschaltet. Falls Sie bei der Ausstellung von Let’s-Encrypt-Zertifikate die alte DNS-API verwendet haben, scheitert … Neue Hetzner DNS API und acme.sh weiterlesen →
Wenn Sie Ihre Domains bei Hetzner verwalten, wurden Sie in den vergangenen Monaten dazu aufgefordert, die Domains in ein neues DNS-Verwaltungstool zu migrieren. Das gelingt zumeist problemlos (zumindest in meinen Fällen). Allerdings hat Hetzner nun auch die alte API zur DNS-Administration abgeschaltet. Falls Sie bei der Ausstellung von Let’s-Encrypt-Zertifikate die alte DNS-API verwendet haben, scheitert die Erneuerung der Zertifikate mit unspezifischen Fehlern (invalid domain). Ich verwende zur Zertifikatsausstellung normalerweise acme.sh und bin auf das Problem erst aufmerksam geworden, als das erste Zertifikat auf einem meiner Server abgelaufen ist. (Ein ordentliches Monitoring hätte dieses Hoppala natürlich verhindert. Es war nicht die wichtigste Domain …) Ich habe keinen Weg gefunden, den Zertifiktaserneuerungsmechanismus von acme.sh irgendwie zu aktualisieren, also gewissermaßen die vorhandene Konfiguration auf die neue API zu migrieren. Die Lösung bestand darin, in der Hetzner-Console einen neuen API-Key einzurichten und dann mit acme.sh die Zertifikate neu auszustellen. Falls Sie viele Server administrieren, ist das, gelinde formuliert, unbequem … Hinweis/Klarstellung: Sie sind von diesem Problem NICHT betroffen, wenn die Domain-Validierung mit anderen Verfahren erfolgt, z.B. durch das Ablegen einer Datei in /var/www/html. Dieser Blog-Artikel bezieht sich explizit auf den Zertifikatserneuerungsprozess, wenn Sie bisher die alte Hetzner-DNS-API verwendet haben! Ich verwende als Tool acme.sh, aber das Problem hat nichts mit acme.sh an sich zu tun, sondern mit der Frage, wie der Domain-Validierung erfolgt. Kommt dabei die alte Hetzner-DNS-API zum Einsatz, wird es Probleme geben. API-Key Zuerst brauchen Sie einen neuen API-Key für die Hetzner-Cloud-API. Den erstellen Sie in der Hetzner-Konsole unter Security / API-Tokens. Der Token muss read/write sein, weil acme.sh für die Validierung Ihrer Domain vorübergehend eine zusätzlichen DNS-Eintrag hinzufügt, die DNS-Konfiguration also ändert. Den vollständigen Token-Code können Sie nur einmal ansehen/kopieren. <img loading="lazy" decoding="async" src="https://kofler.info/wp-content/uploads/hetzner-api.png" alt="Der Screenshot zeigt die Hetzner‑Cloud‑Konsole beim Einrichten eines neuen API‑Tokens. In einem Dialog „API‑Token hinzufügen“ werden ein Feld für die Beschreibung sowie die Berechtigungen „Lesen“ oder „Lesen & Schreiben“ angeboten. Rechts oben ist der Button „API‑Token hinzufügen“ markiert, links unten ist der Menüpunkt „Sicherheit“ hervorgehoben. Im Hintergrund sind die Token‑Reiter und die Seitenleiste sichtbar." width="1732" height="1038" class="size-full wp-image-9573" srcset="https://kofler.info/wp-content/uploads/hetzner-api.png 1732w, https://kofler.info/wp-content/uploads/hetzner-api-850x509.png 850w, https://kofler.info/wp-content/uploads/hetzner-api-1280x767.png 1280w, https://kofler.info/wp-content/uploads/hetzner-api-768x460.png 768w, https://kofler.info/wp-content/uploads/hetzner-api-1536x921.png 1536w" sizes="auto, (max-width: 1732px) 100vw, 1732px" /> Neuen Hetzner-API-Key einrichten Hetzner bietet aktuell keine Möglichkeit, die Gültigkeit des Keys irgendwie einzuschränken. Ein RW-Key gibt damit weit mehr Rechte, als zur DNS-Administration erforderlich wären. Die API bietet alle erdenklichen weiteren Funktionen (create a server, delete a server usw.). Dass der Key mit so vielen Rechten ausgestattet ist, macht mich nicht glücklich, aber es ist aktuell nicht zu ändern. acme.sh aktualisieren, Zertifikate neu erstellen und einrichten acme.sh muss das Verfahren Hetzner Cloud DNS API unterstützen. Dieses ist verhältnismäßig neu. Eventuell müssen Sie Ihre vorhandene acme.sh-Installation aktualisieren: acme.sh --upgrade Mit acme.sh --list gewinnen Sie einen Überblick, welche Zertifikate es auf dem Server gibt (Output verkürzt): acme.sh --list Main_Domain SAN_Domains CA Created Renew eine-firma.de www.eine-firma.de LetsEncrypt.org 2026-05-12 2026-07-11 mail.eine-firma.de smtp.eine-firma.de,... LetsEncrypt.org 2026-05-12 2026-07-11 Jetzt speichern Sie das Token in einer Umgebungsvariablen und wiederholen die Kommandos zur Zertifikatsausstellung sowie zum Kopieren der Zertifikate an den Zielort, wobei Sie die bisherige acme.sh-Option --dns dns-hetzner durch --dns dns-hetznercloud ersetzen. Die folgenden Beispielkommandos zeigen die Neuausstellung der Zertifikate und deren Deployment. Sofern Sie exakt die gleichen Namen/Pfade wie bei der ursprünglichen Zertifikatsausstellung verwenden, sollte danach alles wieder funktionieren (d.h. der Webserver verwendet die neuen Zertifikate). export HETZNER_Token='oqCF...' # wichtig ist die geänderte Option --dns dns_hetznercloud acme.sh --issue --dns dns_hetznercloud --server letsencrypt \ -d eine-firma.de -d www.eine-firma.de # Zertifikate in /etc/letsencrypt speichern (setzt voraus, dass # Apache so konfiguriert ist, dass das Programm die Zertifikate # von dort liest) acme.sh --install-cert -d eine-firma.de \ --cert-file /etc/letsencrypt/eine-firma.de.cert \ --key-file /etc/letsencrypt/eine-firma.de.key \ --fullchain-file /etc/letsencrypt/eine-firma.de.fullchain \ --reloadcmd 'systemctl restart apache2' Sie müssen die Kommandos natürlich an Ihre Gegebenheiten anpassen. Quellen/Links https://github.com/acmesh-official/acme.sh/wiki/dnsapi2#dns_hetznercloud https://github.com/acmesh-official/acme.sh/issues/6554 https://docs.hetzner.cloud/reference/cloud#description/getting-started https://www.hetzner.com/de/news/dns-beta/
Da ist Coding mit KI frisch aus der Druckerei ausgeliefert, schon taucht ein neues Tool auf, das mehr Effizienz verspricht. Graphify erstellt einen sogenannten Knowledge Graph, also eine interne Datenbank über die Verknüpfungen zwischen Komponenten (Text, Code, Bilder, was auch immer) eines Projekts. In der Folge können KI-Tools wie Claude Code auf diese Datenbank zugreifen … Graphify weiterlesen →
Da ist Coding mit KI frisch aus der Druckerei ausgeliefert, schon taucht ein neues Tool auf, das mehr Effizienz verspricht. Graphify erstellt einen sogenannten Knowledge Graph, also eine interne Datenbank über die Verknüpfungen zwischen Komponenten (Text, Code, Bilder, was auch immer) eines Projekts. In der Folge können KI-Tools wie Claude Code auf diese Datenbank zugreifen und sich damit rascher und vor allem Token-sparender im Projekt orientieren. Graphify funktioniert besonders gut für ungeordnete Verzeichnisse, in denen Sie PDFs, Screenshots etc. zu einem Thema ablegen, um diese Informationen später wieder zu nutzen. Aktualisiert 10.5.2026, 23.6.2026 Installation Graphify ist ein Python-Programm (Open Source, MIT-Lizenz), das Sie am besten mit uv tool install auf Ihrem Rechner einrichten. (uv ist ein moderner Python-Modulmanager, über den ich demnächst hier schreiben will.) Beachten Sie, dass der Paketname graphifyy mit Doppel-Y lautet, während das Kommando graphify heißt. uv tool install graphifyy installiert das Programm. Sofern PATH das Verzeichnis .local/bin enthält, kann graphify anschließend sofort gestartet werden. graphify install richtet Skill-Dateien für die auf Ihrem Rechner gefundenen KI-Tools (in meinem Fall: Claude) ein. $ uv tool install graphifyy $ graphify install skill installed -> /Users/kofler/.claude/skills/graphify/SKILL.md CLAUDE.md -> created at /Users/kofler/.claude/CLAUDE.md Done. Open your AI coding assistant and type: /graphify . Verwendung Im Projektverzeichnis starten Sie nun das KI-Tool Ihrer Wahl (in meinem Fall: Claude Code). Dort steht Graphify jetzt als Skill zur Verfügung. Einfach /graphify . analysiert das Projektverzeichnis und erstellt nach vielen Rückfragen das Verzeichnis graphify_out. Das dauert geraume Zeit und verbrennt etliche Tokens. Das Verzeichnis enthält die folgenden Dateien: ls -l graphify-out/ drwxr-xr-x 4 kofler staff 128 7 Mai 09:54 cache/ -rw-r--r-- 1 kofler staff 213 7 Mai 10:10 cost.json -rw-r--r-- 1 kofler staff 8523 7 Mai 10:10 GRAPH_REPORT.md -rw-r--r-- 1 kofler staff 139973 7 Mai 10:10 graph.html -rw-r--r-- 1 kofler staff 137091 7 Mai 10:09 graph.json -rw-r--r-- 1 kofler staff 7912 7 Mai 10:10 manifest.json Ich habe meine Tests anhand einer Swift-App mit ca. 2000 Zeilen Code in diversen Dateien durchgeführt. Die Ergebnisse sehen eindrucksvoll aus, der unmittelbare Erkenntnisgewinn war aber — zumindest bei diesem Projekt — überschaubar. <img loading="lazy" decoding="async" src="https://kofler.info/wp-content/uploads/graphify1.png" alt="Der Screenshot zeigt einen anklickbaren „Knowledge Graph“ als Netzwerkvisualisierung in einem Browserfenster. In der Mitte sind farbige Knoten mit Verbindungen zu sehen, die Code-Elemente wie „ShoppingViewModel“ und zugehörige Methoden darstellen. Rechts befindet sich ein „Node Info“-Panel mit Details zum ausgewählten Knoten sowie einer Suche. Darunter listet ein „Communities“-Bereich Kategorien mit Checkboxen auf." width="1920" height="1591" class="size-full wp-image-9563" srcset="https://kofler.info/wp-content/uploads/graphify1.png 1920w, https://kofler.info/wp-content/uploads/graphify1-784x650.png 784w, https://kofler.info/wp-content/uploads/graphify1-1159x960.png 1159w, https://kofler.info/wp-content/uploads/graphify1-768x636.png 768w, https://kofler.info/wp-content/uploads/graphify1-1536x1273.png 1536w" sizes="auto, (max-width: 1920px) 100vw, 1920px" /> Der anklickbare »Knowledge Graph« <img loading="lazy" decoding="async" src="https://kofler.info/wp-content/uploads/graphify2.png" alt="Der Screenshot zeigt einen geöffneten Markdown-Report mit einer Analyse von Projektzusammenhängen. Links ist eine Navigationsleiste mit Abschnitten wie „Summary“, „God Nodes“ und „Communities“ sowie einer Community-Liste. Im Hauptbereich stehen „Knowledge Gaps“ mit 30 isolierten Nodes und Hinweisen auf fehlende Kanten. Darunter folgen „Suggested Questions“ zu Verbindungen zwischen Komponenten wie ContentView, PlanTabView und ShoppingViewModel." width="2356" height="2360" class="size-full wp-image-9564" srcset="https://kofler.info/wp-content/uploads/graphify2.png 2356w, https://kofler.info/wp-content/uploads/graphify2-649x650.png 649w, https://kofler.info/wp-content/uploads/graphify2-958x960.png 958w, https://kofler.info/wp-content/uploads/graphify2-350x350.png 350w, https://kofler.info/wp-content/uploads/graphify2-768x769.png 768w, https://kofler.info/wp-content/uploads/graphify2-1533x1536.png 1533w, https://kofler.info/wp-content/uploads/graphify2-2045x2048.png 2045w" sizes="auto, (max-width: 2356px) 100vw, 2356px" /> Kurzfassung der Projektzusammenhänge im Markdown-Format Wenn Sie Änderungen in der Code-Basis oder in Ihren Dateien durchführen, aktualisieren Sie den Knowledge Graph: /graphify . --update # merge changed content into existing graph Der Knowledge Graph kann jetzt die Grundlage für Analysen mit /graphify explain oder graphiy query sein (Ausgabe etwas gekürzt): /graphify explain "the sync process" Here's what the graph tells us about the sync process, grounded in the extracted edges: The sync process is orchestrated by ShoppingViewModel.pullMergePushSave (RestShopping.swift:125-175), which implements the Pull-Merge-Push lifecycle documented in CLAUDE.md. The graph found 16 nodes directly connected to this concept. The three phases (all EXTRACTED edges): 1. Pull — apiPullItems (RestShopping.swift:62-93) fetches items from the remote REST API since the last sync timestamp. 2. Merge — mergeItems (RestShopping.swift:178-193) resolves conflicts using Timestamp-Wins: whichever version of an item has the newer updatedAt wins. Two design rationale nodes connect here: - Timestamp-Wins Conflict Resolution → mergeItems [EXTRACTED] - Soft Delete Pattern → ShoppingItem [EXTRACTED] — items are never truly removed; isDeleted = true propagates deletions to other devices through the sync 3. Push — apiPushItems (RestShopping.swift:96-120) uploads the merged state back to the server. 4. Persist — saveLocally (ViewModel.swift:172-178) writes the final state to the local JSON file. mergeItems then calls replaceItem to update the ViewModel's live state. Wire format bridge: ItemDTO (RestShopping.swift:9-53) shares data with ShoppingItem [EXTRACTED] — it translates between the app's model and the API's integer-boolean/ISO 8601 wire format. Trigger points: ContentView and StatusView both connect to pullMergePushSave in the graph. ContentView runs it via .task, .onChange(scenePhase), and a 40-second timer. StatusView (in Settings) provides a manual trigger. setupNewFamily and joinFamily also call pullMergePushSave as a final step after family registration. The most interesting angle here: the Soft Delete pattern is the load-bearing coupling between ShoppingItem (the model) and the sync logic — if you ever changed ShoppingItem to hard-delete, mergeItems would silently stop propagating deletions. Want me to trace the path from ShoppingItem.isDeleted through to what happens when a remote device pulls? /graphify query "Where in code is the Category class used? Could we drop the @Observable attribute?" Here's what the graph found — and where its limits are: Where Category is used (from the graph): The BFS found 10 nodes. The confirmed connections [EXTRACTED]: - Category → shares_data_with → ShoppingViewModel (ViewModel.swift:1-181) — the ViewModel holds the categories: [Category] array - Category.predefinedCategories (Category.swift:24-37) ↔ ShoppingViewModel — the ViewModel calls this at init to populate its categories - .predefinedCategories() → calls → Color — each category has a color assigned What the graph is missing: There are no direct edges from Category to the view layer (CategoriesView, CategoryButton, EditItemView, CategoryRadioButton). Those views access categories through vm.categories and mutate category.isSelected/category.isExpanded directly — but the graph didn't capture these view→Category property access edges since they go through the ViewModel and aren't explicit call-site imports. On dropping @Observable: The graph can't answer this definitively — it would require the actual property mutation sites. But from the CLAUDE.md rationale node captured in the graph: "Mutable reference-type state (isSelected, isExpanded) is mutated directly from views." That design decision is precisely why @Observable is needed. Without it, those direct mutations on the reference type wouldn't trigger SwiftUI view updates — CategoriesView and EditItemView would stop reacting to category selection changes. Verdict from the graph: @Observable cannot be safely dropped without a larger refactor (e.g., moving isSelected/isExpanded into the ViewModel as @State or @Published backing). The graph confirms the coupling exists; reading Category.swift:4-112 directly would show exactly which properties are var vs let. Die Website preist den größten Vorteil von Graphify an, dass derartige Abfragen auf der Basis des lokalen Knowledge Graphs nun wesentlich weniger Token verbrauchen als wenn das KI-Tool mit find und grep die Codebasis durchsucht und (immer wieder neu) analysiert. Bei meinen Tests ließ sich das Ausmaß der Ersparnis schwer messen. Persönliche Einschätzung Die Idee von Graphify ist gut. Allerdings wirkt Graphify ein wenig wie ein Fremdkörper innerhalb von Claude Code. Nur /graphify-Kommandos berücksichtigen die Graph-Knowledge-Datenbank. Die Skill-Datei ist mit über 1000 Zeilen und einer Menge eingebetteten Code auch eher abschreckend. Aus Coding-Perspektive wäre es wünschenswert, die Generierung, Aktualisierung und Auswertung der Knowledge-Datenbank direkt in Claude Code bzw. in andere KI-Tools zu integrieren. Damit könnte das in der Datenbank aggregierte Wissen bei allen Aktionen berücksichtigt werden, nicht nur bei /graphify-Kommandos. Ganz generell stellt sich die Frage, ob und wie weit Graph Knowledge Databases das bekannte RAG-Konzept ablösen oder zumindest ergänzen kann (also Retrieval-Augmented Generation, um eigenes Wissen in Vektordatenbanken zu speichern und einem LLM zugänglich zu machen). Siehe z.B. diesen Artikel über einen ähnlichen Ansatz mit kommerziellen Hintergrund. Wenn es primär darum geht, den Kontext zu verkleinern und so Kosten zu sparen (idealerweise ohne Qualitätsverlust), hat das Projekt Headroom ein weiteres spannendes Konzept realisiert. Headroom agiert als eine Art Kompressor zwischen Ihren Prompts und dem KI-Tool/Sprachmodell. Allerdings wäre wohl auch in diesem Fall ein in das jeweilige CLI/KI-Tool integrierte Lösung noch besser. Quellen/Links https://graphify.net/ https://github.com/safishamsi/graphify https://github.com/safishamsi/graphify/blob/v7/docs/how-it-works.md https://docs.astral.sh/uv/ https://thenewstack.io/pinecone-nexus-rag-obsolete/ https://github.com/headroomlabs-ai/headroom
Es kommt selten vor, dass ein IT-Buch innerhalb von 18 Monaten eine zweite Auflage erfährt und dabei in großen Teilen neu geschrieben werden muss. Genau das ist uns mit diesem Buch passiert! Wir haben die Gelegenheit genutzt und das Buch komplett aktualisiert und stark erweitert. Der Fokus liegt jetzt bei Agentic Coding, MCP und Skills. … 📚 Coding mit KI (2. Aufl.) weiterlesen →
Es kommt selten vor, dass ein IT-Buch innerhalb von 18 Monaten eine zweite Auflage erfährt und dabei in großen Teilen neu geschrieben werden muss. Genau das ist uns mit diesem Buch passiert! Wir haben die Gelegenheit genutzt und das Buch komplett aktualisiert und stark erweitert. Der Fokus liegt jetzt bei Agentic Coding, MCP und Skills. <img loading="lazy" decoding="async" src="https://kofler.info/wp-content/uploads/ki2.jpg" alt="Das Bild zeigt das Cover eines deutschsprachigen Fachbuchs zum Programmieren mit Künstlicher Intelligenz. Der Titel „Coding mit KI“ steht groß in Gelb, darunter der Untertitel „Das Praxisbuch für die Softwareentwicklung“. Aufgelistet sind Themen wie Prompt Engineering, Agentic Coding sowie lokale LLMs ohne Cloud. Oben sind die Autoren (Michael Kofler, Bernd Öggl, Sebastian Springer) genannt, unten das Logo von Rheinwerk Computing." width="200" height="266" class="alignnone size-full wp-image-9383" /> Wir haben in diesem Buch den »State of the Art« im Bereich KI und Agentic Coding abgesteckt. In unzähligen Tests haben wir ausprobiert, wie weit die Versprechen der KI-Hersteller zutreffen, aber auch, wo heutige KI-Tools versagen. Wir haben lokale Modelle und Open-Source-Tools ebenso verwendet wie kommerzielle KI-Tools von Claude, Cursor, Google und OpenAI. Ein eigenes Kapitel behandelt den neuen Trend der CLI-basierten KI-Tools, also z.B. Claude Code oder OpenAI Codex. Hier gibt es weitere Informationen zum Buch und den obligatorischen Bestell-Link.
Glücklicherweise muss ich nicht allzu oft unter Windows arbeiten. Aber hin und wieder — aktuell für die Überarbeitung meines Scripting-Buchs — lässt es sich nicht vermeiden. Wenn schon Windows, dann wenigstens so komfortabel wie möglich! Und so habe ich in den vergangenen Wochen mein Terminal/PowerShell-Setup optimiert: Nerdfont installiert informativen Prompt eingerichtet (Oh My Posh) bessere … PowerShell-Tuning weiterlesen →
Glücklicherweise muss ich nicht allzu oft unter Windows arbeiten. Aber hin und wieder — aktuell für die Überarbeitung meines Scripting-Buchs — lässt es sich nicht vermeiden. Wenn schon Windows, dann wenigstens so komfortabel wie möglich! Und so habe ich in den vergangenen Wochen mein Terminal/PowerShell-Setup optimiert: Nerdfont installiert informativen Prompt eingerichtet (Oh My Posh) bessere Tastaturunterstützung im Terminal (mit Emacs-Tastenkürzeln!) Editor für den Textmodus installiert (je nach Geschmack: Edit, nano, Emacs, NeoVim) sudo aktiviert Update 27.5.2026: less installiert Dieser Artikel liefert dazu ein paar Details. Der Text beweist gleichzeitig, dass man selbst unter Windows mit relativ wenig Mühe ein produktives Setup einrichten kann. Das erforderliche Fundament liefert Microsoft direkt aus: das Windows Terminal mit vielen High-end-Funktionen inklusive GPU-Rendering, die PowerShell sowie das Paketverwaltungskommando winget. <img loading="lazy" decoding="async" src="https://kofler.info/wp-content/uploads/powershell1.png" alt="Der Screenshot zeigt ein Windows Terminal mit einer PowerShell-Sitzung und dem Prompt-Theme von „Oh My Posh“. Ausgeführt wurde der Befehl `ls`, der den Inhalt des Verzeichnisses `C:\Users\ms\no-sync\scripting-buch\code-en\08` auflistet. Angezeigt werden Spalten wie Mode, LastWriteTime, Length und Name. In der Liste sind u. a. CSV-, Log- sowie Python-, PowerShell-, SH- und TXT-Dateien, wobei `analyze-population.ps1` hervorgehoben ist." width="1452" height="790" class="size-full wp-image-9525" srcset="https://kofler.info/wp-content/uploads/powershell1.png 1452w, https://kofler.info/wp-content/uploads/powershell1-850x462.png 850w, https://kofler.info/wp-content/uploads/powershell1-1280x696.png 1280w, https://kofler.info/wp-content/uploads/powershell1-768x418.png 768w" sizes="auto, (max-width: 1452px) 100vw, 1452px" /> PowerShell in einem Windows Terminal mit den JetBrains Nerd Font und »Oh My Posh« Nerdfonts Moderne CLI-Tools stellen im Terminal alle erdenklichen Zeichen und Symbole dar, um auf Dateitypen, den Git-Status oder Fehlerursachen hinzuweisen. In »gewöhnlichen« Fonts fehlen diese Zeichen; im Terminal wird dann ein Rechteck, ein Fragezeichen oder ein anderes Ersatzzeichen angezeigt. Das lässt den Charme moderner Kommandos und Prompt-Frameworks ins Leere laufen. Abhilfe schafft die Installation eines Fonts, der einen Coding-Zeichensatz um Tausende Symbole und Sonderzeichen ergänzt. Auf der Seite https://nerdfonts.com stehen ca. 100 geeignete Fonts zum freien Download zur Auswahl. Aber welcher Font ist der beste? Wenn Sie sich nicht entscheiden können, ist der beliebte JetBrainsMono Nerd Font eine gute Wahl für erste Experimente. Er basiert auf dem freien Mono-Font der Firma JetBrains (IntelliJ, PyCharm etc.). Dieser Font hat noch einen Vorteil: Er lässt sich im Handumdrehen mit winget installieren. Sie sollten die Installation in einem Terminal mit Admin-Rechten durchführen, damit die Fonts auch dann zur Verfügung stehen, wenn Sie in einem Admin-Terminal arbeiten. # in einem Admin-Terminal winget install -e --id DEVCOM.JetBrainsMonoNerdFont Oh My Posh Die Fish oder die Zsh mit der Erweiterung »Oh My Zsh« zeigen im Prompt alle erdenklichen Kontextinformationen an: den Hostnamen, den Verzeichnisnamen, den Git-Zweig und -Status etc. Genau das kann auch Oh My Posh, eine Plattform- und Shell-unabhängiges Prompt-Framework. Die Installation gelingt unter Windows am schnellsten mit winget: winget install JanDeDobbeleer.OhMyPosh -s winget Damit Oh My Posh in interaktiven PowerShell-Sessions aktiviert wird, bauen Sie die folgenden Anweisungen in die Profile-Datei ein (notepad $Profile, wobei Sie notepad durch Ihren Lieblingseditor ersetzen): # Datei Documents/PowerShell/Microsoft.PowerShell_profile.ps1 # Oh My Posh nur in interaktiven PowerShell-Sessions verwenden if (-not [Console]::IsInputRedirected -and (Get-Module -Name PSReadLine -ErrorAction SilentlyContinue)) { oh-my-posh init pwsh | Invoke-Expression } Wenn Sie jetzt ein neues PowerShell-Tab öffnen, wird Oh My Posh erstmals aktiv. Sie werden von einem informativen und mehrfarbigen Default-Prompt begrüßt. Unter https://ohmyposh.dev/docs/themes stehen über 100 weitere Prompt-Themen zur Wahl. Zur Aktivierung bauen Sie den Themennamen in das oh-my-posh-Init-Kommando in der Profile-Datei ein, z.B. so: # Datei Documents/PowerShell/Microsoft.PowerShell_profile.ps1 oh-my-posh init pwsh --config "easy-term" | Invoke-Expression Um die neue Konfiguration zu aktivieren, lesen Sie die Profile-Datei neu ein: . $PROFILE Starship Eine Alternative zu Oh My Posh ist das Framework Starship. Es wurde in Rust entwickelt und ist schneller/effizienter als Oh My Posh. Dafür gibt es aber weniger vordefinierte Themen; generell ist die Konfiguration sperriger. Ich habe beide Frameworks ausprobiert, bin dann aber bei Oh My Posh geblieben. Tastenkürzel in der PowerShell In der PowerShell unterstützt Sie das Modul PSReadLine bei der Kommandoeingabe (siehe auch die Dokumentation zu Set-PSReadLineOption). Standardmäßig schlägt PSReadLine das letzte Kommando mit den selben Anfangsbuchstaben zur Vervollständigung durch Cursor rechts vor. Tab bewirkt, dass begonnenen Dateinamen oder Schlüsselwörter komplettiert werden. Das Verhalten von PSReadLine kann durch Optionen in der Profile-Datei beeinflusst werden. Diese Datei öffnen Sie am bequemsten mit notepad $Profile, wobei Sie notepad durch Ihren Lieblingseditor ersetzen. Damit die Änderungen wirksam werden, laden Sie die Datei mit . $Profile neu. Das folgende Listing schlägt einige Änderungen/Verbesserungen vor. Gleich das erste Kommando bewirkt den größten Unterschied: Nach der Eingabe der ersten Buchstaben haben Sie die Wahl zwischen mehreren ähnlichen zuletzt ausgeführten Kommandos, die Sie mit den Cursortasten aus einer Liste wählen. Mit F2 können Sie zwischen der Listenansicht und dem Defaultverhalten (InlineView) umschalten. <img loading="lazy" decoding="async" src="https://kofler.info/wp-content/uploads/powershell-readline.png" alt="Der Screenshot zeigt ein PowerShell-Fenster mit einer History-Auswahl für zuletzt ausgeführte Befehle. Links werden Treffer angezeigt, die mit „edit“ beginnen, etwa „edit $PROFILE“ oder das Bearbeiten verschiedener Skriptdateien. In der Liste sind außerdem Kommandos zu Scheduled Tasks und ein „git commit“ sichtbar. Rechts steht „History(5/10)“ als Hinweis auf die Trefferliste." width="1452" height="790" class="size-full wp-image-9528" srcset="https://kofler.info/wp-content/uploads/powershell-readline.png 1452w, https://kofler.info/wp-content/uploads/powershell-readline-850x462.png 850w, https://kofler.info/wp-content/uploads/powershell-readline-1280x696.png 1280w, https://kofler.info/wp-content/uploads/powershell-readline-768x418.png 768w" sizes="auto, (max-width: 1452px) 100vw, 1452px" /> Auswahl aus zuletzt ausgeführten Kommandos, die die Buchstaben »ed« enthalten Falls Sie bei InlineView bleiben wollen, sollten Sie zumindest die beiden HistorySearch-Kommandos in Erwägung ziehen. Normalerweise blättern Cursor auf und Cursor ab durch alle bisherigen Kommandos. Mit den hier vorgeschlagenen Einstellungen können Sie dagegen git eingeben und dann durch die bisherigen git-Kommandos blättern. Emacs- und Vi-Fans werden begeistert sein, dass die PowerShell per EditMode die vertrauten Tastenkürzel akzeptiert. Die if-Abfrage im folgenden Listing stellt sicher, dass die Einstellungen nur in interaktiven Sessions gelten, aber z.B. nicht, wenn die PowerShell ein einzelnes Kommando via SSH ausführt. # Ergänzungen in der Profile-Datei if (-not [Console]::IsInputRedirected -and (Get-Module -Name PSReadLine -ErrorAction SilentlyContinue)) { # zeigt Vervollständigungsliste an, Auswahl per Cursortasten Set-PSReadLineOption -PredictionViewStyle ListView # Cursor auf/ab berücksichtigen die bisherige Eingabe Set-PSReadLineKeyHandler -Key UpArrow ` -Function HistorySearchBackward Set-PSReadLineKeyHandler -Key DownArrow ` -Function HistorySearchForward # Emacs- oder Vi-Tastenkürzel (per Default: Windows-Tastenkürzel) Set-PSReadLineOption -EditMode Emacs Set-PSReadLineOption -EditMode Vi # besser sichtbare Farbe für Inline-Vervollständigung Set-PSReadLineOption -Colors @{ InlinePrediction = '#884488' } # keine Duplikate in der Kommando-History speichern Set-PSReadLineOption -HistoryNoDuplicates } Terminal-Editoren An GUI-Editoren herrscht unter Windows kein Mangel — die Palette reicht von notepad.exe über Notepad++ bis hin zu VS Code und anderen KI-tauglichen Programmen/IDEs. Aber oft wollen Sie einfach nur ein paar Zeilen Text ändern, eine Konfigurationsdatei vervollständigen etc. — und zwar, ohne das Terminal zu verlassen. (Das gilt insbesondere, wenn Sie via SSH remote arbeiten!) Dazu brauchen Sie einen Editor, der im Terminal ausgeführt werden kann. edit: Durchaus nicht die schlechteste Wahl ist edit. Mitte 2025 hat Microsoft diesen Mini-Editor vorgestellt — als GitHub-Projekt in der Programmiersprache Rust! Damit liegt Microsoft voll im Zeitgeist. Zur Installation führen Sie winget install microsoft.edit aus. In der Folge lädt edit <file> die gewünschte Datei. Bemerkenswert an edit ist die intuitive, einfache Bedienung. Text wird mit den Cursortasten markiert, mit Strg+C und Strg+V kopiert und wieder eingefügt etc. Die Cursorposition kann mit der Maus verändert werden, auch das lokalisierte Menü lässt sich per Maus bedienen und gibt IT-Veteranen ein wenig Turbo-Pascal-Vibes. Fortgeschrittene Funktionen fehlen allerdings: kein Syntaxhighlighting, keine Code-Vervollständigung, keine Einstellungen … <img loading="lazy" decoding="async" src="https://kofler.info/wp-content/uploads/powershell-edit.png" alt="Das Bild zeigt den Windows-CLI-Editor „Edit“ beim Bearbeiten einer PowerShell-Profildatei. Oben ist die Menüleiste mit „Datei“, „Bearbeiten“, „Ansicht“ und „Hilfe“ zu sehen; das Menü „Ansicht“ ist geöffnet. Darin stehen Optionen wie „Statusleiste fokussieren“, „Gehe zu Datei“, „Gehe zu Zeile:Spalte“ und „Zeilenumbruch“. Im Editor ist PowerShell-Code mit PSReadLine-Einstellungen sichtbar." width="1452" height="790" class="size-full wp-image-9524" srcset="https://kofler.info/wp-content/uploads/powershell-edit.png 1452w, https://kofler.info/wp-content/uploads/powershell-edit-850x462.png 850w, https://kofler.info/wp-content/uploads/powershell-edit-1280x696.png 1280w, https://kofler.info/wp-content/uploads/powershell-edit-768x418.png 768w" sizes="auto, (max-width: 1452px) 100vw, 1452px" /> Der relativ neue CLI-Editor »Edit« nano: In der Linux-Welt ist nano das Gegenstück zu edit. Der Editor hat zwar nur relativ wenige Funktionen, ist dafür aber einfach zu bedienen. Praktischerweise zeigt das Programm alle erforderlichen Tastenkürzel gleich in der Statusleiste an. Die Installation gelingt unkompliziert mit winget install -e --id GNU.Nano. vi/NeoVim: Die einen lieben ihn, andere hassen ihn — das Editor-Urgestein vi. Vi-Fans verwenden unter Windows am besten die Variante NeoVim (siehe https://neovim.io). NeoVim ist aber nur die Basis: Damit das Programm sein ganzes Potential ausschöpfen kann, brauchen Sie diverse Erweiterungen (Git, LSP, Fuzzy Finding usw.) und Konfigurationseinstellungen. Das Setup gelingt am schnellsten mit Frameworks wie LazyVim oder AstroNvim. Emacs: Mich hat der Vi nie überzeugen können, ich bin im Emacs-Lager. Unter Windows ist das allerdings ein Abenteuer. Von abgespeckten Emacs-Klonen wie mg, zile oder jmacs gibt es keine Windows-Ports, die im Terminal funktionieren. Also muss es die Vollversion sein: winget install -e --id GNU.Emacs. winget kümmert sich leider nicht darum, das Emacs-Installationsverzeichnis zum Path hinzuzufügen. Sie müssen sich selbst um diesen Schritt kümmern. Die ausführbare Datei befindet sich üblicherweise in C:\Program Files\Emacs\emacs-<n.n>\bin. Beim Start des Editors müssen Sie an die Option -nw denken (no window), sonst erscheint der Emacs in einem eigenen Fenster statt im Terminal. Noch eine Besonderheit betrifft die Konfigurationsdatei ~/.emacs. Die Windows-Version des Emacs liest diese Datei normalerweise (abhängig von der HOME-Umgebungsvariablen) nicht aus C:\Users\name\.emacs, sondern aus C:\Users\name\AppData\Roaming\.emacs. Wenn Emacs Unicode-Zeichen fehlerhaft anzeigt, bauen Sie die folgenden Anweisungen in .emacs ein: # Datei C:\Users\<name>\AppData\Roaming\.emacs (prefer-coding-system 'utf-8) (set-default-coding-systems 'utf-8) (set-terminal-coding-system 'utf-8) (set-keyboard-coding-system 'utf-8) (set-language-environment "UTF-8") sudo Um unter Windows ein Kommando mit Administratorrechten auszuführen, müssen Sie zuerst umständlich ein Terminal mit Admin-Rechten öffnen. Unter Linux und macOS klappt das mit sudo viel unkomplizierter. Ab Version 11 / 24H2 gibt es sudo auch unter Windows. Microsoft hat das Kommando komplett neu implementiert und nur den Namen übernommen. Die Funktionsweise und Optionen sind anders als unter Linux oder macOS. Insbesondere gibt es keine (Passwort-)Authentifizierung; stattdessen erscheint vor sudo-Aktivitäten nur der UAC-Bestätigungsdialog (User Account Control). sudo muss zuerst aktiviert werden. Sie finden die Option in den Einstellungen unter System / Erweitert / Terminal. Erweitert**. Im rechten Bereich sind Optionen für **Terminal** (Standard „Windows-Terminal“) und **PowerShell** zu sehen. Darunter ist der Schalter **„sudo aktivieren“** eingeschaltet („Ein“) inklusive Hinweis auf mögliche Sicherheitsrisiken. Eine Dropdown-Option konfiguriert, wie sudo Apps ausführt, z. B. „In einem neuen Fenster“." width="1456" height="940" class="size-full wp-image-9541" srcset="https://kofler.info/wp-content/uploads/powershell-sudo.png 1456w, https://kofler.info/wp-content/uploads/powershell-sudo-850x549.png 850w, https://kofler.info/wp-content/uploads/powershell-sudo-1280x826.png 1280w, https://kofler.info/wp-content/uploads/powershell-sudo-768x496.png 768w" sizes="auto, (max-width: 1456px) 100vw, 1456px" /> sudo unter Windows aktivieren Es gibt drei Arten, wie sudo-Kommandos ausgeführt werden können: in einem neuen Fenster (gilt per Default, forceNewWindow), mit deaktivierter Eingabe (disableInput, die Standardeingabe wird blockiert) oder inline (normal, also wie unter Linux mit der Möglichkeit, direkt im Terminal mit dem ausgeführten Kommando zu interagieren). Statt in den Einstellungen können Sie sudo auch in einem Terminal mit Admin-Rechten aktivieren: sudo config --enable forceNewWindow|disableInput|normal Sobald sudo zur Verfügung steht, können Sie das Kommando wie in den folgenden Beispielen anwenden. (Das erste Kommando setzt voraus, dass das Programm edit installiert ist.) sudo edit C:\Windows\System32\drivers\etc\hosts sudo notepad C:\Windows\System32\drivers\etc\hosts sudo winget upgrade --all sudo pwsh -c "Restart-Service -Name Spooler" Beachten Sie, dass sudo Restart-Service -Name Spooler nicht funktioniert! sudo kann nur »echte« Kommandos (Executables) ausführen, keine CmdLets. Für CmdLets müssen Sie den Umweg über eine neue PowerShell-Instanz nehmen. Der Windows-Implementierung von sudo fehlt auch die Option -s, um eine neue Shell zu starten. Stattdessen führt sudo pwsh zum Ziel. Sicherheitsbedenken: Microsoft warnt davor, sudo ohne unmittelbare Notwendigkeit zu aktivieren. Die Warnung bezieht sich insbesondere auf die Inline-Variante. In der sudo-Implementierung von Linux wurden über den Verlauf von Jahrzehnten immer neue Sicherheitsprobleme gefunden und behoben. Vor diesem Hintergrund rate ich dazu, die Warnungen Microsofts ernst zu nehmen. sudo ist eine vergleichsweise neue, bislang eher selten genutzte Funktion. gsudo: Eine Alternative sudo ist das schon länger verfügbare Kommando gsudo. Dieses Open-Source-Projekt bietet mehr Features als die Microsoft-Implementierung. less Wie man als Entwickler/Admin ohne less leben kann ist mir schleiferhaft. Unzähligen Windows-Admins scheint dies aber zu gelingen. Ich habe dazu aber keine Lust. less ist nur ein winget-Kommando entfernt! winget install jftuga.less Quellen/Links https://nerdfonts.com https://ohmyposh.dev https://starship.rs https://github.com/MicrosoftDocs/PowerShell-Docs/blob/main/reference/5.1/PSReadLine/Set-PSReadLineOption.md Editoren https://github.com/microsoft/edit https://neovim.io https://www.lazyvim.org https://astronvim.com https://www.gnu.org/software/emacs sudo https://github.com/microsoft/sudo https://learn.microsoft.com/windows/advanced-settings/sudo https://github.com/gerardog/gsudo less https://github.com/jftuga/less-Windows