4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ひとり朝会・夕会システムをつくって AI と朝会・夕会している話 (基本設計と Python での実装例)

Last updated at Posted at 2026-01-13

ひとり朝会・夕会システムをつくって AI と朝会・夕会しているので、基本設計と Python での実装例を記します。

  • 私は Python で実装しましたが、お好きな言語で実装いただけると思います。
  • Python 実装例として「手動トリガー版」と「スケジュール実行版」を示していますが、「手動トリガー版」をお好きなスケジュール実行ソフトで実行いただいてもよいです。

実装は Claude CodeObsidian を前提としています。ただ、設計自体は他の生成 AI (ただしローカルファイルを閲覧・編集できるかできるよう補助したもの)、他のテキスト閲覧・編集ソフトでも可能です。

朝会・夕会の流れやプロンプトはジャストアイデアです。目標達成のための自動朝会のやり方について知見をお持ちの方は、アドバイスいただけるとありがたいです。

ひとり朝会・夕会システムの基本設計

私が構築した朝会・夕会システムの基本設計は以下です。

凡例
:robot: : これは自動でやります。
:boy: : これはユーザがやります。

ユーザの事前準備

  • :boy: Obsidian 保管庫以下に、ディレクトリ MtgRoom/ を作成します (名前は何でも可)。
  • :boy: MtgRoom/README.md に中長期的な目標や、重要な予定を書いておきます。
    • AI に日報を確認してもらうとき考慮してほしい自分のゴールを書けばよいです。
  • :boy: 日報置き場 MtgRoom/Daily/ も作成しておきます。
  • :boy: Claude Code に MtgRoom/Daily/ 以下への書き込みを許可しておきます。

朝会の流れ

  • :robot: 朝会の時刻になったら、その日の日報 MtgRoom/Daily/YYYYMMDD.md を新規作成し、Obsidian で日報を開き、また、音を鳴らします。
  • :robot: 標準出力に 朝会をやるので日報に「## 今日やるタスク」を記入してください。記入が終わったらエンターキーを押してください。 と表示します。
  • :boy: 日報に「今日やるタスク」を記入してエンターキーを押します。
  • :robot: Claude Code に以下の「朝会での生成 AI へのプロンプト」を投げます (Claude Code には回答完了時に音が鳴るように設定しています)。
  • :boy: 音が鳴ったら Obsidian 上にフィードバックが反映されているので、確認します。
YYYYMMDD.md
## 今日やるタスク
## 朝会でのフィードバック
## 今日やったタスク
## 夕会でのフィードバック
朝会での生成 AI へのプロンプト
## 説明
このディレクトリは私 (クッキー) の進捗管理のためのプロジェクトです。
README.md には目標、予定表、タスク一覧を書いています。
Daily/20260113.md には今日の日報を書いています。
今は朝会なので、日報で記入済みなのは「## 今日やるタスク」までです。

## 依頼事項
README.md の目標を達成し、また、予定表にある予定をこなす上で
Daily/20260113.md の「## 今日やるタスク」が最適なものになっているか考え、
Daily/20260113.md の「## 朝会でのフィードバック」にフィードバックを記入してください。
フィードバックには以下の内容を含めてください。
- 今日まず着手すべき最優先のこと
- 今日はやらない方がよいこと
- 今日のミニマムなゴール

夕会の流れ

  • :robot: 夕会の時刻になったら、Obsidian で日報を開き、また、音を鳴らします。
  • :robot: 標準出力に 夕会をやるので日報に「## 今日やったタスク」を記入してください。記入が終わったらエンターキーを押してください。 と表示します。
  • :boy: 日報に「今日やったタスク」を記入してエンターキーを押します。
  • :robot: Claude Code に以下の「夕会での生成 AI へのプロンプト」を投げます (Claude Code には回答完了時に音が鳴るように設定しています)。
  • :boy: 音が鳴ったら Obsidian 上にフィードバックが反映されているので、確認します。
夕会での生成 AI へのプロンプト
## 説明
このディレクトリは私 (クッキー) の進捗管理のためのプロジェクトです。
README.md には目標、予定表、タスク一覧を書いています。
Daily/20260113.md には今日の日報を書いています。

## 依頼事項
README.md の目標を達成し、また、予定表にある予定をこなす上で
Daily/20260113.md の「## 夕会でのフィードバック」にフィードバックを記入してください。
フィードバックには以下のアドバイスを含めてください。
- 明日以降作業をするときに私 (クッキー) が実践するとよいこと (今日やったことに基づき具体的に)

Python 実装例

以下の実装例では、ミーティング用ディレクトリを ~/Dropbox/obsidian/Mercury/Zinnia/ (Mercury が保管庫名) とします (異なる場合は DailyMeeting のクラス変数を変更)。

ディレクトリ構成
~/
└─ Dropbox/obsidian/Mercury/Zinnia/  # ミーティング用ディレクトリ (Obsidian 保管庫下)
    ├─ .claude/settings.local.json  # Claude への書き込みや Web 検索の許可
    ├─ meeting.py  # 朝会・夕会クラスの実装 (ただ後述のようにこれ自体の置き場はどこでもよい)
    ├─ README.md  # 中長期目標や重要な予定 (AI に伝えたい自分のゴール)
    └─ Daily/  # 日報置き場
        ├─ 20260101.md
        ├─ 20260102.md

STEP1. 手動トリガー版

先の基本設計を Python (標準ライブラリのみ) で実装したのが下記の meeting.py です。
python meeting.py --am で朝会、python meeting.py --pm で夕会が開始できます。
ただ、これだと自分でトリガーする必要があります (それでもよければこれでよいです)。

  • このスクリプト自体はどこに置いて実行してもよいです (アラームも Obsidian URI も実行場所を問わないし、Claude 呼び出し時には明示的にミーティング用ディレクトリを作業ディレクトリにしているため)。
meeting.py
import pathlib
import datetime
import subprocess
import argparse


class DailyMeeting:
    mtg_room = 'Mercury/Zinnia/'  # Obsidian 保管庫名と保管庫下のミーティング用ディレクトリパス
    mtg_room_path = pathlib.Path('~/Dropbox/obsidian/' + mtg_room).expanduser()

    @classmethod
    def daily_report(cls, today):
        return 'Daily/' + today + '.md'

    @classmethod
    def alerm(cls):  # アラームを鳴らす (Windows でない場合は修正ください)
        subprocess.run([
            "powershell.exe", "-Command",
            "(New-Object Media.SoundPlayer 'C:\\Windows\\media\\Alarm01.wav').PlaySync()",
        ], check=True)

    @classmethod
    def obsidian(cls, page):  # Obsidian を開く
        subprocess.run([
            "cmd", "/c", "start", f"obsidian://vault/{cls.mtg_room}{page}",
        ], check=True)

    @classmethod
    def open_daily_report(cls, today):  # 日報を開く (まだなければ作成)
        daily_report = cls.daily_report(today)
        daily_report_path = cls.mtg_room_path / daily_report
        if not daily_report_path.is_file():
            daily_report_path.write_text('\n\n'.join([
                '## 今日やるタスク',
                '## 朝会でのフィードバック',
                '## 今日やったタスク',
                '## 夕会でのフィードバック',
            ]), newline='\n', encoding='utf8')
        cls.obsidian(daily_report)

    @classmethod
    def prompt(cls, today):  # Claude へのプロンプト
        return '\n'.join([
            '## 説明',
            'このディレクトリは私 (クッキー) の進捗管理のためのプロジェクトです。',
            'README.md には目標、予定表、タスク一覧を書いています。',
            cls.daily_report(today) + ' には今日の日報を書いています。',
        ])

    @classmethod
    def claude(cls, prompt):  # Claude を呼ぶ
        subprocess.run(
            ['claude', '--allowedTools=Write', '-p', prompt],  # 要書き込み許可オプション
            cwd=cls.mtg_room_path, check=True,
        )

    def task(self):  # 朝会 (夕会) のメイン処理内容
        today = datetime.datetime.now().strftime('%Y%m%d')
        type(self).open_daily_report(today)  # 日報を開く (まだなければ作成)
        type(self).alerm()  # アラームを鳴らす
        print(f'{type(self).task_name}をやるので日報を記入してください。')
        _ = input('日報の記入が終わったらエンターキーを押してください。')
        prompt = type(self).prompt(today)
        print('------------------------------')
        print(prompt)
        print('------------------------------')
        type(self).claude(prompt)  # Claude を呼ぶ


class DailyMeetingAm(DailyMeeting):
    task_name = '朝会'

    @classmethod
    def prompt(cls, today):
        return '\n'.join([
            super().prompt(today),
            '今は朝会なので、日報で記入済みなのは「## 今日やるタスク」までです。',
            '',
            '## 依頼事項',
            'README.md の目標を達成し、また、予定表にある予定をこなす上で',
            cls.daily_report(today) + ' の「## 今日やるタスク」が最適なものになっているか考え、',
            cls.daily_report(today) + 'の「## 朝会でのフィードバック」にフィードバックを記入してください。',
            'フィードバックには以下の内容を含めてください。',
            '- 今日まず着手すべき最優先のこと',
            '- 今日はやらない方がよいこと',
            '- 今日のミニマムなゴール',
        ])


class DailyMeetingPm(DailyMeeting):
    task_name = '夕会'

    @classmethod
    def prompt(cls, today):
        return '\n'.join([
            super().prompt(today),
            '',
            '## 依頼事項',
            cls.daily_report(today) + 'の「## 夕会でのフィードバック」にフィードバックを記入してください。',
            'フィードバックには以下のアドバイスを含めてください。',
            '- 明日以降作業をするときに私 (クッキー) が実践するとよいこと (今日やったことに基づき具体的に)',
        ])


if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--am', action='store_true')
    parser.add_argument('--pm', action='store_true')
    args = parser.parse_args()
    if args.am:
        DailyMeetingAm().task()
    elif args.pm:
        DailyMeetingPm().task()
    else:
        print('--am か --pm を指定してください。')

STEP2. スケジュール実行版

朝 (夕) 会の時刻になったら自動で会が開始するようにしたい場合、先の手動トリガー版を直接他のスケジューラソフトからトリガーしてもよいですが、「遅刻を許容」「休止期間を設定可能」とするため、schedule ライブラリを利用した自作クラスで定期実行します。

まず、参考リンクにリンクがある scheduled_task.py を取得し、どこかに配置し、そこから Task, TaskContainer クラスをインポートし、DailyMeetingTask を継承させます。

import pathlib
+ import sys
+ sys.path.append(pathlib.Path('~/tools/lib').expanduser().as_posix())
+ from scheduled_task import Task, TaskContainer
import datetime
import subprocess
import argparse


- class DailyMeeting:
+ class DailyMeeting(Task):

次に、朝会クラスと夕会クラスに schedule() メソッドを実装して既定の開始時刻を設定し、最大実行回数や遅刻許容幅を指定して TaskContainer に入れて定期実行する関数を実装し、オプションを指定しなければこれを実行するようにします。

class DailyMeetingAm(DailyMeeting):
    # 略
+     def schedule(self):
+         return self.scheduler.every().day.at('06:30')


class DailyMeetingPm(DailyMeeting):
    # 略
+     def schedule(self):
+         return self.scheduler.every().day.at('15:30')


+ def run_daily_meetings():
+     TaskContainer([
+         DailyMeetingAm(max_count=5, lateness_limit=3600),  # 朝会 (1時間まで遅刻可)
+         DailyMeetingPm(max_count=5, lateness_limit=3600),  # 夕会 (1時間まで遅刻可)
+     ], period=300).run()  # 5分周期で判定


if __name__ == '__main__':
    # 略
    else:
-        print('--am か --pm を指定してください。')
+        run_daily_meetings()

改修した meeting.py を実行すると、以下のようにスケジュール実行が開始します。

$ python meeting.py
[TaskContainer] スケジュール実行を開始します
[Task] [朝会] 次回の実行予定: 2026-01-14 06:30:00
[Task] [夕会] 次回の実行予定: 2026-01-14 15:30:00

これをタスクスケジューラに登録し、PC が起動したら起動するようにすれば既定の時刻に朝会・夕会が始まります。遅刻を 1 時間許容しているので、PC 起動が 06:30 に間に合わなくても、07:30 に間に合えばそのタイミングで朝会をしてもらえます。

備考

Windows のタスクスケジューラに個別のスクリプトを登録するのはちょっと面倒でメンテナンス性が悪いので、meeting.py を直接登録するのではなく、「定期実行の集約スクリプト」に集約してから登録するのが便利だと思います。私は以下のようにしています。

ディレクトリ構成
~/
├─ tools/
│   ├─ lib/  # 共用ライブラリ
│   │    ├─ __init__.py  # 空ファイル
│   │    └─ schedule_task.py  # スケジュール実行タスク用クラス
│   │
│   └─ bin/  # 共用実行ファイルやスクリプト
│        └─ run_scheduled_tasks.py  # タスクスケジューラに登録するのはこちら ★
│
└─ Dropbox/obsidian/Mercury/Zinnia/  # ミーティング用ディレクトリ (Obsidian 保管庫下)
    ├─ .claude/settings.local.json  # Claude への書き込みや Web 検索の許可
    ├─ lib/  # 専用ライブラリ
    │    ├─ __init__.py  # 空ファイル
    │    └─ meeting.py  # 朝会・夕会クラス
run_scheduled_tasks.py ★
import pathlib
import sys
sys.path.append(pathlib.Path('~/Dropbox/obsidian/Mercury/Zinnia/lib').expanduser().as_posix())
from meeting import run_daily_meetings


if __name__ == '__main__':
    run_daily_meetings()

応用例

この記事の基本設計はシンプルな仕様 (日報を記入しフィードバックをもらう) に絞って書きましたが、必要に応じてタスクのカンバンボードも配置し (以下の ★) 1、これも加味して AI にアドバイスを求めることもできます。

ディレクトリ構成
~/
├─ tools/
│   ├─ lib/  # 共用ライブラリ
│   │    ├─ __init__.py  # 空ファイル
│   │    └─ schedule_task.py  # スケジュール実行タスク用クラス
│   │
│   └─ bin/  # 共用実行ファイルやスクリプト
│        └─ run_scheduled_tasks.py  # タスクスケジューラに登録するスクリプト
│
└─ Dropbox/obsidian/Mercury/Zinnia/  # ミーティング用ディレクトリ (Obsidian 保管庫下)
    ├─ .claude/settings.local.json  # Claude への書き込みや Web 検索の許可
    ├─ lib/  # 専用ライブラリ
    │    ├─ __init__.py  # 空ファイル
    │    ├─ meeting.py  # 朝会・夕会クラス
    │    └─ validate_tasks.py  # ★ README とカンバンとの整合性や締切を検証する関数
    │
    ├─ README.md  # 中長期目標・重要な予定・タスク一覧
    │
    ├─ Tasks/  # ★ カンバンボード (タスクを進行状況ごとにサブディレクトリに分けているだけ)
    │    ├─ Not Started/*.md  # 未着手のタスク
    │    ├─ In Progress/*.md  # 進行中のタスク
    │    ├─ Completed/*.md  # 完了したタスク
    │    └─ Archived/*.md  # 完了したタスク (もうほとんど参照しないもの)
    │
    └─ Daily/  # 日報置き場
        ├─ 20260101.md
        ├─ 20260102.md
  1. ちなみに構成図中の validate_tasks.py は次のようなスクリプトです。https://gist.github.com/CookieBox26/11193972998eedd79b1c2ba8ede1094d

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?