0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

子どもと8日間の夏休みを堪能しながら、issueを109件起票して95件消化した方法

0
Posted at

結論: 育児をしながらでも、個人開発は前に進められる

子どもと8日間の夏休みを堪能しながらスマホでissueドリブン開発

お盆に子どもを連れて8日間の旅行に出ました。5つの都道府県をまわり、カブトムシを採り、川でも遊びました。

その8日間で、issueを109件起票し、95件が閉じました。

やっていたのは3つです。スマホでCommandMateを開き、そこからClaude Codeに気づいたことを渡してissueにする。スマホでplanを確認・承認する。そして、完成したものを隙間時間に動作確認する。自宅の開発機は起動したままにしていましたが、PCを開いて操作することは8日間、一度もありませんでした。

以前は、育児をしているとまとまった時間が取れないので、長期休暇は「開発しない期間」だと諦めていました。今回はその前提が崩れました。

この記事では次の内容をまとめます。

  • 8日間で実際に何が起きたか
  • 気づきからマージまでをスマホで完結させる3つの手順
  • エージェントに任せてもマージ事故が起きない理由
  • うまくいかなかった日と、その原因

対象読者

  • 育児や本業があり、まとまった開発時間を取りにくい個人開発者
  • AIエージェントに任せたいが「勝手にマージされるのが怖い」で止まっている人
  • issueドリブン開発に興味はあるが、issueを書くコスト自体が重いと感じている人

8日間で何が起きたか

結果を先に出します。集計期間は2026年8月7日0時から14日23時59分まで(JST)です。以下のissue件数は、この期間に3つのリポジトリで起票した109件を母集団にしています。

指標 値
起票したissue 109件
旅行中に消化したissue 95件
うち同日起票・同日クローズ 75件
同日クローズの所要時間 中央値3.7時間
マージ済みPR 148本
コミット 192
リリース 22本

対象は3つのリポジトリです。CommandMate本体、公式スキル群のcommandmate-skills、そして開発中の地図サービスです。道具そのものを直しながら、その道具で成果物を作っていた形になります。

数字の内訳も書いておきます。192コミットの内訳は、通常のコミット136件、マージコミット30件、botによる18件、リリース用コミット8件です。旅行終了時には109件のうち14件が開いていました。その後8件が閉じ、2026年8月17日の再集計時点では6件が開いています。

一番効いた数字は「同日起票・同日クローズが75件」でした。起票した109件の68.8%が、思いついたその日のうちに閉じています。この75件の所要時間は中央値3.7時間、最短15分でした。

マージ済みPRの148本は、同じ期間に3つのリポジトリでマージされたPRの総数です。issueとPRは1対1ではなく、ブランチ間の反映やリリース用のPRも含みます。

やったことは3つだけ、すべてスマホで完結する

流れはこれだけです。

  1. スマホでCommandMateを開き、Claude Codeにissue化を頼む
  2. planを確認・承認し、skillsに投げてissueドリブン開発で消化する
  3. 完成したら隙間時間に動作確認する

この3つを、移動中と寝かしつけ後にスマホから回します。

大事にしていたのは、1回あたりの操作を1〜2分に収めることです。子どもを待たせない長さでなければ、そもそも続きません。頻度は1時間に1〜2回、手が空いたときだけです。

言い換えると、開発のために生活の時間を切り出してはいません。すでにある隙間に、1〜2分の操作を差し込んでいるだけです。

用意していた環境

3つの手順を回すために、旅行前に環境を揃えておきました。旅行中にセットアップはしていません。

CommandMate: 並列セッションを1画面で見る

npx commandmate@latest

git worktree単位で独立したエージェントセッションを並列に走らせ、ブラウザから一覧・操作できるツールです。スマホのブラウザからも同じ画面が開きます。Auto Yesを有効にすると、Agent CLIの確認待ちで止まりにくくなります。

Auto Yesは、信頼できるリポジトリと作業範囲に限定して使います。計画の承認やマージのゲートを代替するものではありません。

導入手順は公式ページにまとまっています。

commandmate-skills: issueドリブン開発のワークフロー

issueドリブン開発で使うcommandmate-skillsは、CommandMateのGUIから対象worktreeへインストールできます。

Cloudflare Tunnel: スマホから開発環境につなぐ

旅行中は、Cloudflare Tunnelを使ってCommandMateのWeb UIへ外から到達できるようにしておきました。必要なのはCloudflare Tunnelそのものではなく、外出先から開発環境へ安全に接続できる経路です。VPNや認証付きリバースプロキシでも代替できます。

セキュリティの注意

CommandMateをスマホから安全に利用するための設定は、少し古い内容ですがCodex CLIをスマホから操作する方法を参照してください。

動作確認するアプリへの経路も旅行前に用意しました。ローカルで動かす場合はポート番号を固定してCloudflare Tunnelの別ルートから到達できるようにする、確認環境へ公開する、またはCommandMateのExternal Appsへ登録する方法があります。CommandMateのWeb UIへつなぐだけでは、別ポートで動くアプリには到達できません。

手順1: 気づいたらメモ感覚でissue化を頼む

個人開発のことを頭の片隅に置きながら育児をしていると、アイデアは自然に浮かびます。無理に日常と紐づけようとしなくても、勝手に出てきます。

出てきたら、その場でスマホからCommandMateを開き、Claude Codeに渡すだけです。自分が書くのは一行で、調べてissueの形にするのはClaude Codeの仕事です。

スマホからのわずかな入力でも、しっかりとしたissueになる

実例を1つ出します。子どもを自転車に乗せて移動していたときに、こう思いました。

スマホから入力した実際の一行

「子連れの自転車は12km/hも出ない」

作っている地図サービスでは当初、標準的なシティバイクでの時速を使用して到達圏を計算していましたが、実際の到達距離との差分に違和感を覚えました。この一行をCommandMateからClaude Codeに渡すと、背景や影響範囲、実装時の注意点まで整理したissueを起票してくれました。書いてあったのは次のような内容です。

  • 指標との整合: 指標は「3分以内に行き先を決められた割合」である。30分と言って35分かかるほうが有害なので、過小評価に倒すほうが安全である
  • 1つ目の地雷: 速度の正本がコード内に2か所ある。片方だけ直すと、地図のポリゴンとカードの表示時間が食い違う
  • 2つ目の地雷: キャッシュキーに速度が入っていない。バージョンを上げないと古い結果が最大30日配られ、直したのに変わらないという壊れ方になる
  • 影響の概算: 配信中の施設が34件から25件前後に減る。ただし概算であり、実数は回すまで分からない
  • 検査が落ちる予告: 圏内30件以上を求める検査が赤くなる見込みである。通すために閾値を黙って下げるなら、それは約束を下げる判断になる
  • 決定事項9項目と、触る可能性のあるファイルの完全な列挙

人間がするのは、起票されたissueをざっと斜め読みして、Claude Codeとの認識がずれていないか確認することです。これくらいであれば、育児や移動の隙間時間でも十分に対応できます。

10時45分に起票し、15時25分にクローズしました。4時間40分です。その間、自分は子どもと遊んでいました。

issueの形式が、そのまま実行の入力仕様になる

起票されるissueは、どれも同じ形をしています。

## 背景(なぜ今か)
## 現状(実測。日付つき)
## 問題
## 決定事項(着手前に決めた)
## 対象ファイル(完全な列挙)
## 受入条件(機械可読)

これは人間向けの説明文ではありません。後段の自動実行に渡す入力仕様です。

  • 対象ファイルの完全な列挙は、変更してよい範囲の宣言になる。ここから外れた変更は機械が止める
  • 決定事項を着手前に固めておくと、実装中の判断ブレが減る
  • 受入条件は、そのまま検証ゲートに変換される

issueを書くのはClaude Codeですが、内容を確認して方針を決めるのは人間です。この分担なら、育児の合間でも無理なくissueドリブン開発を回せます。

手順2: skillsに投げて、issueドリブン開発で消化する

issueが揃ったら、番号を並べて渡すだけです。

/cmate-orchestrate #118 #119 #120

cmate-orchestrateは4段で動きます。

段 何をするか
plan dry-runで依存とファイル衝突を解いた実行計画を作る
dispatch 承認後にworktreeへ配り、検証ゲートで監督する
merge 検証を通ったものだけPRを作成し、マージする
uat 受入テストと、回数上限つきの修正ループを回す

最初にスマホでplanを読み、依存関係、変更対象、実行順を確認して承認します。ここは人間が行う操作です。承認後はissueごとにworktreeが切られて並列に走ります。依存関係は有向グラフとして解決されるので、順番を自分で考える必要はありません。走っている間、自分は子どもと遊んでいます。

ほとんど画面を見ていない日に、3本入っていた

旅行6日目は雨でした。子どもの相手で拘束時間が長く、その日はほとんど画面を見ていません。あとからログを見ると、こうなっていました。

13:31:35  PR作成  feat: 町丁目の候補一覧を、入力があるときだけ出す
13:31:39  PR作成  fix:  施設の帰属マージで同じ出典が繰り返される
13:31:43  PR作成  feat: 出典と注記を畳んで画面の占有を減らす
            ↓ 1時間25分後、人間の操作なしで
14:56:57  マージ
14:57:01  マージ
14:57:05  マージ

独立した3件が8秒間隔でPRになり、1時間25分後にやはり8秒間隔でマージされていました。planは事前にスマホで承認しており、PR作成からマージまでに追加の操作はしていません。この日のコミットは5件で、8日間で最小です。それでも機能は3つ増えていました。

なぜエージェントに任せられるのか

ここが一番不安になるところだと思います。答えは単純で、エージェントの「できました」を一切信じていないからです。信用しなくても済む形にしています。

verifyは誰が、いつ実行するのか

cmate-orchestrateでは、実装を担当するワーカーへ作業を任せたあと、オーケストレーターが次のコマンドを起動して待ちます。このwaitがワーカーの作業完了を検出すると、続けてverifyを実行します。

commandmate wait <worktree-id> --verify

ここから先は人間もワーカーも判定しません。CommandMateサーバーが、実装されたworktreeの中で次の順に確認します。

  1. 実際に変更があるか
  2. issueごとに宣言した変更範囲を外れていないか
  3. .commandmate/verify.yamlに書かれたlint、型チェック、テストなどが通るか

すべて通ったときだけ、オーケストレーターはPR作成とマージへ進みます。失敗した場合は、CommandMateが残した終了コードとログをワーカーへ渡して修正させます。回数上限まで直らなければ、人間に判断を求めます。

つまり、人間がスマホからverifyを毎回実行していたわけではありません。人間がplanを承認したあとは、オーケストレーターが実行を指示し、CommandMateサーバーが結果を判定していました。

verifyの有無で何が違うのか

Claude CodeやCodex単独でも、lintやテストを実行できます。ただし、実装と検証を同じエージェントセッションに任せるため、何を実行するか、実行を忘れていないか、失敗をどう解釈するかもエージェント次第です。人間は完了報告やログを読んで、本当に合格しているか判断する必要があります。

CommandMateのverifyを使うと、実装エージェントが止まったあとに、CommandMateサーバーがあらかじめ決めたゲートを別プロセスで実行します。

Claude Code・Codex単独 CommandMateのverifyあり
検証する主体 実装したエージェント自身 CommandMateサーバー
合格条件 指示やセッションごとに変わりうる verify.yamlに定義した同じ条件
不合格時 報告を人間が読み、次の対応を決める マージへ進まず、ワーカーの修正ループへ戻る
人間の確認 実行した検査と結果も確認する 例外とゲート外の動作確認に集中する

嬉しいのは、エージェントを信用しなくてよくなることではなく、信用する対象を「エージェントの完了報告」から「毎回同じコマンドを実行した結果」へ変えられることです。CIも同じ役割を担えますが、verifyはPRを作る前のworktreeで判定し、その結果をオーケストレーターのマージ条件へ直接つなげられます。

verify.yamlは誰が、いつ、どのように書くのか

.commandmate/verify.yamlはissueごとに作るファイルではありません。旅行へ出る前など、最初に自動実行の環境を整えるときに、リポジトリ単位で一度用意してGitで管理します。

ファイルが無い場合は、/cmate-verifyを実行します。するとcmate-verifyスキルが次の流れで作成します。

  1. GitHub Actions、package.json、Makefileなどから、既存の検証コマンドを探す
  2. lint、型チェック、テストなどのゲート案を人間に提示する
  3. 人間が内容を確認・承認する
  4. .commandmate/verify.yamlを書き出し、その場で一度実行する

つまり、YAMLを人間がゼロから書く必要はありません。ただし、スキルが無断で合格条件を決めるのではなく、最後は人間が内容を承認します。ファイルが無いままverifyを実行しても、検証を省略して合格にはならず、設定エラーで止まります。

たとえば、CommandMate本体では次のように「何が通れば合格か」を宣言していました。

version: 1
gates:
  - id: lint
    command: "npm run lint"
  - id: typecheck
    command: "npx tsc --noEmit"
  - id: unit
    command: "npm run test:unit"

cmate-orchestrateはissueごとに実行契約を作り、そのissueで使うゲートを選びます。指定を省略した場合は、verify.yamlの全ゲートが対象です。オーケストレーターがissueのたびにverify.yamlを書き換えるわけではありません。

verifyの結果はどう判定されるのか

実行すると、ゲート1つにつき1行、最後に全体の判定が出ます。

GATE work-evidence PASS (commits=3, uncommitted=2)
GATE lint PASS (exit=0, 12.0s)
GATE unit FAIL (exit=1, 45.0s)
RESULT failed

RESULT passedにならなければマージへ進みません。

判定は実際の終了コードだけを見る

出力の要約でも、エージェントの自己申告でもありません。コマンドを実行して、終了コードを直接読みます。

これが重要な理由は2つあります。

1つ目は、パイプでつなぐと終了コードの意味が変わりうることです。pipefailが無効なシェルでnpm test | grep ...と書くと、$?は最後のgrepのものになります。テストの失敗が消える可能性があります。

2つ目は、テストランナーが緑でも異常終了しうることです。vitestは全テストが通っていても、未処理のPromise拒否で終了コード1を返す場合があります。出力を眺めた要約は、これを「成功」と報告してしまいます。

人が見ていない時間に走らせる以上、判定は機械が読める1つの値でなければなりません。

「何も書いていないのに合格」を塞ぐ

最初のゲートがコミットと未コミット変更の有無を見ます。着手すらしていない状態で合格を主張する経路を、入口で潰します。

合格の意味を過大評価しない

verifyが確認するのは、宣言したゲートの範囲だけです。画面の使いやすさなど、lintやテストでは担保できない条件は、受入テストと人間の確認に残します。

実際、静的な検査だけのゲート集合が合格を返し、中心機能が動かないまますり抜けた例が3件ありました。合格は「宣言したゲートが通った」以上のことを意味しません。ここを忘れると、緑を見て安心したまま壊れたものを配ることになります。

だから検証が要になる

検証が薄いと、遊んでいる間に進んだ結果を自分で全部見直すことになります。それでは1回1〜2分では終わりません。

任せられる範囲は、検証の質でそのまま決まります。ゲートが厚ければ任せられる範囲が広がり、薄ければ自分で見る量が増えます。この仕組みで最初に投資すべきなのは、issueの書き方や並列度ではなく検証だと思っています。

issueで宣言した対象ファイルから外れた変更や、テストの失敗があればverifyは通りません。通ったものだけがマージされ、通らなければ修正ループに戻るか、人間が呼ばれます。

手順3: 隙間時間に動作確認する

マージされたら、スマホで実際に動いているものを開いて自分で触ります。旅行前に用意したアプリ用のCloudflare Tunnel、公開済みの確認環境、またはCommandMateのExternal Apps経由で、移動中でも確認できます。

見ているのは進捗ではありません。「自分が呼ばれているか」と「触ってみてどうか」の2点だけです。違和感があれば、その場でまたissueにします。手順1に戻るだけです。

このループが回り始めると、アイデアが消えなくなります。以前は「あとでやろう」と思ったものの大半が忘れられていました。今は浮かんだ時点でissueになるので、寝ている間に形になっています。

進まなかった日もある

うまくいった日だけ書くと嘘になるので、谷も出しておきます。

  • カブトムシを採った夜のコミットはゼロ。前の3日は毎晩動いていたのに、その夜だけ完全に止まっている
  • ある日は6時間、ひとつも検証が通らなかった。触ってはいた。何も終わらなかっただけである
  • 雨で拘束された日は5コミットで、8日間で最小。見に行けなければ、やはり止まる
  • 109件のうち6件は8月17日時点でも開いたまま。全部は消化していない

全自動ではありません。確認できない日はアウトプットが落ちます。ただし、ゼロにはなりませんでした。

決めるのは人間だという点も変わっていません。先ほどの「閾値を黙って下げない」という判断も、最終的に下げるかどうかも、自分が決めています。

同じことを始めるには

やることは3つです。

  1. CommandMateを入れる(公式ページ、npx commandmate@latest)
  2. CommandMateのWeb UIから、必要なスキルを対象worktreeへ入れる(commandmate-skills)
  3. 認証を設定したCloudflare Tunnelなどで、スマホから安全につながるようにする

あとはissue番号を並べるだけです。

/cmate-orchestrate #1 #2 #3

issueの書き方のコツ

  • 対象ファイルは「主要な変更点」ではなく、完全に列挙する
  • 受入条件は機械が読める形で書く
  • 決定事項は着手前に書く
  • 実測値には日付を添える

企画段階には向いていない

そもそも何を作るかが決まっていない段階は、issueにできません。そこはChatGPTなどのアプリで壁打ちして、作るものを決めてから流し込めばよいと思います。

作るものが決まり、受入条件と変更範囲を言葉にできるタスクなら、この流れに乗せやすくなります。

よくあるつまずきと始め方

  • issueが大きすぎる: 分割させれば済む。cmate-issue-authoringが読み取り専用の分割計画を出してくれる
  • 検証が整っていない: cmate-verifyがCI定義やpackage.jsonからゲートを起案し、cmate-verify-advisorが実行履歴から改善案を出す。強化方向だけ適用でき、弱める変更は必ず提案止まりになる。中心機能を担保するゲートが揃うまでは自動マージを有効にせず、人間が差分と動作を確認しながら育てる

まとめ: 夏休みは、ちゃんと堪能した

8日間で5つの都道府県をまわりました。カブトムシを採りに行き、川でも遊びました。親に孫の顔を見せて、自分の祖母の世話もしました。

その上で、issueが109件立って95件が閉じました。どちらかを諦める必要はありませんでした。

個人開発が止まる一番の理由は、時間がないことではなかったのだと思います。着手までの摩擦でした。思いついた瞬間にissueになり、寝ている間に形になっているなら、まとまった時間はそもそも要りません。

生活の質を落とさずに、アイデアを形にする。この組み合わせで得られたのは、そこでした。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?