Webseiten einfach zusammenfassen mit Fabric in Alfred und Apple Kurzbefehlen

Ein Schwarz-Weiß-Linienkunstwerk, das eine moderne Büroumgebung darstellt. Zu sehen ist ein eleganter Schreibtisch mit einem Computer, auf dessen Bildschirm Code-Snippets und ein Browserfenster angezeigt werden. Auf dem Schreibtisch befinden sich außerdem ein Notizbuch, eine Kaffeetasse und verschiedene technische Geräte wie ein Smartphone und Kopfhörer. Der Stil ist sauber und minimalistisch, mit klaren Strichen, die Klarheit und Raffinesse vermitteln und an Illustrationen aus Technikmagazinen oder zeitgenössischen Design-Blogs erinnern. Die Komposition betont die nahtlose Integration von Technologie und Produktivität und vermittelt ein Gefühl von Innovation und Effizienz.

Hinweis

Da kurz nach der Veröffentlichung der ers­ten Version die­ses Artikels Fabric in Go neu imple­men­tiert wur­de, habe ich den Artikel über­ar­bei­tet und ergänzt.


Einführung in die Nutzung von Fabric mit Alfred und Apple Kurzbefehlen

Wie in mei­nem vor­he­ri­gen Artikel ver­spro­chen möch­te ich in die­sem Artikel Wege auf­zei­gen, wie man Fabric auch in Workflows mit der Alfred App sowie in den Apple Kurzbefehlen nut­zen kann. Für die Alfred App wird aller­dings das kos­ten­pflich­ti­ge PowerPack benö­tigt.

Dazu möch­te ich den Beispielsaufruf aus dem vor­he­ri­gen Artikel nut­zen, der auf der Kommandozeile schon eine Webseite zusam­men­fass­te. Eigentlich eine Aufgabe, die man lie­ber mit einem Tastendruck oder einem Klick erle­digt.

Hier noch ein­mal der Aufruf zur Erinnerung:

wget -qO- https://ileif.de/2024/08/07/automatisierung-von-apple-kurzbefehlen-mit-shortery/ |  pandoc -f html -t plain  | fabric -sp summarize

Der Alfred App Workflow

Ziel ist es, einen Workflow für Alfred zu erstel­len, der mit einer Tastenkombination, z.B. ⌃⌥F, die URL eines akti­ven Browser-Fensters über­nimmt, eine Zusammenfassung erstellt und die­se dann in mei­nem Obsidian-Vault im Ordner „17 WebSiteSummaries“ spei­chert. Die Notiz soll den Titel der Webseite tra­gen und einen Properties-Bereich ent­hal­ten, in dem unter ande­rem die URL der Seite als „source“ und der Tag „fabric“ fest­ge­legt wer­den.

Shell-Skripte und auch Python-Skripte lau­fen immer in einer Umgebung, in der Suchpfade, Variablen und im Falle von Python auch instal­lier­te Bibliotheken durch eine oder meh­re­re Konfigurationsdateien defi­niert sind. Für das Terminal gibt es einen fest­ge­leg­ten Ablauf, in dem bestimm­te Konfigurationen gela­den wer­den. Zusätzlich kom­men bei Python die vir­tu­el­len Umgebungen hin­zu. Wenn jedoch Skripte in Tools wie Alfred oder in den Kurzbefehlen aus­ge­führt wer­den, wer­den nur mini­ma­le Konfigurationsdateien gela­den, wodurch mög­li­cher­wei­se wich­ti­ge Suchpfade für bestimm­te Programme feh­len. Wie die­ses Problem für Python und vir­tu­el­le Umgebungen gelöst wer­den kann, habe ich in dem Artikel „Python-Skripte in Alfred-Workflows mit vir­tu­el­len Umgebungen nut­zen“ beschrie­ben.

Den Ansatz habe ich nun auch auf das Ausführen von Shell-Skripten über­tra­gen. Theoretisch könn­te die gesam­te ~/.zshrc gela­den wer­den, aber ich benö­ti­ge nur die Suchpfade für Go sowie die Einbindung der Alias-Definitionen. Gegebenenfalls muss auch der Suchpfad für die Homebrew-Apps hin­zu­ge­fügt wer­den:

export PATH="$PATH:$HOME/go/bin:$HOME/Applications"

if [ -f "$HOME/.config/fabric/fabric-bootstrap.inc" ]; 
    then . "$HOME/.config/fabric/fabric-bootstrap.inc"; 
fi

Die Datei ist bei mir unter $HOME/.fabenv gespei­chert und kann von dort gela­den wer­den. Was die if ... fi habe ich in dem vor­he­ri­gen Artikel beschrie­ben.

Der Workflow in der Alfred App sieht so aus:

Ein Workflow in der Alfred-App, der aus einem Hotkey-Trigger, einer Aktion zum Abrufen der URL des aktuellen Browser-Tabs, einem Skriptmodul und einer Benachrichtigung besteht. Der Workflow wird durch die Tastenkombination ⌃⌥F ausgelöst und zeigt nach der Ausführung des Skripts eine Benachrichtigung an.

Als Trigger ver­wen­de ich einen Hotkey-Trigger, der die “Current Front Browser Tab” auf­ruft. Da sowohl die URL als auch der Titel der Webseite benö­tigt wird, muss in der Aktion das “Output Format” auf “URL⇥Title” ein­ge­stellt sein. So wer­den die URL und der Title, die mit einem TAB getrennt als ein String an die “Spilt Arg” über­ge­ben wird, die wie­der­um dar­aus, mit den Einstellung “Split with Tab”, Output as Vaiables” und “Varable Prefix split”, die­se dann an die “Run Script”-Aktion wei­ter gibt.

Hier wird in der Kopfzeile als „Language: /bin/zsh — ‑norcs”, “with input as argv “ und ”run­ning ins­tances: Sequentially” ein­ge­stellt. In den Skriptbereich wird die­ses Skript ein­ge­fügt und ange­passt:

# Übergabe der Parameter aus dem Split-Modul
url=$split1
title=$split2

# Lädt die Konfigurations- oder Initialisierungsdatei '.fabenv', die sich im angegebenen Pfad befindet
# Diese Datei enthält die notwendigen Pfad Information und Umgebungsvariablen
source $HOME/.fabenv

# Verarbeitet den Titel: Ersetzt alle Vorkommen von ':' und '/' durch '-'
# Dies ist notwendig, da ':' und '/' in Dateinamen ungültige Zeichen sind
FILENAME=$(echo "$title" | sed 's/[:\/]/-/g')

# Definiert das Zielverzeichnis, in dem die Markdown-Datei gespeichert werden soll
# Der Pfad enthält Leerzeichen, daher ist er in Anführungszeichen eingeschlossen
TARGET_DIR="$HOME/Documents/01 Meine Dokumente/ObsidianNotes/17 WebSiteSummaries"

# Setzt den vollständigen Dateinamen mit der .md-Erweiterung
# Der Dateiname basiert auf dem bereinigten Titel
FULL_FILENAME="${FILENAME}.md"

# Erstellt die Markdown-Datei im Zielverzeichnis mit dem Frontmatter-Block
{
  echo "---"
  echo "source: ${url}"
  echo "erstellt:"
  echo "geändert:"
  echo "tags: fabric"
  echo "---"
  echo ""
} > "${TARGET_DIR}/${FULL_FILENAME}"

# Führt den Befehl 'wget' aus, um den Inhalt der URL zu holen und durch eine Pipe an 'pandoc' weiterzuleiten
# 'pandoc' konvertiert den HTML-Inhalt in reinen Text
# 'fabric' fasst den Text in deutscher Sprache zusammen
# Die Ausgabe wird an das Ende der bereits erstellten Notiz angehängt
wget -qO- $url | pandoc -f html -t plain | fabric -sp summarize_german | >> "${TARGET_DIR}/${FULL_FILENAME}"

# Fügt weitere Informationen am Ende der Notiz hinzu
{
  echo ""
  echo "---"
  echo "Ordner: `=this.file.folder`"

Im Property-Bereich der Notiz set­ze ich die Schlüssel „erstellt:“ und „geän­dert:“ ein, die in mei­nem Vault auto­ma­tisch vom Plugin Update time on edit befüllt wer­den. Zudem wird die­se Notiz mit „fabric“ getaggt. Ich defi­nie­re auch noch einen Footer, den alle mei­ne Notizen ent­hal­ten, der mit­hil­fe des DataView-Plugins den Ordner anzeigt, in dem sich die Notiz befin­det. Für den Rest soll­ten die Kommentare im Skript aus­rei­chen­de Erklärungen lie­fern.

Am Ende des Workflows wird eine Benachrichtigung ange­zeigt, sobald das Skript durch­ge­lau­fen ist. Da die Antwort des LLMs oft eini­ge Sekunden benö­tigt, kann es vor­kom­men, dass die Notiz bereits mit dem Property-Bereich in die Vault geschrie­ben und ange­zeigt wird, wäh­rend der rest­li­che Inhalt noch fehlt. Es kann also einen Moment dau­ern, bis der gesam­te Text in der Notiz erscheint.

Nicht jede Webseite lässt sich auf die­se Weise abgrei­fen. Wenn wget den Text nicht kor­rekt aus dem HTML extra­hie­ren kann, wird statt­des­sen ein belie­bi­ger Text gene­riert, der mög­li­cher­wei­se nichts mit der eigent­li­chen Webseite zu tun hat.

Soweit der Alfred-Workflow, der in allen Webkit- und Chrome-basier­ten Browsern funk­tio­nie­ren soll­te. In Firefox hin­ge­gen funk­tio­niert der Workflow nicht.

Der Apple Kurzbefehl

Eigentlich woll­te ich den Apple Kurzbefehl mit einem ähn­li­chen Skript wie bei der Alfred-Lösung imple­men­tie­ren. Die URL der aktu­el­len Webseite soll­te an das Skript über­ge­ben und dort genutzt wer­den. Es stell­te sich jedoch her­aus, dass bei der Aktion „URL-Eingabe von Bildschirminhalt“ nicht die URL als Argument an die Aktion „Shell-Skript aus­füh­ren“ über­ge­ben wird, son­dern der Pfad zu einer loka­len Kopie der HTML-Datei der Webseite.

Ein klei­ner Test-Kurzbefehl zeigt das Problem auf:

Ein Screenshot eines macOS-Kurzbefehl-Editors zeigt einen Workflow namens “URL-Test”. Der Workflow beginnt mit dem Empfang einer URL-Eingabe, gefolgt von der Anzeige einer Kurzbefehlseingabe. Anschließend wird ein Shell-Skript ausgeführt, das den eingegebenen Wert mit dem Befehl echo $1 im Terminal ausgibt. Das Shell-Skript verwendet die Shell zsh, und die Eingabe wird als Argument übergeben. Zum Abschluss wird das Ergebnis des Shell-Skripts im Kurzbefehleditor angezeigt. Der Editor selbst ist in einem dunklen Farbschema gehalten, und auf der rechten Seite befindet sich eine Liste verfügbarer Skripte.

Nachdem „URL-Eingabe von Bildschirminhalt“ in einem akti­ven Browserfenster auf­ge­ru­fen wur­de, wird in der Aktion „Ergebnis anzei­gen“ tat­säch­lich die URL der Webseite ange­zeigt:

Ein Screenshot eines kleinen Fensters mit dem Titel “URL-Test”. Im Fenster wird eine URL angezeigt: https://help.obsidian.md/Linking+notes+and+files/Aliases. Unten im Fenster befinden sich zwei Schaltflächen: eine zum Teilen (Symbol mit einem Pfeil) und eine orangefarbene Schaltfläche mit der Aufschrift “Fertig”. Das Fenster hat ein schlichtes, graues Design mit den typischen macOS-Fenstersteuerungsknöpfen in der oberen linken Ecke.

Aber das Shell-Skript erhält etwas völ­lig ande­res, wie die zwei­te Ergebnisanzeige zeigt:

Ein Screenshot eines Fensters mit dem Titel “URL-Test”. Im Fenster wird ein Dateipfad angezeigt:

Leider habe ich den Test nicht sofort durch­ge­führt, sodass ich letzt­lich eini­ge Zeit damit ver­bracht habe, das Problem zu ana­ly­sie­ren.

Eine wei­te­rer Punkt, der Zeit in Anspruch nahm, war der unter­schied­li­che Inhalt der $PATH-Variable bei Alfred und den Kurzbefehlen. Während bei Alfred der Pfad zu den von Homebrew instal­lier­ten Befehlen im Suchpfad ange­ge­ben war, fehl­te die­ser in der Apple-Kurzbefehle-Version.

Der Workaround, ohne die Homebrew-Befehle, ist zwar letzt­lich etwas ein­fa­cher, aber ich woll­te die Hürden an die­ser Stelle doch ein­mal doku­men­tie­ren.

Der Apple Kurzbefehl

Ich habe mir für den Workaround zunut­ze gemacht, dass mit der Option „Bildschirminhalt emp­fan­gen“ eine loka­le Kopie der Webseite erstellt wird und der Pfad zu die­ser Datei beim Aufruf des Shell-Skripts in der Aktion „Shell-Skript aus­füh­ren“ über­ge­ben wird. Ob dies ein Feature oder ein Bug ist, der irgend­wann besei­tigt wird, wird die Zukunft zei­gen.

Das Shell-Skript sieht dann fol­gen­der­ma­ßen aus:

source $HOME/.favenv
cat $1 | fabric -sp summarize_german

Und so läuft der Prozess ab:

  1. Die URL und der Titel der Webseite wer­den an den Kurzbefehl über­ge­ben und in den ent­spre­chen­den Variablen gespei­chert.
  2. An die Aktion „Shell-Skript aus­füh­ren“ wird über die Variable URL der Pfad zur loka­len HTML-Datei über­ge­ben.
  3. Im Skript wird zunächst der Suchpfad über die Konfigurationsdatei um die Go-spe­zi­fi­schen Pfade erwei­tert. Anschließend wird der Inhalt der loka­len HTML-Datei an fabric über­ge­ben und mit dem Pattern summarize_german vom LLM ver­ar­bei­tet.
  4. Die Ausgabe des Shell-Skripts wird in der Variablen Text gespei­chert. Dann wird in einem Text die Notiz zusam­men­ge­stellt, inklu­si­ve Property-Bereich und Footer.
  5. Dieser Text wird dann in der Obsidian-Vault gespei­chert.

Zum Speichern der Notiz in der Obsidian-Vault nut­ze ich die Kurzbefehl-Erweiterung Actions for Obsidian mit der Aktion „Create Note“. Alternativ kann das Speichern auch mit der Aktion „Datei sichern“ umge­setzt wer­den, aber im Zusammenhang mit Obsidian lohnt es sich, etwas Geld in Actions for Obsidian zu inves­tie­ren.

Das gan­ze sieht dann so aus:

Screenshot eines Apple Kurzbefehls namens “WebSummary”. Der Kurzbefehl beginnt mit der Aktion „Bildschirminhalt empfangen“, um die URL und den Titel einer Webseite zu erhalten. Es folgen Aktionen, um den Titel anzupassen und ein Shell-Skript auszuführen, das die Webseite zusammenfasst. Das Ergebnis wird in der Variablen „Text“ gespeichert und dann in einer neuen Notiz in Obsidian mit einem Property-Bereich und Footer gespeichert.

Wie im Alfred-Workflow kann es vor­kom­men, dass bestimm­te Webseiten sich nicht abgrei­fen las­sen. In die­sem Fall wird je nach ver­wen­de­tem LLM ein belie­bi­ger Text als Ausgabe erschei­nen.

Zusammenfassung und Ausblick auf zukünftige Anwendungen

Ich hof­fe, dass ich mit die­sem Artikel nicht nur ein nütz­li­ches Tool vor­ge­stellt habe, son­dern auch einen Ausgangspunkt für eige­ne Lösungen bie­ten konn­te, wie Fabric in ande­re Workflows inte­griert wer­den kann. Ich habe hier Alfred und Apple Kurzbefehle genutzt, bin aber über­zeugt, dass sich die Ansätze auch in Raycast und ande­ren Workflow-Tools ein­set­zen las­sen.

Beide Beispiel-Workflows sind sicher­lich noch nicht voll­stän­dig aus­ge­reift. Beispielsweise fehlt in bei­den ein Fehlerhandling. Ich könn­te mir zudem vor­stel­len, dass über einen Auswahl-Dialog ande­re Patterns aus­ge­wählt wer­den könn­ten. Außerdem lau­fen die Workflows lokal auf mei­nem MacBook Pro, daher habe ich noch nicht getes­tet, ob mit der “Remote Shell-Skript”-Aktion die Ausführung des Fabric-Aufrufs auf einem Server statt­fin­den kann. Solange kei­ne loka­len LLMs invol­viert sind, soll­te eigent­lich ein Raspberry Pi aus­rei­chen. So könn­te ein Kurzbefehl auch auf einem iPad oder iPhone funk­tio­nie­ren.

Es ist also gut mög­lich, dass ich in die­sem Blog noch wei­te­re Anwendungen vor­stel­len wer­de.

Wie immer: Kritik, Korrekturen und Lob ger­ne in die Kommentare.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert