WriteSpeech
Deutscher Windows-Schreibassistent im Hintergrund – kopierte Texte mit einem globalen Hotkey überarbeiten oder über das Mikrofon diktieren. Native WPF-Oberfläche, Tray, lokale Profile und getrennte, sicher gespeicherte API-Schlüssel.
Schnellstart auf Windows
releases/WriteSpeech-Setup-1.0.3-win-x64.exestarten. Windows 10/11 x64 erforderlich; .NET wird self-contained mitgeliefert. Installation ohne Administratorrechte fest nach%LOCALAPPDATA%\Programs\WriteSpeech, Startmenü-Verknüpfung, Desktop-Verknüpfung und Start nach Setup optional. Vor Updates/Deinstallation im Tray ausdrücklich „WriteSpeech beenden“ wählen; X schließt nur das Fenster. Ein laufender Assistent oder anderes Setup blockiert den Vorgang mit Hinweis, ohne Prozesse zu beenden.- Unter Einstellungen einen eigenen OpenRouter-API-Schlüssel eingeben und Schlüssel speichern wählen. Optional ausdrücklich Verbindung testen: Das authentifiziert
/auth/key; ein öffentlicher Modellkatalog allein gilt nicht als Schlüsselprüfung. - Standardmodell auswählen/eingeben (anfangs
openai/gpt-4o-mini). Modellkatalog laden ist eine bewusste Netzwerkaktion. Verfügbarkeit, Kosten und Guthaben hängen vom Anbieter ab. - Im gewünschten Editor Text auswählen und Strg+C drücken. Ctrl+Alt+W überarbeitet den kopierten Unicode-Text mit dem aktiven Profil. Nach der Benachrichtigung Strg+V drücken.
- Unter Sprache ein unterstütztes OpenRouter-Audiomodell wählen (Standard:
google/gemini-2.5-flash). Ctrl+Alt+S startet/stoppt ein Diktat. Das kleine Aufnahmefenster nimmt keinen Tastaturfokus. Stopp verarbeitet, Abbruch verwirft.
X blendet das Hauptfenster in den Tray aus. Ein Doppelklick auf das Tray-Symbol öffnet es. Über das Tray-Menü: Profil wechseln, aufnehmen, Zwischenablage verarbeiten, letztes Ergebnis kopieren, Einstellungen und ausdrücklich beenden. WriteSpeech.exe --hidden startet verborgen. Eine zweite Instanz aktiviert die erste. „Mit Windows anmelden starten“ schreibt nur in den Run-Schlüssel des aktuellen Benutzers, ohne Administratorrechte.
Profile und Bedienung
Sieben bearbeitbare deutsche Startprofile: Professionell, Freundlich, Kurz & präzise, Grammatik & Rechtschreibung, Locker, Technisch, Eigener Prompt. Profile lassen sich erstellen, bearbeiten, löschen und im Tray oder auf Home aktivieren. Das letzte Profil kann nicht gelöscht werden. Aktives Profil und Standardprofil sind unabhängig; der zuletzt aktive Zustand bleibt auch nach Neustarts erhalten. „Standardprofil aktivieren“ schaltet ausdrücklich zurück.
Ein Profil enthält Name, Stil-/System-Prompt, optional eine eigene Modell-ID/Temperatur sowie ein Ausgabelimit. Modellüberschreibung hat Vorrang vor dem Standardmodell. Temperatur 0–2, Ausgabelimit 64–16384 Tokens. Abgeschnittene Antworten werden nicht als vollständiges Ergebnis akzeptiert. Der feste Sicherheitsprompt behandelt den Eingangstext als untrusted data, fordert Bedeutungstreue, keine erfundenen Fakten und nur Ergebnistext. Ergebnisse von KI weiterhin selbst prüfen.
Hotkeys: Ctrl, Alt, Shift, Win mit A–Z, 0–9 oder F1–F24; mindestens Ctrl/Alt/Win erforderlich. Profilwechsel und „letztes Ergebnis kopieren“ sind optional. Duplikate und bekannte reservierte Kombinationen werden abgewiesen. Windows-Registrierungsfehler benennen die Kombination und empfehlen einen anderen Hotkey oder das Schließen der belegenden App. Die gesamte Registrierung wird bei Konflikten zurückgerollt; wenn inzwischen auch die alten Hotkeys belegt sind, wird das explizit gemeldet.
Ein einzelner Schreibvorgang läuft gleichzeitig. Weitere Verarbeitungsaktionen erzeugen keine parallelen OpenRouter-API-Anfragen. Abbrechen stoppt Aufnahme/HTTP/Pipeline. Beim expliziten Beenden werden Hotkeys, Audio und Tray freigegeben. Der Aufnahme-Timer läuft ausschließlich während einer Aufnahme. Die Codex-Verbrauchsanzeige fragt bei laufender App alle fünf Minuten den lokalen Codex-App-Server ab (siehe unten).
Codex-Plan: Verbrauch und Benachrichtigungen
Unter Codex sowie über das Tray-Menü Codex-Verbrauch erscheinen die verbleibenden Prozente und lokalen Reset-Zeiten der vom Codex-Dienst gemeldeten Zeitfenster. Das können beispielsweise fünf Stunden und eine Woche sein; ein Tagesbudget wird nur angezeigt, wenn Codex tatsächlich ein Tagesfenster meldet. Voraussetzung: Die offizielle Codex-CLI ist auf Windows im PATH verfügbar und dort mit einem ChatGPT-Konto angemeldet (codex login). Eine Anmeldung nur mit API-Schlüssel oder der OpenRouter-Schlüssel ist dafür nicht ausreichend. Ohne CLI/Anmeldung zeigt die Seite einen Hinweis statt geschätzter Zahlen.
Beim Start und anschließend alle fünf Minuten startet WriteSpeech kurz codex app-server und fragt über dessen lokale Standardschnittstelle ausschließlich Kontotyp und Verbrauchsfenster ab. WriteSpeech liest oder speichert weder ChatGPT-Zugangsdaten noch überträgt sie selbst; die CLI kommuniziert für den Abruf mit Codex. Eine manuelle Aktualisierung ist auf der Codex-Seite möglich. Beim beobachteten Unterschreiten von 50 %, 25 % oder 10 % Rest und nach einem beobachteten Reset erscheint eine Windows-Tray-Benachrichtigung (sofern Benachrichtigungen aktiviert sind). Beim ersten Abruf sowie während die App nicht läuft werden keine rückwirkenden Benachrichtigungen erzeugt. Reset-Hinweise setzen einen erfolgreichen Abruf davor und danach voraus. Die Anzeige ist nur so aktuell wie der letzte erfolgreiche Abruf.
Sprache: OpenRouter-Audiomodell wählen
WriteSpeech sendet WAV-Audio als input_audio an die feste OpenRouter-Chat-URL. Ein Audiomodell transkribiert es; anschließend überarbeitet das Schreibprofil den erkannten Text über OpenRouter. Derselbe unter Einstellungen gespeicherte OpenRouter-Schlüssel wird für beide Anfragen verwendet.
Beispiel unter Sprache:
| Feld | Beispiel |
|---|---|
| Mikrofon | Windows-Standardmikrofon oder eines der erkannten Geräte |
| OpenRouter-Audiomodell | google/gemini-2.5-flash oder google/gemini-2.5-pro |
| Sprache | de (leer für automatische Erkennung) |
Nur die explizit angebotenen OpenRouter-Audioeingangsmodelle können für Transkription gespeichert oder verwendet werden. Die Auswahl ist bewusst begrenzt; Modellverfügbarkeit, WAV-Unterstützung, Preise und Guthaben vor der Nutzung bei OpenRouter prüfen. Die Modellliste für Textüberarbeitung bleibt davon unabhängig. HTTP-Weiterleitungen werden nicht verfolgt.
Alte Konfigurationen mit einem separaten STT-Endpunkt werden beim Laden auf das OpenRouter-Standard-Audiomodell umgestellt; Profile und andere Einstellungen bleiben erhalten. Ein vormals gespeicherter speech.dpapi-Schlüssel wird nicht mehr gelesen oder verwendet und kann bei Bedarf manuell entfernt werden. Audio geht nur bei ausdrücklich gestarteter Aufnahme und deren Stopp/automatischem Zeitlimit an OpenRouter. Abbruch lädt nichts hoch.
Aufnahme: WinMM waveIn, 16 kHz / Mono / 16-bit PCM, einstellbares Limit 5–300 Sekunden (anfangs 120). Maximal 9,6 MB PCM, 10 MB WAV-Grenze vor Base64-Kodierung für die OpenRouter-JSON-Anfrage; Puffer und WAV bleiben ausschließlich im begrenzten Arbeitsspeicher und werden nach Ende verworfen/geleert. Keine temporären Audiodateien. Manche Geräte unterstützen dieses Format nicht: Fehlermeldung statt stiller Ersatzaufnahme. Bei fehlendem Mikrofon oder Zugriffsverweigerung Windows Datenschutz & Sicherheit → Mikrofon → Desktop-Apps zulassen, Gerät und Gerätestatus prüfen.
Zwischenablage und optionales Einfügen
- Automatisches Einfügen ist standardmäßig AUS.
- Keine Auswahl wird aus fremden Apps ausgelesen: vor dem Hotkey ausdrücklich kopieren. Der Eingang ist Unicode aus der Zwischenablage, kein Screenshot oder Tastaturmitschnitt.
- Beim Start werden Profil und ursprüngliches Vordergrundfenster einschließlich fokussiertem Kindfeld aufgenommen. Ein Profilwechsel während einer Anfrage verändert diese Anfrage nicht.
- Fehler, ungültige/leere/abgeschnittene Antworten sowie Abbruch vor dem erfolgreichen Schreiben verändern die Zwischenablage nicht. Bei gesperrter Zwischenablage gibt es begrenzte Wiederholungen; niemals „erfolgreich“ ohne tatsächliches Schreiben.
- Optionales Einfügen wartet bis zu 1,2 Sekunden auf physisch losgelassene Modifikatoren. Fenster, Prozess, Kindfokus, Clipboard-Sequenz und Integritätsstufen müssen passen. Unterstützt sind native
Edit,RichEdit*,WindowsForms10.EDIT*mit Caret, ohne Passwort-/Nur-Lesen-Status. - Die Paste-Anforderung wird direkt an das geprüfte native Feld per
WM_PASTEmit 500-ms-Grenze geschickt; keine globalenSendInput-Tastendrücke und kein Fokus-Erzwingen. Ein Fokuswechsel kann deshalb nicht Tasten in eine andere App umleiten. Wie bei jeder externen Nachricht sind Zustand/Selection nicht atomar über Prozessgrenzen sperrbar; ein unmittelbar nach der Prüfung geänderter Inhalt kann nicht erkannt werden. - Andere Ziele, Browser/komplexe moderne Editoren, erhöhte/elevated Apps oder unbekannte Rechte: Ergebnis nur kopieren + Hinweis zum manuellen Strg+V. WriteSpeech verlangt keine erhöhten Rechte und umgeht UIPI nicht.
- „Einfügeanforderung gesendet“ ist keine Behauptung, dass eine Auswahl ersetzt oder Text tatsächlich angenommen wurde. Nach dem erfolgreichen Clipboard-Schreiben kann ein späterer Abbruch dieses Schreiben nicht rückgängig machen.
Daten, Datenschutz und Sicherheit
Benutzerdaten: %LOCALAPPDATA%\WriteSpeech
| Datei | Inhalt |
|---|---|
settings.json |
Profile, aktive/default IDs, Modelle, Hotkeys, Optionen, Mikrofon und Dunkelmodus; keine Schlüssel |
settings.backup.json |
Letzte gültige vorherige Konfiguration; auch beim ersten Speichern angelegt |
openrouter.dpapi |
Binär, Windows DPAPI CurrentUser, OpenRouter-Schlüssel |
%TEMP%\WriteSpeech\startup-*.log |
Nur bei Startfehlern: Exception-Typ, HResult, Meldung und Stack (auch innere Exceptions); außerhalb des Einstellungsverzeichnisses. Vor Weitergabe selbst prüfen. Wenn auch TEMP nicht schreibbar ist, erscheint die Diagnose im Fehlerdialog. |
JSON wird validiert, über eine geflushte temporäre Datei atomar ersetzt und mit gültiger Sicherung versehen. Bei Beschädigung: Wiederherstellungsnotice, gültige Sicherung laden; wenn beide unlesbar sind, explizite Standardwert-Notice. Beschädigte Dateien bleiben bis zum bewussten Speichern vorhanden. Unbekannte Fehlerdetails werden nicht mit Inhalten protokolliert. DPAPI-Dateien sind an den Windows-Benutzer gebunden, keine portablen Schlüsseldateien. Benutzer mit Zugriff auf denselben Windows-Account können dessen Prozesse/Daten verwenden; DPAPI ist keine Isolation innerhalb desselben Kontos.
OpenRouter und der gewählte Modellanbieter erhalten den ausdrücklich verarbeiteten Text samt Stilprompt. Bei Diktaten erhalten OpenRouter und das gewählte Audiomodell Audio und Sprachhinweis, danach OpenRouter den erkannten Text. OpenRouter-Anfragen erfolgen nur durch die ausdrücklich ausgelösten Aktionen „überarbeiten“, „Aufnahme verarbeiten“, „Verbindung testen“ und „Modellkatalog laden“. Bei installierter und angemeldeter Codex-CLI erfolgen zusätzlich die beschriebenen Verbrauchsabfragen beim Start und im Leerlauf. Audio/Text/API-Schlüssel werden nicht geloggt. Das letzte Ergebnis bleibt nur im Sitzungsspeicher; die Windows-Zwischenablage und gegebenenfalls deren systemeigener Verlauf bleiben separat unter Windows-Kontrolle. Anbieter-Datenschutzbedingungen, Aufbewahrung und Abrechnung gelten zusätzlich.
HTTP: feste Rewrite- und Transkriptions-URL https://openrouter.ai/api/v1/chat/completions; authentifizierter Schlüsseltest /api/v1/auth/key; Katalog /api/v1/models. Rewrite/Test/Katalog maximal 90 s, Transkription 120 s; Nutzerabbruch wirkt sofort auf HTTP. Antworten auf 4 MB begrenzt. Fehler für 401/403, 429, Modell-/Anfragefehler, Netzwerk, Timeout und ungültiges JSON sind benutzerfreundlich und enthalten keine Serverantworten mit potenziellen privaten Daten. Der Dunkelmodus ist unter Einstellungen → Start & Verhalten wählbar und wird in settings.json gespeichert (Standard: hell).
Reproduzierbar bauen und testen
Alle .NET-Kommandos werden über mcr.microsoft.com/dotnet/sdk:10.0 ausgeführt; kein Host-SDK erforderlich. Das einzige Bind-Mount ist dieses Repository (/work), unter Host-UID:GID. HOME, SDK-Home, NuGet-Cache und temporäre Build-Dateien liegen in .home, .dotnet, .nuget, .tmp im Repository. Voraussetzung Linux: Docker, Bash, Python 3, file, sha256sum, Git. Keine weiteren Projekte/Worktrees werden verwendet.
# im Repository-Root
bash scripts/verify.sh
bash scripts/publish.sh
bash scripts/installer.sh
Einzelaufruf über denselben kontrollierten SDK-Wrapper:
bash scripts/docker.sh dotnet run --project tests/WriteSpeech.Tests -c Release
bash scripts/docker.sh dotnet build src/WriteSpeech.Desktop/WriteSpeech.Desktop.csproj -c Release
Windows PowerShell mit Docker Desktop im Linux-Container-Modus:
.\scripts\build.ps1 -Publish
# UID/GID im Linux-Container standardmäßig 1000:1000; bei Bedarf -Uid / -Gid setzen.
.\scripts\windows-check.ps1
# explizit erlaubte lokale Clipboard-/Mikrofontests, keinerlei Upload:
.\scripts\windows-check.ps1 -Clipboard -Microphone
PowerShell führt SDK-Builds ebenfalls im vorgeschriebenen Docker-Image aus. Der Windows-Integrationstest startet danach die self-contained Windows-Test-EXE direkt; hierfür kein Host-SDK. Ohne Flags werden der echte WPF-App.xaml-Themewechsel (einschließlich absichtlich eingefrorenem Brush und materialisierten Styles), DPAPI und echte Hotkey-Konflikt-/Rollback-Registrierung getestet. Clipboard-Test ersetzt vorübergehend den Clipboard-Inhalt und versucht ihn anschließend wiederherzustellen; vorab relevante Daten sichern. Mikrofontest nimmt fünf Sekunden lokal auf und verwirft sie. Testfixture-Dateien liegen ausschließlich im Repository und werden entfernt.
Core-Tests sind eine unabhängige Konsolen-Verhaltenstestsuite (Exit 1 bei Fehlern), keine lediglich kompilierten dotnet test-Platzhalter. HTTP-/Plattform-Fakes nur im Testprojekt. Projektstruktur:
src/WriteSpeech.Core net10.0: Profile, Persistenz, HTTP, Hotkeys, Pipeline, Paste-Regeln
src/WriteSpeech.Desktop net10.0-windows: WPF, Tray, Win32, DPAPI, WinMM
tests/WriteSpeech.Tests plattformunabhängige Verhaltenstests
tests/WriteSpeech.WindowsCheck echte optionale Windows-Integrationsprüfungen
scripts/ reproduzierbare Docker-/PowerShell-Builds, ZIP, NSIS
installer/ per-user NSIS-Quellen
releases/ einziges versionierbares Lieferbinary: Setup-EXE
.delivery/logs/ lokale, ignorierte rote/grüne Tests und Build-Ausgaben
docs/acceptance.md Abnahmematrix und Windows-Checkliste
Publish erzeugt artifacts/WriteSpeech-win-x64/WriteSpeech.exe (self-contained, komprimiertes Single-File, keine WPF-Trimmung) und ein ignoriertes portables ZIP als Build-Zwischenergebnis. installer.sh kompiliert das tatsächlich gebündelte Setup in einem wegwerfbaren Debian-Bookworm-Dockercontainer mit nsis und p7zip-full (APT nur im Container, einziges Bind-Mount dieses Repository). Der NSIS-Loader ist PE32; er verweigert nicht-x64/Windows vor Version 10. Compiler-Version, Archivlisting/-Test/-Extraktion und exakte Payload-Hashes werden protokolliert. Setup/Extraktion gehören anschließend der aufrufenden UID:GID. Nur die Setup-EXE wird als Lieferbinary zur Versionierung bereitgestellt, keine doppelte ZIP. Native Runtime-Komponenten werden beim ersten Windows-Start in den normalen .NET-Bundle-Cache des Benutzers extrahiert.
Releases und Versionen
Die stabile SemVer-Version MAJOR.MINOR.PATCH steht ausschließlich in src/WriteSpeech.Desktop/WriteSpeech.Desktop.csproj (<Version>). scripts/release-version.py liest sie für NSIS: Windows-Dateiversion MAJOR.MINOR.PATCH.0, Produktversion und „Apps & Features“-DisplayVersion MAJOR.MINOR.PATCH, Lieferdatei releases/WriteSpeech-Setup-MAJOR.MINOR.PATCH-win-x64.exe. Die .NET-App übernimmt die Projektversion. Die assemblyIdentity im Windows-Manifest ist eine feste Manifest-Identität, keine Releaseversion. Version vor dem nächsten Release im Projekt erhöhen, die Schnellstart-Datei und docs/results.md nach dem Bau aktualisieren; das vorherige Lieferbinary aus releases/ entfernen, damit nur ein Setup versioniert bleibt. source-check.py erzwingt den Dateinamen und genau ein Lieferbinary.
Aus dem Repository-Root bash scripts/verify.sh, bash scripts/publish.sh, bash scripts/installer.sh in dieser Reihenfolge ausführen. Danach python3 scripts/source-check.py, git diff --check, Größe/SHA-256 der Setup-EXE und die Änderungen prüfen. Nur Quell-/Dokumentationsänderungen und das Setup committen, den Commit mit einem annotierten vMAJOR.MINOR.PATCH-Tag versehen, main und den Tag zum bestehenden Origin pushen und beide Remote-Refs zurücklesen. Windows-Abnahme gemäß docs/acceptance.md gesondert durchführen.
Deinstallation über Windows „Apps“ oder Uninstall.exe: nur bekannte Programmdateien, eigene Verknüpfungen und HKCU-Uninstallregistrierung werden entfernt. Ein fremd gerichteter Autostarteintrag bleibt erhalten. %LOCALAPPDATA%\WriteSpeech mit Einstellungen, Sicherung und DPAPI-Schlüsseln bleibt bei Installation, Update und Deinstallation immer erhalten. Kein rekursives Löschen. Updates stellen die neue EXE zunächst bereit und behalten die vorige EXE bis zum Abschluss erforderlicher Schreibvorgänge; ein verbliebenes .previous.exe blockiert weitere Updates zur manuellen Wiederherstellung. Dies ist keine transaktionale Garantie bei Stromausfall. Ergebnisse und offene Windows-Abnahme: docs/results.md, docs/acceptance.md.
Verifizierungsstand und Grenzen
Release-Prüfergebnisse einschließlich Core-Tests, self-contained Publish, NSIS-Kompilierung und PE-/Bundle-/Archiv-/Hashprüfung: docs/results.md, lokale ignorierte Logs in .delivery/logs. Windows-Installation/-Deinstallation, UI (einschließlich Dunkelmodus), Tray, globale Hotkey-Ereignisse, DPAPI und Hardwareaufnahme sind auf Linux nicht ausgeführt; deren Checkliste/ausführbarer Prüf-Harness sind enthalten, aber nicht als hier bestanden bezeichnet. Ohne eigene Zugangsdaten wurde kein echter OpenRouter-Audioanruf durchgeführt. HTTP-Vertrag und Fehlerwege werden automatisiert mit kontrollierten Antworten getestet.
Die EXE ist nicht signiert. Windows kann Herausgeber-/SmartScreen-Hinweise anzeigen. Keine Empfehlung, Windows-Sicherheitsfunktionen zu deaktivieren. Für reguläre Verteilung ist Codesigning durch den Herausgeber sinnvoll. Benachrichtigungen richten sich nach Windows-/Fokusassistenz-Einstellungen; Status und Ergebnis sind auch auf Home sichtbar. Keine Offline-KI und keine lokale Spracherkennung. Native Clipboard-/Audio-/Tray-Laufzeit und gerätespezifische Formate vor produktivem Einsatz auf dem Ziel-Windows prüfen. Genauere offene Abnahmen: docs/acceptance.md.