Communitygithub.com

AmanVarshney01/tcut

Nimm reproduzierbare Terminal-Videos (MP4/GIF/SVG/HTML) aus TypeScript-Skripten oder Live-Sessions mit dem tcut-CLI auf. Verwende es, wenn der Benutzer eine Terminal-Demo, einen CLI-Screencast, eine TUI-Aufnahme oder ein animiertes Terminal-GIF für eine README, Webseite oder einen Social-Media-Beitrag benötigt.

Was ist tcut?

tcut ist ein leistungsstarkes CLI-Tool, das Terminal-Sessions in hochwertige Videos (MP4, GIF, SVG, HTML) umwandelt. Es wurde entwickelt, um reproduzierbare Aufnahmen zu erstellen – das bedeutet, dass dasselbe Skript jedes Mal dieselben Pixel liefert. Entwickler können ihre Demos in TypeScript schreiben, anstatt sich mit komplexen DSLs herumschlagen zu müssen. tcut unterstützt sowohl skriptbasierte Aufnahmen (ideal für Agenten und CI) als auch Live-Aufnahmen, bei denen eine echte Shell in einem Ghostty-Terminal gesteuert wird. Die API bietet umfangreiche Steuerungsmöglichkeiten: Tastatureingaben, Warten auf Bildschirminhalte, Markdown-Einblendungen, Zoom-Effekte, Slide-Übergänge und sogar einen Browser-Viewer für Web-Demos. Ausgaben können nach der Aufnahme ohne erneute Ausführung des Skripts gerendert, geschnitten und zusammengefügt werden. Das Tool ist besonders nützlich für READMEs, Dokumentationen, Social-Media-Posts und Tutorials, bei denen konsistente, professionelle Terminal-Demos gefragt sind. Es kann auch als Bibliothek in Bun-Projekten verwendet werden und bietet Funktionen zum Testen und Diffen von Aufnahmen.

Funktioniert mit✓Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/AmanVarshney01/tcut/tree/HEAD/skills/tcut

In Ihrer bevorzugten KI fragen

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

Dokumentation

tcut — Terminal-Sessions als Video

tcut zeichnet eine echte Shell (PTY + Headless-Ghostty-Terminal) auf und rendert deterministische Videos. Skripte sind reines TypeScript – keine DSL. Gleiche Aufnahme, gleiche Pixel, jedes Mal.

Einrichtung

bun add -g termcut   # Bun >= 1.4, installiert den Befehl `tcut`

MP4/GIF/WebM benötigen ffmpeg im PATH. SVG und HTML-Player benötigen nichts weiter. Alles unterstützt --json für maschinenlesbare Ergebnisse; nie werden Abfragen gestellt.

Zwei Aufnahmemöglichkeiten

Skriptbasiert (bevorzugt für Agenten) – schreibe demo.video.ts, führe tcut demo.video.ts aus:

import { defineVideo } from "tcut";

export default defineVideo(
  { output: ["demo.mp4", "demo.gif"], preset: "x", theme: "Catppuccin Mocha", keys: true, maxPause: "1.5s" },
  async (t) => {
    await t.run("bun --version");        // tippt es, drückt Enter, wartet auf die Rückkehr der Eingabeaufforderung
    await t.expect(/1\.\d+/);            // überprüft den gerenderten Bildschirm (bricht das Video ab, wenn nicht vorhanden)
    await t.sleep("1.5s");
  },
);

Live – tcut rec -o demo.gif öffnet eine Shell, zeichnet auf, bis exit eingegeben wird, und schreibt sowohl die exakte Aufnahme (demo.cast) als auch ein bearbeitbares Skript (demo.video.ts) des Getippten. tcut rec -o demo.mp4 -- npm create vite zeichnet einen einzelnen Befehl auf.

Die t-API (innerhalb von defineVideo)

  • t.run(cmd, { wait? }) – tippen + Enter + auf die Shell-Eingabeaufforderung warten (bildschirmbasiert, kein Timer)
  • t.type(text) / t.paste(text) / t.enter() / t.escape() / t.tab() – TUIs Taste für Taste steuern
  • t.up/down/left/right/pageUp/pageDown/home/end(), t.ctrl("c"), t.alt("b"), t.shift("tab"), t.key("f5"), t.scrollUp/scrollDown()
  • t.wait(regex?, { scope: "line" | "screen" }) – warten, bis der Bildschirm den Text anzeigt; t.expect(re) – überprüfen
  • t.sleep("800ms") – Dauern akzeptieren "500ms", "1.5s", Zahlen (ms)
  • t.hide(async () => { ... }) – Einrichtung außerhalb des Sichtfelds ausführen (Zustand bleibt erhalten; Hintergrundjobs hier nicht beenden)
  • t.print(markdown) / t.title(text) – Markdown-Bildunterschriften in das Video rendern, ohne zu tippen
  • t.zoom({ rows: [0, 5], cols: [0, 60], duration: "500ms" }) – einen Bereich vergrößern; t.zoom(null) setzt zurück
  • t.slide("In die Cloud bereitstellen", { eyebrow: "3", subtitle: "…", during }) – Vollbild-Übergangskarte zwischen Feature-Demos: große zentrierte Überschrift in echter Typografie, ein- und ausgeblendet, zeichnet ein Kapitel mit demselben Namen auf; during: async () => … führt cd/clear/Server-Setup unsichtbar im Hintergrund aus
  • t.chapter("Installieren") – echte MP4-Kapitel-Metadaten und ein Schnittpunkt: --chapters Installieren / --split-chapters zur Renderzeit
  • t.expect(/…/, { scope: "scrollback" }) sieht Ausgaben, die aus dem Bild gelaufen sind; t.scrollback() gibt das gesamte Transkript zurück; -o demo.log schreibt es
  • Pfeile werden als SS3 gesendet, wenn das Programm den Cursor-Anwendungsmodus aktiviert hat, t.paste() wird in Klammern gesetzt, wenn das Programm danach gefragt hat – Editoren verhalten sich wie bei einem echten Terminal; print("[text](url)") erstellt einen klickbaren Link in SVG/HTML
  • title: "auto" folgt OSC-Titeln; tcut doctor demo.cast erklärt, was eine Aufnahme verwendet hat und was tcut nicht anzeigen kann (Inline-Bilder)
  • t.timelapse(async () => { await t.run("bun install") }, { speed: 8 }) – alles darin wird 8× schneller abgespielt (maxPause entfernt nur Stille; dies komprimiert die Ausgabe)
  • t.snapshot("shot.png") / t.snapshot("hero.svg") – Standbild genau dieses Moments bei jedem Rendering (screenshot = Alias), t.clear(), t.resize(cols, rows), t.screen() / t.line() zum Lesen des Bildschirms
  • Browser-Bereich: browser: { position: "right" | "overlay", width } in der Konfiguration, dann t.browser.goto(url), t.browser.waitFor(/text/), t.browser.click(sel), t.focus("browser" | "terminal") – zeichnet eine echte WebView neben/über dem Terminal auf (Dev-Server-Demos)

Konfigurationsgrundlagen

output (Array = mehrere Formate), preset: "readme" | "x" | "youtube" | "square", theme (~600 Ghostty-Themes, tcut themes), cols/rows oder width/height (px), fps, scale: 2 (gleiches Layout, 2× die Pixel – für Retina/HiDPI oder alles, was ein Spieler hochskaliert), typingSpeed/typingJitter, keys: true (Tastendruck-Overlay, ein Chip nach dem anderen; { limit, font, color, background, radius, position }), maxPause: "1.5s" (Leerlaufkomprimierung), requires: ["bun", "eza"] (vor der Aufnahme schnell fehlschlagen, wenn ein Tool fehlt – auch in tcut test), windowBar: "none" + margin: 0 + borderRadius: 0 für ein nacktes Terminal, title, marginFill ("transparent" = echte Alpha in png/webp/gif/webm/svg/html; mp4 fällt zurück), shadow: true (weicher Schlagschatten; margin standardmäßig 40), watermark: "© du" oder { image: "logo.png", position: "top-left", opacity, size }.

Schneiden und Zusammenfügen (keine Neuaufnahme)

Alles auf der sichtbaren Zeitleiste der Aufnahme, sodass jedes Format funktioniert und das Ergebnis immer noch eine .cast ist:

tcut render demo.cast --from 2s --to 10s -o clip.gif      # Zeitfenster
tcut render demo.cast --chapters Zoom,Intro -o clip.mp4    # Kapitel, in dieser Reihenfolge
tcut render demo.cast --split-chapters -o demo.mp4         # demo-01-intro.mp4, demo-02-zoom.mp4 …  (ideale Clip-Bibliothek für Remotion)
tcut cut demo.cast --from 2s --to 10s                      # schreibt demo-cut.cast
tcut concat intro.cast demo.cast --gap 500ms -o launch.mp4 # gleiche cols×rows erforderlich; Bildschirm wird an jeder Naht zurückgesetzt

Erneutes Rendern ohne erneute Ausführung

Aufnahme (.cast) und Rendering sind getrennt:

tcut render demo.cast --theme "Gruvbox Dark" -o demo.svg
tcut render demo.cast --width 1280 --height 720 --speed 1.5 -o demo.mp4

CI / Testen

  • tcut test demo.video.ts – führe das Skript als Test aus (schnell, keine Video-Kodierung)
  • tcut diff a.cast b.cast [--images dir] – vergleiche den Bildschirmtext zweier Aufnahmen, beende mit 1 bei Abweichung

Fallstricke

  • Hintergrund-Dev-Server in der PTY: bun run dev </dev/null >/tmp/dev.log 2>&1 & (stdin-Leser erhalten SIGTTIN; verlorene Logs übermalen TUIs)
  • Warte auf den Bildschirm, nicht auf die Zeit: bevorzuge t.run / t.wait(/Local:/, { scope: "screen" }) gegenüber langen Wartezeiten
  • t.hide behält den Zustand bei – ein verstecktes kill am Ende sickert in das letzte Bild ein
  • Für TUIs (nvim, lazygit, claude) starte mit t.run(cmd, { wait: /etwas-auf-dem-bildschirm/ }) und steuere dann mit Tasten

Vollständige Referenz: https://tcut.amanv.dev/llms.txt

tcut als Bibliothek verwenden

import { defineVideo, renderCast } from "termcut" (nur Bun). defineVideo(config, script) gibt ein Video zurück: await video.run({ force, log }) zeichnet auf und rendert und gibt { outputs, screenshots, durationSeconds, recording } zurück; video.record() und video.render(recording, { overrides, clip }) teilen die Schritte auf; renderCast(file, overrides) rendert jede Aufnahme ohne Shell neu. Ebenfalls exportiert: recordLive, cutRecording, concatRecordings, selectChapters, buildSvg, buildHtml, replayFrames, diffCasts, diagnoseCast, generateScript, runScriptTests, publishFiles. Übergib in CI explizites theme/font ("auto" liest das laufende Terminal) und rendere jeweils ein Video.

Individual skills in this repo

This repo contains 7 individual skills — each has its own dedicated page.

Verwandte Skills