Communitygithub.com

xbmaxx/hermes-intro-cinematic

Verwendet, um ein Startfilm-Intro zum Hermes Desktop hinzuzufügen.

Was ist hermes-intro-cinematic?

Diese Fähigkeit passt den Einführungsfilm von Hermes Desktop an, der normalerweise nur einmalig für Gäste abgespielt wird. Sie ermöglicht es, das Intro bei **jedem Start** abzuspielen und eine eigene Sprachspur über die integrierten Soundeffekte zu legen, ohne diese zu ersetzen. Der Skill ändert die Anzeigelogik, um die Wiedergabe zu erzwingen, erlaubt das Hinzufügen einer Voiceover-Audiodatei (`intro-voiceover.mp3`) und bietet detaillierte Anleitungen zum Neupacken der App für eine ausgelieferte Version. Die Implementierung erfordert drei gezielte Code-Änderungen in den Dateien `intro-reveal.ts`, `intro-root.tsx` und `main.ts`, wobei eine modulinterne `playedThisSession`-Flagge unerlässlich ist, um Endlosschleifen zu vermeiden. Sie unterstützt die Entwicklungsplattformen Vite und Electron und wird mit Testfällen, einer Opt-out-Möglichkeit und Browser-Verifikationsschritten geliefert.

Funktioniert mit~Claude Code~Codex CLI~Cursor
npx skills add xbmaxx/hermes-intro-cinematic

In Ihrer bevorzugten KI fragen

Öffnet einen neuen Chat, in dem dieser Agent-Skill bereits geladen ist.

Dokumentation

Hermes Intro Cinematic

Hermes Desktop enthält bereits einen 22-sekündigen Intro-Film – sieben Beats, ein Live-Cube-Viewport, parallele Agenten, die Nous-Marke – mit synthetisiertem Sound. Er existiert, aber fast niemand sieht ihn zweimal: Die Berechtigung ist guestOnboardingEnabled && !seen.

Diese Fähigkeit sorgt dafür, dass der Film bei jedem Start abgespielt wird, und ermöglicht es, eine eigene Sprachspur unter die eingebauten Cues zu legen.

Wann verwenden

  • „Lass die Hermes-Startanimation jedes Mal abspielen.“
  • „Lege meine Audiospur auf die Boot-Animation – darüber, nicht als Ersatz für die Soundeffekte.“
  • Jede Änderung an apps/desktop/src/components/intro-reveal/.

Was der Film bereits ist

TeilPfad
Tor (wann er abgespielt wird)apps/desktop/src/components/intro-reveal/index.tsx
Berechtigung + Phasenspeicherapps/desktop/src/store/intro-reveal.ts
Overlay-Bootsrc/components/intro-reveal/intro-root.tsx
Takt, Punktzahl, Canvasuse-intro-clock.ts, timeline.ts, viewport-cube.ts
Synthesizer-Cuessound.ts
Natürliches Fensterelectron/intro-reveal-window.ts, electron/main.ts

Timing-Mathematik: INTRO_TOTAL_MS = 17 600 ist Partitur-Zeit; Wandzeit ist × INTRO_PACE (1.25) = 22 000 ms, plus INTRO_EXIT_MS 900 ms → 23 125 ms insgesamt.

Wiederholung bei jedem Start – drei Änderungen, alle erforderlich

  1. src/store/intro-reveal.ts – isIntroRevealEnabled() darf nicht mehr die Gast-Einführung voraussetzen; shouldPlayFirstRunIntro() gibt !playedThisSession außerhalb der Einführung zurück. Eine modulebene playedThisSession-Flagge ist zwingend erforderlich: Der Effekt des Tors wird immer dann erneut ausgeführt, wenn die Phase zu 'hidden' zurückkehrt – genau das passiert, wenn der Film endet – ohne die Flagge würde er sich unendlich wiederholen.
  2. src/components/intro-reveal/intro-root.tsx – das Overlay-Fenster prüft isOnboardingEnabled() und würde vor dem Zeichnen zurückkehren. Ändere es auf dasselbe Prädikat wie den Haupt-Renderer.
  3. electron/main.ts – introRevealController wird mit enabled: GUEST_ONBOARDING konstruiert, sodass der Hauptprozess open ablehnt. Setze es auf true; die Lebendigkeit wird im Renderer entschieden.

beginOnboardingFlow() / queueGuideAfterIntro() / takeGuideShape() schützen sich alle selbst mit isOnboardingEnabled(), sodass sie bei deaktivierter Einführung nichts tun – keine zusätzliche Änderung nötig.

Aus-Schalter: localStorage['hermes-intro-reveal-always-v1'] = '0', oder starte mit HERMES_SKIP_INTRO=1 / --skip-intro.

Eine Audiospur überlagern

Lege eine Datei unter apps/desktop/public/intro-voiceover.mp3 ab (Vite kopiert public/ unverändert nach dist/), dann in sound.ts:

export function startVoiceover(cutAtMs: number): { stop: () => void }

– erstelle ein Audio-Element, setze volume, starte es und setTimeout(stop, cutAtMs - 300), damit die letzten 300 ms ausklingen statt zu klicken. Rufe es neben startPad() in use-intro-clock.ts auf und stoppe es im Effekt-Cleanup.

Verwende ein <audio>-Element, niemals fetch() + decodeAudioData(). Der gepackte Renderer läuft auf file://, wo fetch und decodeAudioData durch CORS blockiert werden; Media-Elemente laden file://-Assets problemlos.

Die beiden Spuren sind von Natur aus unabhängig – Element-Audio und WebAudio-Cues mischen sich auf Betriebssystemebene. Nichts dämpft etwas. Verbinde $hapticsMuted mit beiden und abonniere es, anstatt es einmal zu lesen, sonst gerät der Stummschaltungs-Toggle außer Sync.

Schnittpunkt:

const cutMs = Math.round((INTRO_TOTAL_MS + INTRO_EXIT_MS) * INTRO_PACE)  // 23 125

In eine gepackte App ausliefern

Quellcode-Änderungen wirken erst, wenn das ASAR neu gepackt wird. Hier zwei Fallstricke, die sich lohnen zu prüfen:

Finde die App, die der Benutzer tatsächlich startet – gehe niemals von /Applications aus.

ps aux | grep '[H]ermes.app/Contents/MacOS/Hermes'
defaults read com.apple.dock persistent-apps | grep -o '/[^"]*Hermes\.app'

Hermes-Updates landen in ~/.hermes/hermes-agent*/apps/desktop/release/mac-arm64/Hermes.app und das Dock zeigt oft dorthin, während /Applications/Hermes.app eine veraltete 0.0.0-Kopie sein kann. Bestätige mit CFBundleShortVersionString (0.17.x ist echt, 0.0.0 nicht).

Aktualisiere auch app.asar.unpacked/dist/. Gepackte Builds listen dist/** in asarUnpack auf, und resolveRendererIndex() bevorzugt diese Kopie – wenn nur das ASAR neu gepackt wird, überschattet der veraltete entpackte Baum es.

npm install --workspace apps/desktop --ignore-scripts \
  --engine-strict=false --min-release-age=0
cd apps/desktop && node ../../node_modules/vite/bin/vite.js build
node scripts/bundle-electron-main.mjs     # Hauptprozess-Änderungen benötigen diesen Schritt ebenfalls

asar extract "$RES/app.asar" "$WORK"
rm -rf "$WORK/dist" && cp -R apps/desktop/dist "$WORK/dist"
asar pack "$WORK" "$WORK/app.asar"
mv -f "$WORK/app.asar" "$RES/app.asar"
cp -R apps/desktop/dist/. "$RES/app.asar.unpacked/dist/"
codesign --force --deep -s - "$APP"      # ad-hoc; Hermes wird ad-hoc signiert ausgeliefert

--ignore-scripts ist bei langsamen Netzwerken wichtig: Der Electron-Binär-Download wird zum Erstellen oder Neupacken nicht benötigt, sondern nur zum Ausführen des Dev-Modus.

Ohne Electron verifizieren

Rendere den Film in einem einfachen Browser – kein Packen, kein Binär-Download:

cd apps/desktop && node ../../node_modules/vite/bin/vite.js --host 127.0.0.1 --port 5174
page.add_init_script("""
window.hermesDesktop = {
  guestOnboardingEnabled: true, skipIntro: false,
  introReveal: { ready(){}, skip(){},
    open(){ return Promise.resolve() }, close(){ return Promise.resolve() },
    onSkip(){ return () => {} }, onClosed(){ return () => {} } }
};
""")
page.goto("http://127.0.0.1:5174/?win=intro")
page.evaluate("import('/src/components/intro-reveal/intro-root.tsx').then(m => m.mountIntroReveal())")

Der eigene Mount-Aufruf der Route tut ohne die Brücke nichts; der manuelle Import nach dem Stubbing ist das, was tatsächlich zeichnet. Um die Audiospur zu prüfen, stubbe window.Audio und zeichne Instanzen auf – bestätige, dass currentTime mit dem Film fortschreitet und dass paused === true, volume === 0 am Schnittpunkt.

Vertragstests, die es wert sind, in src/store/intro-reveal.test.ts behalten zu werden:

  • Der Film wird bei einem normalen Start abgespielt, selbst wenn hermes-intro-reveal-seen-v1 gesetzt ist
  • Der Film wird genau einmal abgespielt – finishIntroReveal() darf ihn nicht erneut scharfschalten
  • Der Opt-out-Schlüssel und das skipIntro-Startflag werden beachtet
  • Die Einführungslogik für den ersten Durchlauf bleibt unberührt

Fallstricke

  • Das Entfernen von playedThisSession führt zu einer unendlichen Wiederholungsschleife, nicht zu einem fehlerfreien Start.
  • INTRO_TOTAL_MS ist Partitur-Zeit. Das Vergessen von INTRO_PACE schneidet die Sprachspur 4,4 s zu früh ab.
  • Das enabled-Flag des Hauptprozesses und die eigene Wächterfunktion des Overlays sind separate Tore; wird eines verpasst, wird nichts gerendert und es erscheint kein Fehler.
  • Vier unabhängige Schichten halten den Bildschirm zurück (normales Schließen, Esc + 1,2 s Fallback, lokaler Deadman, 34-s-Hauptprozess-Watchdog). Entferne keine, während du das Timing änderst.
  • hermes update ersetzt die App durch den offiziellen Build. Der Patch bleibt in Git bestehen; führe den Installer nach dem Update erneut aus.

Verwandte Skills