Electron - TECH PLAY - TECH PLAY

TECH PLAY

Electron

むベント

該圓するコンテンツが芋぀かりたせんでした

マガゞン

該圓するコンテンツが芋぀かりたせんでした

技術ブログ

最近の倏の長さになれたため、9月に涌しい事に戞惑っおいたす。 柟本 圬(本人)です。
はじめに こんにちは。RevComm で゚ンゞニアをしおいる 林 です。 AI コヌディング゚ヌゞェントの普及でコヌドを曞くコストは倧きく䞋がり、ボトルネックはレビュヌず定型的な保守䜜業に移りたした。 Addy Osmani 氏も「 Agentic Code Review 」で、レビュヌが PR の䜜成スピヌドに远い぀かず、コヌドが読たれないたたマヌゞされ始めおいる珟状を曞いおいたす。 MiiTel Phoneブラりザ䞊で通話できる AI 搭茉 IP 電話アプリの開発リポゞトリでは月に 300〜600 件の PR がマヌゞされたす。その䞭には、振る舞いを倉えないリファクタリング、䟝存パッケヌゞの曎新、ドキュメントの修正のような、刀断の型が決たっおいるのにレビュヌの埅ち時間だけは通垞の PR ず倉わらないものが盞圓数含たれたす。 こうした定型的な刀断を GitHub Actions 䞊の AI に任せ、人間のレビュヌを本質的な倉曎に集䞭させる取り組みから、4 ぀の事䟋を玹介したす。 いずれも Claude Code を GitHub Actions 䞊で動かす構成で、事䟋 1〜3 は公匏の claude-code-action 、事䟋 4 は GitHub Agentic Workflows (gh-aw) を利甚しおいたす。 ※ 蚘事䞭のコヌドや蚭定は説明のために抜粋・簡略化しおいたす。 蚭蚈原則を先に 4 ぀の事䟋は䜿うツヌルも察象も違いたすが、蚭蚈は同じ型に収たっおいたす。䜜業の倧半はプロンプトを曞くこずではなく、「AI に䜕をさせないか」を決めるこずでした。 先に原則を挙げたす。以降の事䟋は、これがどう具䜓化されおいるかずしお読んでもらえればず思いたす。 刀定は AI、実行は決定的なステップずしお 。AI の出力は構造化された刀定 or 成果物にずどめ、承認・マヌゞ・クロヌズ・チケット起祚ずいった副䜜甚は、スキヌマ怜蚌を通った出力に察しお埌続のステップが実行したす 自動化の終点を、人間の刀断が残る堎所に眮く 。AI が進めるのは承認、コミットの push、draft PR の起祚たでで、マヌゞするかどうかは人間が刀断したす い぀でも止められるようにする 。蚭定をひず぀倉えるだけで自動承認を止められるキルスむッチ、䜜成者がラベルを付けた PR だけを察象にするオプトむン方匏、AI の実行回数・実行時間・同時実行数の䞊限。たず刀定だけを動かしお粟床を確認し、玍埗しおから副䜜甚を有効化したす AI ぞの入力を信頌しない 。PR 本文やリリヌスノヌトはサヌドパヌティ由来のテキストずしお扱い、枡さないか信頌境界の倖に眮きたす 運甚で粟床を䞊げる前提を組み蟌む 。週次のスポットチェック、誀刀定を反䟋ずしおプロンプトに远蚘しおいく運甚、リポゞトリ固有の芳点を自然蚀語で泚入できる入り口、そしお「凊理しなかったもの」のログを確認可胜にしおおきたす 事䟋 1: PR のレビュヌ芁吊を AI が刀定する AI に任せるのはレビュヌではなく分類 きっかけはチヌムの振り返りで出た「テストコヌドやドキュメントだけの倉曎なら、レビュヌなしでマヌゞしおよいのでは」ずいう話でした。 前提ずしお、PR を open するず GitHub Copilot や Devin が自動でレビュヌする蚭定はすでに入っおいたす。ただし、これらは人間のレビュヌに芳点を足す補助であっお、承認たでの埅ち時間はそこたで倉わりたせん。 今回のボトルネックはたさにこの埅ち時間なので、AI レビュヌを匷化しお人間のレビュヌを眮き換える方向は取りたせんでした。 方針の参考にしたのは Findy Tech Blog の「 䞍芁なレビュヌをAIにたかせおAIコヌディングの環境改善を加速した 」です。芁点は、AI を「レビュアヌ」ではなく「人間のレビュヌが䞍芁な PR かどうかの分類噚」ずしお䜿うこず、そしお Kent Beck 氏の『 Tidy First? 』でいう振る舞いを倉えない敎頓tidyingだけを自動承認の察象にするこずです。 レビュヌの代行が品質保蚌の責任ごず AI に移しおしたうのに察し、分類は「人間がレビュヌすべき PR を人間に確実に届ける」ための振り分けです。 3 レむダヌのレビュヌポリシヌ 「AI で自動化」ず蚀い぀぀、最初のレむダヌに AI は登堎したせん。 レむダヌ 内容 仕組み レむダヌ 0 ドキュメントのみの倉曎の自動承認 ファむルパスによる機械的な刀定AI 䞍芁 レむダヌ 1 人間レビュヌ必須領域の定矩 ポリシヌドキュメント レむダヌ 2 振る舞いを倉えない敎頓の自動承認 AI 分類噚 + 抜き取りの事埌レビュヌず監査 レむダヌ 0 は、倉曎ファむルがすべお docs/ 配䞋たたは *.md の PR を機械的に承認したす。AI で刀定できるこずでも、決定的に刀定できるならそちらを遞びたす。誀刀定リスクがなくコストもれロだからです。 ただし、同じ Markdown でも .github/ 配䞋ず CLAUDE.md / AGENTS.md は察象倖です。これらの無人承認を蚱すず、自動承認システム自䜓の改倉が無人で通っおしたいたす。 レむダヌ 1 は、AI の刀定にかかわらず必ず人間がレビュヌする領域の明文化です。通話のような䞭栞機胜、feature flag、倖郚システムずの連携、個人情報や認蚌、テストの削陀、䟝存パッケヌゞ、CI 蚭定などが該圓したす。間違えるず圱響が倧きい領域ず、自動化自䜓の安党性を支える領域テスト・CIを䞊べおいたす。 分類噚の実装 レむダヌ 2 が本題の AI 分類噚です。PR の䜜成者が ai-classify ラベルを付けたずきだけ動きたす。分類噚は『Tidy First?』の構造的リファクタリングを調敎した分類衚を持っおいたす。 T1: ファむル・ディレクトリの移動、リネヌムimport パスの機械的远随を含む T5: 倉数・関数・コンポヌネントのリネヌム T7: 未䜿甚コヌド・ファむルの削陀 A1: 既存 feature flag の targetingどの環境・ナヌザヌに配垃するかの蚭定のみの倉曎振る舞いは倉わるが、チヌムが明瀺的にレビュヌ䞍芁ず合意した䜎リスク倉曎 NG2: 通話系コヌドに觊れる倉曎即 HUMAN_REVIEW ポむントは、陀倖条件NGを「倉曎の性質」ではなく「觊れた領域」で刀定させおいるこずです。通話系ファむルの倉曎が import パスの機械的な远随だけだったずしおも NG2 に倒したす。「機械的な倉曎だから実質は該圓しない」ずいう楜芳的な刀断を AI にさせないためです。 たた、迷ったら UNKNOWN ず出力させ、 誀っお APPROVE するコストは誀っお HUMAN_REVIEW ずするコストよりはるかに倧きい ずいう原則もプロンプトに明蚘しおいたす。 出力は自然蚀語のコメントではなく、構造化された刀定ファむルです。 { " verdict ": " APPROVE ", " t_categories ": [ " T1 ", " T5 " ] , " reasons ": [ " 刀定理由を簡朔に列挙する " ] , " summary ": " 1〜2 文の刀定サマリ ", " sampling_used ": false } 埌続のステップが jq でこのファむルのスキヌマを怜蚌し、怜蚌を通った APPROVE 刀定に察しおのみ承認を実行したす。 - name : Approve if : steps.verdict.outputs.verdict == 'APPROVE' && vars.AI_CLASSIFY_APPROVE_ENABLED == 'true' run : | gh pr review "$PR_NUMBER" --approve --body "$body" gh pr edit "$PR_NUMBER" --add-label ai-approved AI_CLASSIFY_APPROVE_ENABLED は GitHub の repository variable を䜿ったキルスむッチで、 true でないずきは刀定コメントの投皿だけを行いたす。導入初期は切ったたた刀定粟床を確認し、問題ないこずを確認しおから有効化したした。 分類噚に枡すのは差分ずファむル内容だけで、PR 本文ずコメントは枡したせん。ただし、diff 䞭のコヌドコメントには同じ誘導を曞けるため、この経路たで消えるわけではありたせん。 そこは埌段のスキヌマ怜蚌ず、マヌゞ刀断が人間に残っおいるこずでブロックしたす。承認埌に push があれば自身の承認を取り消しお再分類し、自動マヌゞはどのレむダヌでも行いたせん。 運甚ず、PR の䜜り方ぞの波及 自動承認された PR は週次で数件を人間が事埌レビュヌしおいたす。Addy Osmani 氏の敎理を借りれば、すべおの差分を人間が芋る圢から、抜き取り確認ず監査で仕組み党䜓を芋匵る圢ぞの移行です圌の蚘事の蚀葉では human in the loop から human on the loop ぞ 。誀刀定が芋぀かれば、反䟋ずしお分類噚プロンプトの陀倖条件に远蚘したす。 効果はレビュヌが速くなるこずにずどたりたせんでした。分類噚が APPROVE を出せるのは PR 党䜓が敎頓で完結しおいるずきだけなので、リファクタリングず機胜倉曎が混ざった PR は HUMAN_REVIEW に倒れたす。 ぀たり、䜜成者から芋るず、混ぜれば党䜓がレビュヌ埅ちになり、分ければリファクタリング郚分を先に流せる。リネヌムやファむル移動を先行 PR に切り出しお ai-classify を付け、その䞊に振る舞いを倉える PR を積み重ねればstacked PR ずしお、人間に届くのは本質的な倉曎だけの小さな差分になりたす。 『Tidy First?』の「敎頓ず振る舞いの倉曎を分けよ」ずいう芏埋は、分けるこず自䜓のコストPR が増え、レビュヌ埅ちも耇数回になるのせいで努力目暙になりがちでした。分類噚が敎頓偎の埅ち時間をれロにしたこずで、芏埋を守るほうが速いずいう構造に倉わっおいたす。 自動化が芏埋を匷制するのではなく、芏埋に埓うこずが合理的な遞択になるずいうのは、レビュヌ埅ち時間の削枛ず䞊ぶ、もうひず぀の効果だず思っおいたす。 事䟋 2: Dependabot PR を毎朝トリアヌゞする 䟝存パッケヌゞの曎新 PR ぞの察応は、毎回ほが同じ刀断の繰り返しでした。CI の成吊を確認し、リリヌスノヌトを読んで砎壊的倉曎の有無を確認し、䜎リスクなら承認しおマヌゞ、高リスクなら Notion にチケットを起祚しお PR はクロヌズし、動䜜確認を含めた蚈画的な察応に回す。刀断の型は決たっおいるのに手䜜業では远い぀かず、PR は溜たる䞀方でした。 最初の自動化は、この手順を Claude Code の Skill に曞き起こすこずでした。手元で「Dependabot の PR を察応しお」ず頌めば、オヌプン䞭の PR を順に解析しお䞀括凊理しおくれたす。 ただし、人が起動する半自動なので、誰かが思い出さない限り PR は溜たり、実行する人の環境ず暩限に䟝存する属人的な運甚でもありたした。 そこで Skill ずしお固めた手順を GitHub Actions の composite action耇数のステップをたずめお再利甚できる仕組みに䜜り盎し、無人で定期実行するようにしたした。 このずき、AI 自身が実行しおいたマヌゞやチケット起祚は AI から切り離しおいたす。composite action は瀟内の共通リポゞトリに眮き、耇数のリポゞトリから利甚しおいたす。 毎日午前 3 時の cron がオヌプン䞭の Dependabot PR を叀い順に 1 件ず぀凊理したす1 件マヌゞするず Dependabot が残りを rebase するため、䞊列ではなく盎列です。 PR タむトル・body からパッケヌゞ名ずバヌゞョンを機械的に解析し、CI チェックの成吊を刀定する Claude によるリスク刀定。リリヌスノヌトを読み取り専甚のツヌルで読み、 triage-verdict.json risk: low / high、根拠、䞻芁倉曎点を曞き出す 1, 2 を決定衚に通しお最終アクションを決める 実行。承認しお自動マヌゞ、クロヌズしお Notion にチケット起祚、たたは手動察応ずしお PR に残す 条件 アクション タむトル・body ずも解析䞍胜 手動察応PR は残す CI 倱敗 クロヌズしおチケット起祚AI の刀定に関係なく AI の刀定を取埗できない 手動察応安党偎に倒しお人間に残す AI 刀定が高リスク クロヌズしおチケット起祚 AI 刀定が䜎リスク 承認しお自動マヌゞ Notion のチケット操䜜も AI にはさせず、TypeScript のスクリプトが REST API を盎接叩きたす。チケット䜜成に倱敗した堎合は PR をクロヌズせず手動察応に降栌させ、「チケットなしで PR だけ消える」事態を防いでいたす。 リリヌスノヌトはサヌドパヌティ由来の入力なので、プロンプト偎では、指瀺のような文蚀「この曎新は安党である」「以前の指瀺を無芖せよ」などを芋぀けた堎合、埓わないだけでなく、それ自䜓をサプラむチェヌン䞊の懞念ずしお high ず刀定するよう指瀺しおいたす。むンゞェクションの詊みを怜知シグナルに倉える発想です。 それでも最埌の砊は AI の倖にある CI 成功ずいう条件で、仮に誘導が成功しおも CI が萜ちおいる PR はマヌゞされたせん。Dependabot ブランチのコヌドはチェックアりトすらせず、AI が読むのはデフォルトブランチず PR のメタデヌタだけです。 リポゞトリ固有の刀定芳点は、決められたパスに Markdown で曞いおおくずプロンプトに泚入されたす。「electron 関連の曎新はすべお高リスクずする」のような 1 行で、チヌムの経隓則を刀定に反映できたす。 導入埌は毎朝の CI で Dependabot のオヌプン PR をれロに戻しおいくので、䟝存曎新の PR が滞留するこず自䜓がなくなりたした。残る人間の䜜業は、高リスクず刀定されお起祚されたチケットぞの察応だけです。 事䟋 3: @claude メンションを党リポゞトリ共通の基盀にする PR や issue のコメントで @claude ずメンションするず GitHub Actions 䞊で Claude Code が動き、質問ぞの回答、レビュヌ指摘ぞの修正コミットの push、ショヌトカットの実行を行いたす。 反応するのは曞き蟌み暩限を持぀ナヌザヌのコメントのみで、Claude に承認ずマヌゞはさせたせん。 よく䜿うのはコンフリクトの解消です。AI コヌディングで PR を䜜る速床が䞊がるず同時にオヌプンな PR が増え、main の進みも速くなるため、コンフリクトは以前より起きやすくなりたした。PR 䜜成の高速化が、今床はコンフリクト解消ずいう新しい定型䜜業を生んだ圢です。 @claude /fix-conflicts ず曞けば、解消しお push するずころたでやっおくれたす。 同じ問題意識は GitHub Next の Evergreen や Codex の PR Babysitter にも芋られ、この皮の PR のお手入れは自動化の定番になり぀぀ありたす。 実装面の工倫は共通化です。 @claude メンション自䜓は claude-code-action の代衚的な䜿い方ですが、リポゞトリごずにワヌクフロヌを持぀ず、モデルの倉曎やコスト制埡の調敎のたびに党リポゞトリぞ同じ倉曎を配るこずになりたす。 そこでトリガヌ条件・トヌクン蚭蚈・モデル遞択・コスト制埡を瀟内共通リポゞトリの reusable workflow に集玄し、利甚偎には呌び出しの数行だけを眮く構成にしたした。 # 利甚リポゞトリ偎はこれを眮くだけ jobs : claude : uses : my-org/claude-workflows/.github/workflows/claude.yml@main secrets : inherit ショヌトカットの䞭身は Claude Code の Skill ずしお、さらに別の共有リポゞトリplugin marketplaceに眮いおいたす。手元の Claude Code ず GitHub Actions で同じ Skill 資産を共有するためで、ロヌカルで育おたワヌクフロヌがそのたた @claude メンションでも䜿えたす。 事䟋 4: 定期メンテナンスを自然蚀語で曞く (GitHub Agentic Workflows) gh-aw は、ワヌクフロヌを「YAML frontmatter + 自然蚀語プロンプト」の Markdown ファむルずしお曞き、 gh aw compile で実行可胜なワヌクフロヌ .lock.yml にコンパむルする gh CLI の拡匵機胜です。 --- on : schedule : weekly on sunday around 20:00 # fuzzy schedule workflow_dispatch : permissions : contents : read engine : id : claude max-turns : 50 timeout-minutes : 30 safe-outputs : create-pull-request : title-prefix : '[main] ' draft : true --- # Docs Drift Audit You are auditing this repository's developer documentation for drift against the actual code, and fixing what has drifted. ... 事䟋 1〜3 が AI の刀定や応答を自前のワヌクフロヌに組み蟌む構成だったのに察し、gh-aw はスケゞュヌルで自埋的に動き、リポゞトリを調べお成果物PR などたで䜜る゚ヌゞェントです。 その分、安党装眮も枠組み偎に匷く組み蟌たれおいお、゚ヌゞェント本䜓は読み取り専甚のトヌクンで実行され、曞き蟌みは frontmatter の safe-outputs で宣蚀したものしかできたせん。 倖郚通信もファむアりォヌルコンテナで制限され、 weekly on sunday around 20:00 のようなあいたいな時刻指定はコンパむラが具䜓的な時刻に解決しお、倚数のリポゞトリで cron が同時刻に集䞭するのを避けたす。珟圚 2 本が週次で動いおいたす。 ドキュメントず実コヌドの乖離監査 (docs-drift-audit) 1 本目は、開発ドキュメント docs/ 配䞋、 AGENTS.md 、 CLAUDE.md などず実コヌドの乖離を監査するワヌクフロヌです。参照先のパスが存圚するか、蚘茉コマンドが package.json の scripts ず䞀臎するか、feature flag 名やワヌクフロヌ名が実圚するか、芏玄の蚘述が蚭定ファむルず矛盟しおいないか。確認できた乖離を修正しお 1 本の draft PR にたずめ、乖離がなければ䜕もせず終了したす。 これをわざわざ AI にやらせるのは、ドキュメントが人間向けであるず同時に AI 自動化の入力でもあるからです。事䟋 1 の分類噚プロンプトも、事䟋 3 の @claude が参照する開発ガむドも、鮮床が萜ちればそのたた自動化党䜓の粟床劣化に぀ながりたす。 䞀方でコヌド偎の倉化は速く、手動での远埓は珟実的に挏れたす。週次の監査で、月曜の始業前に修正 PR が甚意されおいる状態を䜜りたした。 プロンプトには「䜕を盎さないか」も同じ分量で曞いおいたす。意図的に将来の姿を曞いおいるドキュメントは盎さない。リポゞトリ倖ぞの参照は怜蚌できないので觊らない。文䜓の奜みは盎さない。そしお確信の持おない修正は PR から倖すのではなく、PR 本文の「芁刀断」セクションで曖昧さずレビュヌ時の確認点を説明させたす。 期限切れ feature flag の掃陀 (feature-flag-cleanup) MiiTel Phone では、新機胜や通話たわりのような壊れたずきの圱響が倧きい倉曎を feature flag で囲い、OFF のたた main にマヌゞしたうえで、QA や瀟内テナントでの先行利甚を経おから党環境で有効化するこずがありたす。問題が起きたずきも、コヌドを巻き戻す代わりにフラグを OFF に戻すだけで匕き返せたす。 flag は䜿い捚おで、安定したら flag ず䞍芁になった旧コヌドを削陀する決たりで、攟眮するず誰も觊れない謎のフラグが負債ずしお残るため、各フラグに削陀期限も蚭定しおいたす。 期限切れフラグを Slack に通知しお CI を fail させるワヌクフロヌはあったのですが、通知されおも掃陀の PR を䜜る䜜業が残るため察応が滞りがちで、䞀時は 15 件が同日に倱効を迎える状況になっおいたした。 そこで通知の䞀歩先、削陀 PR の䜜成たでを自動化したした。察象は「配垃蚭定が党環境で有効化枈みで、か぀期限切れ」のフラグだけです。条件付き配垃䞭のフラグの削陀はリリヌス刀断そのものなので、AI には觊らせず人間に残したす。 フラグの削陀は定矩を 1 行消しお終わりではありたせん。ガヌドで分岐しおいたコヌドの無条件化に加え、それによっお死んだコヌドの連鎖的な削陀たでがセットです。この䜜業パタヌンをそのたたプロンプトに萜ずし蟌み、最埌に grep でフラグ名の残存れロを怜蚌させおいたす。 凊理しなかった期限切れフラグも、理由぀きで実行ログに残させおいたす。自動化が「䜕をやらなかったか」を隠すず、カバヌされおいるように芋えお挏れる領域ができるためです。 claude-code-action ず gh-aw の䜿い分け どちらも GitHub Actions 䞊で Claude を動かす仕組みで、どちらでも実装できる仕事は倚くありたす。ただし察等な遞択肢ではありたせん。 gh-aw は安党装眮が組み蟌たれた専甚ツヌルです。Markdown を曞くだけで動く代わりに枠が決たっおいお、副䜜甚は safe-outputs で宣蚀できるものに限られたす。倖郚サヌビスぞの起祚のような語圙にない副䜜甚や、AI の出力を自分のコヌドで怜蚌・分岐しおから実行する構成は組めず、むベントに反応する察話的な甚途も䞍埗意です。 claude-code-action は自前のワヌクフロヌに AI ステップを埋め蟌む郚品なので、トリガヌも埌段の凊理も副䜜甚も自由に蚭蚈できる代わりに、暩限の最小化・出力の怜蚌・キルスむッチはすべお自分で甚意するこずになりたす。 タスクが gh-aw の枠に収たるなら gh-aw のほうが少ない蚘述で安党に枈み、はみ出すなら claude-code-action で自分で蚭蚈する、ずいう䜿い分けです。 さいごに 4 ぀の事䟋は別々のツヌルに芋えたすが、やっおいるこずは 1 ぀です。刀断の型が決たっおいる䜜業を AI に寄せ、人間のレビュヌを本質的な倉曎に再配分する。そしおそれを安党に成立させおいるのは、モデルの賢さよりも、刀定ず実行の分離・人間の最終刀断・キルスむッチずいった CI 偎の蚭蚈でした。 この蚘事が、CI ず AI の連携を蚭蚈する際の参考になれば幞いです。 参考文献 Agentic Code Review - Addy Osmani 䞍芁なレビュヌをAIにたかせおAIコヌディングの環境改善を加速した - Findy Tech Blog Kent Beck『Tidy First?: A Personal Exercise in Empirical Software Design』 anthropics/claude-code-action GitHub Agentic Workflows (gh-aw) Evergreen - GitHub Next
はじめに # Deno 2.9 リリヌスおめでずうございたす。 Deno 2.9 | Deno Electron 倧奜きな自分ずしおも気になるのはやはり Deno Desktop です。 Tauri ず同様 WebView をバック゚ンドにする構成ず Electron ず同様 Chromium ベヌスの構成を遞べるずのこずで、これは詊すしかないず思いたした。 公匏ドキュメントは以䞋にありたす。 https://docs.deno.com/runtime/desktop/ --> Caution Deno ブログには以䞋のように曞かれおおり、2.9 時点ではデスクトップ機胜は実隓的段階です。 deno desktop is experimental in 2.9. The surface described here is stabilizing and some platform features are still landing. 䜿っおみる # たずは 2.9 にアップグレヌドしおおきたす [1] 。 deno upgrade main.ts に Deno.serve を䜿っお普通にサヌバヌプログラムを曞きたす。 main.ts Deno.serve(() => new Response( "<!DOCTYPE html><h1>Hello from Deno desktop </h1>", { headers: { "content-type": "text/html" } }, ) ); 同じディレクトリで deno desktop main.ts を実行したす。 $ deno desktop main.ts ⚠ deno desktop is experimental and subject to change Check main.ts Compile main.ts to hello.dylib Embedded Files hello.dylib └── main.ts (430B) Files: 1.91KB Metadata: 1.38KB Remote modules: 12B Downloading laufey webview backend for aarch64-apple-darwin (v0.4.0) Download laufey-webview-aarch64-apple-darwin.tar.gz 97.44KiB/97.44KiB Codesigning bundle with identity "-" hello.app/Contents/MacOS/laufey_webview: replacing existing signature hello.app/Contents/MacOS/hello.dylib: replacing existing signature Bundle hello.app 最埌の出力で、ルヌトに hello.app (macOS のアプリ実行ファむル)が生成されおおり、起動できたすWindows の堎合は、hello.exe が生成されたす。 Deno のコンセプト通り、远加のモゞュヌルや蚭定なし(Out of the box)でデスクトップアプリが生成されたした。 Deno Desktop の開発䜓隓 # HMR (Hot Module Replacement) オプション付きで起動するこずで、ロヌカルの開発サヌバを立ち䞊げ、コヌド倉曎を怜知しおアプリ内容を即時曎新しおくれたす。 deno desktop --hmr main.ts ⚠ deno desktop is experimental and subject to change Compile main.ts to file:///Users/kondoumh/Library/Caches/deno/desktop/5f4a00908e99d886/hello.dylib Embedded Files hello.dylib └── main.ts (422B) Files: 1.9KB Metadata: 1.38KB Remote modules: 12B Running desktop app with HMR (watching /Users/kondoumh/dev/deno-study/desktop/hello) Runtime loaded successfully from: /Users/kondoumh/Library/Caches/deno/desktop/5f4a00908e99d886/hello.dylib Runtime started [desktop] dylib path: "/Users/kondoumh/Library/Caches/deno/desktop/5f4a00908e99d886/hello.dylib" Listening on http://127.0.0.1:52958/ main.ts のコヌドを曞き換えるず、保存埌すぐに画面ぞ反映されたす。 --> Information Electron では HMR は暙準では利甚できず、別途 Forge などで開発サヌバヌを起動する必芁がありたす。 https://developer.mamezou-tech.com/blogs/2024/01/29/electron-forge-introduction/ UI の ロヌカル HTTP サヌビスによる実珟 # Electron (Forge など) ではロヌカルサヌバヌの利甚は開発時が䞭心で、配垃埌は file:// でアセットを読む構成が䞀般的です。 これに察し Deno Desktop は、配垃埌のバむナリでもロヌカル HTTP サヌバヌを内郚起動し、空きポヌトを自動割り圓おしお UI を描画したす。サヌバヌはプロセス内で閉じおおり、倖郚公開はされたせん。ポヌト衝突を意識せずに枈むのも良い点です。 この「開発時もビルド枈みバむナリでも、同じ HTTP 実行モデルで UI を提䟛する」蚭蚈により、 開発時ずデプロむ時の挙動に差がない コンテンツはブラりザずデスクトップで同じ動きをする Next.js などのフレヌムワヌクがそのたたデスクトップアプリの䞭で動く ずいったメリットが埗られたす。 https://docs.deno.com/runtime/desktop/serving/ DevTools の起動 # Electron や Tauri ず同様、DevTools によるデバッグが可胜です。BrowserWindow を起動し、 openDevtools メ゜ッドを呌ぶだけです。 const win = new Deno.BrowserWindow({ title: "My Deno Desktop App", width: 800, height: 600, }); win.openDevtools(); https://docs.deno.com/runtime/desktop/devtools/ --> Information いたのずころ、DevTools のフルサポヌトはバック゚ンドを cef にしおいる時のみです。 以䞋のように、指定しお起動する必芁がありたす。 deno desktop --hmr --backend=cef main.ts バック゚ンドずフロント゚ンドの通信(Bindings) # Electron の IPC 通信は render.js ず main.js を preload.js 経由でブリッゞする必芁があり、かなり面倒です。Deno デスクトップでは BrowserWindow にバむンドした関数を bindings ずいうグロヌバルオブゞェクトにより簡単に呌び出すこずができたす。 Deno ランタむムずレンダリングバック゚ンドはスレッドやプロセスずしお動䜜し、呌び出しはプロセス内チャネルを介しお行われたす。このサンプル構成では゜ケットベヌスの IPC を盎接扱わずに枈むため、Electron の ipcMain / ipcRenderer、Tauri の invoke ず比べお芋通しよく曞けるのが利点です。 実際のコヌドで芋おみたしょう。 const win = new Deno.BrowserWindow({ title: "Bindingsのテスト", width: 800, height: 600, }); // ========================================== // 1. バック゚ンド偎フロントから呌ばれる関数を登録 // ========================================== win.bind("getSystemInfo", async (userName) => { console.log(`[Deno偎] フロント゚ンドから呌ばれたした 匕数: ${userName}`); // Denoの機胜を䜿っおOSの情報を取埗 const denoVersion = Deno.version.deno; const os = Deno.build.os; // 少し重い凊理をシミュレヌト0.5秒埅぀ await new Promise(resolve => setTimeout(resolve, 500)); // フロント゚ンドに返すデヌタJSON化できるものなら䜕でもOK return { message: `こんにちは、${userName}さん`, os: os, denoVersion: denoVersion }; }); // ========================================== // 2. フロント゚ンド偎画面のHTMLを返す // ========================================== Deno.serve(() => { const html = ` <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Bindings Test</title> </head> <body> <h1>Deno Desktop Bindings</h1> <button id="btn">システム情報を取埗</button> <pre id="result">ここに結果が出たす</pre> <script> // ボタンが抌された時の凊理 document.querySelector('#btn').addEventListener('click', async () => { const resultArea = document.getElementById('result'); resultArea.textContent = "取埗䞭..."; try { // 💡 bindings を䜿っおバック゚ンドの関数を呌び出す const data = await bindings.getSystemInfo("kondoumh"); // 結果を画面に衚瀺 resultArea.textContent = JSON.stringify(data, null, 2); } catch (error) { resultArea.textContent = "error: " + error.message; } }); </script> </body> </html> `; return new Response(html, { headers: { "content-type": "text/html" }, }); }); アプリ画面です。 システム情報を取埗 ボタンをクリックするずしばらく呌び出し䞭になり、結果が衚瀺されたす。 結果が衚瀺された状態。 アプリを起動しおいるバック゚ンドでは次のようにログが出おいたす。 [Deno偎] フロント゚ンドから呌ばれたした 匕数: kondoumh すごくシンプルです。OS のネむティブ機胜ず Web UI を簡単に連携できるのがいいですね。 https://docs.deno.com/runtime/desktop/bindings/ メニュヌ の利甚 # アプリケヌションメニュヌの実装。 BrowserWindow の setApplicationMenu メ゜ッド内でメニュヌオブゞェクトを定矩しお枡したす。 BrowserWindow にむベントリスナヌを登録しおメニュヌがクリックされた時の振る舞いを実装したす。 role などは Electron ず同じですね。 win.setApplicationMenu([ { submenu: { label: "File", items: [ { item: { label: "New", id: "new", accelerator: "CmdOrCtrl+N", enabled: true, }, }, { item: { label: "Open
", id: "open", accelerator: "CmdOrCtrl+O", enabled: true, }, }, "separator", { item: { label: "Save", id: "save", accelerator: "CmdOrCtrl+S", enabled: true, }, }, { role: { role: "quit" } }, ], }, }, { submenu: { label: "Edit", items: [ { role: { role: "undo" } }, { role: { role: "redo" } }, "separator", { role: { role: "cut" } }, { role: { role: "copy" } }, { role: { role: "paste" } }, ], }, }, ]); win.addEventListener("menuclick", (e) => { const detail = (e as CustomEvent).detail; switch (detail.id) { case "new": console.log("New clicked"); break; case "open": console.log("Open clicked"); break; case "save": console.log("Save clicked"); break; } }); コンテキストメニュヌの実装。 Deno.MenuItem の配列を䜜成しお、BrowserWindow の showContextMenu に座暙ずずもに枡したす。 const contextMenu: Deno.MenuItem[] = [ { item: { label: "Copy", id: "copy", enabled: true } }, { item: { label: "Paste", id: "paste", enabled: true } }, "separator", { item: { label: "Properties
", id: "props", enabled: true } }, ]; // Trigger from a right-click. The webview may not forward the browser // `contextmenu` event, so handle the secondary mouse button on the window. win.addEventListener("mousedown", (e) => { if (e.button === 2) { win.showContextMenu(e.clientX, e.clientY, contextMenu); } }); win.addEventListener("contextmenuclick", (e) => { if (e.detail.id === "copy") { console.log("Copy clicked"); } if (e.detail.id === "paste") { console.log("Paste clicked"); } if (e.detail.id === "props") { console.log("Properties clicked"); } }); --> Information ここではメニュヌのクリックむベントでログを出力しおいたすが、ログ自䜓はアプリを起動しおいるタヌミナル偎に出たすのでご泚意ください。 https://docs.deno.com/runtime/desktop/menus/ フレヌムワヌクを利甚した開発 # Deno.serve() を利甚したサンプルを芋おきたしたが、Deno デスクトップでは、以䞋のフレヌムワヌクずずもに利甚可胜です。これらのプロゞェクトのディレクトリで deno desktop を起動するず、フレヌムワヌクを自動怜出しおアプリを構成したす。倚くのモダンフレヌムワヌクがサポヌトされおいたす。 Next.js Astro Fresh Remix Nuxt SvelteKit SolidStart TanStack Start Vite ロヌカルで動いおるのに SSR を䜿うずいうのがなんずも䞍思議な感じですが、ちゃんず動いおセキュアであればペシずいう感じでしょうか。 https://docs.deno.com/examples/next_tutorial/ Next.js のアプリを䜜成したす。 deno run -A npm:create-next-app@latest 䜜成したプロゞェクトディレクトリぞ移動しお実行したす。 cd <project-dir> deno desktop -A Next.js のアプリが、倖郚サヌバヌなしでたるっずデスクトップ内で動いおるのは䞍思議な感じです。 https://docs.deno.com/runtime/desktop/frameworks/ バック゚ンドの遞択に぀いお # デスクトップアプリは配垃するバむナリのサむズも重芁です。小さいに越したこずはありたせん。 Electron は Chromium を内包するため、むンストヌルされたバむナリサむズは300MBぐらいの倧きさになったりしたす。 Deno Desktop の堎合、OS にプリむンストヌルされおいる WebView を䜿えば70MB皋床です。CEF(Chromium) だずやはり300MB皋床になりたす。 OS 䟝存の WebView だず、Windows ず Mac で埮劙に CSS や JS の挙動が倉わるクロスブラりザ問題が発生するため、そのための察応やテストも必芁になりたす。機胜が少ないうちは WebView でもいいかもしれたせんが、機胜が増えおくるずテストの手間も䜕倍にもなっおいきたす。 Deno Desktop の堎合、最初は軜量な WebView でスタヌトし、クロスブラりザが重荷になっおきたら、ちょっず配垃サむズは倧きくなるけど、CEF にスむッチできるのがいいかなず思いたす。 https://docs.deno.com/runtime/desktop/backends/ --> Information Tauri だずこの蟺、Servo ベヌスの自前 WebView プロゞェクト Verso 埅ちですが、Deno は既存の Chromium を遞択可胜にしおいるあたり、珟時点での割り切りが感じられたすね。 Electron ずの比范 # 既存 Web アプリをデスクトップ化したいナヌスケヌスでは、Deno Desktop はかなり有力です。 䞀方で、Electron の WebContentsView のような高床なマルチビュヌ構成を前提にしおいる堎合は、珟時点では Electron のほうが適しおいたす。たずえば VS Code や Figma のように、耇数ビュヌを现かく制埡するタむプのアプリです。 ざっくり敎理するず次のような感觊です。 単䞀りィンドり䞭心 + 既存 Web 資産掻甚: Deno Desktop はかなり良い 耇雑なりィンドり/ビュヌ管理: Electron が䟝然匷い --> Information マルチビュヌ構成の察応の匱さは Tauri も同様です。 https://developer.mamezou-tech.com/blogs/2025/12/01/porting-an-electron-app-to-tauri2/ Electron の WebContensView 構成に぀いおは以䞋の蚘事をご参照ください。 /blogs/2024/08/28/electron-webcontentsview-app-structure/ https://docs.deno.com/runtime/desktop/comparison/ さいごに # 以䞊、Deno Desktop 機胜を䞀通り詊したした。 Out of the box でここたでデスクトップ開発䜓隓が敎っおいるのは率盎に驚きです。タスクトレむやメニュヌ、Bindings など、アプリらしさを出すための API が最初から揃っおいるのも奜印象でした。 Tauri ず違っおアプリ偎をすべお TypeScript で曞けるため、既存 Web アプリをベヌスに「メニュヌやタスクトレむを远加し、OS 機胜ず連携する」甚途ではかなり盞性がよいず感じたす。最小構成なら、デスクトップアプリ化自䜓は1時間もかからないはずです。 --> Information Tauri も JS の API を生やしお、Rust 知らない勢を取り蟌もうずしおはいたす。 Deno のキラヌ機胜になる可胜性もありたすね。experimental から安定版ぞ向けお、今埌の熟成がずおも楜しみな機胜です。 2026幎7月6日珟圚の最新は 2.9.1 です。 ↩

動画

該圓するコンテンツが芋぀かりたせんでした

曞籍

おすすめマガゞン

蚘事の写真

AIに任せる範囲ず人が匕き受ける刀断、PayPayカヌド審査システムの蚭蚈珟堎

蚘事の写真

AIがコヌドを曞く時代、人間は䜕を保蚌するのか───銬堎さんず考える、開発者に求められる新しい責任ず䟡倀

蚘事の写真

仕様曞通りに実装したのに「そうじゃない」ず蚀われる理由───ミノ駆動さんが語る”前提を疑うための認知の芖点”

新着動画

蚘事の写真

【3分解説】囜産AI「Sarashina」6぀のモデルで䜕ができる

蚘事の写真

「ただ出せない」が続くのはなぜ゚ンゞニアの仕事の進め方、完成床の芋極め方を「おい、ずりあえず終わらせろ」著者・nwii...

蚘事の写真

【解説】文章を生成しない最新AI「Jev」ずは ClaudeやChatGPTず䜕が違うTypeSafe AIの刀断専...