gh CLI, web_fetch 등)를 우선 쓰고, 예시 하나를 여러 건으로 일반화한다 — 폼 하나 제출을 녹화하면 폼 전부를 제출하는 스킬이 된다.
microsoft/skill-recorder · 라이선스 MIT(Microsoft) · 버전 v0.3.1 · 형식 Electron + React 19 데스크탑 앱 · 언어 TypeScript(약 22,400줄) · AI 엔진 GitHub Copilot CLI(@github/copilot-sdk) · 온디바이스 음성인식 Whisper(transformers.js) · 파일 171개 · 최신 커밋 2026-07-30(Giorgio Ughini) · TrendShift Daily #13)
skill-recorder는 "당신이 화면에서 어떤 작업을 한 번 수행하면, 그 과정을 로컬에서 녹화해 GitHub Copilot이 '무엇을 하려 했는지(의도)'와 '어떤 순서로 했는지(단계)'로 재구성하고, 이를 AI 에이전트가 반복 실행할 수 있는 재사용 스킬(SKILL.md)이나 예약 자동화로 바꿔 주는 Electron 데스크탑 앱"이다. 한마디로 "시연 → 스킬"을 자동화하는 녹화기다. 스킬을 손으로 마크다운에 적는 대신, 실제로 한 번 해 보이면 된다.
영리한 견습생에게 일을 가르칠 때, 우리는 매뉴얼을 손으로 써 주지 않는다. 그냥 한 번 시연하면서 "지금 경비 정산서를 올리는 거야"라고 말해 준다. 견습생은 당신의 마우스가 정확히 몇 픽셀을 움직였는지 외우지 않는다 — "무엇을 하려는지(의도)"를 이해하고, 그걸 순서 있는 절차로 자기 노트에 정리한다. 그리고 다음부터는 굳이 화면을 똑같이 클릭하지 않고, 회계 시스템의 정식 기능(API)을 써서 더 빠르고 안정적으로 처리한다. 게다가 당신이 정산서 하나를 보여 줬을 뿐인데, 견습생은 정산서 전부를 처리할 줄 알게 된다.
skill-recorder가 정확히 이 견습생이다. ①녹화로 당신의 작업을 어깨너머로 지켜보되(키 입력이 아니라 앱·URL·클립보드 같은 의미를 본다), ②Copilot이 그걸 "의도 하나 + 순서 있는 단계들"로 재구성해 노트(SKILL.md)에 적고, ③실행할 땐 UI 클릭 재생 대신 gh·web_fetch 같은 네이티브 도구를 우선 쓰며, ④한 건의 예시를 N건으로 일반화한다. "따라 하기"가 아니라 "이해하고 재현하기"인 게 이 앱의 핵심이다.
name·description·선택적 allowed-tools)과 마크다운 지시 본문으로 이뤄진 파일이다. 다운스트림 AI 에이전트(Microsoft Scout, Cowork/M365 Copilot 등)가 이 파일을 자동으로 읽어, description이 지금 할 일과 맞으면 그 절차를 실행한다. 즉 프로그램이 아니라 "AI에게 주는 작업 매뉴얼"이다. skill-recorder가 최종적으로 뱉는 산출물이 바로 이 SKILL.md 한 벌이다.@github/copilot-sdk로 Copilot CLI를 멀티턴 에이전트처럼 몰고 다닌다 — 세션을 만들고, 앱 안에서 정의한 커스텀 도구를 등록하고, 턴을 스트리밍한다. Copilot CLI는 앱에 함께 딸려 오며, 실제 "의도/단계 재구성"과 "스킬 생성" 추론을 담당한다. 그래서 GitHub 계정 + Copilot 접근 권한이 있어야 한다.사용자가 녹화 버튼을 누르고 작업을 한 뒤 "Analyze → Create"를 누를 때, 내부에서 벌어지는 일을 압축하면 이렇다:
여기서 두 가지가 이 앱의 성격을 규정한다. 첫째, ①②는 전부 로컬이고 ③에서만 클라우드 전송이라는 프라이버시 경계다. 둘째, 잡는 신호가 픽셀·키스트로크가 아니라 "의미 이벤트"라는 점이다 — 이 둘이 뒤에서 설명할 "네이티브 도구 우선"과 "일반화"를 가능하게 하는 뿌리다.
첫째, "AI에게 내 반복 업무를 어떻게 가르치나"라는 문제를 프롬프트가 아니라 시연으로 푼다. 요즘 다들 스킬(SKILL.md)이 뜨는 건 알지만, 정작 스킬을 손으로 마크다운에 적는 일은 번거롭고 감이 안 온다. skill-recorder는 그 진입장벽을 없앤다 — "한 번 해 보이면 스킬이 나온다"는 show, don't tell 프레이밍은 그 자체로 공유성이 크다.
둘째, Microsoft 조직 + 진짜 새로운 프리미티브라는 신뢰 조합이다. 스킬/SKILL.md 흐름(Claude·Copilot 스킬)에 올라타면서, 그동안 비어 있던 "스킬 저작(authoring)의 온램프"를 채웠다. 산출물은 Microsoft Scout와 Cowork(M365 Copilot)를 겨냥한다. TrendShift 데일리 2위 토픽이 마침 AI skills라는 점도 맞물렸다.
매크로 녹화기와, 일 잘하는 조수의 차이다. 옛날 매크로/RPA 녹화기는 "3번째 줄, 좌표 (812, 344)를 클릭"을 그대로 재생한다 — 창 크기만 바뀌어도 깨지는 깨지기 쉬운 좌표 재생이다. skill-recorder는 좌표가 아니라 "이 사람이 지금 GitHub 이슈를 닫으려 하는구나"라는 의도를 읽고, 그걸 gh issue close 같은 정식 도구 호출로 바꾼다. 화면이 바뀌어도, 대상이 3건에서 300건으로 늘어도 안 깨진다. "손가락을 흉내 내는 것"과 "일을 이해하는 것"의 차이다.
셋째, 프라이버시 우선 설계가 클라우드 화면 녹화 도구들과의 확실한 차별점이다. 녹화·프레임 추출·음성 전사가 전부 내 컴퓨터에서 일어나고, "Analyze"를 누를 때만 업로드된다. 앱은 녹화 전마다 "비밀정보를 담지 말라"고 반복 경고한다.
넷째, v0.3답지 않은 엔지니어링 완성도가 별을 끈다. 순수·결정론적 코어(zod 스키마 계약 + 단위테스트), 세 갈래 평가(eval) 하네스(describer/automation-builder/skill-builder), 지각 해시 기반 프레임 중복 제거, 도구 샌드박싱 보안 태세, Windows ARM64까지 포함하는 크로스플랫폼, 그리고 번들 의존성 라이선스가 하나라도 미검토면 빌드를 실패시키는 컴플라이언스 게이트까지 — 마치 완제품 같은 밀도라 신뢰가 쌓인다.
대부분의 화면 자동화는 녹화한 클릭을 그대로 재생한다. skill-recorder는 의미 이벤트 → 의도/단계 재구성 → 네이티브 도구 매핑 → N건 일반화로 전혀 다른 산출물을 만든다. 폼 하나 제출을 녹화하면 "모든 행의 폼을 제출하라"는 스킬이 나오고, UI 클릭 대신 gh·web_fetch·M365 API를 우선 쓴다. 심지어 "빌더가 gh 대신 브라우저를 골랐다"는 회귀를 잡는 전용 eval까지 둔다. RPA/UI 리플레이(UiPath, Playwright codegen)와 갈라지는 지점이 여기다.
녹화 자체는 로컬이지만, Analyze를 누르는 순간 이벤트 타임라인(창·문서 제목, URL, 클립보드 미리보기), 추출된 화면 이미지, 내레이션 텍스트가 GitHub 클라우드로 전송돼 Copilot이 처리한다. 그래서 앱은 "비밀번호·토큰·API 키·기밀을 녹화·입력·붙여넣기·표시·복사·내레이션하지 말라"고 녹화 전마다 경고한다. 또 Analyze/Create에는 Copilot 접근 권한이 있는 GitHub 계정이 필수다. "설치하면 알아서 다 되는 로컬 전용 앱"으로 오해하면 안 된다.
skill-recorder는 서버 인프라가 없는 단일 데스크탑 앱이다. 그래서 스택은 "메인 프로세스(Electron·백엔드 역할)", "렌더러(React·프론트)", "AI 추론(Copilot 클라우드 + 온디바이스 Whisper)", "빌드·컴플라이언스 인프라"로 나뉜다. 의존성이 8개뿐인데 하나하나가 전략적으로 골라져 있다.
| 계층 | 구성요소 / 버전 | 역할 |
|---|---|---|
| AI 엔진 | @github/copilot-sdk ^1.0.6 | 이 앱의 심장. Copilot CLI를 멀티턴 에이전트로 구동 — 세션 생성, 커스텀 인프로세스 도구 등록, 턴 스트리밍. describer/builder의 추론을 담당 |
| 온디바이스 ASR | @huggingface/transformers ^4.2.0 | transformers.js. Whisper 음성인식 모델을 내 컴퓨터에서 돌려 내레이션을 전사(99개 언어, GPU 불필요) |
| UI (프론트) | react / react-dom ^19.2.5 | 녹화 HUD, 라이브러리(세션 목록), 계획 편집 타일 등 렌더러 UI. React 19 |
| 데이터 계약 | zod ^4.3.6 | 스키마 백본. 이벤트·번들·분석·스킬 계획 등 모든 데이터 계약을 zod 스키마로 정의하고 입출력 경계마다 검증 |
| 이미지 처리 | sharp ^0.34.5 | libvips 기반. 추출한 화면 프레임을 크롭·리사이즈해 모델에 보내기 전 다듬음. 지각 해시 계산에도 사용 |
| FFI (Windows) | koffi ^3.1.1 | 네이티브 컴파일러 없이 Windows user32/dwmapi/kernel32를 직접 호출 → 전경 창 추적 |
| 창 추적(선택) | get-windows ^9.3.0 optional | macOS/Linux 전경 창 폴링(브라우저 URL은 Apple Events). optional이라 프리빌드가 없어도 Windows가 안 깨짐 |
| 압축 | archiver ^7.0.1 | 내보낸 스킬 폴더·디버그 번들을 zip으로 |
electron/)는 Node 권한으로 창 관리·전역 단축키·파일·OS 이벤트 수집 등 "백엔드" 일을 하고, 렌더러(src/)는 브라우저 창 안에서 React로 UI를 그린다. skill-recorder에서 무거운 로직(녹화·파이프라인·Copilot 호출)은 전부 메인에 있다.빌드·테스트·인프라 계층도 눈여겨볼 만하다. 번들러는 Vite ^8(+vite-plugin-electron), 패키징은 electron-builder ^26, 타입은 TypeScript ^7. 테스트는 별도 프레임워크(Jest/Vitest) 없이 Node 내장 테스트 러너(node --test + --experimental-transform-types)로 14개 *.test.ts를 돌린다. CI는 non-windows.yml·windows.yml·portable.yml 3종이고, Windows 워크플로는 windows-latest와 네이티브 windows-11-arm 이미지 모두에서 돈다. Dockerfile·서버는 없다.
Dockerfile 대신 이 레포엔 묵직한 컴플라이언스 서브시스템이 있다: third_party/compliance-policy.json, scripts/prepare-compliance.mjs, verify-packaged-compliance.mjs, 그리고 npm run compliance:licenses. 번들되는 패키지 중 하나라도 검토된 법적 문서가 없으면 빌드를 실패시킨다. Microsoft의 재배포 규칙(로컬 소스 빌드 vs 재배포 패키지의 경계)을 코드로 강제한 것 — 대기업이 오픈소스를 낼 때 어떻게 라이선스 리스크를 자동화하는지 보여주는 좋은 표본이다.
녹화가 끝나면 electron/pipeline.ts의 processSession(dir)가 후처리를 한다. 설계 원칙이 코드 주석에 못박혀 있다: "OS 이벤트가 1차 신호, 영상은 부수적(opportunistic)" — "영상 전체를 스캔하지 않는다. 이벤트가 1차 신호이고, 이벤트가 놓친 것만 낮은 신뢰 구간에서 프로브 제안으로 나중에 수확한다." 즉 값싼 이벤트를 최대한 쓰고, 비싼 영상 분석은 최소로 아낀다.
이 레포의 가장 배울 만한 설계다. 분절·상관 같은 "정답이 있는" 일은 순수 함수 + zod 검증 + 단위테스트로 결정론적으로 처리하고, "의도 재구성" 같은 애매한 일만 LLM에 맡긴다. 예컨대 이벤트를 단계로 쪼개는 common/bundle.ts(252줄)의 경계 규칙은 완전히 결정론적이다:
// common/bundle.ts — 어디서 새 "단계"가 시작되는가 (순수 규칙)
if (!cur) boundary = "start";
else if (ev.type === "app.activate" && app && app !== curApp) boundary = "app-change";
else if (ev.type === "browser.url" && host && host !== curHost) boundary = "url-change";
else if (ev.type === "terminal.command") boundary = "command";
// 그 외(제목 변경·클립보드·마커)는 현재 단계에 흡수
앱이 바뀌거나, 브라우저 호스트가 바뀌거나, 터미널 명령이 실행되면 새 단계가 열리고 나머지는 현재 단계에 folding된다. 그리고 renderDescription()이 만드는 description.md는 Copilot이 없어도 나오는 결정론적 폴백이다. LLM은 "있으면 더 좋은" 가장자리일 뿐, 코어가 LLM에 종속되지 않는다.
common/correlation.ts(262줄)는 프레임과 이벤트를 ±1500ms로 맞춰 붙인다. 여기서 나오는 두 개념: unexplained 프레임 = 화면은 확 바뀌었는데 근처에 의미 이벤트가 없는 장면(이벤트 스트림이 놓친 미세 단계 후보). silent 이벤트 = 의미 이벤트는 있는데 시각적으로 구별되는 프레임이 안 나온 경우. 이걸로 "프로브 요청"을 만드는데, 비영상 신호가 풍부할수록 빈틈이 짧아 프로브가 줄어드는 자기 조절(self-scaling) 구조다.Describer(electron/describer/describer.ts, 430줄)는 하나의 CopilotClient를 쥐고, 피드백 맥락을 살리려 최대 MAX_LIVE_SESSIONS = 4개의 재개 가능 대화를 유지한다. 프레임이 이미지이므로 pickVisionModel()로 비전 지원 모델을 우선 고른다. 핵심은 에이전트가 볼 수 있는 도구를 커스텀 6종으로만 제한(allowlist)한다는 것:
// 커스텀 도구만 노출. 런타임이 allowlist를 못 지키면
// 조용히 무제한 세션을 만드느니 분석을 실패시킨다
// (approveAll과 겹치면 SDK 기본 도구가 사용자 환경에서 자동 실행될 위험)
const copilot = await client.createSession({
...config,
availableTools: tools.map((t) => t.name), // ← 화이트리스트
});
"실패하면 안전한 쪽으로(fail-closed)" 태도가 분명하다 — 샌드박스를 보장 못 하면 차라리 멈춘다. 만약 에이전트가 submit_analysis 호출을 잊으면 NUDGE_PROMPT가 강제로 마무리시키고, 턴 타임아웃은 180초다.
electron/describer/tools.ts(374줄)가 정의하는 6개 도구 중 get_frames의 트릭이 영리하다. 파일시스템이나 bash 도구를 주지 않고도 모델이 화면을 직접 보게 하려고, JPEG를 base64로 인라인 반환(binaryResultsForLlm)한다. 프레임은 MAX_IMAGES_PER_CALL = 6으로 균등 서브샘플, 이벤트는 MAX_EVENTS = 500, 모든 문자열은 2000자에서 절단한다. submit_analysis는 zod로 검증해 규격이 어긋나면 고칠 수 있는 오류 메시지를 돌려준다. CLI 에이전트에게 셸 권한 없이 시각을 부여하는 깔끔한 방법이다.
스킬 빌더(electron/skillbuilder/builder.ts, 360줄)는 2단계 에이전트다: propose_plan(사용자 검토를 위해 STOP) → submit_skill. 사용자가 편집한 계획이 권위(authoritative)를 가져, 에이전트는 본문만 쓸 수 있고 값·단계를 다시 추가·재배열할 수 없다. 여기에 세 가지 핵심 규율이 얹힌다:
scout-catalog.ts, SCOUT_CATALOGUE_VERSION = "2026-07-26")를 두고, 녹화된 클릭을 gh CLI·web_fetch·workiq_*(M365)로 매핑한다. 브라우저/Playwright는 최후 수단.common/skill.ts, 235줄): 모든 일반화된 단계는 부수효과 없는 calculation이거나 세상을 바꾸는 action(제출·전송·생성·삭제 = "위험 표면")으로 타입이 갈린다.{{id}}로 빼내 UI에서 편집 가능한 "알약(pill)"으로 보여주고, 렌더 시점에 실제 값으로 치환. renderSkillMarkdown()이 YAML 머리말을 찍고 description은 JSON 문자열화해 콜론·쉼표가 YAML을 깨지 못하게 한다.그리고 이 모든 것의 목적인 일반화가 빌더 지시문에 못박혀 있다: "사용자가 특정 집합에 작용했다면(예: 시트 3개 행의 폼 제출), 스킬은 모든 항목(N)을 다뤄야 하며… 예시 3개를 하드코딩하지 않는다." 이것이 "폼 하나 → 폼 전부"를 만드는 규칙이다.
electron/frames/extractor.ts(627줄)는 프레임마다 64비트 dHash(차이 해시)를 계산해, 기존 프레임과 해밍 거리(Hamming distance)가 임계값 이하면 중복으로 버린다:
// 두 프레임의 dHash 해밍 거리가 임계값 이하면 중복
const DEFAULTS = { dedupeThreshold: 8, maxFrames: 300, frameGridSec: 0.5 };
...
const phash = await dhash(file);
if (hamming(existing.phash, phash) <= this.opts.dedupeThreshold) {
/* 거의 같은 화면 → 버림 */
}
영상은 1fps·1280×720·500kbps로 일부러 낮게 잡는다. 주석에 이유가 있다: "화면 캡처의 진짜 비용은 WindowServer가 프레임버퍼를 잡는 것… 이건 이벤트에 앵커된 부수적 보강일 뿐, 아무도 안 보는 영상"이다. 값싼 신호(이벤트)를 주력으로, 비싼 신호(영상)를 절약하는 철학이 프레임 레이트에까지 일관된다.
구조가 알려주는 힌트 셋. 첫째, common/이 "순수 계약" 층으로 완전히 분리돼 Electron을 전혀 import하지 않는다 — 그래서 node --test로 단독 단위테스트가 가능하고, 결정론적 코어가 UI/OS와 얽히지 않는다. 둘째, electron/ 안이 수집(collectors) · 후처리(frames·pipeline) · 추론(describer·builders)으로 또 갈려 있어, 예컨대 새 수집기(터미널 명령 등)를 추가하거나 새 빌더(자동화 외)를 붙이기 쉽다. 셋째, evals/가 1급 시민이다 — describer/automation/skill 세 갈래를 합성 픽스처로 채점해, LLM 부분이 회귀하는지 CI로 지킨다.
common/이 Electron·React를 모른다는 건 우연이 아니다. 비즈니스 로직(분절·상관·스킬 렌더)을 UI/OS 프레임워크에서 분리하면, 테스트가 빨라지고, 나중에 Electron을 걷어내거나 CLI로 재포장하기도 쉽다. "핵심 규칙은 순수 함수로, 지저분한 I/O는 바깥 껍질로"라는 헥사고날/클린 아키텍처의 실전 예다. 규모가 작아도 이 경계를 지킨 게 이 레포의 완성도를 만든다.
"정답이 있는 일은 순수 코드로, 애매한 일만 LLM으로" 나누는 사고틀. 분절·상관·검증은 zod로 결정론화하고, 의도 재구성만 Copilot에 맡긴다. description.md라는 LLM 없는 폴백까지 둔 게 백미다. 이 패턴은 어떤 AI 기능에도 옮겨진다 — "이 기능에서 LLM이 정말 필요한 최소 지점은 어디인가"를 묻는 습관을 배운다.
availableTools allowlist로 에이전트가 볼 도구를 화이트리스트하고, 런타임이 이를 못 지키면 조용히 진행하지 않고 실패시키는 보안 태세. approveAll(자동 승인)과 겹칠 때의 위험을 코드 주석으로 명시한 것도 배울 점이다. LLM에게 도구를 쥐여줄 때 "최소 권한 + 실패 시 안전"을 어떻게 코드로 강제하는지의 표본이다.
셸·파일 도구 없이도 모델이 화면을 보게 하는 법 — JPEG를 base64 인라인으로 도구 결과에 실어 반환. 이미지 6장 서브샘플·이벤트 500개·문자열 2000자 절단 같은 컨텍스트 예산 관리도 함께 배운다. 멀티모달 에이전트를 만들 때 "무엇을, 얼마나, 어떤 형태로 모델에 넣는가"의 실전이다.
좌표 재생이 아니라 의미 이벤트 → 의도 → 네이티브 도구 매핑 → N건 일반화. "폼 하나 → 폼 전부", "클릭 → gh 호출"로 바꾸는 calculation/action 분리와 {{토큰}} 치환. 자동화 도구를 설계한다면 "녹화를 어떻게 견고하고 일반적인 절차로 승격시키나"가 핵심 질문이 된다.
클라우드로 오디오를 보내지 않고 브라우저/Node 런타임에서 Whisper를 직접 돌리는 법. 모델을 첫 사용 시 1회 다운로드(~252MB)해 캐시하고, GPU 없이 CPU ONNX로 99개 언어를 전사한다. "프라이버시가 중요한 기능은 온디바이스로"의 구체적 구현을 배운다.
common/을 프레임워크에서 떼어 node --test로 단독 검증하고, LLM 부분은 합성 픽스처 eval(describer/automation/skill 3종)로 회귀를 지키는 방식. "비결정적인 LLM 기능을 어떻게 CI로 지키나"라는 어려운 문제에 대한 실용적 답이다.
앱을 설치하지 않아도 핵심 아이디어는 체험할 수 있다. 아무 반복 업무(예: 이슈 3개 닫기)를 하면서 "앱 전환 / URL 변경 / 복사 / 명령 실행"만 손으로 메모해 보라. 그 메모를 bundle.ts의 경계 규칙(app-change·url-change·command)대로 단계로 잘라 보면, "픽셀 없이 의미만으로도 절차가 복원되는" 감각과 "어디서 이벤트가 부족한지(unexplained 구간)"가 바로 보인다.
| 항목 | 필요한 것 |
|---|---|
| 플랫폼 | macOS가 1차 타깃. Windows 11(x64·ARM64) 지원, Ubuntu 설치 경로도 있음 |
| AI 접근 | Copilot 접근 권한이 있는 GitHub 계정. Analyze/Create 시 데이터가 GitHub 클라우드로 감. Copilot CLI는 앱에 동봉 |
| 개발(소스 빌드) | Node.js 24. npm ci → npm run compliance:licenses → npm run dev(Vite+Electron 핫리로드) |
| macOS 권한 | Screen Recording(영상)·Accessibility(창 제목)·브라우저별 Automation(URL). 권한이 없으면 앱 전환 추적으로 우아하게 degrade |
| 내레이션(선택) | 첫 사용 시 ~252MB Whisper-small int8 ONNX 모델 1회 다운로드(Xenova/whisper-small). 이후 오프라인·온디바이스, 99개 언어, GPU 불필요 |
| 설치 방식 | 릴리스마다 커밋 고정(commit-pinned) 원라이너로, 검증된 Node 24 런타임을 받아 정확한 릴리스 커밋을 로컬에서 빌드. "전역 설치 없음(Nothing is installed globally)" |
설치 명령은 릴리스 페이지에서 플랫폼별로 복사하는데, 커밋 해시가 박힌 형태다(개념 형태):
# macOS / Ubuntu — <40자 릴리스 커밋>은 릴리스 페이지에서 채워짐
commit="<40-character-release-commit>"
curl -fsSL "https://raw.githubusercontent.com/microsoft/skill-recorder/$commit/install.sh" \
| SKILL_RECORDER_COMMIT="$commit" bash
# 백그라운드 유지: 파이프 뒤에 SKILL_RECORDER_DETACHED=1 추가
# → macOS는 ~/Applications 에 "Skill Recorder (Source)" 앱을 추가
INSTALL.md).버전이 0.3.1인 초기 프로젝트다. 산출된 스킬의 목표 아키텍처는 Scout·Cowork(M365 Copilot)가 활성이고 copilot-studio는 "coming soon" 상태다. 즉 임의의 아무 에이전트에나 바로 꽂히는 범용 포맷이라기보다, Microsoft/GitHub 생태계(Copilot·Scout·M365)에 최적화돼 있다. SKILL.md 자체는 열린 포맷이지만, "네이티브 도구 우선" 매핑은 그 카탈로그(gh·web_fetch·workiq_*)에 묶여 있음을 감안해야 한다.
git clone --depth 1로 받아 electron/pipeline.ts의 processSession()을 읽고, Record→Process→Analyze→Create가 어떤 파일·함수로 이어지는지 한 장으로 그린다. 특히 "어디까지가 로컬이고 어디서 클라우드로 나가는가"의 경계를 표시하라. "왜 description.md를 결정론으로 먼저 만들까?"에 스스로 답하는 게 목표.
종이에 아무 반복 업무의 "앱 전환 / URL / 복사 / 명령"을 시간순으로 적은 뒤, common/bundle.ts의 규칙(app-change·url-change·command가 새 단계, 나머지는 흡수)을 손으로 적용해 단계로 나눠 보라. 같은 로그를 규칙 없이 나눈 것과 비교해, 결정론적 분절이 왜 재현 가능한지 체감한다.
이 앱 없이도 결과물 포맷은 흉내 낼 수 있다. common/skill.ts의 렌더 규칙(YAML name·description·allowed-tools + 본문, {{토큰}} 값)을 참고해, 자기 반복 업무 하나를 SKILL.md로 직접 작성한다. 값(URL 등)은 {{repo}}처럼 토큰화하고, 단계를 calculation/action으로 표시해 보라. Claude Code·Copilot에 넣어 실제로 도는지 확인.
화면 녹화 mp4 하나를 ffmpeg로 0.5초 간격 프레임으로 뽑은 뒤, 파이썬 imagehash(dHash)로 인접 프레임의 해밍 거리를 구해 임계값 8 이하를 버리는 스크립트를 짠다. 원본 프레임 수 대비 얼마나 줄어드는지 세어, extractor.ts가 왜 "화면이 바뀔 때만" 프레임을 남기는지 데이터로 확인하라.
작은 도전: JSON 이벤트 로그(앱·URL·클립보드)를 입력받아 LLM에게 "의도 1개 + 순서 있는 단계"로 재구성시키되, 도구를 화이트리스트로 제한하고 출력은 스키마(zod/JSON Schema)로 검증하는 파이프라인을 직접 구현한다. 그리고 "예시 3건 → N건 일반화" 지시를 프롬프트에 넣어, 하드코딩 없이 일반 절차가 나오는지 eval 픽스처 2~3개로 채점해 보라. skill-recorder의 축소판을 만드는 과제.
| 주차 | 주제 | 구체적으로 |
|---|---|---|
| 1주 | 에이전트 스킬 포맷 | SKILL.md 규격(YAML 머리말·description 트리거·allowed-tools), Claude/Copilot 스킬 생태계, "스킬을 언제·어떻게 자동 로드하나" |
| 2주 | 결정론 코어 + LLM 가장자리 | zod로 데이터 계약 세우기, 순수 함수 분절/상관, LLM 폴백 설계. "LLM이 정말 필요한 최소 지점" 찾기 |
| 3주 | 도구 사용 에이전트 & 샌드박싱 | function calling, availableTools allowlist, fail-closed, 인라인 멀티모달(이미지) 도구, 컨텍스트 예산(서브샘플·절단) |
| 4주 | 관찰→일반화 & RPA 비교 | 의미 이벤트 vs 좌표 재생, 네이티브 도구 매핑(gh·web_fetch), calculation/action, {{토큰}} 일반화. UiPath/Playwright codegen과 대조 |
| 5주 | 온디바이스 ML | transformers.js + Whisper, ONNX Runtime, 모델 양자화(int8), CPU 추론, 프라이버시 우선 기능 설계 |
| 6주(선택) | Electron 앱 + 공급망 | 메인/렌더러 분리, 전역 단축키·화면 캡처 권한, 커밋 고정 소스 릴리스, 라이선스 컴플라이언스 게이트 |
README.md(개요·설치) → electron/pipeline.ts(4단계 흐름) → common/bundle.ts(단계 분절) → common/correlation.ts(프레임 상관) → electron/describer/describer.ts·tools.ts(샌드박스 분석) → electron/skillbuilder/builder.ts·common/skill.ts(스킬 생성) → electron/frames/extractor.ts(dHash) → evals/README.md(평가)@github/copilot-sdk(Copilot CLI를 에이전트로 구동)Xenova/whisper-small) · ONNX Runtime