GitHub Actions活用 - Qiita記事の投稿を完全自動化する【手動・予約投稿対応】
⚠️ 注意事項
免責事項:
- この記事の内容は 2026-01-03 時点の情報に基づいています
- 実際の環境での動作を保証するものではありません
- GitHub ActionsとQiita CLIのライセンスを確認してください
- Qiitaトークンの管理には十分注意してください
📝 TL;DR
- 課題: Qiita記事の投稿作業が手動で手間がかかる
- 解決策: GitHub Actionsで投稿を自動化 + 予約投稿機能
- 効果: 記事投稿時間を10分 → 0分に短縮(100%自動化)
- 導入工数: 約 3時間
-
予約投稿: ファイル名で公開日を指定(例:
2026-01-15-記事タイトル.md)
📊 改善効果サマリー
| 項目 | 改善前 | 改善後 | 削減率 |
|---|---|---|---|
| 投稿作業時間 | 10分 | 0分 | 100%削減 |
| エラー発生率 | 5% | 0% | 100%削減 |
| 予約投稿 | ❌ 不可 | ✅ 可能 | - |
| 導入コスト | - | 3時間 | - |
| 学習コスト | - | 低 | - |
🎯 背景
なぜこの改善に取り組んだか
技術ブログを定期的に書くことは重要ですが、投稿作業と公開タイミングの管理が課題でした。
従来の課題:
- Qiita記事の投稿に毎回10分程度かかっていた
- 予約投稿機能がないため、公開日時を調整できない
- Webブラウザでの手動操作が必要
- 記事のバージョン管理がGitで完結しない
- 投稿ミス(タグの付け忘れ、公開範囲の設定ミスなど)が発生
対象読者
- Qiitaに定期的に記事を投稿している方
- 記事をGitで管理したい方
- 予約投稿機能が欲しい方
- GitHub Actionsで自動化に興味がある方
- Obsidianなどのマークダウンエディタで記事を書いている方
😓 課題
従来の業務フロー
Qiita記事を投稿する際の従来のフローは以下の通りでした。
1. Obsidianで記事を執筆(60分)
2. Qiita Webページにログイン(1分)
3. 「新規投稿」ボタンをクリック(10秒)
4. タイトル、タグ、本文をコピペ(3分)
5. プレビューで確認(3分)
6. 公開範囲(public/private)を設定(30秒)
7. 「投稿」ボタンをクリック(10秒)
8. 投稿後の確認(2分)
合計: 約70分/記事(執筆60分 + 投稿作業10分)
具体的な問題点
-
手動操作が多い
- 詳細: Webブラウザでの手動操作が必要
- 影響: 投稿作業だけで10分程度かかる
- 頻度: 週1回程度の投稿
-
予約投稿ができない
- 詳細: Qiita標準機能に予約投稿がない
- 影響: 公開日時を自分で管理・手動投稿が必要
- 頻度: 週末にまとめて書いて平日に公開したい場合など
-
バージョン管理が不完全
- 詳細: Qiita Web上での編集履歴とGit履歴が分離
- 影響: 記事の変更履歴を追いにくい
-
投稿ミスの発生
- 詳細: タグの付け忘れ、公開範囲の設定ミス
- 影響: 再編集が必要になる
定量的な影響
- 1週間あたり: 1記事 × 10分 = 10分
- 年間: 10分 × 52週 = 520分 ≒ 8.7時間
→ 年間 8.7時間 = 約1日分の工数
💡 解決策
採用したアプローチ
GitHub ActionsとQiita CLIを組み合わせた自動投稿システム + 予約投稿機能を構築しました。
選定理由:
- ✅ 無料で使える(GitHub Actionsの無料枠内で十分)
- ✅ Gitでバージョン管理が完結する
- ✅ Qiita公式のCLIツールを使うので安定性が高い
- ✅ 手動実行と自動実行の両方に対応可能
- ✅ ファイル名ベースの予約投稿が実現可能
代替案との比較:
| 項目 | GitHub Actions | Qiita Web UI | ローカルスクリプト |
|---|---|---|---|
| 導入コスト | 低 | なし | 中 |
| 学習コスト | 中 | 低 | 中 |
| バージョン管理 | 高 | 低 | 中 |
| 自動化 | 高 | 低 | 中 |
| 予約投稿 | ✅ 可能 | ❌ 不可 | ✅ 可能 |
改善後の業務フロー
1. Obsidianで記事を執筆(60分)
2. ファイル名に公開日を指定(例: 2026-01-15-記事タイトル.md)
3. Gitにコミット & プッシュ(30秒)
4. 【自動】指定日時に GitHub Actions が自動投稿(0秒)
合計: 約60.5分/記事(執筆60分 + 投稿作業0.5分)
→ 投稿作業が95%削減 + 予約投稿が可能に
アーキテクチャ図
┌─────────────────┐
│ Obsidian │
│ (記事執筆) │
│ファイル名で日付指定│
│ 2026-01-15-*.md │
└────────┬────────┘
│
│ git push
▼
┌─────────────────┐
│ GitHub │
│ (リポジトリ) │
│ public/*.md │
└────────┬────────┘
│
│ cron (毎日09:00 JST)
▼
┌─────────────────┐
│ GitHub Actions │
│ (ワークフロー) │
│ - 日付フィルタ │
│ - Qiita CLI │
│ - レート制限対策 │
└────────┬────────┘
│
│ Qiita API
▼
┌─────────────────┐
│ Qiita │
│ (記事公開) │
└─────────────────┘
🔧 実装
開発環境
| 項目 | 詳細 |
|---|---|
| OS | Windows 11 |
| Git | 2.43.0 |
| Node.js | 20.x |
| Qiita CLI | 1.6.2+ |
セットアップ手順
1. Qiitaトークンの取得
# 1. Qiitaにログイン
# 2. 設定 > アプリケーション にアクセス
# https://qiita.com/settings/applications
# 3. 「新しくトークンを発行する」をクリック
# 4. 以下の権限を選択:
# ✅ read_qiita - Qiita上のデータを読み取る
# ✅ write_qiita - Qiita上のデータを更新・作成する
# 5. トークンをコピー(一度しか表示されないので注意!)
2. GitHubシークレットの設定
# 1. GitHubリポジトリにアクセス
# 2. Settings > Secrets and variables > Actions に移動
# 3. New repository secret をクリック
# 4. 以下を設定:
# Name: QIITA_TOKEN
# Secret: (ステップ1でコピーしたトークン)
# 5. Add secret をクリック
3. Qiita CLIの初期化
リポジトリのルートディレクトリで以下を実行します。
# リポジトリのルートで実行
npx qiita init
# 以下のファイルが生成されます:
# - qiita.config.json (Qiita CLI設定)
# - .github/workflows/publish.yml (不要なので削除)
# - .gitignore (既存のものがある場合は確認)
生成されたファイルの処理:
# publish.yml は削除(カスタムワークフローを使うため)
rm .github/workflows/publish.yml
4. ディレクトリ構造の作成
# publicディレクトリを作成(まだない場合)
mkdir public
# 最終的なディレクトリ構造:
# .
# ├── .github/
# │ └── workflows/
# │ └── daily-qiita-publish.yml # これから作成
# ├── public/
# │ ├── 2026-01-15-記事タイトル1.md
# │ └── 2026-01-20-記事タイトル2.md
# └── qiita.config.json
実装詳細
ステップ1: 毎日投稿ワークフローの作成
GitHub Actionsのワークフローを定義します。
.github/workflows/daily-qiita-publish.yml を作成:
name: Daily Qiita Publish (毎日投稿)
on:
# 毎日 00:00 UTC(日本時間 09:00)に実行
schedule:
- cron: '0 0 * * *' # 毎日 00:00 UTC = 09:00 JST
# 手動実行も可能
workflow_dispatch:
inputs:
actually_publish:
description: '実際に投稿する(falseの場合はドライラン)'
required: true
type: boolean
default: true
permissions:
contents: read
jobs:
daily-publish:
runs-on: ubuntu-latest
steps:
- name: 📋 入力パラメータの表示
if: github.event_name == 'workflow_dispatch'
run: |
echo "## 🧪 実行パラメータ" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "- **実際に投稿**: ${{ inputs.actually_publish }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: 📦 Qiita CLI インストール
run: |
echo "Installing Qiita CLI..."
npm install -g @qiita/qiita-cli
echo "✅ Qiita CLI installed successfully"
- name: 📅 今日の日付を取得
id: date
run: |
TODAY=$(date -u +%Y-%m-%d)
echo "TODAY=$TODAY" >> $GITHUB_OUTPUT
echo "Today: $TODAY"
echo "## 📅 実行日" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "- **日付**: $TODAY" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
- name: 📝 投稿対象の記事を検出
id: check_articles
run: |
set -euo pipefail
echo "## 📝 投稿対象の記事" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
TODAY="${{ steps.date.outputs.TODAY }}"
PUBLISH_COUNT=0
SKIP_COUNT=0
# 投稿対象のファイルリストを保存するファイル
PUBLISH_LIST="/tmp/publish_files.txt"
> "$PUBLISH_LIST" # ファイルを空にする
# public/ 配下のMarkdownファイルを処理
for file in public/*.md; do
if [ ! -f "$file" ]; then
continue
fi
filename=$(basename "$file")
# ファイル名から日付を抽出(YYYY-MM-DD形式)
if [[ $filename =~ ^([0-9]{4}-[0-9]{2}-[0-9]{2})- ]]; then
publish_date="${BASH_REMATCH[1]}"
# タイトルを抽出
title=$(grep "^title:" "$file" | sed 's/^title: //' | tr -d '"' || echo "タイトルなし")
# 公開日が今日と一致する場合のみ
if [[ "$publish_date" == "$TODAY" ]]; then
# private: false の記事のみ投稿対象
if grep -q "^private: false" "$file"; then
echo "- ✅ **$filename**" >> $GITHUB_STEP_SUMMARY
echo " - タイトル: $title" >> $GITHUB_STEP_SUMMARY
echo " - 公開日: $publish_date" >> $GITHUB_STEP_SUMMARY
echo " - ステータス: **投稿対象**" >> $GITHUB_STEP_SUMMARY
PUBLISH_COUNT=$((PUBLISH_COUNT + 1))
# 投稿対象のファイル名をリストに追加
echo "$filename" >> "$PUBLISH_LIST"
else
echo "- ⏸️ **$filename**" >> $GITHUB_STEP_SUMMARY
echo " - タイトル: $title" >> $GITHUB_STEP_SUMMARY
echo " - 公開日: $publish_date" >> $GITHUB_STEP_SUMMARY
echo " - ステータス: private: true(スキップ)" >> $GITHUB_STEP_SUMMARY
SKIP_COUNT=$((SKIP_COUNT + 1))
fi
else
echo "- ⏰ **$filename**" >> $GITHUB_STEP_SUMMARY
echo " - タイトル: $title" >> $GITHUB_STEP_SUMMARY
echo " - 公開日: $publish_date(まだ)" >> $GITHUB_STEP_SUMMARY
echo " - ステータス: 予約中(スキップ)" >> $GITHUB_STEP_SUMMARY
SKIP_COUNT=$((SKIP_COUNT + 1))
fi
echo "" >> $GITHUB_STEP_SUMMARY
else
echo "- ⚠️ **$filename**" >> $GITHUB_STEP_SUMMARY
echo " - ファイル名に日付がありません(YYYY-MM-DD-title.md 形式が必要)" >> $GITHUB_STEP_SUMMARY
echo " - ステータス: スキップ" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
SKIP_COUNT=$((SKIP_COUNT + 1))
fi
done
echo "---" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**統計**:" >> $GITHUB_STEP_SUMMARY
echo "- 投稿対象: $PUBLISH_COUNT 件" >> $GITHUB_STEP_SUMMARY
echo "- スキップ: $SKIP_COUNT 件" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "PUBLISH_COUNT=$PUBLISH_COUNT" >> $GITHUB_OUTPUT
- name: 🧪 ドライラン(投稿はしない)
if: |
github.event_name == 'workflow_dispatch' &&
inputs.actually_publish == false &&
steps.check_articles.outputs.PUBLISH_COUNT != '0'
run: |
echo "## 🧪 ドライランモード" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "✅ 投稿対象の記事: ${{ steps.check_articles.outputs.PUBLISH_COUNT }}件" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "ℹ️ 実際には投稿していません" >> $GITHUB_STEP_SUMMARY
- name: 🚀 Qiitaに投稿
if: |
(github.event_name == 'schedule' ||
(github.event_name == 'workflow_dispatch' && inputs.actually_publish == true)) &&
steps.check_articles.outputs.PUBLISH_COUNT != '0'
env:
QIITA_TOKEN: ${{ secrets.QIITA_TOKEN }}
run: |
echo "## 🚀 Qiitaに投稿中..." >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
# 投稿対象のファイルリストを読み込む
PUBLISH_LIST="/tmp/publish_files.txt"
if [ ! -f "$PUBLISH_LIST" ]; then
echo "❌ 投稿対象リストが見つかりません" >> $GITHUB_STEP_SUMMARY
exit 1
fi
echo "投稿を開始します..."
echo "" >> $GITHUB_STEP_SUMMARY
# リストに記載されたファイルのみを投稿
COUNT=0
while IFS= read -r filename; do
if [ -n "$filename" ]; then
COUNT=$((COUNT + 1))
# .md 拡張子を削除(Qiita CLIは拡張子なしで指定する)
basename="${filename%.md}"
echo "📤 投稿中 ($COUNT): $filename"
echo "- 📤 $filename" >> $GITHUB_STEP_SUMMARY
npx qiita publish "$basename"
# APIレート制限を避けるため、投稿間隔を空ける(5秒待機)
echo "⏳ 次の投稿まで5秒待機..."
sleep 5
fi
done < "$PUBLISH_LIST"
echo "" >> $GITHUB_STEP_SUMMARY
echo "✅ **投稿が完了しました!**" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "🔗 [Qiitaで確認](https://qiita.com/)" >> $GITHUB_STEP_SUMMARY
- name: ℹ️ 投稿する記事がない場合
if: steps.check_articles.outputs.PUBLISH_COUNT == '0'
run: |
echo "## ℹ️ 投稿する記事がありません" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**理由**:" >> $GITHUB_STEP_SUMMARY
echo "- 公開日が今日で `private: false` の記事がない" >> $GITHUB_STEP_SUMMARY
echo "- または、ファイル名が `YYYY-MM-DD-title.md` 形式ではない" >> $GITHUB_STEP_SUMMARY
- name: 📊 最終サマリー
if: always()
run: |
echo "" >> $GITHUB_STEP_SUMMARY
echo "---" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "## 📊 実行結果" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
if [ "${{ job.status }}" == "success" ]; then
echo "✅ **正常に完了しました**" >> $GITHUB_STEP_SUMMARY
else
echo "❌ **エラーが発生しました**" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "詳細はログを確認してください" >> $GITHUB_STEP_SUMMARY
fi
echo "" >> $GITHUB_STEP_SUMMARY
echo "---" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "💡 このワークフローは毎日 09:00 JST に自動実行されます。" >> $GITHUB_STEP_SUMMARY
ポイント:
- ✅ 日付ベースのフィルタリング: ファイル名の日付(YYYY-MM-DD)を抽出して今日の日付と比較
- ✅ レート制限対策: 投稿間隔に5秒の待機時間を設定
- ✅ ドライラン機能: 手動実行時に
actually_publish: falseでテスト可能 - ✅ 拡張子の処理: Qiita CLIは
.mdなしのファイル名を期待するため自動削除
ステップ2: 記事ファイルの作成
記事ファイルを public/ ディレクトリに配置します。
ファイル名のルール:
YYYY-MM-DD-記事タイトル.md
例:
2026-01-15-GitHub-Actionsで自動化.md
2026-01-20-テスト駆動開発入門.md
記事のフロントマター:
---
title: 記事タイトル
tags:
- GitHub
- Qiita
private: false # false で公開、true で下書き
updated_at: ''
id: null
organization_url_name: null
slide: false
ignorePublish: false
---
# 記事タイトル
本文をここに書く...
注意点:
- ✅
private: falseで公開、trueで下書き保存 - ✅ タグは最大5つまで設定可能
- ✅ ファイル名の日付が公開日になる(例: 2026-01-15 の記事は 2026-01-15 09:00 JSTに自動投稿)
ステップ3: 動作確認
- ドライラン(テスト実行)
# GitHubリポジトリの Actions タブにアクセス
# "Daily Qiita Publish" ワークフローを選択
# "Run workflow" ボタンをクリック
# "実際に投稿する" を false に設定して実行
# → 投稿対象の記事が表示されるが、実際には投稿されない
- 手動実行で投稿
# "実際に投稿する" を true に設定して実行
# → 投稿対象の記事が実際にQiitaに投稿される
- 自動実行(予約投稿)
# 記事をpush
git add public/2026-01-15-記事タイトル.md
git commit -m "Add new article for 2026-01-15"
git push
# → 2026-01-15 09:00 JST に自動的にQiitaに投稿される
📈 効果測定
定量的な効果
作業時間の削減
| 作業 | 改善前 | 改善後 | 削減時間 |
|---|---|---|---|
| Webログイン | 1分 | 0分 | 1分 |
| コピー&ペースト | 3分 | 0分 | 3分 |
| プレビュー確認 | 3分 | 0分 | 3分 |
| 設定確認 | 1分 | 0分 | 1分 |
| 投稿後確認 | 2分 | 0分 | 2分 |
| 合計 | 10分 | 0分 | 10分 (100%削減) |
予約投稿の効果
【改善前】
- 週末に記事を書く
- 平日の朝に手動で投稿(10分 × 5日 = 50分/週)
- 投稿を忘れることもある
【改善後】
- 週末にまとめて記事を書く
- ファイル名で公開日を指定してpush
- 毎朝09:00に自動投稿(0分)
- 投稿忘れゼロ
→ 週50分の削減 + 投稿の確実性向上
年間削減効果の試算
1回あたりの削減時間: 10分
月間投稿回数: 4回
年間投稿回数: 4回 × 12ヶ月 = 48回
年間削減時間: 48回 × 10分 = 480分
= 8時間の工数削減
※ 時給3,000円換算で、年間 24,000円のコスト削減
定性的な効果
-
✅ 投稿ミスの削減
- タグや公開範囲の設定ミスがなくなった
-
✅ バージョン管理の一元化
- Git履歴ですべての変更を追跡可能
-
✅ 予約投稿の実現
- ファイル名で公開日を指定できる
- 週末にまとめて記事を書いて平日に自動公開
-
✅ 心理的負担の軽減
- 「投稿作業が面倒」という心理的障壁が完全になくなった
- 記事執筆だけに集中できるようになった
-
✅ 投稿の確実性向上
- 投稿忘れがなくなった
- スケジュール通りに公開される
🚀 導入方法
導入の流れ
-
準備フェーズ(30分)
- Qiitaトークンの取得
- GitHubシークレットの設定
- リポジトリの準備
-
実装フェーズ(2時間)
- Qiita CLIの初期化
- ワークフローファイルの作成
- テスト記事の作成
- ドライランでテスト
-
検証フェーズ(30分)
- 手動実行でテスト
- 投稿の成功確認
- エラーハンドリングの確認
- ログの確認
必要なリソース
人的リソース
- エンジニア: GitHub Actionsの基礎知識
技術リソース
- GitHub: 無料プラン(Actionsの無料枠)
- Qiita: 無料アカウント
時間リソース
- 初期導入: 約 3時間
- 学習期間: 約 1時間
- メンテナンス: ほぼ不要
⚠️ 留意点・制約事項
技術的な制約
-
Qiita CLIの仕様
- 内容: Qiita CLIは
.md拡張子なしでファイル名を指定 - 対策: ワークフロー内で自動的に拡張子を削除
- 内容: Qiita CLIは
-
トークンの管理
- 内容: Qiitaトークンは漏洩厳禁
- 対策: GitHubシークレットで管理
-
APIレート制限
- 内容: Qiita APIには投稿頻度制限がある
- 対策: 投稿間隔に5秒の待機時間を設定
-
タイムゾーン
- 内容: GitHub Actionsはデフォルトで UTC
- 対策: cron を
0 0 * * *(00:00 UTC = 09:00 JST) に設定
運用上の注意点
- トークンの有効期限: Qiitaトークンに有効期限はないが、定期的に再発行を推奨
-
ファイル名の形式:
YYYY-MM-DD-title.md形式を厳守 -
公開範囲の確認:
private: falseで公開されることを理解 - エラーログの確認: GitHub ActionsのログでエラーをチェックLUCKily
想定されるリスクと対策
| リスク | 影響度 | 発生確率 | 対策 |
|---|---|---|---|
| トークン漏洩 | 高 | 低 | GitHubシークレットで管理 |
| ワークフロー失敗 | 中 | 低 | ログ確認とリトライ |
| 意図しない公開 | 高 | 低 |
private: true で下書き保存 |
| ファイル名ミス | 中 | 低 | ドライランでテスト |
🔄 今後の展開
短期的な改善計画(1〜3ヶ月)
-
IFTTT連携でX(Twitter)への自動投稿(実装済み) -
スケジュール実行で予約投稿機能の実装(実装済み) - 投稿通知の追加(Slackなど)
💬 まとめ
この改善で実現できたこと
- ✅ Qiita記事の投稿時間を100%削減(10分 → 0分)
- ✅ 投稿ミスをゼロに
- ✅ Gitでバージョン管理が完結
- ✅ ファイル名ベースの予約投稿を実現
- ✅ 毎日09:00 JSTに自動実行
学んだこと・気づき
-
GitHub Actionsは手軽に始められる
- 無料枠で十分使える
- YAML設定ファイルもシンプル
- cron式で柔軟なスケジューリングが可能
-
環境変数での認証が推奨
-
credentials.jsonよりも環境変数が安全で簡単 - GitHubシークレットで簡単に管理
-
-
小さく始めて段階的に改善
- まずは手動実行で動作確認
- その後、スケジュール実行を追加
- 最後に予約投稿機能を実装
-
レート制限への配慮が重要
- 連続投稿時は適切な待機時間が必要
- Qiita APIの制限を理解して実装
-
ファイル名ベースのスケジューリングが便利
- 直感的で管理しやすい
- Gitで変更履歴も追跡可能
推奨する人
- ✅ Qiitaに定期的に記事を投稿している方
- ✅ 記事をGitで管理したい方
- ✅ 予約投稿機能が欲しい方
- ✅ GitHub Actionsを試してみたい方
- ✅ 投稿作業を完全自動化したい方
最後に
GitHub ActionsとQiita CLIを組み合わせることで、記事投稿の手間を完全になくし、さらに予約投稿機能まで実現できました。ファイル名で公開日を指定するシンプルな仕組みで、週末にまとめて記事を書いて平日に自動公開するワークフローが確立しました。
補足:
記事の最終確認は投稿前にドライランで確認することをお勧めします。actually_publish: false でテスト実行できます。
📚 参考資料
公式ドキュメント
関連記事
📝 更新履歴
- 2026-01-03: 予約投稿機能を追加、全体を大幅に改訂
- 2025-12-30: 初版公開