すくらっぷ あんど びるどー(したい)

AI・Obsidian・個人開発の試行錯誤ログ。 作業メモを、あとで使える知識に変えるための記録。

ObsidianでProject管理システムを実装する方法。Project別タスク入力欄とMermaid Ganttを自動生成する

はじめに

この記事では、ObsidianのProject管理システムを実際に作る手順をまとめる。

前回の記事では人間用画面とSystem側データを分ける考え方を整理した。この記事では、設計論は繰り返さず、その設計をもとに、次のものを実際に作る。

syurainu.com

  • Project Record
  • Project Index
  • Project別タスク入力欄
  • Gantt日付入力欄
  • Task Index
  • Project Dashboard
  • Mermaid Gantt
  • Mermaid Kanban
  • run_ai_memory.cmd からの一括更新

目標は、人間がObsidian上でタスクと日付を入力するだけで、System側がDashboard、Gantt、Kanbanを自動生成する状態にすることである。

完成イメージ

完成後は、Obsidian上でProjectの全体像を複数の角度から確認できる。

人間が最初に見る入口は、00_人間用/Project/README.md に置く。ここからProject候補、タスク入力、Gantt日付入力欄、生成済みDashboardへ移動できる。
操作ボタンも同じProjectホームにまとめる。人間はここから一括作成、更新、状況確認、次アクション確認を実行する。

まず、DashboardではProject数、進捗、状態分布を確認できる。

Projectの状態分布は、Mermaidの円グラフとして表示する。

Projectごとの流れは、Active Project Flowとして確認できる。

日付が入っているProjectは、Mermaid Ganttとして表示する。

Ganttに使う日付は、Project Recordを直接編集せず、人間用の 04_Gantt日付入力欄.md に入力する。

状態別に眺めたい場合は、Mermaid Kanbanを使う。

画像で見ると分かる通り、この記事で作るものは単なるタスクリストではない。ObsidianのMarkdownを正本にしながら、人間が見るDashboard、Gantt、Kanbanを生成する仕組みである。

前提環境

項目 内容
OS Windows
シェル PowerShell
AIツール Codex
ローカルLLM Ollamaを使う想定。ただし今回の生成処理自体には不要
関連ツール Obsidian、Python、Mermaid
対象サービス Obsidian Vault
実行場所 PowerShell、Obsidian、Codex

MermaidのGanttでは、dateFormataxisFormat を指定できる1。また、MermaidにはKanban構文もあり、状態別のカード表示に使える2

ObsidianのPropertiesはMarkdown先頭のYAMLとして保存されるため、Project Recordのような機械処理用データに向いている3

Project管理では決まった処理はシステムで解決し、タスクを書くのを減らしたかった

Project管理では、次の2つを両立したかった。

  • 人間:Obsidianで見やすく、タスクや日付を書きやすい。
  • System:Project ID、優先度、進捗、期限を機械的に処理できる。

最初は、タスク本文に project_idpriority を直接書く実装をしていたが、流石にこれは手間だし、そもそも一旦格納したデータを何度もやって照合をしてなんてやる必要がない。決まった情報を出すならば普通に出すだけでいい。

ヒューマンエラーはそもそも人がやるから生じる。やらないでいいならば、やらないほうがいい。

- [ ] 課題作成 [project_id:: 001] [priority:: high]

そこで、人間が書くのはタスク本文と日付だけにした。

Project ID、Project名、Tier、Status、Priorityは、Project Recordから自動で付ける。

全体構成

今回使うファイルは次である。

<VAULT_PATH>/
├─ 00_人間用/
│  └─ Project/
│     ├─ README.md
│     ├─ 02_タスク入力欄.md
│     ├─ 03_Projectソートビュー.md
│     └─ 04_Gantt日付入力欄.md
│
└─ 90_System/
   ├─ projects/
   │  ├─ records/
   │  ├─ registry/
   │  └─ indexes/
   │     ├─ project_index.jsonl
   │     ├─ project_dashboard.md
   │     ├─ project_task_index.jsonl
   │     ├─ project_task_dashboard.md
   │     ├─ project_gantt.md
   │     ├─ project_kanban.md
   │     └─ project_master_context.md
   │
   └─ scripts/
      ├─ project_utils.py
      ├─ build_project_index.py
      ├─ build_project_task_input.py
      ├─ build_project_task_index.py
      ├─ sync_project_schedule_input.py
      ├─ build_project_gantt.py
      ├─ build_project_kanban.py
      └─ run_ai_memory.cmd

全体の流れはこうなる。

flowchart TD
    A["Project Record"] --> B["Registry検証"]
    B --> C["Project Index生成"]
    C --> D["Project別タスク入力欄生成"]
    D --> E["人間がタスク本文だけを書く"]
    C --> F["Gantt日付入力欄生成"]
    F --> G["人間が日付だけを書く"]
    E --> H["Task Index生成"]
    G --> I["Project Recordへ日付同期"]
    I --> J["Mermaid Gantt生成"]
    C --> K["Mermaid Kanban生成"]
    H --> L["Task Dashboard生成"]
    C --> M["Project Dashboard生成"]

使ったプロンプト

実装時の指示は、要約すると次の通りである。

Project管理をスリムにしたい。
タスク入力で project_id や priority を人間が手入力しないようにする。
Project RecordからProject別入力欄を自動生成する。
System側はTask IndexとDashboardを作る。
さらに、Mermaidでガントチャートを人間が見られるようにする。

Kanban追加時は、次のように依頼した。

Project管理に、人間が状態を把握するための Mermaid Kanban 自動生成ビューを追加する。
Kanbanは編集用ではなく、project_index.jsonl から生成する読み取り専用ビューとする。

Ganttの日付入力欄を追加したときは、次のように依頼した。

ガンチャートを今のままだと人間がうまく日付をつけにくい。
人間用に日付を入力できる場所を作り、System側Project Recordへ同期する。

手順

1. Project Recordを作る

ProjectごとにMarkdownファイルを作る。

90_System/projects/records/001_university-assignment.md
90_System/projects/records/002_cam-validation.md

frontmatterは次のようにする。

---
type: project_record
project_id: "001"
title: 大学の課題作成
status: active
phase: planning
priority: high
tier: Tier 1
progress: 0
progress_source: task_count
created: 2026-06-17
updated: 2026-06-18
---

Project RecordはSystem側の正本である。人間が普段見る場所ではなく、Pythonが読むためのファイルとして扱う。

2. Project Indexを生成する

Project RecordからIndexを作る。

90_System\scripts\run_ai_memory.cmd project_refresh

生成される主なファイルは次である。

90_System/projects/indexes/project_index.jsonl
90_System/projects/indexes/project_dashboard.md

Dashboardでは、Project数、進捗、状態分布、Active Project Flowを確認できる。

3. Project別タスク入力欄を生成する

人間用のタスク入力欄は、自動生成する。

00_人間用/Project/02_タスク入力欄.md

生成例は次の通りである。

<!-- PROJECT_TASK:START 001 -->
### 001 大学の課題作成
<!-- project_meta: tier=Tier 1 / status=active / priority=high -->

- [ ] 課題作成
<!-- PROJECT_TASK:END 001 -->

人間が書くのは、この1行だけである。

- [ ] 課題作成

所属Projectは、見出し文字列ではなく PROJECT_TASK:START 001 のマーカーで判定する。

4. Gantt日付入力欄を生成する

Ganttの日付も、人間がProject Recordを直接編集しなくて済むようにした。

日付入力欄は次に作る。

00_人間用/Project/04_Gantt日付入力欄.md

入力例は次である。

<!-- PROJECT_SCHEDULE_ITEM:START 001 -->
### 001 大学の課題作成
<!-- project_meta: tier=Tier 1 / status=active / priority=high -->

- 開始日:: 2026-08-21
- 期限日:: 2026-08-28
- 目標日::
- 期間日数::
<!-- PROJECT_SCHEDULE_ITEM:END 001 -->

人間が編集するのは、開始日期限日目標日期間日数 の値だけである。

開始日期限日 があるProjectは、Ganttで期間バーになる。期限日 または 目標日 だけの場合は、マイルストーンとして表示する。

5. Task Indexを生成する

タスク入力欄を解析し、System側Indexへ変換する。

90_System/projects/indexes/project_task_index.jsonl
90_System/projects/indexes/project_task_dashboard.md

出力例は次のようになる。

{"completed":false,"project_id":"001","project_title":"大学の課題作成","priority":"high","status":"active","task_text":"課題作成","tier":"Tier 1"}

これにより、人間がタスク本文だけを書いても、System側ではProject情報付きのデータとして扱える。

6. Mermaid Ganttを生成する

Ganttだけ更新したい場合は、次を使う。

90_System\scripts\run_ai_memory.cmd project_gantt

通常は project_refresh に含めておけばよい。

90_System\scripts\run_ai_memory.cmd project_refresh

生成先は次である。

90_System/projects/indexes/project_gantt.md

日付があるProjectは、次のようにMermaid Ganttへ出力される。

gantt
    title Project進行ガントチャート
    dateFormat  YYYY-MM-DD
    axisFormat  %m/%d
    excludes    weekends

    section Tier 1
    001 大学の課題作成 :crit, active, p001, 2026-08-21, 8d

日付が入っていないProjectは、Ganttに無理やり出さない。代わりに、project_gantt.md の下部に「日付未設定Project」として一覧表示する。

7. Mermaid Kanbanを生成する

Kanbanだけ更新したい場合は、次を使う。

90_System\scripts\run_ai_memory.cmd project_kanban

生成先は次である。

90_System/projects/indexes/project_kanban.md

Kanbanの列はProjectの status から作る。

active = 進行中
paused = 停止中
completed = 完了
cancelled = 中止
archived = アーカイブ

Kanbanは読み取り専用ビューである。カードをドラッグしてProject状態を変える用途にはしない。

実行結果

project_refresh 実行後、ログには次のような出力が出る。

Project validation OK: 11 record(s), 11 registry item(s), 0 warning(s)
Generated: 90_System/projects/indexes/project_index.jsonl
Generated: 90_System/projects/indexes/project_dashboard.md
Generated: 00_人間用/Project/04_Gantt日付入力欄.md
Generated: 00_人間用/Project/02_タスク入力欄.md
Generated: 90_System/projects/indexes/project_task_index.jsonl
Generated: 90_System/projects/indexes/project_task_dashboard.md
Generated: 90_System/projects/indexes/project_gantt.md
Generated: 90_System/projects/indexes/project_kanban.md
Generated: 90_System/output/project_context_pack.md
Generated: 90_System/projects/indexes/project_master_context.md

今回の例では、Projectは11件ある。

Total Projects: 11
Active Projects: 10
Scheduled Projects: 1
Unscheduled Projects: 10

日付を入れた 001 大学の課題作成 だけがGanttに表示され、残り10件は日付未設定Projectとして一覧に残る。これは正常である。

詰まったところ

詰まったこと 原因 対処
タスクのProject所属がぶれる 人間が project_idpriority を手入力していた Project別ブロックを自動生成し、HTMLコメントのIDマーカーで判定する
Ganttに何を出すか迷う 全Projectに期限があるとは限らない 日付ありだけ表示し、未設定は一覧化する
Ganttの日付を入れにくい Project Recordのfrontmatterを直接触る必要があった 04_Gantt日付入力欄.md を作り、人間は日付だけ入力する
余計な .md が増えた iCloud Drive配下で同名Markdownを書き換えたとき、競合コピーができた 内容が変わらない場合は書かない。同期時に重複ファイルを掃除する
.cmd が壊れる可能性 Windowsで改行コードが混ざると予期しない挙動になる CRLFに統一し、実行後ログを確認する

Before / After

Before:
タスクにproject_idやpriorityを手入力する
Ganttを手書きする
Project状態を毎回メモから探す
進捗確認に時間がかかる

After:
Project別入力欄を自動生成する
Gantt日付入力欄で日付だけ入力する
Task IndexとDashboardを自動生成する
GanttとKanbanで状態を視覚化する

再現チェック

実装後は、次の順番で確認する。

py -3 -m py_compile 90_System\scripts\build_project_gantt.py
py -3 -m py_compile 90_System\scripts\build_project_kanban.py
py -3 -m py_compile 90_System\scripts\sync_project_schedule_input.py
90_System\scripts\run_ai_memory.cmd project_schedule_sync
90_System\scripts\run_ai_memory.cmd project_gantt
90_System\scripts\run_ai_memory.cmd project_kanban
90_System\scripts\run_ai_memory.cmd project_refresh

確認するファイルは以下である。

00_人間用/Project/02_タスク入力欄.md
00_人間用/Project/04_Gantt日付入力欄.md
90_System/projects/indexes/project_dashboard.md
90_System/projects/indexes/project_task_dashboard.md
90_System/projects/indexes/project_gantt.md
90_System/projects/indexes/project_kanban.md
90_System/output/ai_memory_run.log

ログに Project validation OKGenerated: が出ていれば、基本的には成功である。

まとめ

この記事では、Obsidianを使ったProject管理を、単なる手書きメモではなく、人間が入力し、System側が整理し、AIが参照できる形にする実装を行った。

人間が判断するべき部分は、人間用の入力欄に残す。たとえば、タスク本文や日付は人間が書く。一方で、Project ID、Priority、Tier、Status、Dashboard、Gantt、Kanban、Context Packのように、決まった形にそろえるべき情報はSystem側で生成する。

こうすることによって、Obsidianの自由さを残したまま、Projectの数、進行状況、日付、次アクションを確認しやすくなる。さらに、AIにVault全体を読ませるのではなく、System側で生成した軽量なContext Packだけを渡せるため、安全面でも扱いやすい。

今回の実装で作った流れは、次のように整理できる。

人間が書く:
Project候補、タスク本文、Gantt用の日付

System側が生成する:
Project Index、Task Index、Dashboard、Gantt、Kanban、Context Pack

AIが参照する:
System側で生成した軽量データ

Project管理で重要なのは、最初から完璧な管理画面を作ることではなく、入力する場所と生成する場所を分けることである。

今回の構成なら、Projectが増えても、タスクや日付の入力方法を大きく変えずに、DashboardやGantt、Kanbanを更新が可能となる……だろう。(とはいえこれProjectが増えたらまた重たくなりそうだからどっかで削除ルールとか作成しないとダメだなと思っている顔)

参考文献


  1. MermaidのGantt構文では、dateFormataxisFormatexcludes などを使って、日付形式や軸表示、除外日を指定できる。
  2. MermaidのKanban構文では、列とカードをテキストで定義できる。この記事では編集用ではなく、状態確認用の表示として使っている。
  3. Obsidian公式ヘルプでは、PropertiesはMarkdownファイル先頭のYAMLとして保存されると説明されている。この記事のProject Recordも同じ考え方で扱っている。