複数のAI CLIエージェント(Claude Code / Antigravity / Codex / Gemini など)を、 それぞれ独立したターミナルで並列に立ち上げて監視するデスクトップアプリです。
- Electron +
node-pty(本物のPTY)+xterm.js - クロスプラットフォーム設計(macOS / Windows / Linux)
- シェル自動判定(mac/Linux →
$SHELL、Windows → PowerShell)
- 並列ターミナル — エージェントをグリッドに並べて同時操作・監視
- 起動コマンド自動入力 — 起動時に
claude/agy等を自動実行 - Git worktree 隔離 — セッションごとに新規ブランチ+作業ツリーで起動し競合防止
- 内蔵 diff レビュー — 各ペインの
diffで起動時点からの変更を色分け表示。変更行内の語句レベル強調・シンタックスハイライト(拡張子判定・依存ゼロの自前トークナイザ)・複数ファイル diff のファイル単位ジャンプ(チップ+↑↓+スクロール追従) - 入力待ち検知 + 通知 — 出力停止をターミナル末尾の内容で分類し、プロンプト/確認質問なら約3秒で「要対応」点灯、作業中表示(スピナー・esc to interrupt)は抑制、判断材料なしは12秒。非アクティブ時はOS通知
- マルチリポジトリ管理 — サイドバーにリポを登録し、リポ単位で branch / diff-stat / worktree を表示。選択リポのセッションだけにステージを絞るフォーカスフィルタ、ダブルクリック即起動、PC全体で起動できる ⌂Home 常設エントリ
- diff からのマージ / PR — worktree 隔離セッションの成果を、diff ドロワーからローカルマージ(「merge ↩ base」=
git merge --no-ff)または GitHub PR 作成(「PR 作成」=push →gh pr create)で取り込み - ステージ操作 — グリッド切替(auto/fit/1/2/3・永続化)。fit は8ペインを標準ウィンドウで2列×4行に収め、通常モードで高さを超えた場合もスクロール可能。900px以下/200%拡大時は3カラムを縦にreflowし、端末行を潰さずスクロールで到達可能。ペインのドラッグ並べ替え、起動中デッキの保存&**再起動後に「↻ 前回のデッキを復元」**で再 spawn。Deck v2 は worktree の親リポジトリ・起動時base/branchも保持し、mainプロセスが現在のGit common-dir・worktree・両branch・merge-baseを再検証してからrepo分類・diff・merge・PRを再有効化
- エージェント・プリセット管理 — Agent 横の ⚙ からカスタムプリセット(表示名+起動コマンド)を追加・編集・削除。Aider 等の任意 CLI をコード変更なしで登録でき、select と Quick launch チップに反映(localStorage 永続)。さらにプリセットごとに**起動後コマンド(init)**を設定でき、エージェント起動が落ち着いてから
/effort ultracodeのようなスラッシュコマンドを自動入力(ビルトインの claude / agy にも設定可・毎回の手入力を省略) - キーボード操作 — ペイン移動(1–9)・前後循環([ ])・クイック起動(Enter)・終了(W)・コマンドパレット(K・fuzzy 検索でセッションへジャンプ)。修飾キーは macOS が ⌘、Windows / Linux が Ctrl+Shift(素の Ctrl はシェル/readline のキーのため、ターミナルアプリの慣習に準拠)
- スケジュール起動(⏰) — 「リポジトリ × エージェント × 時刻」を登録すると指定時刻にセッションを自動起動。繰り返し(一回のみ / 毎日 / 曜日指定)、worktree 隔離(発火ごとに日時付きブランチで一意化)、有効/無効トグル・次回発火表示・起動時の OS 通知に対応。Agent 横の ⏰ かリポジトリ行の ⏰ から登録(
userData/schedules.jsonに永続化、スケジューラは main プロセス常駐で 30 秒間隔の壁時計照合 — スリープ復帰でも取りこぼし/二重発火なし) - 多言語対応(5言語) — UI を 日本語 / English / 简体中文 / 繁體中文 / 한국어で切り替え(サイドバー下部のセレクタ)。初回は OS のロケールに追従(
zh-Hans-HKのような明示スクリプト付きロケールも正しく解決)。文字列は依存ゼロのlib/i18n.js辞書({key: {ja, en, zhHans, zhHant, ko}})で一元管理し、5言語の充足と{param}一致を CI が検査
最新版は Releases から取得してください。 バージョンタグを切ると CI が各 OS の成果物を自動ビルドして添付します(RELEASE.md)。
| OS | ファイル | 初回起動 |
|---|---|---|
macOS (Apple Silicon -arm64 / Intel -x64) |
.dmg |
Gatekeeper 警告 → 右クリック → 開く(または xattr -dr com.apple.quarantine) |
| Windows (x64) | .exe(インストーラ) |
SmartScreen → 詳細情報 → 実行 |
| Linux (x64) | .AppImage / .deb |
AppImage は chmod +x で実行(要 libfuse2)/deb は apt install ./…deb |
⚠️ 現在配布中のビルドは未署名です(GitHub Releases が正本)。上記の初回起動手順で開けます。 リリース CI は署名用 secrets が設定されていれば macOS を署名+公証しますが、v0.4.0-beta.10 時点では未設定のため未署名で出荷しています。Windows も未署名です。 App Store 配布は予定していません(サンドボックスとシェル起動が非互換のため非対応)。 アップデート: 起動時と 6 時間ごとに Releases を確認し、パッケージ版ではアプリ内でダウンロード+インストールします(Squirrel.Mac / NSIS / AppImage)。ダウンロードは通知をクリックしてから始まります(自動ダウンロードはしません)。未署名の macOS ビルドは Squirrel.Mac が自己インストールを拒否するため、ブラウザでのダウンロード導線にフォールバックします。
npm install
npm run rebuild # node-pty を Electron 向けに再ビルド
npm start
npm startで「NODE_MODULE_VERSION mismatch」が出たらnpm run rebuild。 mac は Xcode CLT(xcode-select --install)、Windows はビルドツールが必要な場合あり。
純粋ロジックは lib/ に切り出し、Node 標準テストランナーで検証します(依存ゼロ・電子/PTY不要)。
npm test # = node --test (test/*.test.js を実行)CI(GitHub Actions)は ubuntu / macOS / windows のマトリクスで node --test に加え、
実ランナー上で Electron をヘッドレス起動するスモーク(npm run smoke — 起動 / preload /
IPC / node-pty を検証。Linux は xvfb 経由)を実行します。
electron-builder で .dmg を生成します(node-pty は asar 外に展開して同梱)。
現在のリリースは未署名で、GitHub Releases を正本に配布します。
npm run pack:unsigned # 未署名 .dmg ← 現在のリリース手順Apple Developer ID による署名+公証(
npm run dist)はリリース CI が対応済みです。MAC_CSC_LINK/MAC_CSC_KEY_PASSWORD/APPLE_ID/APPLE_APP_SPECIFIC_PASSWORD/APPLE_TEAM_IDの 5 secrets が揃っていれば署名+公証(アプリ内自動更新が有効)、 未設定なら未署名ビルドへ graceful fallback します。証明書の準備手順と GitHub Releases 公開フローは RELEASE.md を参照してください。
アプリは起動時と 6 時間ごとに Releases feed を確認し、新版があれば右下のトースト+OS 通知(バージョンごとに一度)でお知らせします。パッケージ版では通知からアプリ内でダウンロード+インストールまで完結します(autoDownload は無効なので、ダウンロードはユーザーのクリック後に始まります)。未署名 macOS ビルドや更新メタデータの無い旧リリースでは、ブラウザでダウンロードページを開くフォールバックに切り替わります。
- テレメトリ・解析・クラッシュレポートは一切送信しません。 収集も送信もしていません。
- アプリが自発的に行う外部通信はアップデート確認のみです(起動時と 6 時間ごとに
api.github.com/github.comへ HTTPS アクセス。ダウンロードを選んだ場合は成果物の取得)。AGENTDECK_UPDATE_FEED環境変数で向き先を変更でき、到達不能でもアプリは通常どおり動作します。 - リポジトリ登録・スケジュール(
userData/配下の JSON)と UI 設定(localStorage)は すべてローカル保存です。ターミナルの内容が外部に送られることはありません。 - エージェント CLI(
claude/codex等)自身の通信は各 CLI のポリシーに従います。
- Agent を選ぶ(Startup command 自動入力・編集可)
- Working directory を指定(git リポジトリならステータス表示)
- 必要なら Isolate in git worktree をオン+ブランチ名入力
- ▶ Launch agent → ペイン追加 & コマンド自動実行
diffで変更レビュー、killで終了
起動コマンドは agy(antigravity プリセットに設定済み)。agy --model <model> で
モデル指定、agy -p "..." でヘッドレス。インストール先: mac/Linux ~/.local/bin/agy、
Windows C:\Users\<Username>\AppData\Local\agy\bin。
willink-oss/agentdeck(i-Willink の OSS 組織)で公開しています。
| パス | 役割 |
|---|---|
.github/workflows/ci.yml |
OSマトリクスで npm test + ヘッドレス起動スモーク(npm run smoke) |
.github/pull_request_template.md |
PR テンプレート |
.github/ISSUE_TEMPLATE/ |
bug / feature テンプレート |
LICENSE |
MIT(i-Willink) |
CONTRIBUTING.md |
開発・テスト・PR 規約 |
.gitignore で node_modules/ と .agentdeck-worktrees/ 相当は除外済みです。
agentdeck/
├── main.js # Electron main:PTY・git worktree/diff/merge・リポ登録・スケジューラ・IPC
├── preload.js # contextBridge 経由の IPC
├── lib/ # DOM/Electron 非依存の純粋ロジック(テスト対象)
│ ├── git-utils.js # defaultShell / sanitizeBranch / worktreeFolderName
│ ├── diff.js # classifyLine / diffToSegments
│ ├── attention.js # shouldFlagAttention
│ ├── repos.js # normalizePath / addRepo / findRepo / effectiveRepos / findEff
│ ├── gitstat.js # parseNumstat / parseWorktreeList / formatStat
│ ├── layout.js # normalizeLayoutMode / gridTemplateFor / gridAutoRowsFor
│ ├── workspace.js # Deck v2(レイアウト+repo/worktree metadata)の保存/復元
│ ├── fuzzy.js # score(⌘K パレットの部分列マッチ)
│ ├── version.js # compare / isNewer(アップデートチェック)
│ ├── presets.js # ビルトイン定義 + validate / keyFor / merge(プリセット管理)
│ ├── schedule.js # validate / nextFireAt / shouldFire / markFired(スケジュール起動)
│ ├── i18n.js # t(key) / 辞書(ja / en / zh-Hans / zh-Hant / ko)
│ ├── worktree-identity.js # main 専用: 保存 worktree の再検証(12 の拒否パス)
│ └── session-merge.js # main 専用: merge/PR の事前条件 + コンフリクト時 abort
├── renderer/ # UI(順序ロードの classic script 群 — global lexical scope を共有)
│ ├── index.html # script の並び順がロード順(boot を含む 07 → 08 の順を維持)
│ ├── 00-state.js # 共有状態・定数・DOM refs・lib バインディング
│ ├── 01-launch-form.js# 起動フォーム(preset select / quick chips)
│ ├── 02-repos.js # リポジトリパネル(サイドバー・ポーリング・フィルタ)
│ ├── 03-deck.js # レイアウト切替・ペイン並べ替え・デッキ保存/復元
│ ├── 04-sessions.js # セッション起動/kill・attention 検知・PTY ルーティング
│ ├── 05-diff.js # diff ドロワー(merge / PR)
│ ├── 06-keys-palette.js # ⌘ショートカット・リネーム・⌘K パレット
│ ├── 07-overlays-boot.js # プリセット管理・右クリックメニュー・update toast・boot
│ ├── 08-schedules.js # スケジュール起動(⏰ モーダル・schedule:fire ハンドラ)
│ └── styles.css # 配色は PULSE(@willink-labs/pulse)の別名定義のみ
├── e2e/
│ └── smoke.cjs # CI 用ヘッドレス起動スモーク(3 OS・起動/preload/IPC/node-pty)
└── test/ # node --test 用ユニットテスト
配色は PULSE(i-Willink のデザインシステム)に従う。@willink-labs/pulse の dark ビルドを renderer/index.html で読み込み、styles.css は自前の色を一切持たず PULSE ロールの別名を定義するだけ。トークン契約側で色が変われば、Flutter アプリ・Web と同時にここへ届く。
割り切りが 2 つある。どちらも「デザインシステムは端末の外枠を統べるが、中身の意味は統べない」という線引き:
- ANSI 16 色は PULSE 化しない(
renderer/00-state.jsのTERM_THEME)。端末が赤を出すのは「エラー」、緑は「成功」という契約で、利用者は長年の慣れで読む。背景・前景・カーソル・選択色だけが PULSE に追従する。 - diff ビューアの syntax 配色は PULSE に該当ロールが無いため、最も近いアクセントを借りている(
--syntax-kw/--syntax-num)。
killでは worktree とブランチを残す(作業保全優先。不要分はgit worktree prune)。- diff は
git diff <base>(追跡ファイル)+ untracked 一覧。 - 入力待ち検知はヒューリスティック(出力停止+末尾分類)。プロンプト/質問は素早く、不明なケースは保守的に点灯するが、誤検知は依然あり得る。
- merge はローカル
git merge --no-ffのみ(コミット済み履歴が対象。未コミット分はセッション内で commit してから)。コンフリクト時はgit merge --abortで原状復帰。 - PR 作成は
originリモート+認証済みghCLI が前提(push →gh pr create)。worktree 隔離セッションのみ対象。 - デッキ復元は各セッションの起動設定を再 spawn するもの(ライブ端末出力・スクロールバックは復元しない)。worktree セッションは既存ディレクトリでシェルを開き直すが、保存情報と現在のGit状態が一致しない場合は安全な通常shellへ降格し、merge / PRを無効化する。
- スケジュール起動はアプリ起動中のみ発火する(OS のタスクスケジューラには登録しない)。非起動中に過ぎた回はスキップされるが、「一回のみ」は起動時に直近 5 分以内なら猶予発火する。精度は ±30 秒。
- シングルウィンドウ構成のため、ウィンドウを閉じると実行中の全セッションが終了する。実行中セッションがある場合は閉じる前に確認する(macOS の「閉じてもアプリは生存」慣習との差で黙って失わないように)。
- SSHから同じライブセッションへ再接続する用途には、direct PTYに加えて任意のtmuxバックエンド(GUI終了=detach、明示終了=terminate)を追加する
- tmux実装後、同じbackend契約の上にZellij 0.44系のpane制御/read-only watchを追加する
- 配布を絞るなら Tauri +
portable-pty(Rust)へ移植
- ライセンス: MIT — LICENSE
- 開発・PR 規約: CONTRIBUTING.md
- 行動規範: CODE_OF_CONDUCT.md
- 脆弱性の報告: SECURITY.md
- ビルド・配布(macOS): RELEASE.md
Issue / PR を歓迎します。1 PR = 1 トピック、npm test がグリーンであることをご確認ください。