lelelemon’s blog

カメの歩みでのんびり学んでいます。

1分話して残す日記アプリ「1min Voice Journal」の紹介と、今回のアップデート

はじめに

こんにちは。個人開発しているiOSアプリ「1min Voice Journal」をアップデートしました。

ブログではまだ紹介していなかったので、アプリの概要と、今回追加した機能をまとめます。

アプリはこちらから無料でダウンロードできます。

1min Voice Journal

1min Voice Journal

  • Yoshiki Takamatsu
  • ライフスタイル
  • 無料
apps.apple.com

1min Voice Journalとは

1min Voice Journalは、1分以内の音声で、その日の出来事や気持ちを残す日記アプリです。

文章を書くのが面倒な日でも、思いついたことを話して記録できます。名前やメールアドレスの登録は不要です。

話した内容を文字と「今日の一言」に

録音した内容から、AIが文字起こし・感情ラベル・短い「今日の一言」を作成します。

うまくまとめようとせず、その日にあったことや、いまの気持ちを話して使えます。

あとから読んだり、聞き返したり

保存した日記は、一覧から開いて文章を読んだり、音声を再生したりできます。

自分の言葉や声を、そのときの記録として残せます。

初回リリース時には、Voicyでも紹介しました。

voicy.jp

今回のアップデート

無料で1日3回のAI解析

文字起こしから「今日の一言」の作成まで、無料で1日3回利用できます。残り回数はホーム画面で確認できます。

朝の予定や夜の振り返りなど、記録したいタイミングで使えます。解析に失敗した場合は、回数を消費しません。

音声だけでも保存

解析に失敗した場合や、AIを使わない場合も、音声だけを日記として保存できます。

保存した音声は一覧から聞き返せます。AI解析の利用回数にも含まれません。

毎日のリマインダー

好きな時刻に、日記を残すための通知を設定できます。通知のオン・オフや時刻は、あとから変更できます。

AIへの送信設定とデータ削除

AI解析の前に、送信するデータや取り扱いを確認し、同意する流れを追加しました。同意後も、設定から送信を停止できます。

また、AI利用のための匿名アカウントとサーバーデータを削除できるようにしました。削除後も、端末内の日記と録音は残ります。

技術構成

技術 用途
Swift / SwiftUI アプリの処理・画面のUI
SwiftData 日記データの端末内保存
AVFoundation 音声の録音・再生
UserNotifications リマインダー通知
Supabase サーバー処理・匿名認証・利用回数管理
OpenAI API 文字起こし・感情ラベル・「今日の一言」の作成

日記と録音は端末内で管理します。AI解析は同意した場合に行い、再試行に備えて文字起こしや解析結果をサーバーに一時保存します。

終わりに

一日の出来事や気持ちを、1分だけ話して残す。そんな日記の続け方に役立ててもらえたら嬉しいです。

興味を持っていただけたら、ぜひ試してみてください。

1min Voice Journal

1min Voice Journal

  • Yoshiki Takamatsu
  • ライフスタイル
  • 無料
apps.apple.com

「Running Race Mate」をアップデートしました。レース計画の画像・PDF出力やペースバンドに対応

はじめに

こんにちは。以前公開した、ランニングレース前の準備をまとめるiOSアプリ「Running Race Mate」をアップデートしました。

今回のアップデートでは、区間ごとのペースや補給の計画、持ち物の準備をより細かく設定できるようにしました。
また、作成した計画を画像・PDFやペースバンドとして持ち出せるようになりました。

以前のアプリ紹介記事はこちらです。

lelelemon.hatenablog.com

アプリはこちらからダウンロードできます。基本機能は無料で、今回追加した詳細な計画・出力機能などはProで利用できます。

Running Race Mate

Running Race Mate

  • Yoshiki Takamatsu
  • ヘルスケア/フィットネス
  • 無料
apps.apple.com

どんなアプリか

Running Race Mateは、マラソンやハーフマラソン、10kmレースなどに向けた準備を、レースごとにまとめて管理するアプリです。

目標タイムから計算したペースや通過タイム、補給のタイミング、持ち物チェックリスト、当日のメモなどを保存できます。

レース前は、大会の案内を確認したり、補給を何個持つか考えたり、忘れ物がないか確認したりと、走ること以外にも準備があります。
そうした情報をひとつにまとめ、レース前に見返せるようにしています。

今回追加した機能

レース計画を画像・PDFやペースバンドに出力

今回のアップデートでは、作成した計画を「Race Card」として出力できるようにしました。

大会名や目標タイム、区間ペース、通過時刻、関門、補給予定、メモなどをまとめて確認できます。

  • 画像として保存・共有
  • PDFとして保存・印刷
  • ペースバンドとして出力
  • ランナー本人向け/サポート向けの表示を選択

たとえば、計画を画像として保存しておいたり、PDFを印刷して持っていったりできます。
サポートしてくれる人に、通過時刻や補給の受け取り予定を共有するときにも使えます。

アプリの中で計画を作るだけでなく、当日確認しやすい形で持ち出せるようにしました。

画像・PDFの保存や共有、印刷ができるRace Card出力画面

区間ごとのペースとA・B・Cプランの比較

これまでは、目標タイムをもとにした基本のペース計算が中心でした。
今回、区間ごとのペース戦略を設定し、A・B・Cの複数プランを比較できるようにしました。

たとえば、目標を狙うプランと、少し余裕を持って走るプランを用意して、それぞれの通過予定を確認できます。

また、任意の通過地点やエイド、給水所、関門を登録できるようになりました。
設定した計画で、関門までどのくらい余裕があるかも確認できます。

ペース戦略、通過地点、補給予定を確認できるレース詳細画面

補給・給水と持ち物の準備を細かく設定

補給・給水の予定では、タイミングや量を設定できるようにしました。
よく使う設定はプリセットとして再利用できます。

持ち物チェックリストも、項目やカテゴリ、必須設定、期限を編集できるようにしています。
期限に合わせた通知や、チェックリストのテンプレート保存にも対応しました。

レースの計画を複製したり、テンプレートや別のレースから設定を引き継いだりできるので、次の大会に向けた準備にも使えます。

準備状況をまとめて確認

準備状況のダッシュボードでは、関門の通過予定や補給の設定、必須の持ち物のチェック状況などをまとめて確認できます。

細かく設定できる項目が増えた分、どこを見直せばよいかも分かるようにしました。
レース前に、計画と準備の両方を振り返るための画面です。

レース前の準備状況をまとめて確認できる画面

無料で使える機能とProについて

今回、追加機能を利用できる「Running Race Mate Pro」を用意しました。
Proは買い切りで、一度の購入で対象機能を利用できます。サブスクリプションではありません。

無料のままでも、次の機能を利用できます。

  • レースプランの作成・保存・履歴の確認
  • レースの基本情報の編集
  • 基本のペース・固定区間の通過タイム計算
  • 標準の持ち物チェックリスト

区間ごとの詳細なペース設定、A・B・Cプランの比較、詳細な補給・給水計画、チェックリストのカスタマイズ、計画の複製・再利用、Race Card出力、準備状況のダッシュボードはProで利用できます。

まずは無料の基本機能でレースプランを作り、より細かく準備したい場合にProを使ってもらえればと思います。

技術構成

主な技術と用途は次のとおりです。

技術 用途
Swift / SwiftUI レース計画の処理と各画面のUI
StoreKit 2 Proの購入・購入の復元・利用権限の管理
UserNotifications レース前やチェックリストの期限通知

レースの計画データは、引き続き端末内に保存します。

購入機能にはStoreKit 2を使い、購入済みかどうかの確認や、購入の復元に対応しました。

終わりに

今回、Running Race Mateに、詳細なレース計画と、作成した計画を持ち出すための機能を追加しました。

ペースや補給を考えるところから、持ち物を準備し、当日に確認するところまで、レースごとにまとめて扱えるようになりました。

次の大会に向けた準備で、少しでも役立ててもらえたら嬉しいです。
興味を持っていただけたら、ぜひ試してみてください。

Running Race Mate

Running Race Mate

  • Yoshiki Takamatsu
  • ヘルスケア/フィットネス
  • 無料
apps.apple.com

iPhoneを動かして光の彫刻を作るアプリ「MOTION INK」を公開しました

はじめに

こんにちは。iPhoneを動かして空間に光を描くアプリ「MOTION INK」を開発・公開しました。

MOTION INKは、iPhoneを持った手の動きを、立体的な光の軌跡として残せるアプリです。

アプリはこちらです。

MOTION INK

MOTION INK

  • Yoshiki Takamatsu
  • グラフィック/デザイン
  • 無料
apps.apple.com

Neonの光を描いている画面

どんなアプリか

画面の「長押しで描く」を押したままiPhoneをゆっくり動かすと、空間に光の線が描かれます。

描いた線を戻したり、キャンバスをすべてクリアしたりすることもできます。

指を離して右下の「仕上げる」をタップすると、「光のお披露目」画面へ切り替わり、描いた軌跡が立体的な作品として表示されます。

完成した作品を表示する「光のお披露目」画面

完成した作品には名前を付けて、端末内のギャラリーへ保存できます。保存した作品は後から見返せるほか、リプレイ動画や静止画として共有できます。

カメラはiPhoneの動きを認識するために使いますが、カメラ映像や音声は保存・共有されません。

3種類の光のブラシ

MOTION INKでは、光の表現が異なる3種類のブラシを用意しています。

  • Neon:鮮明な中心と柔らかな光を持つブラシ
  • Ember:火の粉のような表現を加えた暖色系のブラシ
  • Aurora:色と太さが変化する幻想的なブラシ

ブラシとは別に、光の色をシアン、バイオレット、コーラルから選択できます。

Neonは無料で利用できます。EmberとAuroraは、MOTION INK Proで利用できます。

Proでは、次の機能も利用できます。

  • 1080pの高画質動画書き出し
  • 透かしなしでの共有
左からNeon、Ember、Aurora。ブラシごとに異なる光の表現を楽しめます

作った理由

今回のアプリでは、「iPhoneを動かした軌跡そのものを、作品として残せないか」と考えました。

一般的なお絵描きアプリでは画面を指やペンでなぞりますが、MOTION INKでは、iPhoneを持った手の動きを入力として使います。

同じ形を描こうとしても、動かす速さや方向によって毎回違う形になります。思ったとおりに描ける部分と、偶然できる形の両方を楽しめるものを目指しました。

また今回は、RevenueCatが主催するモバイルアプリ開発イベント「Shipaton 2026」への参加をきっかけに開発しました。

工夫したところ

描画から作品鑑賞への切り替え

描画中は、カメラ映像の上に光の軌跡を表示します。

「仕上げる」をタップすると暗い展示空間へ切り替わり、描いた軌跡がゆっくり回転します。

単に線を保存するのではなく、自分の動きが光の作品になったと感じられる見せ方を意識しました。

iPhoneの動きを滑らかな光として描画

ARKitで取得した位置をそのまま線にすると、手の細かな揺れまで反映されてしまいます。

そこで、位置の変化を滑らかに補正してから、光の軌跡として描画しています。

また、iPhoneの動きを追跡できなくなった場合は描画を止め、離れた位置同士が一本の線でつながらないようにしました。

技術構成

主な技術と用途は次のとおりです。

技術 用途
Swift 描画データや作品データなど、アプリ全体の処理
SwiftUI 描画画面、ギャラリー、作品表示などのUI
ARKit iPhoneの位置と向きを取得
RealityKit 光の軌跡を立体的に描画
AVFoundation リプレイ動画の生成と書き出し
RevenueCat MOTION INK Proの購入と利用状態の管理

処理の流れ

flowchart TD
    A["iPhoneを動かす"] --> B["ARKitで位置を取得"]
    B --> C["座標を滑らかに補正"]
    C --> D["RealityKitで光の軌跡を描画"]
    D --> E["「仕上げる」をタップ"]
    E --> F["光の作品として表示"]
    F --> G["端末内に保存"]
    F --> H["動画・静止画を書き出し"]

終わりに

今回、iPhoneを動かして光の彫刻を作るアプリ「MOTION INK」を公開しました。

iPhoneを動かす速さや方向によって、描くたびに異なる光の形が生まれます。

自分の動きがどのような作品になるのか、その変化を楽しんでもらえたら嬉しいです。

興味を持っていただけたら、ぜひ試してみてください。

MOTION INK

MOTION INK

  • Yoshiki Takamatsu
  • グラフィック/デザイン
  • 無料
apps.apple.com

DroidKaigi 2026 に参加してきました

はじめに

こんにちは。先日開催されたDroidKaigi 2026に参加してきました。

DroidKaigiは、Android技術情報の共有とコミュニケーションを目的とした、Androidエンジニアが主役のカンファレンスです。

2026年は9月1日から3日まで、ベルサール渋谷ガーデンで開催されました。

droidkaigi.jp

1日目のワークショップには参加せず、2日目から参加しました。
本記事では、DroidKaigi 2026に参加して印象に残ったことや、会場で感じたことを書いてみたいと思います。

お馴染みの大看板

参加賞Tシャツ

参加した理由

今回参加した理由は、ほかのエンジニアがどのような課題を持ち、どのように開発を進めているのかを知りたいと思ったためです。(最近はAndroid開発から少し離れ気味ではありますが…)

普段から技術記事や動画で情報を見ることはできますが、カンファレンスでは、実際に開発している方の経験や試行錯誤を直接聞けます。

新しい技術を知るだけでなく、今の自分の開発を見直すきっかけにもなればと思い、参加しました。また、自分のAndroid開発に対するモチベーションも高めたいという気持ちも、密かにありました。

ちなみに、DroidKaigiへの参加は今回で2回目です。前回参加したときとは自分の担当業務や興味のある分野も変わっているため、今回はまた違った視点でセッションを聞くことができました。

印象に残ったセッション

今回もさまざまなテーマのセッションがありました。

これまでは自分が興味のあるセッションを中心に聴講していましたが、今回は少し選び方を変え、次の観点で参加するセッションを決めました。

  • チームに共有できそうな内容
  • 実際の業務や今後の開発に活かせそうな内容
  • 現在の自分の知識で、ある程度理解できそうな内容

自分の理解度から大きく離れたセッションは、せっかく聴講しても内容を十分に持ち帰れないことがあります。そのため今回は、自分が理解できることを前提に、その後の開発につなげられそうなセッションを選びました。

同じ時間帯に4つのセッションが並行して行われていましたが、上記の観点に合うものがない場合は、無理にすべての時間でセッションを聴講せず、スポンサーブースを回るなど、ほかのことに時間を使いました。

以下では、特に印象に残ったセッションについて取り上げてみたいと思います。

デバイス操作はAIエージェントの時代へ。mobile-mcpを活用したAndroid UI/E2Eテストの挑戦

2026.droidkaigi.jp

Mori Atsushiさんのこちらのセッションを聴講しました。

このセッションでは、mobile-mcpを使ってAIエージェントにエミュレーターや実機を操作させ、アプリの動作確認やテストを行わせる方法について紹介されていました。

AIにコードを書かせた後、意図した画面になっているか、既存の動作が壊れていないかについては、手元でアプリを起動し、人が目で確認するのが当たり前だと思っていました。

特に印象に残ったのは、AIによるデバイス操作を、従来のE2Eテストの単純な置き換えとして使うのではなく、実装後の軽量な動作確認やバグ調査などに使うという考え方です。

たとえば、実装した機能がひとまず動いているか確認する、ログを監視しながら不具合を再現する、古い実装と新しい実装を切り替えて挙動を比較するといった使い方が紹介されていました。

一方で、AIによるデバイス操作には時間やコストがかかります。また、AIが操作の手順を飛ばしたり、期待した状態になっていないにもかかわらず、テストに成功したと判断したりする可能性もあります。

そのため、繰り返し実行する回帰テストは従来の自動テストを使い、開発中の軽い確認や調査にはAIによるデバイス操作を使うなど、目的に応じた使い分けが必要だと感じました。

また、AIにただ「この画面をテストして」と依頼するだけではなく、画面の開き方や期待する状態をまとめたリファレンスファイルを用意するなど、AIが迷わず操作できる仕組みを作ることも重要でした。

コードを書かせるときと同じように、デバイスを操作させる場合も、AIが理解しやすい情報を人間側で準備する必要があるのだと思います。

mobile-mcpは聞いたことがありましたが、まだ使ったことはありません。まずは個人開発のアプリで、実装後の簡単な動作確認を任せるところから試してみたいと思います。

あなたのANRはどこから? — 発生する仕組みを診断し、症状別に処方する

2026.droidkaigi.jp

次に印象に残ったのは、chomiさんのこちらのセッションです。

ANR(Application Not Responding)が発生する仕組みや原因の調べ方について、実際の事例を交えながら紹介されていました。

自分もAndroid開発をしていると、ANRに遭遇することがあります。

ただ、クラッシュと比べると原因を示す情報が分かりにくく、アプリがその後も動作する場合もあるため、これまでは対応の優先度をあまり上げられていませんでした。

しかし、操作しても画面が反応しない状態は、ユーザーから見るとアプリが壊れているのとほとんど変わりません。

さらに、ユーザーが認識できるANRの発生率は、Android vitalsのコア指標のひとつです。基準を超えると、Google Play上でアプリが見つかりにくくなったり、ストアの掲載ページに警告が表示されたりする可能性があることを知りました。

全デバイスを対象とした基準では、1日のアクティブユーザーのうち0.47%以上がユーザー認識ANRを経験すると、Google Playが定める全体の基準値を超えます。端末モデルごとにも8%という基準があるそうです。

個人的には、想像していたよりもシビアな数値だと感じました。

セッションでは、メインスレッドでのI/O、アプリ起動時の重い初期化、Binder呼び出し、ロックの競合など、ANRにつながる複数の原因が紹介されていました。

ANRというと、単純にメインスレッドで重い処理をしている状態を想像していました。しかし実際には、メインスレッド自身が働きすぎている場合だけでなく、ほかの処理やロックを待たされている場合もあります。

同じANRでも原因によって確認する場所や対処方法が異なるため、まずはスタックトレースを見て、メインスレッドが何をしているのかを整理することが大事だと学びました。

今後はANRを後回しにせず、Play ConsoleのAndroid vitalsを定期的に確認したいと思います。また、メインスレッドでI/Oを行っていないか、起動時に不要な初期化をしていないかについても、実装やレビューの際に注意していきたいです。

こちらのセッションも、普段の開発に直接持ち帰れる学びが多かったです。

AI に Inclusive UI を書かせよう — Design Rules Skill で Compose UI を作り直す

2026.droidkaigi.jp

bamiさんのこちらのセッションも印象に残りました。

独自のDesign Rules Skillを整備し、AIにInclusive UIを実装させるアプローチについてのお話でした。

自分は今回、Inclusive UIという言葉を初めて知りました。

これまでUIを実装するとき、画面の見た目や使いやすさを考えることはあっても、それを使う人の視力や身体の状態、認知特性まで具体的に想像することは、あまりできていなかった気がします。

視力が低下している人、手を自由に動かしにくい人、認知症の人など、さまざまな人がいます。

自分にとって分かりやすいUIであっても、誰かにとっては意味を理解しにくかったり、操作できなかったりするかもしれません。

セッションでは、トイレのピクトグラムを例に、アイコンだけでは意味を推測しづらい人もいることが紹介されていました。

記号だけに頼るのではなく言葉を添える、色だけで状態を表現せず、文字やアイコンも組み合わせるといった工夫は、特定の人だけでなく、多くのユーザーにとって分かりやすいUIにつながります。

また、AIに「アクセシビリティを考慮して」「使いやすいUIにして」と伝えるだけでは、必要な対応がすべて実装されるとは限りません。

コントラスト、文字サイズ、ボタンの文言、エラーの表示方法などについて、何をどのように実装するのかを具体的なルールにし、AIが参照できるSkillとして渡すという考え方が印象に残りました。

AIが良いUIを考えてくれることを期待するのではなく、人間が考えた「誰も取りこぼさないためのルール」を、AIが実装できる粒度まで明文化する必要があるのだと思います。

一方で、AIがルールに沿って実装したからといって、それだけでInclusive UIが完成するわけではありません。

TalkBackや文字サイズを大きくした状態、Accessibility Scannerなどを使って確認し、最終的には当事者と一緒に、本当に情報が届くかを確かめることも必要だと紹介されていました。

AIに実装を任せる範囲が広がるほど、人間側には、何を大切にするのかを言葉やルールとして定義する役割が求められるのだと感じました。

まずは普段実装している画面について、アイコンだけで意味を伝えようとしていないか、色だけに頼っていないか、エラーを見たユーザーが次に何をすればよいか分かるか、といった観点で見直してみたいと思います。

会場で感じたこと

コーヒーがおいしい

前回に引き続き、コーヒーの提供があり、とてもおいしかったです。午前と午後に1杯ずついただいてしまいました。
連続してセッションを聴いていると、それなりに疲れてきます。コーヒーを飲みながら一息つくことで、気分を切り替えて次のセッションに参加できました。
本当においしかったので、次回も提供があれば、ぜひ立ち寄ってみることをおすすめします。

スポンサーブースの賑わい

今回も多くの企業がスポンサーとして参加していました。
各社が趣向を凝らしたブースを出しており、アンケートの実施や自社サービスの紹介、DroidKaigiに向けて作成したアプリの展示など、さまざまな企画が行われていました。
ブースではいろいろな方とお話しさせていただき、最近のAIを活用した開発や、これまで知らなかった企業の製品について伺いました。
このように、普段は接点のない方と直接話せる機会があることも、カンファレンスに参加する良さだと感じました。

参加して良かったこと

今回参加して良かったのは、新しい技術を知ることができただけでなく、普段の開発について考え直すきっかけをもらえたことです。

セッションを聞いていると、「この考え方は今のプロジェクトでも使えそう」「この部分はもう少し学び直したい」と思う場面が何度もありました。

今回知ったことの中から、まずは次のことに取り組んでみたいと思います。

  • Play ConsoleのAndroid vitalsを定期的に確認し、ANRの傾向を把握する
  • mobile-mcpを使い、AIからデバイスを操作できる環境を整える
  • 普段実装しているUIが、色やアイコンだけに頼ったものになっていないか見直す

すべてを一度に始めるのではなく、現在の開発に取り入れやすいものから少しずつ試していきたいです。

終わりに

今回は、DroidKaigi 2026に参加して感じたことを書きました。

技術的な学びはもちろんですが、さまざまなエンジニアの考え方や経験に触れられたことも、良い刺激になりました。参加した目的のひとつだった、Android開発へのモチベーションを高めることもできたように思います。

日々の開発だけでは、どうしても目の前のタスクに集中してしまいます。今回のようなカンファレンスに参加して、一度立ち止まり、普段とは違う視点から開発について考える時間も大事だと感じました。

今回得た知識をそのままにせず、まずは小さく試しながら、今後の開発に活かしていきたいと思います。

運営スタッフ、登壇者、スポンサー、参加者の皆さん、ありがとうございました!

AIコーディングエージェント向けの AGENTS.md を作るWebアプリを公開しました

はじめに

こんにちは。AIコーディングエージェントと開発を進めるとき、プロジェクトごとのルールをまとめた `AGENTS.md` を用意しています。
ただ、毎回ゼロから書いたり、既存のテンプレートをコピーして不要な箇所を削ったりするのは、少し手間に感じていました。
そこで今回、プロジェクトの概要を入力すると、AIエージェント向けの `AGENTS.md` のたたき台を作れるWebアプリ「AGENTS.mdジェネレーター」を作りました。

アプリはこちらです。

agents-md-generator-4vr.pages.dev

ソースコードも公開しています。

https://github.com/mytysoldier/agents-md-generatorgithub.com

どんなアプリか

AGENTS.mdジェネレーターは、プロジェクトの概要や技術スタックを入力するだけで、AIコーディングエージェント向けの `AGENTS.md` のたたき台をサクッと作れるWebアプリです。

まず、プロジェクト概要を入力します。技術スタックや追加で守ってほしいことは任意で入力できます。
たたき台を作成した後は、プロジェクトに合わせて内容を編集し、最終的な `AGENTS.md` を確認できます。

生成した内容は、次の方法で利用できます。

  • Markdownをコピーする
  • `AGENTS.md` ファイルとしてダウンロードする
  • たたき台の編集画面へ戻り、内容を修正する

生成結果には、主に次のような内容を含められます。

  • プロジェクトの目的
  • 技術スタック
  • プロジェクトで使うコマンド
  • 実装方針とコーディング規約
  • テスト・品質確認のルール
  • Git・Pull Request運用
  • AIエージェントの作業手順
  • 禁止事項と安全上の制約

作った理由

AIコーディングエージェントを使う場合、実装内容だけではなく、プロジェクトで守るルールも明確に伝える必要があります。

たとえば、次のような内容です。

  • Issueを作業単位にする
  • 実装前に目的・実装範囲・受け入れ条件を確認する
  • 変更後にlint・型チェック・テストを実行する
  • 関係ない機能を勝手に追加しない
  • 秘密情報をコミットしない
  • Pull Requestを作成する前に変更内容を確認する

こうしたルールはプロジェクトごとに異なりますが、何もない状態から考え始めると、抜け漏れが出やすいと感じています。

そこで、最低限のプロジェクト概要からたたき台を作り、必要な項目だけを後から編集できる形にしました。
最初から完璧な `AGENTS.md` を作るというより、「何を書けばよいか分かる状態」を素早く作ることを目指しています。

工夫したところ

入力内容を外部へ送信・保存しない

プロジェクト概要や運用ルールには、公開前の情報や内部向けの内容が含まれることもあります。
入力内容と生成結果はブラウザ内だけで扱い、外部への自動送信・自動保存は行わないようにしました。

アカウント登録や利用状況の分析もありません。ページを再読み込みしたり閉じたりすると入力内容は失われますが、まずは気軽に使えて、入力内容を外部に出さないことを優先しました。

最小入力から始められるようにした

最初から細かいルールをすべて入力しようとすると、ツールを使い始める前に疲れてしまいます。
そのため、必須入力はプロジェクト概要だけにしています。

技術スタック、実行コマンド、Git運用、テスト方針、禁止事項などは、たたき台を作ったあとで必要なものだけを編集できます。
テンプレートを一から書くのではなく、作成してから直す流れにしたことで、少しでも始めやすくなればと思っています。

技術構成

今回のアプリは、次の構成で作りました。

  • TypeScript
  • React
  • Vite
  • Tailwind CSS
  • Vitest
  • React Testing Library
  • Cloudflare Pages

静的なWebアプリとして公開しているため、サーバー、データベース、ログイン機能、外部APIは使用していません。
個人開発の初期リリースとして、URLへアクセスすればすぐに使えて、運用コストも増えにくい構成を選びました。

また今回、Cloudflare Pagesを初めて使いました。GitHubリポジトリと連携させることで、Pull Requestごとにプレビュー環境を作成でき、`main` へマージすると本番環境へ自動デプロイされる構成を簡単にセットアップできます。
これまで Webアプリの公開基盤は Vercel を使うことが多かったですが、選択肢が増えたので良かったです。

開発の進め方

開発はGitHub Issueを中心に進めました。
設計、データモデル、Markdown生成ロジック、入力画面、プレビュー、コピー・ダウンロード、公開設定といった単位でIssueを分けています。
各Issueでは、目的、実装範囲、受け入れ条件、スコープ外を確認してから実装するようにしています。

AIコーディングエージェントと開発を進める場合も、プロジェクト全体のルールを `AGENTS.md` にまとめておくことで、細かい前提を毎回伝えなくても進めやすくなります。
実装後は、lint、型チェック、テスト、buildを実行して確認し、Pull Request単位でレビューする流れにしています。

終わりに

今回、AIコーディングエージェント向けの `AGENTS.md` を作るためのWebアプリを公開しました。
AIを使った開発では、実装スピードだけでなく、どのようなルールで進めるかを最初に揃えることも大事だと感じています。

AGENTS.mdジェネレーターは、プロジェクトごとのルール作りを少し楽にするためのツールです。
生成された内容はそのまま使うのではなく、プロジェクトの実情に合わせて確認・編集してから使ってもらえればと思います。
今後も実際に使いながら、入力体験やテンプレートを少しずつ改善していく予定です。

GitHubでの個人開発の活動を可視化する「Output Pulse」というダッシュボードを作りました

はじめに

こんにちは。個人開発でコードを書いていると、コミットやPull Request、Issueなどが積み上がっていきます。
GitHubを開けばそういった活動ログは画面やCLIで確認できるものの、「最近どれくらい開発できているか」「何を完了したか」を期間ごとに振り返ったり、グラフなどで視覚的に確認したいと思うようになりました。

そこで今回、GitHub上の個人開発の活動を定期的に収集し、確認できる個人用ダッシュボード「Output Pulse」を作りました。
コミット数だけでなく、作成したPull Request、マージしたPull Request、完了したIssueをまとめて確認できます。

ソースコードはこちらで公開しています。

github.com


なお、Privateリポジトリを含む個人の活動データを扱っているため、ダッシュボード自体は一般公開していません。ログインした自分だけが閲覧できる形にしています。

どんな仕組みか

Output Pulseは、GitHubでの個人開発の活動を定期的に収集し、ダッシュボードで振り返るための仕組みです。

毎日3回、自分が所有するPublic/Privateリポジトリから、次の活動データを取得します。

  • デフォルトブランチへ到達したコミット
  • 作成したPull Request
  • マージしたPull Request
  • 完了したIssue

ダッシュボードでは、主に次の情報を確認できます。

  • コミット数
  • 作成Pull Request数
  • マージPull Request数
  • 完了Issue数
  • 前期間との増減
  • 日別の活動実績
  • 週別の活動推移
  • 完了したIssueのタイトルと日時
  • 最終同期日時と同期結果

表示期間は7日、30日、90日、今年、全期間などへ切り替えられるようにしました。
以下は直近7日の表示例です。

同期が完了すると、成功・失敗や取得件数などがSlack DMで通知されます。普段ダッシュボードを開いていなくても、定期同期が動いていることを確認できるようにしています。

システム構成

flowchart TD
    Schedule["GitHub Actions<br/>JST 08:00 / 14:00 / 22:00"] --> Collector

    subgraph GitHub["GitHub"]
        API["GitHub API"]
        Repositories["Public / Private<br/>個人リポジトリ"]
    end

    Repositories --> API
    API -->|"Commit / PR / Issueを取得"| Collector["Collector<br/>Node.js / Octokit"]

    Collector -->|"Drizzle ORMでUpsert"| Neon[("Neon PostgreSQL")]

    subgraph Database["データベース"]
        AppSchema["app schema<br/>収集処理用テーブル"]
        DashboardSchema["dashboard schema<br/>Grafana専用View"]
    end

    Neon --> AppSchema
    AppSchema --> DashboardSchema

    DashboardSchema -->|"SELECTのみ"| Grafana["Grafana Cloud<br/>活動ダッシュボード"]
    Viewer["ログイン済みの個人利用者(自分)"] --> Grafana

    Collector -->|"同期結果を通知"| Slack["Slack DM"]

常駐サーバーは用意せず、GitHub Actionsの実行中だけ、TypeScriptで実装したCollectorが起動します。

GitHub ActionsからGitHub APIへアクセスし、コミット、Pull Request、完了Issueを取得します。取得したデータはDrizzle ORMを使ってNeon PostgreSQLへ保存します。
Grafana Cloudは、Neon PostgreSQLに用意したGrafana専用Viewへ読み取り専用ユーザーで接続します。

データ収集、保存、表示、通知をそれぞれ分け、必要なサービスだけで小さく構成しました。

採用した主な技術は次のとおりです。

  • TypeScript/Node.js
  • GitHub Actions
  • Octokit
  • Drizzle ORM
  • Neon PostgreSQL
  • Grafana Cloud
  • Slack Web API
  • Vitest
  • Docker Compose

作った理由

個人開発では、完成したアプリやリリース数に目が向きやすいですが、その途中にはIssueの整理、実装、Pull Requestの作成、レビュー対応など、さまざまな活動があります。
GitHub上にはそれらの記録が残っているものの、リポジトリをまたいで振り返ろうとすると、それぞれの履歴を確認しなければなりません。

また、コミット数だけでは「何を完了したか」が分かりにくく、Issueだけでは実装量や継続的な活動が見えにくいと感じました。
そこで、コミット、Pull Request、完了Issueを一緒に可視化することで、個人開発の活動全体を振り返れるようにしたいと思いました。

数値を増やすこと自体が目的ではありませんが、開発を継続できているか、どの時期に活動量が増減しているかを確認する材料として使っていく予定です。

工夫したところ

常駐サーバーを持たない構成にした

個人用のダッシュボードなので、最初からWebサーバーや独自の管理画面を用意する必要はないと考えました。
常にリアルタイムで反映する必要はないため、収集処理は決まった時間にだけ動かし、GitHub Actionsをスケジューラー兼実行環境として利用しています。

表示部分も独自に実装せず、Grafana CloudからPostgreSQLを参照する形にしました。
GrafanaはこれまでもローカルでDockerコンテナとして起動して使っていましたが、クラウド版があることを知り、Grafana Cloudを使ってみたかったというのもあります。
これにより、アプリケーションサーバーを常時運用せず、比較的小さな構成で継続運用できるようにしています。

同じデータを再取得しても重複しないようにした

定期同期では、前回の成功時刻以降だけでなく、その48時間前からデータを再取得します。
これはGitHub API側の反映遅延や、一時的な失敗による取得漏れを減らすためです。

一方で、期間を重ねて取得すると同じイベントを何度も受け取ることになります。
そのため、コミットはSHA、Pull RequestやIssueはGitHub上のIDを識別に使用しています。Pull Requestの作成とマージはイベント種別を分けて保存し、同じデータを再取得しても重複計上されないようにしています。

手動で実行するケースも想定し、必要に応じて期間指定や全再同期も実行できるようにしました。

1つのリポジトリの同期が失敗しても、同期全体を止めない

複数リポジトリを対象にしているため、1つのリポジトリで取得に失敗しただけで、ほかのリポジトリまで同期できなくなるのは避けたいと考えました。

そこで、リポジトリ単位でトランザクションを分けています。
取得に成功したリポジトリは保存し、失敗したリポジトリの途中データだけをロールバックします。その後も残りのリポジトリの処理は継続します。
一部だけ失敗した場合は、同期結果を「一部失敗」として記録し、Slack DMで確認できるようにしています。

Privateリポジトリの情報を表示側へ出さない

今回の仕組みではPrivateリポジトリも集計対象にしています。

ただし、Grafanaへ表示したいのは活動件数や推移であって、リポジトリの詳細ではありません。
そのため、ダッシュボードにはリポジトリ名、GitHub URL、Pull Request本文、Issue本文、コメント、コード差分、コミットメッセージなどを表示しない設計にしました。
もともとは一般公開も想定してこの設計にしました。最終的には自分だけがアクセスする形に変更しましたが、意図しない情報露出を防ぐため、この制限は残しています。

PostgreSQLでは、収集処理が使う「app schema」と、Grafanaが参照する「dashboard schema」を分けています。
Grafana用のデータベースユーザーには、dashboard schemaのViewをSELECTする権限だけを付与し、内部テーブルの参照や書き込みは許可していません。

flowchart LR
    Collector["Collector専用ユーザー"] -->|"必要最小限の読み書き"| App["app schema<br/>内部テーブル"]
    App --> Views["dashboard schema<br/>集計View"]
    Grafana["Grafana読み取り専用ユーザー"] -->|"SELECTのみ"| Views
    Grafana -.->|"アクセス不可"| App

学んだこと

ダッシュボードは、集計する数字を決めるところが難しい

開発活動を可視化するといっても、単純にコミット数だけを表示すればよいわけではありません。
コミット数は活動量を確認しやすい一方で、小さく分けたコミットと大きなコミットを同じ1件として扱います。また、コミット数が多いことが成果の大きさをそのまま表すわけでもありません。

今回は、コミット、作成Pull Request、マージPull Request、完了Issueを並べることで、1つの数字だけに寄りすぎない形にしました。
「何件実施したか」と「何を完了したか」の両方を見られることが大事だと感じました。

差分同期は、前回の続きだけを取ればよいわけではない

最初は、最後に同期した時刻以降のデータを取得すれば十分に思えます。
ただし、APIの反映遅延や途中失敗を考えると、境界時刻のデータが漏れる可能性があります。

一定期間を重ねて再取得し、データ側で重複を排除する形にすることで、同期処理での取得漏れを防ぎやすくしました。

再取得しても結果が変わらない、冪等な処理にすることの大切さを改めて学びました。

MVPでは独自UIを作らない選択肢もある

活動データを表示するためのWebアプリを独自に作ることも考えられます。

ただ、今回必要だったのは、数値カード、時系列グラフ、一覧、期間切り替えといった一般的なダッシュボード機能です。
Grafana Cloudを使うことで、独自UIやログイン機能を作らず、データ収集と集計ルールの実装に集中できました。

MVPでは、すべてを自分で実装するのではなく、目的に合う既存サービスを組み合わせることも大事だと感じました。

終わりに

今回、GitHubでの個人開発の活動を定期的に収集し、Grafana Cloudで振り返るための「Output Pulse」を作りました。
作ったアプリだけでなく、その途中にあるコミット、Pull Request、完了Issueも含めて見えるようになったことで、日々の活動を少し振り返りやすくなりました。
Webブラウザから、PC・スマホどこからでもアクセスできるのも嬉しいポイントです。

前々から欲しいと思っていた仕組みで、大部分の実装にAIを活用しましたが、実際に構築して運用を始められたことには達成感があります。

日々このダッシュボードを眺めることで、最近あまり開発していないな、と気づくきっかけにもなりますし、自分を奮い立たせる、やる気スイッチの役割も担ってくれると思っています。
まずはこの構成で継続的に動かしながら、実際に振り返りで役立つ指標や、見やすい期間の切り替え方を確認していく予定です。

市場データから次に作るアプリ候補を毎週提案する「App Opportunity Scout」という自動化の仕組みを作りました

はじめに

こんにちは。個人開発では「何を作るか」を考える時間も大事ですが、毎回ゼロから市場を調べて候補を比較するのはなかなか大変です。
そこで今回、Apple公式のランキングやProduct Huntの情報を毎週取得し、自分の開発条件に合うアプリ候補を自動で提案してくれる「App Opportunity Scout」を作りました。

この仕組みは特にUIを持たず、裏側で動く自動化の仕組みです。
画面としてお見せできるものがないのは少し心許ないのですが、この記事ではシステム構成を中心に軽く紹介したいと思います。

ソースコードはこちらです。

github.com

どんな仕組みか

App Opportunity Scoutは、画面を持たない自動バッチです。週次で動かす形でいったん運用をしています。
毎週月曜の朝にGitHub Actionsで起動し、Apple公式データとProduct Huntから市場データを取得します。その後、個人開発で取り組みやすい候補へ絞り込み、OpenAI APIで候補の生成・採点を行います。

候補はそのまま登録するのではなく、別途Notionで管理している既存アイデアと完全一致・意味的な重複を確認します。重複がなく、根拠とスコアの基準を満たしたものだけを、最大3件までNotionへ登録する形にしました。
※毎回大量に候補が積み上がっていくと管理しきれなくなるので、いったんファーストリリースでは最大3件で始めています

システム構成

flowchart TD
    Schedule["GitHub Actions<br/>毎週月曜 7:17 JST"] --> Fetch

    subgraph Sources["市場データの取得"]
        AppleRSS["Apple公式 RSS<br/>日本 Top Free"]
        AppleLookup["iTunes Lookup API"]
        ProductHunt["Product Hunt API<br/>直近7日の投稿"]
    end

    AppleRSS --> Fetch["Python バッチ<br/>市場データを取得"]
    AppleLookup --> Fetch
    ProductHunt --> Fetch

    Fetch --> Normalize["共通形式へ正規化"]
    Normalize --> Select["ルールベースで<br/>最大30件へ選別"]
    Normalize --> Snapshot["週次 Snapshot"]
    Snapshot --> History["scout-data ブランチ"]
    Snapshot -. "調査用データ" .-> Artifact["GitHub Actions Artifact<br/>30日保持"]

    Select --> OpenAI["OpenAI Responses API<br/>候補生成・採点"]

    OpenAI --> Duplicate["既存候補との重複判定"]
    ExistingNotion["Notion<br/>既存アプリ候補"] --> Duplicate

    Duplicate --> Register["条件を満たす<br/>上位最大3件を登録"]
    Register --> NewNotion["Notion<br/>新しいアプリ候補"]
    Register --> Slack["Slack Incoming Webhook<br/>実行結果を通知"]

作った理由

毎回自分が作りたいと思ったアプリをその場その場で考えて作ってきました。
もちろんあくまで趣味でやっていることなのでそれはそれでいいのですが、世の中でどういうアプリが流行っているのか、個人開発するならどういうアプリが良いのか。
この辺りの市場感を養うことで、仕事等にも活かせる場面がありそうに思うようになりました。

市場調査することで色々な発見があり楽しいと思えるものの、時間がかかるし毎度調査するのも大変です・・
これを継続するには「調べる → 比較する → アイデアとして残す」という流れを自動化したいと感じました。

今回の仕組みでは、Appleのランキングから現在の需要を、Product Huntから新しいプロダクトやテーマの動きを見るようにしています。

ただし、ランキングが高いことや投票数が多いことだけで、個人開発で作るべきアプリとは限りません。そのため、自分が使いたい技術、興味のある領域、MVPとして作れる期間などをあらかじめ設定し、候補の評価に使うようにしました。

工夫したところ

AIに渡す前に、ルールベースで候補を絞った

外部から取得したデータをすべてAIへ渡すのではなく、まず最大30件まで絞っています。

Appleは公式順位を優先し、Product Huntは投票数・コメント数・公開日時をもとに選別します。同じカテゴリに偏りすぎないようにもしています。
AIに任せる部分を小さくすることで、入力データを追いやすくしつつ、候補の根拠を確認しやすくしました。

既存アイデアとの重複を保守的に扱った

Notionにはすでに自分で考えたアプリ候補があるので、新しい候補を無条件で追加すると似たアイデアが増えてしまいます。

まず、候補の内容が既存アイデアと完全に一致していないかを確認します。そのあと、名前や概要が似ている候補は、AIを使って内容として同じアイデアではないかを判定します。
「重複しているか判断が難しい」候補は登録しないようにしています。候補数を増やすよりも、Notionをあとで見返したときに迷わないことを優先しました。

データが少ない新しい候補を、不利にしない

週次の記録を保存して、順位・評価数・投票数・コメント数などの変化を、候補を評価する材料として使えるようにしています。
ただ、初回の取得時や履歴が少ない段階では、前週との比較ができない項目もあります。比較できないことを「伸びていない」とは扱わず、分かるデータだけで判断するようにしました。

あわせて、どの程度のデータが揃っているかも記録しています。候補を見るときに、判断の根拠がどこまで十分かを確認できるようにするためです。

学んだこと

MVPでは、情報源を増やしすぎないことが大事

市場調査の情報源はたくさんありますが、最初からGoogle TrendsやGoogle Play、レビュー本文の取得などまで広げると、運用も実装も複雑になります。
今回はApple公式データとProduct Huntに絞りました。まずは毎週ちゃんと動き、Notionに見返せる候補が溜まることを優先しています。

AIの出力だけで完結させない

AIに候補を考えてもらう部分は便利ですが、入力データの選別、登録条件、既存候補との照合まで全部を任せると、あとから判断理由を追いにくくなります。
ルールベースで扱う部分と、AIに任せる部分を分けることで、仕組み全体が少し扱いやすくなりました。

終わりに

今回は、次に作るアプリの種を見つけるための調査フローを、自分用に小さく自動化してみました。
ここから見つかった候補を実際にMVPとして作り、公開まで繋げていけたらと思っています。
まずは毎週動かしながら、出てくる候補の質や、自分が本当に見たい市場データを確かめていく予定です。