Communitygithub.com

AmanVarshney01/tcut

從 TypeScript 腳本或即時終端機工作階段錄製可重現的終端機影片(MP4/GIF/SVG/HTML)。當使用者需要終端機示範、CLI 畫面錄影、TUI 錄製或用於 README、網站或社群貼文的動畫終端機 GIF 時使用。

tcut 是什麼?

tcut 是一款專為開發者和 AI 代理設計的終端機錄影工具,能將終端機工作階段轉換為確定性(deterministic)影片,確保每次錄製的像素完全一致。它支援近乎所有的輸出格式:MP4(需 ffmpeg)、GIF、WebM、SVG 和 HTML,並提供 `--json` 輸出以利程式化處理。主要特色是「腳本優先」的錄影方式:使用者只需撰寫純 TypeScript 腳本(無需領域特定語言 DSL),透過 `tcut demo.video.ts` 命令即可產生完全可重現的錄影。這對於需要準確展示 CLI 操作流程的 AI 代理尤其實用,因為腳本的執行結果不依賴計時器,而是基於螢幕內容的比對(透過 `t.expect()` 斷言)。此外,tcut 也支援即時錄影(`tcut rec`),錄製的 `.cast` 檔案可獨立於原始腳本重新渲染,改變主題、解析度或速度,而無需重新執行指令。它還能與 CI/CD 整合,透過 `tcut test` 進行驗證測試,以及 `tcut diff` 比較兩次錄影的螢幕文字。tcut 支援 Ghostty 終端機模擬器,內建近 600 種主題,並可設定滑鼠點擊覆蓋、按鍵提示、視窗陰影與浮水印等視覺元素。進階功能包含瀏覽器面板(同時錄製 WebView 與終端機)、幻燈片過場、時間壓縮(timelapse)、章節標記與片段剪輯,適合製作高品質的產品示範、教學影片與開發者內容。

相容平台✓Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/AmanVarshney01/tcut/tree/HEAD/skills/tcut

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

tcut — 終端機工作階段轉換為影片

tcut 會錄製一個真實的 Shell(PTY + 無頭模式的 Ghostty 終端機),並渲染出確定性的影片。腳本使用純 TypeScript 撰寫,無需領域特定語言。每次錄影結果相同,像素一致。

設定

bun add -g termcut   # 需要 Bun >= 1.4,安裝後可使用 `tcut` 指令

MP4/GIF/WebM 格式需要 ffmpeg 在 PATH 環境變數中。SVG 和 HTML 播放器無需其他依賴。所有模式皆支援 --json 輸出機器可讀的結果,且不會要求使用者互動。

兩種錄影方式

腳本模式(代理推薦) — 撰寫 demo.video.ts,執行 tcut demo.video.ts:

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");        // 模擬輸入並按下 Enter,等待提示字元返回
    await t.expect(/1\.\d+/);            // 對渲染後的螢幕進行斷言(若未出現則影片失敗)
    await t.sleep("1.5s");
  },
);

即時模式 — tcut rec -o demo.gif 會開啟一個 Shell,錄製直到輸入 exit,然後同時寫出精確的錄影檔(demo.cast)以及一份可編輯的腳本(demo.video.ts),記錄了所有輸入內容。tcut rec -o demo.mp4 -- npm create vite 則只錄製單一指令。

t API(在 defineVideo 內部使用)

  • t.run(cmd, { wait? }) — 模擬輸入 + 按下 Enter + 等待 Shell 提示字元(基於螢幕內容,非計時器)
  • t.type(text) / t.paste(text) / t.enter() / t.escape() / t.tab() — 逐鍵驅動 TUI 應用程式
  • 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" }) — 等待螢幕出現特定內容;t.expect(re) — 進行斷言
  • t.sleep("800ms") — 時間長度接受 "500ms"、"1.5s" 或數字(毫秒)
  • t.hide(async () => { ... }) — 在鏡頭外執行設定(狀態會持續保留;請勿在此處結束背景工作)
  • t.print(markdown) / t.title(text) — 將 Markdown 字幕渲染到影片中,不實際輸入文字
  • t.zoom({ rows: [0, 5], cols: [0, 60], duration: "500ms" }) — 放大特定區域;t.zoom(null) 重置
  • t.slide("部署到雲端", { eyebrow: "3", subtitle: "…", during }) — 在功能展示之間插入全螢幕過場卡片:正規排版、大型置中標題,帶有淡入淡出效果,並同時記錄同名的章節;during: async () => … 可在背景隱藏執行 cd/clear/伺服器設定
  • t.chapter("安裝") — 真實的 MP4 章節元資料,以及剪輯點:可在渲染時使用 --chapters 安裝 / --split-chapters 切割
  • t.expect(/…/, { scope: "scrollback" }) 可檢查已滾動出畫面的輸出;t.scrollback() 回傳完整轉錄文字;-o demo.log 可寫入檔案
  • 當程式啟用應用程式游標模式時,方向鍵以 SS3 傳送;當程式要求時,t.paste() 使用括號貼上模式 — 編輯器的行為如同真實終端機;print("[text](url)") 可在 SVG/HTML 中產生可點擊連結
  • title: "auto" 會跟隨 OSC 視窗標題;tcut doctor demo.cast 可解釋錄影使用了哪些功能以及 tcut 無法顯示的內容(例如內嵌圖片)
  • t.timelapse(async () => { await t.run("bun install") }, { speed: 8 }) — 內部所有操作以 8 倍速度播放(maxPause 僅移除靜音;此選項會壓縮輸出內容)
  • t.snapshot("shot.png") / t.snapshot("hero.svg") — 在每次渲染時捕捉當前時刻的靜態畫面(screenshot 為別名);t.clear()、t.resize(cols, rows)、t.screen() / t.line() 用於讀取螢幕內容
  • 瀏覽器面板:在設定檔中加入 browser: { position: "right" | "overlay", width },然後使用 t.browser.goto(url)、t.browser.waitFor(/text/)、t.browser.click(sel)、t.focus("browser" | "terminal") — 可在終端機旁/上方錄製真實的 WebView(適合開發伺服器示範)

設定要點

output(陣列,可指定多種格式)、preset: "readme" | "x" | "youtube" | "square"、theme(約 600 種 Ghostty 主題,使用 tcut themes 列出)、cols/rows 或 width/height(像素)、fps、scale: 2(維持相同佈局,但像素加倍 — 適用於 Retina/HiDPI 或任何會被放大的播放器)、typingSpeed/typingJitter、keys: true(按鍵覆疊,一次顯示一個按鍵標籤;可設定 { limit, font, color, background, radius, position })、maxPause: "1.5s"(閒置壓縮)、requires: ["bun", "eza"](在錄影前快速失敗,若缺少工具則直接報錯 — 亦可用於 tcut test)、windowBar: "none" + margin: 0 + borderRadius: 0 可得到裸終端機、title、marginFill("transparent" 可在 png/webp/gif/webm/svg/html 中實現真正的透明度;mp4 會使用替代方案)、shadow: true(柔和陰影效果;邊距預設為 40)、watermark: "© you" 或 { image: "logo.png", position: "top-left", opacity, size }。

剪輯與合併(無需重新錄製)

所有操作皆基於錄影的可見時間軸,因此所有格式皆適用,且結果仍是 .cast 格式:

tcut render demo.cast --from 2s --to 10s -o clip.gif      # 時間範圍
tcut render demo.cast --chapters Zoom,Intro -o clip.mp4    # 依照指定順序選取章節
tcut render demo.cast --split-chapters -o demo.mp4         # 輸出 demo-01-intro.mp4, demo-02-zoom.mp4 …(適合做為 Remotion 的剪輯素材庫)
tcut cut demo.cast --from 2s --to 10s                      # 寫出 demo-cut.cast
tcut concat intro.cast demo.cast --gap 500ms -o launch.mp4 # 需要相同欄×列數;每個接縫處會重置畫面

重新渲染而不重新執行

錄影(.cast)與渲染是分開的:

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 / 測試

  • tcut test demo.video.ts — 以測試形式執行腳本(快速,不進行影片編碼)
  • tcut diff a.cast b.cast [--images dir] — 比較兩次錄影的螢幕文字,若發生偏差則回傳 exit 1

注意事項

  • 在 PTY 中啟動背景開發伺服器:bun run dev </dev/null >/tmp/dev.log 2>&1 &(標準輸入讀取程式會收到 SIGTTIN;零散日誌會覆蓋 TUI 畫面)
  • 等待螢幕內容,而非等待時間:優先使用 t.run / t.wait(/Local:/, { scope: "screen" }) 而非長時間的 sleep
  • t.hide 會保留狀態 — 在結尾處隱藏的 kill 會影響最後一幀畫面
  • 對於 TUI 應用程式(nvim, lazygit, claude),請使用 t.run(cmd, { wait: /something-on-screen/ }) 啟動,然後以按鍵驅動

完整參考資料:https://tcut.amanv.dev/llms.txt

將 tcut 作為函式庫使用

import { defineVideo, renderCast } from "termcut"(僅限 Bun)。defineVideo(config, script) 回傳一個 Video 物件:await video.run({ force, log }) 會錄製並渲染,回傳 { outputs, screenshots, durationSeconds, recording };video.record() 和 video.render(recording, { overrides, clip }) 可分別執行兩個步驟;renderCast(file, overrides) 可在無需 Shell 的情況下重新渲染任何錄影檔。此外也匯出:recordLive、cutRecording、concatRecordings、selectChapters、buildSvg、buildHtml、replayFrames、diffCasts、diagnoseCast、generateScript、runScriptTests、publishFiles。在 CI 環境中請明確指定 theme/font("auto" 會讀取執行中的終端機設定),並一次只渲染一個影片。

Individual skills in this repo

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

相關技能