はじめに

Claude Code でデバッグや実装を行った際に、その場では確認や原因の理解を行いますが、自身でドキュメントやネット記事を読み漁っていた時代よりも血肉となりづらくあります。
そこで、「技術ブログのドラフト」としてセッション内のやり取りをまとめてもらうことで、下記が同時に達成できるのではと考えました。

  • アウトプットまでの工数の低減
  • 人間にも読みやすくすることでのあらためての学習/復習 の機会創出
  • エージェントの知見としての蓄積

先日Obsidian CLIもリリースされたということで、保存先はObsidianを利用したいと思います。

※ObsidianCLIの説明はここでは省きます。

解決前の課題

  • Claude Code でデバッグ・実装を行っても、その知見が会話の中で消えてしまう
  • 後で記事にしようと思っても、詳細を思い出せない
  • 業務をしながら人力でその場でドラフトを作っておくのも負荷が高い

対応内容

Claude Code のカスタムスキルを作成しました。スキルは以下を自動で行います。

  1. 会話履歴から技術的な情報(症状・原因・対応・学び)を抽出
  2. 技術ブログテンプレートに沿って Markdown を生成
  3. Obsidian CLI でアクティブ vault の Outputs/YYYYMMDD_<slug>.md に保存

※ObsidianCLIの利用はObsidianのアプリケーションが起動している必要があります。

トリガーとなる言葉

  • 「ブログにして」
  •  「Obsidian に残して」
  •  「記事にまとめて」
  •  「下書き作って」
  •  「ブログネタにしたい」

Obsidian CLI(obsidian create)を使うことで、Claude Code の Bash ツールから直接 Obsidian vault にファイルを作成できます。

スキルの内容

---

name: obsidian-bugfix-blog-draft

description: バグ修正・エラー調査・実装対応の内容を技術ブログの下書きとして Obsidian CLI 経由で Obsidian vault に保存するスキルです。ユーザーが「ブログにして」「Obsidianに残して」「記事にまとめて」「下書き作って」「ブログネタにしたい」などと言ったとき、または不具合解決・実装完了後にアウトプットを求めてきたときに必ず使います。Claude Code でデバッグ・実装作業をしていて、その知見を技術ブログとして残したい場面で積極的に活用してください。

---

# Obsidian 技術ブログ下書きスキル

## 目的

解決済みの不具合・調査対応・実装内容を、技術ブログとして育てやすい下書きに整理し、Obsidian CLI を使って vault 内に Markdown ノートとして保存する。

## 環境前提

- Obsidian CLI: `obsidian` コマンド

- 利用可能なコマンド(ファイル操作):

- `obsidian create path="Outputs/note.md" content="内容"` — ノート作成(フォルダ指定あり)

- `obsidian read path="Outputs/note.md"` — ノート読み取り

- `obsidian append path="Outputs/note.md" content="内容"` — ノート追記

- `obsidian create name="Note" content="内容"` — ノート作成(スラッシュなしの単純名)

- Vault 指定: コマンドの**前**に `vault=<name>` を付ける(省略時はアクティブ vault)

- 例: `obsidian vault=my-vault create path="Outputs/note.md" content="..."`

- 保存先: `Outputs/YYYYMMDD_<slug>.md`

- `content=` の改行は `\n` にエスケープして渡す(Obsidian CLI の公式仕様)

## 手順

### 0. CLI の確認(必須 / preflight)

以下を Bash ツールで実行し、**成功した場合のみ** 手順 1 に進む。

失敗した場合は **作業を停止** し、後述の「失敗時の診断付き停止」に従う。

```bash

# 1. CLI の存在確認

command -v obsidian || { echo "ERROR: obsidian コマンドが見つかりません"; exit 1; }

# 2. CLI の動作確認

obsidian version || { echo "ERROR: obsidian コマンドが実行できません"; exit 1; }

```

### 1. 会話から情報を収集する

以下の情報を会話履歴から読み取る。不足していても捏造せず、`TODO:` として残す。

| 項目 | 内容 |

|------|------|

| タイトル | 一言で表す記事タイトル |

| 症状 | 何が起きていたか |

| 発生環境 | OS・ランタイム・ツール・バージョン |

| 根本原因 | なぜ起きたのか |

| 対応内容 | 実際に行った修正 |

| なぜ直ったか | 仕組みの説明 |

| コマンド・設定・差分 | 後で役立つ技術的断片 |

| 学び・再発防止 | 次回への教訓 |

 

### 2. ノート名と Markdown 本文を Claude 側で決定する

Bash 実行前に以下を確定させる。

 

**ノート名の決定(Claude 側で行う):**

- 日付: `YYYYMMDD` 形式(今日の日付)

- slug: タイトルから英数字・ハイフンのみで生成。日本語タイトルの場合は内容を表す英語キーワードを使う

- 例: 「Laravelのキャッシュ問題を修正」→ `laravel-cache-fix`

- ノート名: `Outputs/YYYYMMDD_<slug>`

- **同名ノートが存在する可能性がある場合**: ユーザーに上書きするか確認してから進む。無条件に上書きしない

**Markdown 本文のテンプレート:**

```markdown

---

title: <記事タイトル>

created:

tags:

- bugfix

- troubleshooting

- <関連技術タグ>

status: draft

source: claude-code

---

# <記事タイトル>

## 概要

問題・影響・解決内容を 2〜4 文で要約する。

## 症状

- 何が起きたか

- どう見えていたか

- 実際のエラー文(または代表例)

## 環境

- OS:

- 言語 / ランタイム:

- 関連ツール / バージョン:

## 根本原因

なぜ起きたのかを平易に説明する。

## 対応内容

実際に行った修正を説明する。

## なぜ直ったのか

手順だけでなく、仕組みとしてなぜ有効だったかを書く。

## 再現・確認メモ

分かる範囲で再現方法や確認方法を書く。

## コマンド / 設定 / 差分

```(コードブロック)

## 学び・再発防止

- 次回気をつける点

- 事前に確認すべきこと

## ブログ本文の下書き

公開記事として育てやすい自然文のドラフトをここに書く。

```

### 3. Obsidian CLI で保存する

以下のシェルコマンドを Bash ツールで実行する。

slug・保存パスは手順 2 で Claude 側が決定済みの値をそのまま使う。

```bash

# 手順 2 で決定した値を設定する

VAULT_NAME="<確認済みの Vault 名>"

DEST="Outputs/<YYYYMMDD_slug>.md"

# Markdown 本文を heredoc で保持し、\n エスケープして CLI に渡す

CONTENT=$(cat <<'MARKDOWN'

<ここに生成した Markdown 全文を貼る>

MARKDOWN

)

obsidian vault="$VAULT_NAME" create path="$DEST" content="$(echo "$CONTENT" | awk '{printf "%s\\n", $0}')" \

&& echo "保存完了: $DEST" \

|| { echo "ERROR: 保存に失敗しました"; exit 1; }

```

**注意点:**

- `vault=` はコマンドの**前**に書く(公式仕様)。省略するとアクティブ vault が使われる

- フォルダを含むパスは `path=` を使う。スラッシュなし単純名なら `name=` でも可

- `content=` には `\n` でエスケープした文字列を渡す(Obsidian CLI の公式仕様)

- heredoc の `'MARKDOWN'` はシングルクォートで囲む(変数展開を防ぐ)

- 本文にコードブロック(` ``` `)を含む場合は `~~~` を使って heredoc 干渉を回避する

- Vault を直接操作しない。必ず CLI 経由で操作すること

- ファイルを上書きする場合は `overwrite` フラグを追加する(ユーザー確認後のみ)

### 4. 結果をユーザーに伝える

保存完了後、以下を報告する。

```

Obsidian に下書きを保存しました。

- ファイル: Outputs/YYYYMMDD_.md

- タイトル: <記事タイトル>

- ステータス: draft

未確定の箇所は TODO: で明示しています。

あとから Obsidian で開いて推敲してください。

```

## 書き方の方針

- 技術的に役立つ具体情報を優先する(抽象的な感想は不要)

- エラーメッセージは可能な限り正確に残す

- 事実と推測を混在させない

- コマンド・バージョン・ログ・原因は捏造しない

- 完成品より、あとで育てやすい下書きを目指す

## 失敗時の診断付き停止

**obsidian コマンドで問題が発生した場合、チャットへの Markdown 出力は行わない。**

保存の保証ができないため、作業を停止してユーザーに以下を案内する。

### CLI が見つからない場合

```

obsidian コマンドが見つかりません。以下を確認してください:

1. Obsidian アプリがインストールされているか

2. Obsidian 設定 → CLI が有効化されているか

3. PATH に obsidian が含まれているか: echo $PATH

確認後、再度お試しください。

```

### CLI は存在するが実行に失敗する場合

```

obsidian コマンドの実行に失敗しました。以下を確認してください:

1. Obsidian アプリが起動しているか

2. 指定した Vault 名が正しいか: obsidian vault= files total

3. CLI バージョンが古くないか: obsidian version

確認後、再度お試しください。

```

### 保存コマンドが失敗した場合

```

Obsidian への保存に失敗しました。以下を確認してください:

1. 指定した保存先パスが正しいか

2. Vault 内に Outputs/ ディレクトリが存在するか

3. 同名ファイルが存在する場合、overwrite オプションが必要か

確認後、再度お試しください。

```

実践

デモとして簡易的なショッピングカートのバグ修正を依頼してみた
バグとしては2つの指摘がされました。

# Bug 1: remove_item の修正
def remove_item(self, name):
for i, item in enumerate(self.items):
if item["name"] == name:
self.items.pop(i) # 見つけたインデックスiを渡すことで正しいアイテムを削除するように修正。
return
raise ValueError(f"Item '{name}' not found in cart")

# Bug 3: apply_bulk_discount の修正
def apply_bulk_discount(self):
"""5個以上購入で10%割引を適用"""
if self.get_item_count() >= 5: # 「5個以上で10%割引」の仕様とあるのに6個以上でないと割引が適用されなかった。
self.set_discount(10)

次にClaude Codeにて「その対応でなぜ解決できたのか、ブログにしておいてください 」と投げます。

そうすると下記のように出力されました。

かなりわかりやすくまとめてくれているように思います。
ベースとして人間も理解しやすい形としてブログのような形式にしてますが、もしアウトプットしないとしても自身の知見としても吸収しやすく、蓄積もこれまで利用していたObsidianに勝手に溜まっていくので、かなりいい感じに運用できてます。

まとめ

周囲を見ていてもやはりAIによるコーディングによって自身の知見になっている感覚が薄かったり、それゆえにアウトプットも落ち込んでいくというのをよく見ておりました。

こういったアプローチも組み込むことで、「人間の知見蓄積」「アウトプットの効率化」「エージェント知見蓄積」と良いところ取りができそうな気がしてます。

まだ改善点はありますが、いつになっても学びは常にしていきたいなと思います。