Communitygithub.com

AmanVarshney01/tcut

TypeScript 스크립트나 라이브 세션에서 재현 가능한 터미널 비디오(MP4/GIF/SVG/HTML)를 녹화합니다. 사용자가 터미널 데모, CLI 스크린캐스트, TUI 녹화, 또는 README/웹사이트/소셜 게시물용 애니메이션 GIF를 원할 때 사용하세요.

tcut란 무엇인가요?

tcut은 실제 셸(PTY + 헤드리스 Ghostty 터미널)을 녹화하여 결정론적 비디오를 렌더링하는 도구입니다. 스크립트는 별도의 DSL 없이 일반 TypeScript로 작성되며, 동일한 녹화 조건에서 항상 동일한 픽셀 결과를 보장합니다. MP4/GIF/WebM 출력에는 ffmpeg가 필요하지만 SVG와 HTML 플레이어는 추가 의존성이 없습니다. tcut은 스크립트 기반(선호)과 라이브 녹화 두 가지 방식을 지원합니다. 스크립트 방식에서는 `defineVideo`로 구성과 시퀀스를 정의하고, `t.run()`, `t.type()`, `t.wait()` 등 풍부한 API로 터미널 입력과 화면 어서션을 제어합니다. 또한 `t.zoom()`으로 특정 영역 확대, `t.slide()`로 트랜지션 카드 삽입, `t.browser`로 실제 WebView를 터미널 옆에/위에 함께 녹화하는 기능, 그리고 타임랩스, 스냅샷, 컷/조인 등 고급 기능을 제공합니다. CI 환경에서는 `tcut test`로 빠른 테스트 실행, `tcut diff`로 녹화 비교가 가능하여 회귀 방지에 유용합니다. 전체 참고 문서는 https://tcut.amanv.dev/llms.txt 에서 확인할 수 있습니다.

지원 대상✓Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/AmanVarshney01/tcut/tree/HEAD/skills/tcut

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

tcut — 터미널 세션을 비디오로

tcut은 실제 셸(PTY + 헤드리스 Ghostty 터미널)을 녹화하고 결정론적 비디오를 렌더링합니다. 스크립트는 별도의 DSL 없이 일반 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는 셸을 열고 exit 입력 시까지 녹화한 후, 정확한 녹화 (demo.cast)와 입력된 내용의 편집 가능한 스크립트 (demo.video.ts)를 함께 저장합니다. tcut rec -o demo.mp4 -- npm create vite는 단일 명령어만 녹화합니다.

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", 숫자 (ms) 허용
  • t.hide(async () => { ... }) — 카메라 밖에서 설정 실행 (상태는 유지되나, 여기서 백그라운드 작업을 종료하지 말 것)
  • t.print(markdown) / t.title(text) — 타자 없이 비디오에 마크다운 캡션 렌더링
  • t.zoom({ rows: [0, 5], cols: [0, 60], duration: "500ms" }) — 영역 확대; t.zoom(null)은 초기화
  • t.slide("Deploy to the cloud", { eyebrow: "3", subtitle: "…", during }) — 기능 데모 사이의 전체 화면 전환 카드: 실제 타이포그래피로 큰 중앙 제목 표시, 페이드 인/아웃, 같은 이름의 챕터 기록; during: async () => …는 그 뒤에서 cd/clear/서버 설정을 보이지 않게 실행
  • t.chapter("Install") — 실제 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 (px), fps, scale: 2 (동일 레이아웃, 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 (부드러운 그림자; 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] — 두 녹화의 화면 텍스트 비교, 차이 시 exit 1 반환

주의사항

  • PTY 내부의 백그라운드 개발 서버: bun run dev </dev/null >/tmp/dev.log 2>&1 & (stdin 리더는 SIGTTIN 수신; 로그가 TUI 위에 덮어쓰기)
  • 시간이 아닌 화면을 기준으로 대기: 긴 sleep 대신 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"는 실행 중인 터미널을 읽음) 한 번에 하나의 비디오만 렌더링하세요.

Individual skills in this repo

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

관련 스킬