「この作業、毎回やってるからAIに任せたい」と思ったとき、いまは手順書を書く必要がある。Microsoftが2026年7月29日に公開した microsoft/skill-recorder は、そこを逆転させる。手順を書く代わりに、実際にその作業を1回やって見せる。画面・ウィンドウの切り替え・訪れたURL・(任意で)声の解説を記録し、GitHub Copilotがそれを「意図+順序つきの手順」として再構成し、エージェントが再利用できる形に変換する。
30秒でわかる Skill Recorder
・何ができるか:作業を1回録画すると、Copilotが「何をしたか」を意図+手順に再構成し、そこから SKILL.md(要求時に走るスキル)またはAutomation(スケジュール実行)を生成する
・何を解決するか:スキルを文章で書き起こす手間。1件のフォーム送信を録れば「全件送信」へ一般化させる、という設計思想を掲げている
・何を代替するか:Claude Codeのスキル作成は代替しない。エクスポート先は Scout と Cowork(Microsoft 365 Copilot)で、Claude Codeは選択肢に無い(後述・ソース実読で確認)
・実体:★398・MIT・TypeScript・Electron製デスクトップアプリ。最新は v0.3.1(2026-07-30)
本記事はリポジトリを実際にクローンし、テストスイートの実行とスキル生成関数の直接実行まで行って書いている。READMEに書かれていない仕様(エクスポート先・日本語名の扱い)はソースと実行結果を根拠にした。AIエージェント全般の設計を俯瞰したい場合は、まずAIエージェントフレームワーク比較2026|LangGraph・CrewAI・Dify等9種をStar数・実コードで検証を参照してほしい。
Skill Recorderとは——「書くスキル」から「録るスキル」への反転
Agent Skillsは、ここ数か月で「フォルダに SKILL.md を置く」という形式にほぼ収束した。だが収束したのは形式であって、中身を用意する手間は誰も解決していない。手順書は結局、人間が思い出しながら文章にする必要がある。
Skill Recorderはこの前提を反転させる。READMEの1行目がそのまま設計思想になっている。
Record yourself doing a task once, then turn it into a skill your AI agent can repeat. (出典: microsoft/skill-recorder README)
思い出して書くのではなく、やって見せる。人間が業務を教えるときに実際にやっていることと同じ手順だ。そして重要なのは、記録した操作をそのまま再生する(UIクリックのリプレイ)のではない、と明言している点である。READMEは生成物について「Both prefer the agent’s native tools (like the gh CLI or web_fetch) over replaying UI clicks」と書く。つまり「ブラウザでこのボタンを押す」ではなく「gh CLIでPR一覧を取る」に翻訳することを狙っている。
この方針はソース側の指示文にも一致していた。electron/skillbuilder/instructions.ts には ## Prefer native tools (read the catalogue below) という見出しがあり、「When a service ships a first-class CLI on the device, prefer it over the browser」と続く。UI操作の記録を、UI操作ではない形に落とすことが明示的な設計目標になっている。
npm test を実行した結果リポジトリの実体は、GitHub APIで取得した値で次の通りだった。
| 項目 | 実測値(2026-08-02 JST) |
|---|---|
| Star / Fork | 398 / 48 |
| ライセンス | MIT |
| 主要言語 | TypeScript(714,690バイト)/JavaScript・CSS・PowerShell・Shellが続く |
| 作成日 | 2026-07-29 |
| 最新リリース | v0.3.1(2026-07-30 16:34 UTC) |
| コミット数 | 103 |
| 主なコントリビューター | GiorgioUghini(32)・adilei(30)・adilei-powerapps(9) |
| Open Issues | 26 |
公開から4日で★398という立ち上がりだが、コミット数103・コントリビューター3名という規模感の通り、まだ若いプロジェクトである。なお2026-08-05にGitHub APIで再取得したところ、★1,780・fork 179・Open Issues 29(最終push 2026-08-04)まで伸びていた。3日で約4.5倍で、リリースはv0.3.1のままだがmainは動き続けている。以下の検証はすべてv0.3.1時点のソースに対するものである。v0.1.0・v0.2.0・v0.2.1・v0.3.0 の4リリースは 2026-07-29 19:50:29〜19:50:31 UTC の3秒間に、v0.3.1のみ翌日に公開されている。初期リリース群がまとめて発行された形だが、その理由はリポジトリ上に記載がないため、ここでは事実の記載にとどめる。
エクスポート先はScoutとCowork——Claude Codeは選択肢に無い
ここが本記事でもっとも伝えたい点であり、READMEを読むだけでは分からない部分だ。
READMEは生成物を一貫して「an agent」「your AI agent」としか書かない。どのエージェント向けなのかは本文に登場しない。そこでソースを読むと、common/skill.ts に対象が列挙されていた。
実際にリポジトリをクローンし、リポジトリ自身のローダー経由でこの定数を実行して出力させた結果が次である。
common/skill.ts の ARCHITECTURES / TARGETS を v0.3.1 で実行して出力したもの=== ARCHITECTURES ===
scout enabled=true
cowork enabled=true
copilot-studio enabled=false
=== TARGETS ===
skill/scout enabled=true Scout skill
automation/scout enabled=true Scout automation
skill/cowork enabled=true Cowork skill
skill/copilot-studio enabled=false Copilot Studio
つまり選べる出力先は Scout・Cowork・Copilot Studio(無効) の3系統4枠で、Claude Codeも、Cursorも、汎用の「ローカルの .claude/skills/ に置く」も選択肢に無い。
ソース内の各対象の説明文(note)はそれぞれこう書かれている。Scoutが「Microsoft Scout: native WorkIQ, browser, files, and built-in skills.」、Coworkが「Microsoft 365 Copilot (Cowork): native Teams, Outlook, Calendar, SharePoint, files, and built-in skills.」、Copilot Studioは「Coming soon.」のみ。Scoutについては筆者の知識時点より後に登場した製品のため、リポジトリが自称する上記の説明以上の内容は本記事では断定しない。
形式は同型なのに、行き先が違う
後述の通り、生成される SKILL.md は name / description / allowed-tools というfrontmatterを持つ。これはAgent Skillsとして広く見る形と同型である。しかしそれは「Claude Codeに持っていける」ことを意味しない。アプリのUIが提示するエクスポート先に選択肢が無い、というのが実装上の事実だ。ファイルを手で移せば読める可能性はあるが、allowed-tools に入る値が workiq_search_chats のようなScout固有のツール名である以上、そのまま機能する保証は無い。本記事では移植可否を検証していないため、断定を避ける。
Automation側も同様にMicrosoft寄りで、common/automation.ts のコメントには「rendered to Scout’s import JSON and written into an importable bundle folder (Scout imports it; it is not auto-loaded like a skill)」とある。スケジュールの表現も「Scoutの3種(single / interval / multi)を写したもの」と明記され、intervalMinutes には「1440を割り切ること」というバリデーションまで入っていた。
何が記録され、どこへ送られるのか
画面録画ツールである以上、「何が・どこへ行くのか」は使う前に確認したい部分だろう。
READMEの記述は明快だ。録画・保存・フレーム抽出・ナレーションの文字起こしは端末内で行われ、録画中は何も外部に出ない。送信が起きるのは Analyzeを押したときで、そこで初めてイベントの時系列・抽出画像・ナレーションのテキストがGitHubのクラウドへ渡る。
記録される信号そのものは common/config.ts に単一の定義がある。注目すべきはこのファイル冒頭のコメントだ。
The recorder captures every available signal on every recording — there is no user-facing capture level. (出典:
common/config.ts)
記録項目を選ぶUIは無い。設計判断として「重なり合うOS権限をなぞるだけの段階的ピッカー」をやめ、透明性は「何が記録されるか」の説明で担保する、と書かれている。実際の項目と必要な権限は次の通り。
| 記録される信号 | 内容 | 必要な権限 |
|---|---|---|
| App switches | 前面アプリの切り替え(アプリ名・bundle・pid) | 不要 |
| Clipboard copies | コピーした内容の形式・長さ・ハッシュ・短いプレビュー | 不要 |
| Window titles | ウィンドウとドキュメントのタイトル | OS権限が一度必要 |
| Browser URLs | アクティブなブラウザタブのURL(macOS) | OS権限が一度必要 |
| Screen video + keyframes | 低フレームレートの画面録画と抽出キーフレーム | 画面収録の権限 |
(出典: common/config.ts の CAPTURE_SOURCES / FULL_CAPTURE)
ナレーションは任意で、READMEによればWhisperがサポートする99言語で端末内で文字起こしされ、初回のみ約252MBのモデルをダウンロードする。日本語の音声解説を付けられるのは、日本語話者にとっては素直に利点だ。
秘密情報の扱いについては、READMEが2か所で警告している。パスワード・トークン・APIキーなどを「録画・入力・貼り付け・表示・コピー・読み上げ」しないこと、とかなり具体的に列挙されている。この警告が単なる文言でないことは、テストコードからも読み取れた。electron/recording-privacy.test.ts には次の2件があり、手元でも合格を確認している。
・詳細な開示内容をレビューするまで、録画開始のたびに警告を出す(startDecision() が show-warning を返し続ける)
・レビュー済みの記録はアプリのプロセスをまたいで残らない(次回起動時はまた警告から始まる)
「一度チェックしたら二度と出ない」タイプの同意UIにしていない点は、扱うデータの性質を踏まえた妥当な設計に見える。
ナレーションの扱いにも、同じ「黙って進めない」という方針が現れている。electron/narration/analyze-gate.ts はたった1行の純粋関数だが、コメントが意図を説明していた。
The narration is the user’s own words describing their intent, so analysis must never silently run without it when it’s available but not yet transcribed. (出典:
electron/narration/analyze-gate.ts)
音声が保存されていて、まだ文字起こしが無いときだけ「文字起こし→解析」の順に進む。音声が無いセッション、あるいは既に文字起こし済みのセッションはそのまま解析へ行く。ユーザーが自分の言葉で吹き込んだ意図を、取りこぼしたまま解析を走らせないための門である。録画映像から推測するより本人の説明のほうが正確なのだから、理屈は通っている。
なおナレーション周りには、Whisperが無音区間で定型句を幻覚(hallucinate)する既知の問題への対処も入っている。transcribe.ts には「Whisper hallucinates stock phrases over silence/noise; drop the usual suspects」というコメントとともに、無音判定と定型句の除去が実装されていた。音声を扱うツールとしては現実的な作り込みだ。
録画から生成までの流れ
アプリの操作フローは4段階で、READMEの「How it works」と実装の構成が一致している。
⌘⇧R でどこからでも開始"] --> B["🎛️ Control
常に前面の小バーで
マイクのミュート切替・破棄"] B --> C["🧠 Analyze
Copilotが意図と
順序つき手順を再構成"] C --> D{"内容を確認・編集"} D -->|直したい| C D -->|承認| E["📋 propose_plan
一般化の方針・固定値・
使う native tool を提案"] E --> F{"自然言語で修正"} F -->|refine| E F -->|確定| G["✨ submit_skill
SKILL.md を描画"] G --> H["Scout / Cowork へ
エクスポート"]
ポイントは、承認ゲートが2段あることだ。1段目はAnalyze直後の「意図と手順」の確認(画面上で手順をクリックして編集・並べ替え・追加・削除できる)、2段目はスキルを書く前のプラン提示である。common/skill.ts のコメントによれば、propose_plan は「どう一般化するか、どんな固定値が必要か、どのnative toolを使うか」を先に出し、ユーザーが自然言語で詰めてから初めて submit_skill に進む。いきなり成果物を出さず、方針を先に見せる構成になっている。
手順を「計算」と「実行」に割る
プランの中の手順は、ただの文字列ではなく型を持っている。PlanStepKind は calculation と action の2値で、コメントが理由を説明している。
common/skill.ts の PlanStepKind の定義とコメントに基づく読む・導出する・判断する・整形するだけで外部に影響を与えないものが calculation、submit・send・create・deleteのように世界を変えるものが action。分ける理由はコメントに「Splitting them keeps the plan honest about side effects; the actions are the risky surface」と書かれている。副作用のある手順だけを危険面として明示するという考え方だ。
録画から自動生成されたスキルを人間がレビューするとき、全手順を等しく読むのは現実的でない。「どれが取り返しのつかない操作か」が型で分かれているのは、レビュー負荷の面で理にかなっている。
Skill Recorderが生成するSKILL.mdを実際に描画して確かめた
renderSkillMarkdown() はCopilotに依存しない純粋関数なので、手元で直接呼べる。実際に呼び出して、このツールが吐くバイト列そのものを確認した。
リポジトリのテストがNode標準のテストランナーと --experimental-transform-types(TypeScriptをそのまま実行する仕組み)を使っているため、同じローダーを借りて実行する。
git clone https://github.com/microsoft/skill-recorder.git
cd skill-recorder && npm ci
# リポジトリ自身のテストを実行(Copilotのサインイン不要)
npm test
手元(macOS)での実行結果は 58 tests / 58 pass / 0 fail、所要 1.2秒だった。テスト対象は音声処理・マイク・ナレーション・フレーム抽出・録画コントロール・プライバシー・セッション管理・コンプライアンスなど14ファイルで、Copilotへのサインインなしで通る。
補足:npx vitest run と打つと14ファイルすべてが “No test suite found” で失敗する。このリポジトリはvitestではなく Node標準の node --test を使っており、正しい入口は npm test である。また install.sh はNode 24を固定・検証する(Expected Node.js 24, got ... で停止)が、テスト自体は手元のNode v22.13.1でも通った。
その上で renderSkillMarkdown() に、コロンとカンマと日本語を含む説明文・allowed-tools 2件・{{portal}} という値トークンを含む本文を渡した。出力は次の通り(234バイト)。
---
name: submit-expense-records
description: "Use when: submitting expense records, 経費精算: colons, commas"
allowed-tools:
- Bash(git *)
- workiq_search_chats
---
Open https://contoso.example/expenses and submit each row.
確認できたことが3つある。
・descriptionは必ずダブルクォートで囲まれる。コロンやカンマが入ってもYAMLが壊れないよう JSON.stringify を通している(ソースのコメントにも「so colons/commas in it never break the YAML」とある)。日本語もそのまま通る
・{{id}} トークンは書き出し時に実際の値へ置換される。プラン段階では {{portal}} という名前付きの固定値として扱われ、レンダリング時にURLへ展開された
・allowed-tools はfrontmatterに配列で入る。ここに workiq_search_chats のようなScout固有のツール名が入るため、形式が同じでも中身は行き先に依存する
この {{id}} の仕組みは、READMEが掲げる「1件の送信を録れば全件送信を教えられる」という一般化と対になっている。SkillPlan のスキーマを読むと、プランは手順の羅列だけでなく generalization(録画された具体例をどう一般化したか、という説明)と values(URL・パス・定数などの固定リテラル)を別々のフィールドとして持つ。録画に映った「1回きりの具体値」を固定値として切り出し、繰り返す部分だけを手順として残す、という分離だ。
言い換えれば、録画から作られるのは「操作の記録」ではなく「変わらない部分と変わる部分に分解された手順」である。ここが単なるマクロ記録ツールとの分岐点で、レビュー時に values を見れば「このスキルが決め打ちしている値」が一覧で分かる構造にもなっている。
日本語のスキル名は消える——slugifySkillNameの実測
日本語で作業して日本語で解説を吹き込む使い方を考えると、無視できない挙動が見つかった。
スキル名を作る slugifySkillName() は、[^a-z0-9]+ に当たる文字をすべてハイフンに潰し、前後のハイフンを削り、60文字で切る。日本語は英数字ではないため、丸ごと消える。同じ関数を手元で実行した結果が次である。
"経費精算を提出する" -> "recorded-skill"
"日報を作成" -> "recorded-skill"
"Slackに投稿する" -> "slack"
"請求書PDFを保存" -> "pdf"
"会議メモを整理" -> "recorded-skill"
distinct inputs: 5 distinct slugs: 3 => [ 'recorded-skill', 'slack', 'pdf' ]
5つの異なる業務名が3つの名前に潰れ、うち3件は同一の recorded-skill になった。日本語が完全に消えた場合はフォールバック値の recorded-skill が使われる仕様(ソース上 return slug || "recorded-skill";)で、これは名前の衝突を意味する。また「請求書PDFを保存」が pdf になるように、たまたま混ざったASCII断片だけが名前になるケースも起きる。
ただし、これを「バグ」と決めつけるのは正しくない。ビルダー側の指示を確認すると、electron/skillbuilder/scout-catalog.ts と cowork-catalog.ts の双方に `name` — kebab-case, `^[a-z0-9-]+$` という要求が書かれており、ツール定義(electron/skillbuilder/tools.ts)にも「kebab-case skill id, e.g. “submit-expense-records”」と例示がある。モデルには英語のkebab-caseで名前を出すよう指示されているため、通常の経路では日本語名にならない想定だ。slugifySkillName はあくまで、モデルが指示に従わなかった場合に不正な名前を通さないためのガードレールである。
とはいえ、日本語話者が実運用で気に留める価値はある。プランを日本語で詰める過程で名前が日本語に寄れば、静かに recorded-skill に落ちる。生成後はスキル名だけ目視するのが安全だ。なお、混在時の挙動も測っており、「Slack へ investor update を投稿」→ slack-investor-update、「PR 一覧を取得 (GitHub)」→ pr-github と、ASCII部分は素直に残る。60文字の上限も実測で確認した(140文字の入力→60文字)。
skill-recorderは外部にデータを送信するか——Copilotへ渡る3経路をソースで実測
skill-recorderのセキュリティで最初に確認すべきは、録画したデータが本当にローカル処理で完結するのかという点だ。前述の送信境界はREADMEの「What gets captured」に基づくものだが、これはREADMEの自己申告である。画面と音声とクリップボードを録るツールを業務で使うなら、その申告をソース側で数え直しておきたい。v0.3.1を対象に実測した結果を、確認できたこととこの方法では確認できないことに分けて示す。
送信APIの呼び出しは0件——ただし「通信が無い」ではない
まずfirst-partyのソースツリー(electron/=メインプロセス、common/=共有ロジック、src/=React側の10ファイル)に対して、送信に使われるAPIを検索した。
git clone https://github.com/microsoft/skill-recorder.git
cd skill-recorder && git checkout v0.3.1
# 送信系APIの呼び出しを数える
grep -rnE "fetch\(|axios|XMLHttpRequest|https?\.request\(|net\.connect\(|new WebSocket" \
--include="*.ts" --include="*.tsx" electron/ common/ src/
# 実行時依存を一覧する(分析SDKの混入確認)
node -e 'console.log(Object.keys(require("./package.json").dependencies).join("\n"))'
grepのヒットは0件だった。net.Socket / dgram / tls.connect / http2 をツリー全体で探しても0件。ランタイムに存在する http(s) のURLリテラルも electron/collectors/windows-url-provider.ts の1つだけで、これはブラウザのアドレスバーから読んだ文字列を組み立てているだけである(他のURLはすべて scripts/compliance.mjs というビルド時のライセンス/ソース取得スクリプトに属し、アプリの実行には関与しない)。
テレメトリも同様に見当たらない。telemetry / analytics / Application Insights / Mixpanel / Amplitude / PostHog / Segment / Sentry / Datadog を横断検索して出てくるのは、electron/logger.ts の1行目のコメント1件のみだった。
Minimal tagged logger. Replaced/extended when telemetry lands. (出典:
electron/logger.ts)
計測基盤は現時点では入っていないが、入る前提で置かれているという状態だ。実行時依存も @github/copilot-sdk・@huggingface/transformers・archiver・koffi・react・react-dom・sharp・zod の8個のみで、分析SDKは含まれない。
grepで0件=送信が無い、ではない
ここが本節でもっとも誤解されやすい点だ。アプリ本体にHTTPクライアントが無いのは、通信をしないからではなく通信を外部プロセスに委譲しているからである。electron/copilot-cli-path.ts は RuntimeConnection.forStdio({ path: cliPath }) で同梱のCopilot CLIバイナリを子プロセスとして起動し、stdio経由で会話する。手元で npm ci 後に実体を確認したところ、node_modules/@github/copilot-darwin-arm64/copilot は 152MBのMach-O 64-bit実行ファイル(arm64)だった。GitHubへの実際の送信はこのコンパイル済みバイナリの内側で起きるため、アプリのソースをいくら読んでも中身は分からない。本記事の方法で確認できるのは「アプリ本体が独自に外へ出ていない」ことまでである。
整理すると、v0.3.1が外部と通信しうる経路は次の3つに分かれる。
| 経路 | 何が出るか | いつ | 本記事での確認度 |
|---|---|---|---|
| 同梱Copilot CLI(152MB・stdio起動) | イベント時系列・画面フレーム・ナレーション | Analyzeを押したとき | バイナリのため内容は確認不能 |
@huggingface/transformers |
モデルの取得のみ(録画データは出ない) | 初回のナレーション文字起こし | 既定ホストは実測で https://huggingface.co/、テンプレートは {model}/resolve/{revision}/ |
install.sh + npm |
取得のみ(録画データは出ない) | インストール時 | Node 24を nodejs.org/dist/latest-v24.x から、依存をnpmレジストリから |
Whisperモデル(Xenova/whisper-small・README表記で約252MB)の取得先は、インストール済みの @huggingface/transformers の env.js を読んで確認した。文字起こし自体は端末内で走るが、モデルの初回取得はHugging Faceへの外向き通信になる。企業の送信先許可リストを運用しているなら、huggingface.co は登録対象になる。
Analyzeで実際に外へ渡るデータ——画面フレームはbase64でCopilotに渡る
describerはセッションの中身を丸ごと投げつけるのではなく、Copilotセッションにツールを渡してモデルに引かせる作りになっている。electron/describer/tools.ts が公開しているのは get_timeline / get_events / list_frames / get_frames / get_narration / submit_analysis の6つだ。
注目すべきは get_frames の実装である。返り値は次のように作られていた。
・data: readFileSync(file).toString("base64") ——抽出済みの画面フレームが、実データのbase64としてモデルに渡る
・指示文(electron/describer/instructions.ts)は「イベントが沈黙している、または曖昧な箇所だけフレームを見ろ」と書いている
・ただしこれは方針であって制限ではない。ツール自体はセッション全区間のフレームにアクセスできる
つまり「モデルが必要と判断した画面の絵は、実際の画像として外へ出る」。何枚出るかはモデルの判断に依存し、コード側の上限で縛られてはいない。録画中に映ってはいけないものが映っていた場合、それがAnalyzeで渡らない保証はない。
社内の機密データを扱うときの注意点——情報漏洩につながる3つの導線
社内の機密データが写り込んだ録画をどう扱うかは、skill-recorderを業務導入する際の最大の論点になる。顧客情報の載った画面、認証トークン、社内URL——これらが録画に入ったとき、ツール側に何の緩和があり、何が無いのか。ここも実測で切り分けた。結論を先に言えば、機密情報のマスキングは実装されておらず、情報漏洩につながりうる導線は「Analyzeでクラウドへ送られる」「端末に残るファイル」「生成物と不具合報告」の3方向にある。
機密情報のマスキングは実装されていない——120文字上限は「フィルタ」ではない
機密の写り込みに対して、ツール側にどんな緩和があるのかを探した。結論から言うと、秘匿情報を検出・除去する仕組みは無い。
redact / mask / sanitize / scrub / secret / password / api key / credential をランタイム全体で検索しても、秘匿情報処理に該当するヒットは0件である(引っかかるのは値トークンの仕組みとブラウザ名の判定文字列だけだった)。
唯一それらしい処理が、クリップボード収集の長さ上限だ。electron/collectors/clipboard.ts は700msごとにクリップボードをポーリングし、形式・長さ・sha1の先頭16桁・120文字までのプレビューを記録する。ただしこの関数には、作者自身によるこんなコメントが付いている。
One-line, length-capped preview with newlines collapsed (privacy milestone tightens this). (出典:
electron/collectors/clipboard.ts)
「プライバシー対応のマイルストーンでここを厳しくする」——つまり現状は緩いと作者が認識している。
では120文字という上限が実務でどれだけ効くのか。同じ preview() の処理を移植し、ダミーの(実在しない)資格情報を食わせて測った。
PREVIEW_MAX = 120 文字
AWS access key ID 風: 長さ 20字 -> 切り詰め=なし
GitHub PAT 風 : 長さ 40字 -> 切り詰め=なし
OpenAI APIキー 風 : 長さ 51字 -> 切り詰め=なし
DB接続文字列 風 : 長さ 68字 -> 切り詰め=なし postgres://svc_user:[email protected]:5432/customers
社内URL+クエリ 風 : 長さ 69字 -> 切り詰め=なし https://intra.example.co.jp/hr/salary?employee=12345&token=...
顧客名簿1行 風 : 長さ 46字 -> 切り詰め=なし
6種すべてが120文字未満で、1文字も切り詰められなかった。資格情報や1行分の個人情報は、そもそも120文字に届かない。この上限は長文を切り詰めるためのものであって、秘匿情報のフィルタとして設計されてはいない。パスワードマネージャからコピーしたトークンを録画中に貼れば、その値はプレビューとしてほぼ丸ごとイベントに残る。
記録項目を絞るUIが無いことは前述の通りで(common/config.ts:「there is no user-facing capture level」)、「このウィンドウだけ除外」「この区間はクリップボードを録らない」という設定も存在しない。録画を開始するか、しないかの二択である。
公平のために、設計上の配慮も2点挙げておく。セッション開始時点でクリップボードに入っていた内容はベースラインとして使うだけで送出されない(録画中にコピーしたものだけを拾う)。そして録画開始の警告は前述の通りプロセスごとにリセットされ、RecordingPrivacySession はメモリ上のみで永続化されない——「一度同意したら二度と出ない」を意図的に避けている。
録画データの保存先と権限——守っているのはアプリではなくOS
生成物と録画データの置き場所は、ソース上で次のように分かれていた。
| 対象 | 保存先 | 定義箇所 |
|---|---|---|
| 録画セッション(イベント・フレーム・映像・音声) | userData/sessions/ |
electron/recorder/session-store.ts |
| Whisperモデル | userData/models/ |
electron/narration/whisper.ts |
| 生成されたスキル | ~/.copilot/skills/ |
electron/skillbuilder/builder.ts |
| 生成されたAutomation | ~/.copilot/automations/ |
electron/automationbuilder/builder.ts |
macOSの userData は ~/Library/Application Support/ 配下である。ここでディレクトリ権限を確認したところ、アプリ側は mkdir に mode を一切指定しておらず(すべて { recursive: true } のみ)、作られる権限はumask任せになる。手元の既定環境(umask 022)で実測すると ディレクトリ755・ファイル644、つまりオーナー以外にも読める許可ビットが立つ。
ただし、これを「他ユーザーから丸見え」と書くのは誤りだ。同じ手元で親側を確認すると次の通りだった。
drwx------ ~/Library
drwx------ ~/Library/Application Support
親が700で閉じているため、既定のmacOS単独ユーザー環境では実際には保護されている。重要なのは、守っているのはアプリではなくOSのディレクトリ配置だという点である。したがって緩い許可ビットが効いてくるのは、データがこの保護チェーンの外に出た瞬間——バックアップ、クラウド同期フォルダ、共有ホームディレクトリ、そして次に述べるzipである。
情報漏洩を招きやすい導線——デバッグzipは録画を丸ごと固める
企業導入で最も気をつけたいのは、実はここだった。アプリには「セッションの詳細をダウンロード」する機能があり、その実装が electron/debug-bundle.ts の writeDebugBundle() である。ソースのコメントが挙動をそのまま説明している。
the entire session directory (events, frames, screen video, voice audio, analysis, …) is included verbatim under
session/… which means it contains private capture data; callers must warn before invoking this. (出典:electron/debug-bundle.ts)
セッションディレクトリを丸ごと、そのままzipに入れる。イベント列だけでなく、画面録画の映像・音声・抽出フレームまで入る。既定の保存先は ~/Downloads/skill-recorder-debug-<セッションID>.zip で、生成後は shell.showItemInFolder でユーザーに手渡される。electron/ipc.ts のコメントには、その意図が hand the file to the user to attach と書かれていた——添付するため、つまり不具合報告に付ける動線である。
不具合報告のために完全性を優先する設計自体は理解できる(コメントも「completeness beats size」と明示している)。だが運用面で見れば、画面録画と音声が丸ごと入ったzipを、公開issueに添付する動線が用意されているということだ。社内画面を録ったセッションでこれを実行し、そのままアップロードすれば事故になる。
自分の環境に残っているものは、次のコマンドで棚卸しできる。
# 録画セッションの保存先(アプリ名は環境により Skill Recorder / skill-recorder)
ls -ld ~/Library/Application\ Support/*[Ss]kill*[Rr]ecorder*/
du -sh ~/Library/Application\ Support/*[Ss]kill*[Rr]ecorder*/sessions/ 2>/dev/null
# 作りっぱなしのデバッグzip(録画・音声が丸ごと入っている)
ls -lh ~/Downloads/skill-recorder-debug-*.zip 2>/dev/null
# 生成されたスキル/Automationに社内URLや資格情報が残っていないか
ls -la ~/.copilot/skills/ ~/.copilot/automations/ 2>/dev/null
grep -rniE "https?://|password|passwd|token|api[_-]?key|secret|bearer" ~/.copilot/skills/ 2>/dev/null
生成物への機密混入と、企業導入時のセキュリティチェックリスト
成果物である SKILL.md 側にも、機密が残る経路がある。前述の通り値トークンは書き出し時に実際のリテラルへ置換される——本記事で描画した例でも、プラン段階では名前付きトークンだったものが最終的に https://contoso.example/expenses という実URLになった。録画中に触れた社内ポータルのURL・ファイルパス・リポジトリ名がプランの固定値に拾われていれば、それはSKILL.mdに平文で残る。
さらにエクスポート先は任意のフォルダを選べる(electron/ipc.ts の openDirectory / createDirectory、既定は ~/Downloads)。つまり作業中のリポジトリ配下を指定できる。生成物をそのままコミットしてしまう事故は、この一手で起きうる。
以上を踏まえた導入時のチェックを、実測で裏が取れている事実と対応させて整理する。
| 観点 | 実測で分かっていること(v0.3.1) | 運用でやること |
|---|---|---|
| 外部送信 | アプリ本体にHTTPクライアント0件・分析SDK0件。ただし送信は同梱152MBバイナリに委譲され内容は確認不能 | 「ローカル完結」と説明しない。Analyze時にGitHubへ渡る前提で扱う |
| 送信先の許可リスト | Copilot CLI(GitHub)と huggingface.co(モデル取得)が対象 |
プロキシ/FW許可リストに登録。モデルは初回のみ約252MB |
| 記録範囲 | 記録項目を選ぶUIは設計上存在しない | 録画専用の環境・アカウント・ブラウザプロファイルを用意し、業務画面と分離する |
| 秘匿情報のマスキング | 実装なし。クリップボードの120文字上限は資格情報を1文字も切り詰めない | 録画前にパスワードマネージャ・シークレット表示・機密タブを閉じる。録画中はコピー操作を避ける |
| 保存先の権限 | dirs 755 / files 644(mode指定なし・umask依存)。macOSでは親が700で保護 | バックアップ・同期フォルダ・共有ホームに載せない。載る場合は権限を明示的に絞る |
| デバッグzip | セッションを丸ごと(映像・音声込み)~/Downloads に固める |
issue添付の前に必ず中身を展開して確認。社内画面のセッションでは使わない |
| 生成物への混入 | 固定値は書き出し時に実リテラルへ置換され、任意フォルダにエクスポート可能 | 共有・コミット前にSKILL.mdを目視レビュー。リポジトリ配下へ出す運用なら .gitignore を先に整備 |
確認できたこと/確認できないことの線引き
確認できた:アプリ本体(electron/ common/ src/)に送信APIの呼び出しが0件であること、分析SDKが依存に無いこと、マスキング処理が存在しないこと、クリップボードの120文字上限が資格情報に対して機能しないこと、保存先パスと既定権限、デバッグzipがセッションを丸ごと含むこと。いずれもv0.3.1のソース実読と手元での実行による。
確認できない:同梱Copilot CLIバイナリ(152MB・コンパイル済み)が実際に何をどこへ送っているか。本記事はパケットキャプチャを行っておらず、READMEの記述とアプリ側のコードから推定できる範囲を超えない。ここを厳密に確定させたい組織は、自分たちのネットワーク側で観測するのが筋である。
Skill Recorderのインストールと同梱の評価ハーネス
配布形態も一般的なアプリと違うので触れておきたい。Skill Recorderはビルド済みバイナリを配らない。READMEいわく「published as a source release」で、1コマンドが①固定されたNode.jsランタイムをダウンロードし、②リリースのコミットを自分のマシンでビルドし、③再起動できるアプリとして登録する。グローバルには何もインストールされない。
# 実際のコマンドはリリースページに掲載された40文字のコミットハッシュを入れる
commit="<40-character-release-commit>"
curl -fsSL "https://raw.githubusercontent.com/microsoft/skill-recorder/$commit/install.sh" \
| SKILL_RECORDER_COMMIT="$commit" bash
READMEはこの方式の意図を「The commit pins both the downloaded script and the source it builds」と説明する。取得するスクリプトとビルドされるソースの両方が同じコミットに固定されるという設計だ。install.sh を読むと、Node 24系を https://nodejs.org/dist/latest-v24.x から取得し、取得後に [ "${node_version%%.*}" = "24" ] でメジャーバージョンを検証して合わなければ停止する、という実装になっていた。
実行前にスクリプトを読みたい場合の手順、更新、アンインストールは INSTALL.md に分けて書かれている。curlをそのままbashへパイプする形が気になるなら、まずそちらを読むのが筋だろう。ターミナルを閉じてもアプリを動かし続けたい場合は SKILL_RECORDER_DETACHED=1 を付ける、といった環境変数もREADMEに列挙されている。インストール先はmacOSなら ~/Applications で、Spotlight・Launchpad・Dockから再起動できる。
なお動作要件として、READMEは「You’ll need a GitHub account with Copilot access」と明記している。Copilot CLI自体はアプリに同梱される(electron/copilot-cli-path.ts は @github/copilot-<platform>-<arch> というパッケージからバイナリを解決していた)。macOSが主対象で、Windows 11(x64/ARM64)もサポート対象、Ubuntu向けのインストール手順も用意されている。
評価用のハーネスが同梱されている(describer / builder)
もう一点、若いリポジトリとしては珍しい部分がある。Copilotの「describer(記録から意図と手順を起こす部分)」と「builder」に対して、fixtureベースの評価スイートが同梱されている。
npm run eval # describerを合成録画に対して採点
npm run eval:builder # スキル/automationの一般化を採点
evals/README.md は、あえて実キャプチャを使わない理由を「Live capture … is flaky and slow, and it’s not the part we’re trying to measure」と説明している。イベント列を固定することでdescriberを切り出し、1シナリオ15〜25秒で再現可能にし、失敗したらキャプチャの不安定さではなくモデル/指示文を指していると分かるようにする、という設計だ。ただしこの2コマンドはCopilot CLIへのサインインが必要なため、本記事では実行していない(サインイン不要な npm test のみ実行した)。
類似ツールとの比較——生成側・管理側・完成品集のどこに座るか
「スキル」を扱うOSSは増えたが、担当している工程はそれぞれ違う。Skill Recorderの位置は入力の作り方が決定的に異なる。
| ツール | 主な役割 | スキルの入力元 | エクスポート先 |
|---|---|---|---|
| microsoft/skill-recorder | 録画→スキル生成 | 画面操作・URL・クリップボード・音声ナレーション | Scout / Cowork(Copilot Studioは無効) |
| Agent Skill Creator | スキルの自動生成と配布 | テキストの指示 | 複数プラットフォームへ配布 |
| Agent Skill Harbor | スキル資産の一元管理 | 既存のスキル | Gitで管理・配布 |
| SkillHub | レジストリ | 既存のスキル | npm風にインストール |
| mattpocock/skills | 完成品のスキル集 | 人間が書いたもの | そのまま利用 |
| Microsoft Waza | スキルの品質評価 | 既存のスキル | 評価結果 |
表の通り、入力元に「画面操作の録画」を置いているのはSkill Recorderだけである。テキストで指示して生成させる(Agent Skill Creator)、既にあるスキルを管理・配布する(Skill Harbor / SkillHub)、人間が書いた完成品を使う(mattpocock/skills)、品質を測る(Waza)——これらはいずれも「スキルの中身は言語で表現できる」ことを前提にしている。Skill Recorderが賭けているのは、言語化できていない作業ほど自動化されずに残っているという反対側の仮説だ。
同じMicrosoftから出ているWazaが「できたスキルを測る」側、Skill Recorderが「スキルを作る」側と、工程として綺麗に分かれている点も押さえておきたい。作る側と測る側が別リポジトリとして並行して出ていることからも、Microsoftがスキルを「一度書いて終わり」ではなく、生成・評価・配布まで含めた工程として扱おうとしている様子がうかがえる。
現時点の評価——向いている場面と、待ったほうがいい場面
公開4日で★398という数字は関心の高さを示すが、採用判断は分けて考えたい。
向いている場面
・Microsoft 365 / Scout環境で働いている。エクスポート先がそこに限られている以上、この前提を満たすかどうかが最大の分岐点になる
・説明しづらいGUI作業を自動化したい。Excelとブラウザとチャットを行き来する類の、手順書に書き起こしづらい作業ほど録画の利点が出る
・手順の一般化をレビューしたい。プラン提示→自然言語で修正→確定、という2段ゲートは、生成物をそのまま信じない運用に向く
待ったほうがいい場面
・Claude CodeやCursorでスキルを使いたい。現時点でエクスポート先に無い。この用途なら上の表にある生成側のツールを見るほうが早い
・Copilotのサブスクリプションが無い。Analyzeが動かないため、録画しかできない
・機密性の高い画面を扱う。記録項目を絞るUIが無く、Analyzeで画面画像がbase64のままクラウドへ渡る。前述の通り秘匿情報のマスキングは実装されていない(クリップボードの120文字上限は資格情報を1文字も切り詰めない)。扱う情報を選べる作業に限るのが前提になる
・安定性を求める。v0.3.1・コミット103・公開からわずか4日という段階で、Open Issuesは26件ある。仕様が動く前提で触るべきフェーズだろう
総じて、アイデアとしては筋が良く、適用範囲は現時点でかなり狭いというのが実装を読んだ上での評価だ。「録画してスキルにする」という発想自体はエージェント全般に効くもので、エクスポート先が広がれば評価は変わる。copilot-studio が enabled: false で置かれていることからも、対象を増やす前提の設計にはなっている。
参照ソース
・microsoft/skill-recorder — GitHub(README・INSTALL.md・common/skill.ts・common/config.ts・common/automation.ts・electron/skillbuilder/instructions.ts・evals/README.md を v0.3.1 時点で参照。star・リリース・言語構成はGitHub APIで取得し、2026-08-05に再取得)
・セキュリティ節で追加参照した v0.3.1 のソース:electron/logger.ts・electron/copilot-cli-path.ts・electron/collectors/clipboard.ts・electron/describer/tools.ts・electron/describer/instructions.ts・electron/debug-bundle.ts・electron/ipc.ts・electron/recorder/session-store.ts・electron/narration/whisper.ts・electron/skillbuilder/builder.ts・electron/automationbuilder/builder.ts・package.json(送信APIの検索・依存一覧・保存先・権限は手元のmacOSで実行して確認)
・@huggingface/transformers — env.js(remoteHost の既定値 https://huggingface.co/ と remotePathTemplate を、インストール済みパッケージ v4 系で確認)
・microsoft/skill-recorder Releases(v0.1.0〜v0.3.1の公開日時)
・microsoft/skill-recorder LICENSE(MIT)