Communitygithub.com

tcut — 端末セッションを動画に

TypeScript スクリプトまたはライブセッションから、再現可能な端末動画 (MP4/GIF/SVG/HTML) を録画します。README、Web サイト、SNS投稿のための端末デモ、CLI スクリーンキャスト、TUI 録画、アニメーション GIF が必要な場合に使用します。

tcut — 端末セッションを動画に とは?

tcut は、実際のシェル (PTY + ヘッドレス Ghostty 端末) を録画し、決定論的な動画をレンダリングするツールです。スクリプトはプレーンな TypeScript で記述でき、専用 DSL は不要です。同じ録画からは常に同じピクセルの出力が得られるため、CI/CD やバージョン管理に適しています。対応フォーマットは MP4、GIF、WebM、SVG、HTML で、`ffmpeg` が利用可能な環境ではすべてのフォーマットに対応し、SVG や HTML プレイヤーは追加依存関係なしで動作します。 このツールは主に、以下の2つの方法で利用します: 1) スクリプトモード (`tcut demo.video.ts`) では、`defineVideo` API を使ってキー入力、アサーション、スリープ、キャプション、ズーム、スライドトランジションなどをプログラムで制御します。2) ライブモード (`tcut rec -o demo.gif`) では、実際にシェルを開いて録画し、`.cast` ファイルと編集可能なスクリプトの両方を生成します。 特徴的な API として、`t.run()` によるコマンド実行と画面ベースの待機、`t.hide()` によるオフカメラ処理、`t.timelapse()` による高速再生、`t.slide()` によるフルフレームトランジションカード、さらにブラウザペインの同時録画 (WebView を端末の横またはオーバーレイ表示) があります。録画とレンダリングは分離されており、`tcut render` でテーマ、サイズ、速度を後から変更できます。 tcut は、Claude Code、Cursor、Codex などの AI エージェント環境に特に適しています。スクリプトはテストとしても実行でき (`tcut test`)、2つの録画を比較する `tcut diff` 機能もあります。また、`import { defineVideo, renderCast } from 'termcut'` としてライブラリとしても利用可能で、動画生成パイプラインに組み込むことができます。

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

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

tcut — 端末セッションを動画に は何をしますか?

tcut は実際のシェル (PTY + ヘッドレス Ghostty 端末) を録画し、決定論的な動画をレンダリングします。スクリプトはプレーンな TypeScript で記述します — DSL は不要です。同じ録画から、常に同じピクセルの結果が得られます。

セットアップ

bun add -g termcut   # Bun >= 1.4、`tcut` コマンドをインストール

MP4/GIF/WebM には ffmpeg が PATH 上にある必要があります。SVG および HTML プレイヤーは追加で何も必要としません。すべての機能は --json に対応しており、機械可読な結果を出力します。プロンプトを表示することはありません。

2 つの録画方法

スクリプトモード (エージェント向け) — 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 はシェルを開き、exit するまで録画し、正確な録画 (demo.cast) と、入力された内容の編集可能なスクリプト (demo.video.ts) の両方を書き出します。tcut rec -o demo.mp4 -- npm create vite は 1 つのコマンドだけを録画します。

t API (defineVideo 内で使用)

  • t.run(cmd, { wait? }) — 入力 + Enter + シェルプロンプトを待機 (タイマーではなく画面ベース)
  • 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 () => { ... }) — カメラに映らない場所でセットアップを実行 (状態は保持されます; ここでバックグラウンドジョブを kill しないでください)
  • 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 Install / --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 (同じレイアウトで 2 倍のピクセル — Retina/HiDPI やプレイヤーで拡大表示される場合に使用), typingSpeed/typingJitter, keys: true (キー入力オーバーレイ、一度に 1 チップ; { 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 (ソフトドロップシャドウ; margin はデフォルト 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 # 同じ cols×rows が必要; 各接合部で画面リセット

再実行せずに再レンダリング

録画 (.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] — 2 つの録画の画面テキストを比較、差異があれば exit 1 を返す

注意点

  • PTY 内のバックグラウンド開発サーバー: bun run dev </dev/null >/tmp/dev.log 2>&1 & (標準入力読み取りプロセスは SIGTTIN を受信; 余分なログが TUI 上に再描画される)
  • 時間ではなく画面を待機する: 長いスリープよりも t.run / t.wait(/Local:/, { scope: "screen" }) を優先
  • 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) はシェルなしで任意のキャストを再レンダリング。他にも recordLive, cutRecording, concatRecordings, selectChapters, buildSvg, buildHtml, replayFrames, diffCasts, diagnoseCast, generateScript, runScriptTests, publishFiles をエクスポート。CI では明示的に theme/font を指定し ("auto" は実行中の端末の設定を読み取る)、動画は一度に 1 つずつレンダリングしてください。

Individual skills in this repo

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

関連スキル