📋 タスク永続化 × マルチエージェント同期
別ウィンドウのAIでも進捗を忘れない!
SQLiteで複数チャットをつなぐ「共有カンバンボード」の構築法
〜チャットを閉じてもタスクが消えない。中央DBとWeb GUIで一元管理する自律型タスク管理〜
POTTLE
筆者:ぽトル(Pottle)| 省エネ脱力パンダ
「チャットウィンドウを切り替えるたびに『前回の続きなんだっけ?』とAIに説明し直すのが面倒くさくなった」脱力パンダ。ローカルのSQLiteに全タスクを保存させて、どのチャットからでも同じカンバンを見られるようにしました🐼💤
1. 実現した機能と、使ってみて実感した嬉しさ
どうも、ぽトル(Pottle)です。
複数のAIチャットツールを使い分けていると、必ず困ることがあります。
それは、「別のチャット画面や新しいセッションを開くと、過去のタスクや進捗がリセットされてしまう」という点です。
「さっき別のウィンドウで頼んだブログの執筆、どこまで進んだっけ?」「昨日の夜に計画したHEMSの修正タスク、何が残っている?」といった状況が起きると、文脈を一から入力し直す手間が生じます。
そこで作成したのが、ローカルの単一SQLiteデータベース(kanban.db)を介して、すべてのAIセッションがタスクを読み書きできる「グローバル・カンバンボード」です。
🎉 導入して何が嬉しかったか?
- チャットを跨いだタスクの引き継ぎが自動化された:ウィンドウAで追加したタスクを、ウィンドウBのAIが即座に認識して「次はこれですね」と着手できます。
- ブラウザで視覚的に進捗が見える:HTML形式のカンバン画面(TODO / IN PROGRESS / DONE)が自動更新されるため、作業状況が一目で把握できます。
- 外部サービス不要で完全無料:TrelloやNotionのAPIを使わず、PC内のSQLiteファイル1つで完結するため、認証エラーや課金の心配がありません。
- コンテキスト消費の節約:タスク一覧をプロンプトに長々と貼る必要がなく、必要な行だけをSQLで素早く取得できます。
2. システム構成と動作の流れ
仕組みは、中央のデータベースと操作用CLI、HTMLレンダラーの3要素で構成されています。
[AIチャット A (VS Code / CLI)] ──┐
│ タスク追加・完了更新
[AIチャット B (ブラウザ / Web)] ──┼─▶ [kanban_manager.py]
│ │
[人間 (ターミナル手動入力)] ──┘ ▼
[~/.hermes/kanban/kanban.db] (SQLite)
│
▼
[render_gui.py]
│
▼
[kanban_board.html] (ブラウザで確認)
3. ステップバイステップ作成手順
ステップ1: 準備とデータベース初期化
Pythonの標準機能である sqlite3 を利用するため、追加ライブラリのインストールは一切不要です。保存先ディレクトリを作成するだけで即座に使い始められます。
# 保存先ディレクトリの作成
mkdir -p ~/kanban_data
Python環境確認(標準ライブラリのみで動作します)
python3 -V
ステップ2: タスク操作CLIスクリプト(kanban_manager.py)
AIエージェントがシェルコマンド経由でタスクを追加・更新できるよう、シンプルなPythonスクリプトを作成します。
#!/usr/bin/env python3
"""
kanban_manager.py - SQLiteを用いたグローバルタスク管理CLI
Python標準ライブラリのみで動作します。
"""
import sqlite3
import os
import sys
import argparse
from datetime import datetime
DB_PATH = os.path.expanduser("~/kanban_data/kanban.db")
def init_db():
os.makedirs(os.path.dirname(DB_PATH), exist_ok=True)
conn = sqlite3.connect(DB_PATH)
conn.execute("""
CREATE TABLE IF NOT EXISTS tasks (
id TEXT PRIMARY KEY,
title TEXT NOT NULL,
status TEXT NOT NULL CHECK(status IN ('todo', 'in_progress', 'done')),
priority TEXT NOT NULL DEFAULT 'medium',
description TEXT,
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL
);
""")
conn.commit()
return conn
def add_task(task_id, title, status='todo', priority='medium', description=''):
conn = init_db()
now = datetime.utcnow().isoformat()
conn.execute("""
INSERT OR REPLACE INTO tasks (id, title, status, priority, description, created_at, updated_at)
VALUES (?, ?, ?, ?, ?, COALESCE((SELECT created_at FROM tasks WHERE id = ?), ?), ?)
""", (task_id, title, status, priority, description, task_id, now, now))
conn.commit()
conn.close()
print(f"✅ タスク追加/更新: [{status}] {task_id} - {title}")
def update_status(task_id, status):
conn = init_db()
now = datetime.utcnow().isoformat()
cur = conn.cursor()
cur.execute("UPDATE tasks SET status = ?, updated_at = ? WHERE id = ?", (status, now, task_id))
if cur.rowcount == 0:
print(f"❌ エラー: タスク {task_id} が見つかりません")
else:
conn.commit()
print(f"🚀 ステータス変更: {task_id} -> {status}")
conn.close()
def list_tasks():
conn = init_db()
conn.row_factory = sqlite3.Row
rows = conn.execute("SELECT * FROM tasks ORDER BY created_at ASC").fetchall()
conn.close()
return [dict(r) for r in rows]
if __name__ == '__main__':
parser = argparse.ArgumentParser(description="カンバンタスクマネージャー")
subparsers = parser.add_subparsers(dest='command')
p_add = subparsers.add_parser('add')
p_add.add_argument('--id', required=True)
p_add.add_argument('--title', required=True)
p_add.add_argument('--status', default='todo', choices=['todo', 'in_progress', 'done'])
p_add.add_argument('--priority', default='medium')
p_add.add_argument('--desc', default='')
p_up = subparsers.add_parser('update')
p_up.add_argument('--id', required=True)
p_up.add_argument('--status', required=True, choices=['todo', 'in_progress', 'done'])
p_list = subparsers.add_parser('list')
args = parser.parse_args()
if args.command == 'add':
add_task(args.id, args.title, args.status, args.priority, args.desc)
elif args.command == 'update':
update_status(args.id, args.status)
elif args.command == 'list':
for t in list_tasks():
print(f"[{t['status']}] {t['id']}: {t['title']} ({t['priority']})")
else:
parser.print_help()
CLIの実行例:
# タスクを追加
python3 kanban_manager.py add --id "task_1" --title "ブログ記事の執筆" --status "todo"
進行中に変更
python3 kanban_manager.py update --id "task_1" --status "in_progress"
完了にする
python3 kanban_manager.py update --id "task_1" --status "done"
ステップ3: 美しいHTMLボードを自動生成する(render_gui.py)
タスク更新後に以下のスクリプトを呼び出すことで、スタイリッシュなカンバンボードHTMLを即座に再生成できます。
#!/usr/bin/env python3
"""
render_gui.py - SQLiteのタスクを読み込み、視覚的なHTMLカンバンボードを出力する
"""
import json
import os
from kanban_manager import list_tasks
OUTPUT_HTML = os.path.expanduser("~/kanban_data/kanban_board.html")
def render():
tasks = list_tasks()
tasks_json = json.dumps(tasks, ensure_ascii=False)
html = f"""
AI Kanban Board
📋 AI Task Kanban Board
SQLiteリアルタイム同期
未着手 (To Do)
0
進行中 (In Progress)
0
完了 (Done)
0
"""
with open(OUTPUT_HTML, "w", encoding="utf-8") as f:
f.write(html)
print(f"✨ カンバンボードを出力しました: {OUTPUT_HTML}")
if __name__ == "__main__":
render()
HTMLボードの生成とブラウザ表示:
python3 render_gui.py
open ~/kanban_data/kanban_board.html
📦 GitHubで全コード公開中
本記事で紹介したSQLiteカンバンの管理CLIおよび自動HTML生成スクリプトはGitHubリポジトリから入手できます。
GitHubを見る →
4. まとめ:記憶をつなぐ仕組みが作業を楽にする
AIチャットのセッションが分断されていても、共通のデータベースを1つ用意するだけで、複数のAIがチームのように連携して動けるようになります。
クラウドの重たいSaaSを使わなくても、身近なSQLiteだけで十分実用的な環境が手に入ります。複数のAIツールを並行して使う機会が多い方は、ぜひ試してみてください🐼💤