第 08 章「アプリを作る ── CLI ツール、Flet、Flutter」の 2 番目の角度: サブコマンド構造を持った業務 CLI。
章のどの主張に対応するか
CLI ツールの作成と配布: 1 時間で書いて、
pip installで世界中の Python ユーザーに即配布。
CLI で動く処理を Flet で GUI 化する追加コスト: Flet ライブラリのインストール と数十行の追加コード、1 時間。Flutter で書き直すなら 1 ヶ月。
(章本文「実例: 数字で見る」より)
example-1 が「写真整理 CLI」(単一コマンド)、これは 5 つのサブコマンド を持つ業務 CLI を click で書く。CLI を「アプリ」として育てる入口。
やること
journal.py 1 ファイル / 約 100 行で:
journal add "テキスト" --tag meeting # メモ追加
journal list [--limit N] [--tag タグ] # 一覧
journal search "キーワード" # 全文検索(LIKE)
journal stats # タグ別集計(JSON)
journal export --out out/journal.md # Markdown エクスポート
journal --help # 自動生成のヘルプ
ストレージは SQLite 1 ファイル(out/journal.db)。
make all でデモ実行(8 件投入 → 一覧・検索・集計・エクスポート)。
構成
example-2/
├── README.md
├── journal.py ── click ベースの CLI(約 100 行)
├── Makefile ── デモシナリオ
├── results.md
└── out/
├── journal.db ── SQLite データ
├── stats.json ── stats サブコマンドの出力
└── journal.md ── export サブコマンドの出力
実行
pip install click
make clean && make all
各サブコマンドのヘルプは make help。
なぜこれが「実例」になるのか
業務メモ・日報の世界には 3 つの選択肢がある:
| 選択肢 | コスト | 自由度 |
|---|---|---|
| Notion / Evernote | 月 $10〜 | サービス依存・退会で消える |
| Word + フォルダ | フォントずれ・検索しづらい | × |
| CLI + Markdown | 0 円 | ○ 全部自分のもの |
このフォルダの CLI なら:
- メモは SQLite(1 ファイル、Git で履歴管理可)
- エクスポートは Markdown(章 01 の世界に直結)
- 全文検索は SQL の LIKE(数 ms)
- ヘルプは 自動生成(click)
- スクリプトに組み込める(
for line in $(...); do journal add "$line"; done)
そしてこのまま:
- cron で毎時 stats を JSON 出力(自動レポート)
- メールから add に流す(IMAP で受信 → CLI 呼び出し)
- Flet で GUI 化(章本文の言う「1 時間で GUI」、CLI ロジックを再利用)
- PyPI で配布(
pip install <your-journal>)
これが章で言う「まず CLI、必要なら GUI に上げる」の具体形。
「Flet にする」の意味
このフォルダは Flet を使っていないが、Flet にする手順は:
import flet as ft
from journal import conn # 既存ロジックを再利用
def main(page: ft.Page):
text = ft.TextField(label="メモ")
def add_cb(e):
with conn() as c:
c.execute("INSERT INTO notes (text) VALUES (?)", (text.value,))
text.value = ""
page.update()
page.add(text, ft.ElevatedButton("追加", on_click=add_cb))
ft.app(target=main)
追加 30 行で GUI 完成。CLI のロジック(SQLite アクセス・スキーマ)は 完全に再利用される。書き直しは発生しない。
これが章の「CLI を一段ずつ昇格させる」の意味。
配布
# 1. PyPI に上げる(pyproject.toml を 1 つ書くだけ)
pip install build twine
python3 -m build
twine upload dist/*
# 2. ユーザは
pip install your-journal
journal add "first note"
App Store の審査も Apple Developer Program も要らない。世界中の Python ユーザーに即配布。
計測結果 — 第 08 章 example-2
実行環境: Linux 6.18 / Python 3.11 / click 8.x / SQLite 3.45
規模と性能
| 項目 | 数値 |
|---|---|
journal.py 行数 |
約 100 行(コメント込み) |
| 依存パッケージ | click のみ(SQLite は標準ライブラリ) |
| サブコマンド数 | 5 個 + --help |
| 1 サブコマンドの実行時間 | 数 ms(Python 起動 + SQLite クエリ) |
| 起動オーバーヘッド | 約 50 ms(Python インタプリタ) |
デモシナリオ(make all の出力)
1. メモを 8 件投入
$ journal add "山田農園と打ち合わせ。来月から週次納品" --tag meeting
added #1: 山田農園と打ち合わせ。来月から週次納品
$ journal add "経費レポートを Claude に作らせた、20 分で完了" --tag review
added #2: 経費レポートを Claude に作らせた、20 分で完了
...(計 8 件)
2. 一覧(最新 5 件)
$ journal list --limit 5
8 2026-05-05 06:11 経理: 4 月分の領収書を Claude に分類させた、3 分
7 2026-05-05 06:11 Mochi.ai の LP に「365 日返金保証」を追記
6 2026-05-05 06:11 [todo] 山田農園に来週納品手配のメールを送る
5 2026-05-05 06:11 今月の MRR が目標に到達
4 2026-05-05 06:11 [ops] サーバ再起動 04:00 完了、ダウンタイム 12 秒
3. タグ絞り込み
$ journal list --tag meeting
1 2026-05-05 06:11 [meeting] 山田農園と打ち合わせ。来月から週次納品
4. 全文検索
$ journal search 山田
'山田' に一致: 2 件
6 2026-05-05 山田農園に来週納品手配のメールを送る
1 2026-05-05 山田農園と打ち合わせ。来月から週次納品
5. タグ別集計(JSON, out/stats.json)
{
"total": 8,
"by_tag": [
{"tag": "(no-tag)", "n": 3},
{"tag": "todo", "n": 1},
{"tag": "review", "n": 1},
{"tag": "ops", "n": 1},
{"tag": "meeting", "n": 1},
{"tag": "lead", "n": 1}
]
}
JSON で出すので、cron で集計 → Slack に投げる、なども容易。
6. Markdown エクスポート(out/journal.md)
# 業務日報
件数: 8
## 2026-05-05
- 06:11 `meeting` 山田農園と打ち合わせ。来月から週次納品
- 06:11 `review` 経費レポートを Claude に作らせた、20 分で完了
- 06:11 `lead` 新規顧客 C016 が問い合わせ、料金で要確認
- 06:11 `ops` サーバ再起動 04:00 完了、ダウンタイム 12 秒
...
そのまま月次報告に貼り付けられる Markdown が出る。
7. 自動生成のヘルプ
$ journal --help
Usage: journal.py [OPTIONS] COMMAND [ARGS]...
一行メモから月次報告まで、ひとつの CLI で。
Commands:
add メモを追加。
export Markdown 形式でエクスポート(月次報告用)。
list 最新のメモを一覧。
search 全文検索(LIKE)。
stats 件数・タグ別集計を JSON で。
@click.command() のデコレータと docstring から 自動生成。
--help を書く必要がない。
CLI vs SaaS(章本文との対応)
| 項目 | Notion / Evernote | この CLI |
|---|---|---|
| 月額 | $10〜 | 0 円 |
| データの所有権 | サービス側 | 自分 |
| 検索 | 数 ms(クラウド) | 数 ms(SQLite) |
| エクスポート | 限定的 | Markdown 完全 |
| AI 連携 | 限定的 | journal.py を Claude に渡せる |
| サービス終了で消える? | 消える | 消えない |
来月の運用
cron に登録:
0 9 * * 1 journal export --since "$(date -d 'last week' +%Y-%m-%d)" --out /tmp/weekly.md
毎週月曜 9:00 に「先週の業務日報」が /tmp/weekly.md に出る。それを
Claude に「これを月次報告用に要約して」と渡せば、月次報告も自動。
再現手順
pip install click
make clean && make all
実行は数秒で完了。