AIで個人開発を進める実践手順:アイデアを動く試作品に変える

AIを相談相手兼作業助手として使い、日常の面倒から題材を選び、1枚の仕様メモ、最小実装、テスト、機能追加の順に、小さな個人開発を安全に進める実践手順を紹介します。AIへの依頼を作業単位に分けるコツも学べます。

最初のゴールを「一つの困りごとを解く試作品」に絞る

AIを使った個人開発では、全部を一度に任せるより、目的と作業を小さく分けるほうが進めやすくなります。最初の目標は立派なサービスではありません。「自分のPCで、一つの面倒を減らす動く試作品」です。

たとえば「SNSを作りたい」では、ログイン、投稿、通知、データベースなどが一度に登場します。初心者には、どこが壊れたのか判断しにくい大きさです。「入力した題名から、日付付きの作業メモを1件作る」なら、入力と出力を自分の目で確認できます。

Claude Codeの公式ベストプラクティスは、複雑な作業では調査、計画、実装を分けるよう案内しています。GitHub Copilotの公式ベストプラクティスも、複雑な作業の分割と、要件や入力・出力の具体化を勧めています。特定のAI製品を使うことが重要なのではありません。自分が結果を確認できる大きさにすることが共通点です。

題材は、次の順番で選びます。

  1. 週に2回以上、同じ手順で行う作業を書き出す。
  2. 入力一つと、目で確認できる出力一つに切り分ける。
  3. 失敗しても元データを消さず、やり直せる題材を優先する。
  4. ログイン、クラウド同期、決済、公開は最初の版から外す。
  5. 数日使ったあとに、本当に時間が減ったかを振り返る。

候補は、次の早見表で比べられます。

題材最初の完成形最初は外すもの
作業メモ作成題名からMarkdown(記号で見出しや箇条書きを書く文書)を1件作る同期、検索、画面
写真の整理対象フォルダーから変更予定の一覧だけを作る元画像の削除
定型文作成用件と相手から下書きだけを作る自動送信

この記事では、作業メモ作成ツールを例にします。AIは、材料の候補や調理手順を出す料理助手のような役割です。誰のために何を作るか、味見して完成とするかは人が決めます。

コードより先に仕様メモを作り、AIへの依頼を一変更ずつにする

コードを頼む前に、仕様を1枚へまとめます。長い企画書は不要です。この記事では、初心者が抜けを見つけやすいように7項目へ分けます。この数は公式の決まりではなく、実践しやすくするための型です。

目的:
毎日の作業メモを、決まった形式で素早く作りたい。

利用者:
自分一人。WindowsのPowerShellから使う。

入力:
メモの題名。

出力:
notes/YYYY-MM-DD-題名.md

必須:
- 同名ファイルがあれば上書きしない
- UTF-8で保存する
- 作成後に保存先を表示する

今回はやらない:
- クラウド同期
- ログイン
- GUI(ボタンや入力欄のある画面)

合格条件:
- 日本語の題名で1件作成できる
- 空入力では作成しない
- 同名なら失敗し、先にある内容を変えない

「今回はやらないこと」は、荷物を入れる箱の大きさを決める項目です。箱が決まれば、AIが便利そうな機能を際限なく足すのを防げます。「動けば合格」ではなく、コマンドやファイル内容で判定できる条件を書くのも大切です。Claude Codeの公式資料は、テスト、ビルドの終了結果、期待出力など、AI自身が合否を確認できる手段を与えるよう案内しています。

実装の依頼も、次の6点へ分けます。

  1. 対象ファイル
  2. 今回の変更
  3. 維持する挙動
  4. 確認するケース
  5. 実行する確認コマンド
  6. 提示してほしい証拠

そのまま使える依頼例は次のとおりです。

対象は make_note.py だけです。

今回の変更:
空の題名を拒否し、Windowsで使えない名前を整形してください。

維持する挙動:
UTF-8で保存することと、同名ファイルを上書きしないこと。

確認ケース:
日本語、空入力、予約文字、CON、同名ファイルの5ケース。

確認コマンド:
python -m unittest -v

証拠:
変更したファイル、テスト結果、終了結果、残る注意点を示してください。

これが「一変更・一確認」です。一つの会話で続けても、調査、実装、検証の役割を混ぜません。エラーが出たら、まず実行したコマンドと最初のエラーを材料にします。APIキー、メールアドレス、利用者名などが混ざっていないか確認してからAIへ渡してください。「原因候補を一つに絞り、確認コマンド、最小修正、再確認の順で示して」と頼むと、説明だけで終わりにくくなります。

Pythonで最小の試作品を安全に動かす

次はPython 3で動く完成例です。Pathは、ファイルやフォルダーの場所を扱う標準の道具です。Pythonのpathlib公式資料によると、Path.mkdir(exist_ok=True)は対象が既存のフォルダーならエラーにしません。ただし、同じ場所にフォルダーではないファイルがあればエラーになります。保存時のUTF-8は、日本語などを扱える文字コード(文字を保存する決まり)です。

Windowsでは、< > : " / \ | ? *などを通常のファイル名に使えません。CONNULCOM1などの予約名もあります。拡張子を付けたNUL.txtも予約扱いです。末尾の空白やピリオドも避けます。これらはMicrosoftのファイル名規則で確認できます。

次のコードは、空入力を拒否します。使えない文字と制御文字をハイフンへ置き換えます。予約名には先頭へアンダースコアを付けます。整形後に名前が空になった場合も止めます。

from datetime import date
from pathlib import Path
import re

RESERVED_NAMES = {
    "CON", "PRN", "AUX", "NUL",
    *(f"COM{i}" for i in range(1, 10)),
    *(f"LPT{i}" for i in range(1, 10)),
}


def safe_filename(title: str) -> str:
    original = title.strip()
    if not original:
        raise ValueError("題名を入力してください")

    cleaned = re.sub(r'[\x00-\x1f<>:"/\\|?*]', "-", original)
    cleaned = cleaned.rstrip(" .")

    if not cleaned:
        raise ValueError("ファイル名に使える文字を入力してください")

    first_part = cleaned.split(".")[0].upper()
    if first_part in RESERVED_NAMES:
        cleaned = f"_{cleaned}"

    return cleaned


def create_note(title: str, base_dir: Path = Path("notes")) -> Path:
    filename = f"{date.today().isoformat()}-{safe_filename(title)}.md"
    base_dir.mkdir(exist_ok=True)
    output = base_dir / filename
    body = (
        f"# {title.strip()}\n\n"
        "## 今日やること\n\n"
        "- \n\n"
        "## 振り返り\n\n"
    )

    with output.open(mode="x", encoding="utf-8", newline="\n") as file:
        file.write(body)

    return output


def main() -> None:
    title = input("メモの題名: ")
    try:
        output = create_note(title)
    except ValueError as error:
        raise SystemExit(str(error)) from error
    except FileExistsError:
        raise SystemExit("同名ファイルがあります。上書きしません。")

    print(f"作成しました: {output.resolve()}")


if __name__ == "__main__":
    main()

ファイル名をmake_note.pyとして保存します。PowerShellで次を実行してください。

python .\make_note.py
Get-ChildItem .\notes
Get-Content -Encoding UTF8 .\notes\*.md

ここで重要なのは、保存にxモードを使っていることです。Pythonのopen公式資料では、wモードは既存ファイルの内容を切り詰めます。xモードは新規作成専用です。同じ名前があるとFileExistsErrorで失敗します。

output.exists()で存在を調べてからPath.write_text()で保存する方法も見かけます。しかし、Path.write_text()自体は既存ファイルを上書きします。確認と保存の間に別の処理が同名ファイルを作る可能性もあります。上書き禁止を合格条件にするなら、最初からxモードで作るほうが意図をコードに表せます。

正常系と異常系を試し、差分を見てから次の機能へ進む

AIが「実装できました」と答えても、まだ完成ではありません。正常系(期待どおり使う場合)と異常系(空入力や重複など、困る入力)を分けて確認します。AIの説明ではなく、終了結果、作られたファイル、元の内容が変わっていないことを証拠にします。

ケース入力例期待する結果
日本語買い物メモ日付付きのMarkdownが1件できる
空入力空欄ファイルを作らず、理由を表示する
予約文字会議:質問?使えない文字が-になる
予約名CON_CONを含む名前になる
同名同じ題名を2回2回目は失敗し、1回目の内容は変わらない

Pythonのunittest公式資料では、テストケースを、特定の入力に対する特定の応答を確かめる単位として説明しています。値が等しいか、真か偽か、期待した例外が出るかなどを確認できます。

毎回の手作業を減らすなら、test_make_note.pyを作ります。

from pathlib import Path
from tempfile import TemporaryDirectory
import unittest

from make_note import create_note, safe_filename


class MakeNoteTest(unittest.TestCase):
    def test_japanese_title_creates_utf8_file(self):
        with TemporaryDirectory() as directory:
            output = create_note("買い物メモ", Path(directory))
            self.assertTrue(output.exists())
            self.assertIn("# 買い物メモ", output.read_text(encoding="utf-8"))

    def test_empty_title_is_rejected(self):
        with self.assertRaises(ValueError):
            safe_filename("   ")

    def test_windows_characters_are_replaced(self):
        self.assertEqual("会議-質問-", safe_filename("会議:質問?"))

    def test_reserved_name_is_prefixed(self):
        self.assertEqual("_CON", safe_filename("CON"))
        self.assertEqual("_NUL.txt", safe_filename("NUL.txt"))

    def test_existing_file_is_not_overwritten(self):
        with TemporaryDirectory() as directory:
            base_dir = Path(directory)
            output = create_note("同じ題名", base_dir)
            before = output.read_text(encoding="utf-8")

            with self.assertRaises(FileExistsError):
                create_note("同じ題名", base_dir)

            self.assertEqual(before, output.read_text(encoding="utf-8"))


if __name__ == "__main__":
    unittest.main()

実行コマンドは一つです。

python -m unittest -v
$LASTEXITCODE

$LASTEXITCODEは、直前に動かしたプログラムの終了コード(成功か失敗かを示す数値)をPowerShellで見る変数です。テスト結果と一緒に記録すると、AIの説明に頼らず合否を追えます。

テスト合格は強い証拠ですが、指定していないケースや設計そのものの誤りまでなくなるわけではありません。試作品を数日使い、実際に困った点を一つだけ次の変更候補にします。タグ欄、週ごとの一覧、テンプレート選択などから、使うものを一つ選びます。

変更前後をGit(変更履歴を残す道具)で確かめるなら、次の順番が分かりやすいです。

git status --short
git diff
git add .\make_note.py .\test_make_note.py
git diff --cached

git addは、次の履歴へ入れる変更を選ぶ操作です。この選ばれた状態を「ステージ済み」と呼びます。引数なしのgit diffは、主に作業中でまだステージしていない差分を表示します。git diff --cachedは、ステージ済みの差分を表示します。詳しい違いはgit diffの公式資料で確認できます。

未追跡ファイル(Gitがまだ履歴の対象にしていないファイル)はgit diffだけでは見落とします。git statusの公式資料によると、短い形式では未追跡ファイルが??で表示されます。AIが意図しないファイルを増やしていないか、git status --shortも一緒に見てください。

生成した個人メモを履歴へ入れないなら、リポジトリ直下の.gitignoreへ次のように書けます。

notes/
.env

.envは、接続先や秘密情報などの環境設定に使われることがあるファイル名です。.gitignoreは金庫ではありません。Gitへ「この未追跡ファイルを記録候補から外す」と知らせる規則です。GitHubの無視ファイル公式資料が説明するとおり、すでに追跡されているファイルは、規則を足すだけでは追跡から外れません。APIキー(外部サービスへ接続するための秘密情報)などを一度でも記録・公開した場合は、.gitignoreを追加して終わりにしないでください。

よくある質問

プログラミング未経験でもAIで個人開発を始められますか?

始められます。ただし、AIへ丸ごと任せるのではなく、入力と期待する出力を先に決めます。分からないコードは一行ずつ説明させます。そのうえで、実際のコマンドとテストで確認してください。最初は自分のPCだけで完結し、出力を目で見られる一機能に絞ると、問題の場所を追いやすくなります。

AIには最初から完成アプリを頼んではいけませんか?

禁止ではありません。ただし、初心者が結果を確認できない大きさになると、直ったのか、新しい問題が増えたのかを判断できません。まず「一変更・一確認」を組にします。合格後に次の一機能へ進むほうが、失敗時に戻る場所も明確です。

AIが「実装できました」と答えたら完成ですか?

完成ではありません。先に決めた合格条件と、テストの出力を照らし合わせます。ファイルが作られたか、中身がUTF-8で読めるか、同名時に元の内容が変わっていないかまで確認します。AIの文章より、自分の環境で得た結果を優先します。

同じ名前のファイルを確実に上書きしない方法はありますか?

Path.write_text()は同名の既存ファイルを上書きします。上書き禁止が必要なら、open(..., mode="x", encoding="utf-8")またはPath.open(mode="x", encoding="utf-8")を使います。同名時のFileExistsErrorを、想定外の故障ではなく期待する結果としてテストします。

git diffを見ればAIが変えた内容をすべて確認できますか?

引数なしのgit diffだけでは足りません。ステージ済みの変更はgit diff --cachedで確認します。未追跡ファイルの有無はgit statusで確認します。三つは競合する命令ではなく、変更の状態を別々の角度から見る道具です。

公式一次情報

確認日: 2026-07-27

  • Best practices for Claude Code: 複雑な作業を調査・計画・実装に分け、テストや終了結果などAIが確認できる合格手段を与える方法が書かれています。
  • Best practices for using GitHub Copilot: 作業の分割、具体的な要件、入力・出力例、AI提案コードの人による確認と自動テストが案内されています。
  • pathlib — Object-oriented filesystem paths: Pathによるパス操作、mkdir(exist_ok=True)、既存ファイルを上書きするwrite_text()の動作が書かれています。
  • Built-in Functions — open: wモードが既存内容を切り詰め、xモードが排他的に新規作成することが説明されています。
  • unittest — Unit testing framework: 入力に対する期待結果や例外をテストケースとして確認する標準機能が説明されています。
  • Naming Files, Paths, and Namespaces: Windowsの予約文字、予約名、末尾の空白やピリオドに関する規則が書かれています。
  • git diff Documentation: 作業ツリーの未ステージ差分と、--cachedで見るステージ済み差分の違いが説明されています。
  • git status Documentation: 追跡済みの差分と未追跡ファイルを表示する仕組みが説明されています。
  • Ignoring files: .gitignoreの指定方法と、すでに追跡済みのファイルには別の対応が必要なことが書かれています。

まとめ

AIを使った個人開発の入口は、大きなサービスを一気に作ることではありません。自分が繰り返している面倒を一つ選び、仕様を固定し、一変更ずつ実装します。最後はAIの返答ではなく、自分のPCで得た出力、テスト、Gitの差分で合格を決めます。

今日やることは、次の三つです。

  • 週に2回以上繰り返す作業を一つ選ぶ。
  • 「入力」「出力」「今回はやらないこと」「合格条件」を各1行で書く。
  • AIへ、対象ファイルと一つの変更、確認ケース、確認コマンドをまとめて渡す。

この4行が書ければ、最初の開発依頼は完成です。まずは、自分のPCで一つの出力を作るところまで進めてみてください。

続き(結論と実データ)はnoteに置いています

ここでは手順のところまで書きました。実際に出た数字、うまくいかなかった条件、そのまま使える設定ファイルは、 note の記事にまとめてあります。

noteで続きを読む Xをフォローする