初めてのClaude Codeで家計簿ソフトを自作してみた

今までWindows専用の家計簿ソフトを使っていたが、メイン環境をMacに移したことをきっかけに、Macで完結する家計簿環境が欲しくなった。そこで、AIコーディングアシスタント「Claude Code」を初めて使い、自分好みの家計簿アプリを一から作ってみることにした。本記事では、実際にどのような手順で開発を進めたのかを、これからClaude Codeで同様のツールを作りたい人向けに解説する。

なぜClaude Codeで家計簿ソフトを自作しようと思ったか

  • Macをメインマシンとして使っていたため、家計簿のためにWindowsを立ち上げる必要があり、日々の記帳が面倒だった
  • 市販の家計簿アプリは機能が豊富すぎたり、逆に痒い所に手が届かなかったりした
  • 「毎月の予算内で生活できているか」「無駄遣いがないか」を自分の使い方に合わせて確認したかった
  • 個人利用なので、大掛かりなクラウド環境ではなく、ローカルで完結する軽量な構成にしたかった

これらの要件は、既製品を探すよりも自分で作った方が早いと判断し、Claude Codeでの個人開発に踏み切った。

手順1:要件をClaude Codeに伝え、構成を決める

最初にやったことは、作りたいものの目的を自然な日本語でそのまま伝えることだった。「毎月の予算内で生活できているか、無駄遣いがないかを確認したい」という目的と、「ローカル環境のみで完結させたい(クラウド不要)」という制約を伝えると、技術構成の提案が返ってきた。

最終的に採用した構成は以下の通り。個人用ツールとして無理のないシンプルな選定である。

  • Python + Streamlit(画面・アプリ本体)
  • SQLite(データベース、ローカル1ファイル)
  • Plotly(グラフ描画)
  • pandas(データ加工)

Streamlitは、Pythonのコードだけでフォームやグラフ付きのWebアプリを構築できるフレームワークで、個人用ツールとして必要十分な機能が標準で揃っている点が採用の決め手になった。

手順2:機能を段階的に実装してもらう

いきなり全機能を一度に依頼するのではなく、次のような順序で機能を一つずつ実装してもらった。この進め方により、都度動作確認しながら軌道修正できた。

  • 取引(収入・支出)を記録する基本機能
  • カテゴリ・サブカテゴリを管理する機能
  • 月次サマリー、無駄遣いチェック、月別推移などの分析画面
  • 口座管理(残高・クレジットカードの締め日/支払日設定)
  • CSVエクスポート機能

Streamlitはファイル1つが1画面(ページ)に対応するマルチページ構成を取れるため、機能ごとにファイルを分けて増やしていく形が自然に収まった。

project/
├── app.py                    # トップ画面
├── db.py                     # データアクセス層(SQLite)
└── pages/
    ├── 1_収支記録.py
    ├── 2_月次サマリー.py
    ├── 3_無駄遣いチェック.py
    ├── 4_月別推移.py
    ├── 5_カテゴリ管理.py
    ├── 6_口座管理.py
    └── 7_データ管理.py

トップ画面には、総資産や当月の収支サマリーと合わせて、各画面へのリンクをカテゴリ別にまとめて配置した。

total_assets = sum(get_account_balances().values())

with st.container(border=True):
    st.markdown("##### 総資産")
    st.metric("全口座合計", f"{total_assets:,} 円")

手順3:旧ソフトからのデータ移行を実装する

過去の家計データを活かすため、旧ソフトのCSVエクスポート機能を使って、長年分のデータをインポートする処理を作ってもらった。ここで、単純な取り込みでは済まない技術的な壁にいくつかぶつかった。これから同様の移行を行う人のために、つまずいたポイントを共有する。

壁1:文字コードの違い

旧ソフト(Windows版)が出力するCSVはShift-JIS(cp932)だったため、UTF-8前提で読み込むと文字化けした。複数のエンコーディングを順に試すフォールバック処理を実装することで解決した。

def _decode(file_bytes):
    for encoding in ("cp932", "utf-8-sig", "utf-8"):
        try:
            return file_bytes.decode(encoding)
        except UnicodeDecodeError:
            continue
    raise ValueError("文字コードを判定できませんでした")

壁2:カード引き落としの二重計上

旧ソフトのCSVには、実際の買い物とは別に「カード引落し」という行が存在していた。これは口座からカード利用額が引き落とされたことを示す行で、そのまま取り込むと「購入時の支出」と「引き落とし時の支出」が二重に計上されてしまう。

そこで、引き落とし行のメモに含まれる日付・金額情報から元の購入取引を検索し、見つかった場合は新規取引を作らずに引き落とし日だけを紐付ける方式にした。リンク先が見つからない場合のみ、引き落とし日を日付とする支出として記録する。

matched_tx = find_matching_transaction(purchase_date, amount, card_name)

if matched_tx:
    set_settlement_date(matched_tx["id"], settlement_date)
    # 銀行口座からの引き落とし(支出)とカード側の返済分(収入)を
    # ペアで記録することで、両方の口座残高を正しく反映させる
else:
    # リンク先が見つからない場合のみ、新規の支出として記録
    add_transaction(...)
インポート結果の例(約100ヶ月分、1万件超のデータ)
・通常取引:約1万件
・口座振替(資金移動):500件強
・カード引落しのリンク成功:4,500件強
・リンク先不明で新規記録:数十件

壁3:口座間の資金移動

「貯蓄」「貯蓄引出」「口座振替」「電子マネーチャージ」といったカテゴリは、家計の収入・支出ではなく口座間の資金移動である。当初は単純にスキップしていたが、それでは移動元・移動先どちらの口座残高にも反映されず、残高計算が合わなくなる不具合につながった。

最終的には、資金移動も「移動元の支出」「移動先の収入」のペアとして記録しつつ、収支集計(総収入・総支出)からは除外するフラグを持たせる方式に落ち着いた。

add_transaction(date, "支出", category, amount, from_account, memo, is_settlement_record=True)
add_transaction(date, "収入", category, amount, to_account, memo, is_settlement_record=True)

手順4:実運用でしか見つからないバグに向き合う

データを移行し、実際にしばらく使ってみて初めて気づいた不具合もあった。クレジットカードの引き落とし処理で、銀行口座からの出金記録とカード側の相殺記録の両方を作らなければ口座残高が正しく一致しない、という会計ロジックの不備である。この処理が一部漏れていたため、カードの残高が際限なくマイナスに積み上がっていくというバグが発生していた。

修正前のカード口座残高の推移(イメージ)
数年前:数万円程度
現在:マイナス数十万円まで際限なく悪化

修正後
実際の利用状況に応じて、数万円〜数十万円の範囲で妥当に推移するよう改善

この経験から、「残高が合っていて当然」に見える機能ほど、実データを流し込んで検証しないと気づけない落とし穴があると痛感した。テストコードだけでなく、しばらく実運用してみて自分自身でチェックすることの重要性を実感したポイントである。

手順5:自動テストを整備する

ブラウザでの手動確認だけに頼ると、機能追加のたびに既存機能が壊れていないか確認する手間が大きくなる。そこでStreamlitのテストフレームワーク(AppTest)を使い、ブラウザを介さずに画面の入力・表示をコードでテストできるようにした。

from streamlit.testing.v1 import AppTest

def test_card_auto_settlement():
    at = AppTest.from_file("pages/1_収支記録.py").run()
    # フォームに入力して送信し、結果を検証する
    at.selectbox(key="tx_type").select("支出").run()
    ...
    assert at.session_state["last_settlement_date"] == expected_settlement_date

これにより、機能追加や修正のたびにテストを流すだけで、既存の会計ロジックが壊れていないかを機械的に確認できるようになった。

実際に使ってみて追加できた機能

  • クレジットカードごとに締め日・支払日をマスタ管理し、引き落とし日を自動計算
  • 店舗からカード会社への通知遅延で締め日をまたいでしまうケースに対応する、引き落とし日の手動調整機能
  • 任意の日付時点にさかのぼった口座残高・総資産の確認
  • カテゴリごとに固定した配色でのグラフ表示(月が変わっても色が変わらないようにする調整)
  • 前後の日付・月にワンクリックで移動できるナビゲーション

これらはいずれも、既製の家計簿アプリでは細かすぎて対応されていなかったり、逆に過剰だったりする部分であり、自作したからこそ自分の使い方にぴったり合わせ込めた点である。

これからClaude Codeで同じようなツールを作る人へ

  • 最初から完璧な設計を目指さず、まず目的(何を確認したいか)を明確に伝えることから始めるとよい
  • 機能は一度に全部依頼せず、小さく分けて段階的に実装し、都度動作確認する
  • 既存データの移行がある場合は、文字コードや二重計上など、実データ特有の落とし穴を想定しておく
  • 「残高が合う」ような集計・会計ロジックは、実運用してからバグに気づくことがあるため、自動テストを整備しておくと安心できる
  • DBを直接書き換えるような改修・テストを行う際は、事前にバックアップを取る習慣をつけておくとデータ破損のリスクを避けられる

まとめ

Windows専用ソフトからMac環境への移行をきっかけに、初めてClaude Codeを使って家計簿アプリを一から自作してみた。要件を伝えるだけで実装が進む開発体験は非常に効率的だった一方、CSVの文字コード対応や二重計上防止といった移行特有の課題、さらには実データでしか発覚しない会計ロジックの不具合など、地道な検証作業は避けて通れなかった。段階的に機能を実装し、都度テストで確認するというサイクルを回すことで、最終的には自分の家計管理スタイルに完全に合わせて作り込めるアプリが手に入った。これからClaude Codeで個人用ツールを作ってみたい人にとって、参考になれば幸いである。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA