Communitygithub.com

nikserg/skim

Skim 랜딩 페이지의 데모 비디오와 인터페이스 스크린샷을 재생성합니다. UI가 변경되거나 데모 자산이 오래된 경우 이 스킬을 사용하세요.

skim란 무엇인가요?

이 스킬은 Skim 애플리케이션의 UI가 변경되었을 때 랜딩 페이지에 포함된 데모 비디오와 인터페이스 스크린샷을 자동으로 재생성합니다. 실제 계정이나 메일함, AI 모델을 사용하지 않고 모의 Tauri IPC 레이어를 통해 실제 Skim UI를 구동하여 안전하게 자산을 생성합니다. 주로 Playwright와 ffmpeg를 활용하여 스크립트된 기능 투어 비디오(1280×800)와 라이트/다크 테마의 스크린샷(800px)을 `docs/` 디렉토리에 출력합니다. 이 스킬은 파일만 업데이트할 뿐 git add/commit/push는 수행하지 않으며, 사용자가 생성된 자산을 직접 검토하고 결정하도록 합니다. 또한 UI 변경으로 인해 데모 투어가 깨졌을 때 문제를 진단하고 수정하는 방법도 제공합니다.

지원 대상~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/nikserg/skim/tree/HEAD/demo/skill

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

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

문서

Skim 데모 자산 업데이트

랜딩 페이지와 함께 제공되는 제품 데모 비디오와 라이트/다크 인터페이스 스크린샷을 재생성합니다. 모든 작업은 모의 Tauri IPC 레이어(demo/mock/)를 통해 실행되는 실제 Skim UI를 기반으로 하므로 실제 계정, 메일함 또는 모델에 접근하지 않습니다.

docs/에 출력되는 결과물:

  • skim-demo.mp4 — 스크립트된 기능 투어 (1280×800)
  • skim-light.jpg, skim-dark.jpg — 인터페이스 스크린샷, 너비 800px

커밋 또는 푸시하지 마세요

이 스킬은 디스크의 파일만 업데이트합니다. git add, git commit, git push를 실행하지 마세요. 사용자가 직접 재생성된 자산을 검토하고 무엇을 유지할지 결정합니다. 이들은 큰 diff를 생성하는 바이너리 파일이며, 종료 코드로는 정상으로 보여도 시각적으로 잘못될 수 있습니다. 작업 트리를 더티 상태로 남겨두는 것이 올바른 결과입니다.

사용자가 같은 요청에서 명시적으로 요청하는 경우에만 git을 다루십시오(예: "재생성하고 커밋해줘"). 그렇지 않으면 파일이 업데이트되었고 스테이징되지 않았다고 알려주는 것으로 마무리하세요.

실행하기

저장소 루트에서:

npm run demo

이 명령은 세 단계를 연결합니다: demo:record (Playwright가 실제 UI를 구동하여 → demo/output/raw.webm) → demo:encode (ffmpeg → MP4, docs/로 복사) → demo:shots (두 테마 → docs/).

UI의 일부만 변경된 경우, 필요한 부분만 실행하는 것이 더 빠르고 관련 없는 자산을 바이트 단위로 동일하게 유지합니다:

  • npm run demo:shots — 스크린샷만 (정적 UI, 색상, 레이아웃 변경)
  • npm run demo:record && npm run demo:encode — 비디오만 (흐름, AI 동작)

전제 조건: npm install 및 ffmpeg가 PATH에 있어야 합니다. 전체 실행은 몇 분 정도 소요되며, 녹화가 가장 오래 걸리는 부분입니다.

npm run demo는 demo:browser (playwright install chromium)로 시작합니다. 브라우저가 이미 있으면 아무 작업도 하지 않습니다. 실행 중 "Executable doesn't exist at ...chromium_headless_shell-NNNN" 오류가 발생하면 Playwright의 브라우저 빌드가 라이브러리 버전과 일치하지 않기 때문입니다(^ 범프가 이를 다시 가리키며, headless shell은 Chromium과 별도로 다운로드됩니다). npm run demo:browser 또는 전체 npm run demo를 실행하면 해결됩니다. 데모 문제로 디버깅할 필요가 없습니다. 개별 demo:record / demo:shots 스크립트는 이 검사를 건너뜁니다.

성공을 보고하기 전에 확인하세요

실행이 종료 코드 0으로 종료되어도 깨진 비디오가 생성될 수 있습니다. 처리되지 않은 모의 명령은 오류를 던지지 않고 undefined를 반환하므로 빈 창이 오류 대신 렌더링됩니다. 따라서 종료 코드가 아닌 눈을 믿으세요.

  1. docs/의 세 파일이 최신 mtime을 가지고 있는지 확인합니다.
  2. 크기를 확인합니다: 스크린샷 너비 800px, MP4 1280×800.
  3. MP4 전체에서 프레임을 추출하여 실제로 살펴봅니다. 고정된 초가 아닌 비율로 샘플링하세요. 투어의 길이는 장면이 추가되거나 페이스가 조정될 때마다 변경되므로 하드코딩된 타임스탬프는 쓸모없어집니다:
    dur=$(ffprobe -v error -show_entries format=duration -of csv=p=0 docs/skim-demo.mp4)
    for k in 1 2 3 4 5 6 7; do
      ffmpeg -y -hide_banner -loglevel error \
        -ss $(echo "$dur * $k / 8" | bc -l) -i docs/skim-demo.mp4 -frames:v 1 /tmp/f$k.png
    done
    
    모든 프레임은 내용이 채워진 창을 보여야 하며, AI 장면에는 스트리밍된 텍스트가 있어야 합니다. demo/output/progress.log는 각 장면이 완료될 때 이름을 기록하므로, 잘못된 프레임을 생성한 단계로 다시 매핑하는 데 도움이 됩니다.
  4. 두 스크린샷을 모두 봅니다. 특히 다크 스크린샷을 확인하세요(이메일 본문은 샌드박스 처리된 iframe에서 자체 테마 로직으로 렌더링되므로 다크 온 다크가 발생할 수 있습니다).

어떤 파일이 변경되었고 무엇을 보았는지 보고합니다. 장면이 잘못 보이면 배포하지 말고 수정하세요.

UI 변경 후 투어가 깨질 때

테스트 하네스는 두 가지 계약에 의존합니다. 실패 메시지는 어떤 것이 변경되었는지 알려줍니다:

IPC 명령 이름 (demo/mock/tauri-core.ts). 모의 명령은 src/lib/api.ts를 미러링하는 명령 이름에 대한 switch로 invoke()를 구현합니다. 명령이 이름이 바뀌거나 추가된 경우 일치하는 case를 추가하세요. 증상: 충돌 대신 빈 창 또는 누락된 데이터.

셀렉터와 영어 레이블 (demo/record.mjs). 투어는 .row, .quick-btn:has-text("Summarize"), .ai-input .instruction 같은 것을 클릭합니다. CSS 클래스 이름이 변경되거나 src/lib/i18n/locales/en.json의 문자열이 변경되면 일치하는 단계가 깨지고 시간 초과 오류가 실패한 셀렉터를 알려줍니다. 데모는 locale: "en"을 강제하므로 영어 레이블만 중요합니다.

픽스처도 마찬가지입니다: demo/mock/data.ts는 ai.prompt_* 문자열과 일치하여 빠른 프롬프트가 어떤 스크립트된 응답을 받을지 결정하며, 투어는 해당 응답의 특징적인 단어("sync", "yours", "4.2")를 기다립니다. 픽스처를 다시 작성하면 의존하는 대기 시간이 초과됩니다.

모든 픽스처 데이터와 모든 스크립트된 AI 응답은 demo/mock/data.ts에 있습니다. 데모가 다른 것을 표시하도록 하려면(다른 이메일, 다른 요약, 다른 초안 답장) 이 파일을 편집하세요.

record.mjs를 편집할 때 문제가 될 수 있는 덜 명백한 사항:

  • 작성기 본문은 <textarea>입니다. 스트리밍된 콘텐츠는 값이지 텍스트가 아닙니다. waitText가 아닌 waitValue로 기다리세요.
  • .compose-window textarea는 AI 명령 상자와도 일치합니다(DOM에서 먼저 옵니다). 본문에는 .compose-window > textarea를 사용하세요.
  • 작성 장면은 해시로 탐색하며 그 후에 page.reload()를 호출해야 합니다. 해시만 있는 goto는 SPA를 다시 마운트하지 않으므로 작성기가 나타나지 않습니다.
  • 비디오는 browser.close() 전에 video.saveAs()로 저장하세요. 그렇지 않으면 "target closed" 오류가 발생합니다.

페이스와 테마

기본값은 읽기 쉬운 랜딩 비디오에 맞춰 조정되어 있습니다. 실행마다 환경 변수로 재정의할 수 있습니다(모두 ms): DEMO_READ (화면당 체류 시간), DEMO_BEAT (동작 사이), DEMO_TYPE (키 입력 지연), DEMO_AI_TYPING / DEMO_AI_THINK / DEMO_AI_STEP (AI 스트림 케이던스). 콘텐츠를 추가한 후 장면이 너무 빠르게 느껴질 때 유용합니다.

테마는 2축입니다 — "<cold|warm>-<light|dark>", 예: warm-light (앱 기본값). 두 스크립트 모두 localStorage (skimdemo.theme)를 통해 테마를 강제하며, 모의 명령은 get_settings에서 이를 반환합니다:

  • 비디오는 warm-light로 고정됩니다. DEMO_THEME=cold-dark npm run demo:record로 재정의하세요.
  • 스크린샷은 warm-light → docs/skim-light.jpg와 warm-dark → docs/skim-dark.jpg로 렌더링됩니다(demo/screenshots.mjs의 SHOTS 배열이 테마를 파일 이름에 매핑합니다).

레거시 단일 축 값("light" 및 "dark")은 여전히 구문 분석되지만 cold 팔레트에 매핑되므로 이를 전달하면 오류 없이 잘못된 온도가 렌더링됩니다.

DEMO_PREBUILT=1은 개발 서버 대신 demo/dist-demo의 정적 빌드를 제공합니다. 제한된 환경이나 헤드리스 환경에서 유용합니다.

자세한 내용은 demo/README.md에 있습니다.

관련 스킬