
Claude Code スキルを設計し直した話 — xlsx/pptx/docx を ms-office-suite に統合
はじめに
Claude Code のカスタムスキル機能を使って、Excel・PowerPoint・Word ファイルを扱う処理をまとめた ms-office-suite スキルを作りました。
もともとは xlsx・pptx・docx の3スキルに分かれていたのですが、設計を見直す中で「1つのスキルに統合した方がスッキリするのでは?」という話になり、構造を整理しました。この記事では、その設計上の判断と最終的な構造を紹介します。
背景:もともとの構造
最初、Office ファイル操作は3つの独立したスキルとして作っていました:
.claude/skills/
├── xlsx/
│ ├── SKILL.md
│ └── scripts/
├── pptx/
│ ├── SKILL.md
│ └── scripts/
├── docx/
│ ├── SKILL.md
│ └── scripts/
└── shared/ ← 3スキルで共有するユーティリティ
├── pack.py
├── unpack.py
├── validate.py
└── libreoffice.py
これで一応動いていたのですが、使いながら気になる点が出てきました。
shared/ の居心地の悪さ
shared/ フォルダの問題は、スキルでも何でもないことです。SKILL.md がないので /shared コマンドとして呼び出されることはなく、ただ .claude/skills/ の中に浮いている状態。3スキルの SKILL.md には SHARED_DIR = .claude/skills/shared というパス変数が書かれていて、暗黙の依存関係になっていました。
設計の見直し
まず「3スキルを1つに統合するか」という話になりました。
最初は「コンテキストウィンドウのコスト」を懸念して分けたままにしようと思ったのですが、よく考えると各スキルの SKILL.md はそれぞれ50行程度で、3つ合わせても150行。統合しても大した差はありません。
むしろ問題は ルーティング です。「xlsx を読む」「pptx を変換する」といったタスクに対して、毎回3スキルの説明が全部ロードされるのは非効率です。
そこで辿り着いた構造がこれです:

.claude/skills/ms-office-suite/
├── SKILL.md ← 薄いルーター(30行程度)
├── xlsx.md ← .xlsx 用の詳細指示(必要時に読む)
├── pptx.md ← .pptx 用の詳細指示(必要時に読む)
├── docx.md ← .docx 用の詳細指示(必要時に読む)
└── scripts/
├── xlsx/
│ ├── read_xlsx.py
│ └── write_xlsx.py
├── pptx/
│ ├── read_pptx.py
│ └── write_pptx.py
├── docx/
│ ├── read_docx.py
│ └── write_docx.py
└── shared/
├── pack.py
├── unpack.py
├── validate.py
└── libreoffice.py
ポイント:SKILL.md を薄いルーターにする
SKILL.md には拡張子ごとの振り分けだけ書きます:
---
name: ms-office-suite
description: Read, create, and edit Microsoft Office files (.xlsx, .pptx, .docx).
---
# Microsoft Office Suite Skill
Route by file extension:
| Extension | Instructions | Scripts | Package |
|-----------|-------------|---------|---------|
| `.xlsx` | Read `SKILLS_DIR/xlsx.md` | `scripts/xlsx/` | openpyxl |
| `.pptx` | Read `SKILLS_DIR/pptx.md` | `scripts/pptx/` | python-pptx |
| `.docx` | Read `SKILLS_DIR/docx.md` | `scripts/docx/` | python-docx |
**After identifying the file type, read the corresponding .md file.**
これにより、.xlsx ファイルを扱うときは SKILL.md(30行)+ xlsx.md(40行)だけがロードされます。pptx や docx の詳細は読み込まれません。
ポイント:format-specific .md を分離する
xlsx.md はこんな内容です(抜粋):
# Excel (.xlsx)
## Available Operations
### Read / Extract
```bash
uv run --with openpyxl SKILLS_DIR/scripts/xlsx/read_xlsx.py "$ARGUMENTS"
Edit (Unpack → Edit → Repack)
- Unpack:
uv run SKILLS_DIR/scripts/shared/unpack.py <file.xlsx> - Edit: Modify XML files directly
- Repack:
uv run SKILLS_DIR/scripts/shared/pack.py <dir> <output.xlsx> - Validate:
uv run SKILLS_DIR/scripts/shared/validate.py <output.xlsx>
フォーマット固有の情報(使うライブラリ、スクリプトのパス、注意点)がここに集約されます。
### ポイント:`shared/` は `scripts/shared/` へ
`shared/` を `scripts/shared/` に移したことで、「これはスクリプトの共有ライブラリであって、スキルではない」という意図が構造から伝わるようになりました。
## 共有スクリプトの内容
`scripts/shared/` に入っているのは4つのユーティリティです。
| スクリプト | 役割 |
|-----------|------|
| `unpack.py` | Office ファイル(ZIP)を XML ツリーに展開 |
| `pack.py` | 編集した XML を Office ファイルに再パック(自動修復付き) |
| `validate.py` | ZIP 整合性と XML の well-formedness チェック |
| `libreoffice.py` | LibreOffice ヘッドレス経由のフォーマット変換・数式再計算 |
Office ファイルは ZIP + XML の組み合わせなので、unpack して XML を直接編集する方が python-pptx などのライブラリより細かい制御ができます。pack.py には durableId の値修正など、よくある XML の壊れ方に対する自動修復も入っています。
## 実際に使う流れ
例えば、xlsx ファイルを読む場合:
```bash
uv run --with openpyxl .claude/skills/ms-office-suite/scripts/xlsx/read_xlsx.py "要件表.xlsx" --summary
複数シートがある場合は --sheet でシートを指定できます:
uv run --with openpyxl .claude/skills/ms-office-suite/scripts/xlsx/read_xlsx.py "要件表.xlsx" --sheet "ユーザー要件"
pptx からテキストを抽出したい場合:
uv run --with python-pptx .claude/skills/ms-office-suite/scripts/pptx/read_pptx.py "評価会.pptx"
まとめ
今回の設計変更のポイントをまとめます:
- 統合のメリット:スキルリストがスッキリし、
shared/という中途半端な存在がなくなった - コンテキストの遅延ロード:SKILL.md を薄いルーターにして、フォーマット固有の指示は必要な時だけ読む
- 構造が意図を伝える:
scripts/shared/という場所が「スキルではなく共有スクリプト」であることを明示している
Claude Code のスキル設計は「1機能1スキル」か「関連機能を1スキルにまとめる」か、ユースケース次第だと思います。今回は「Office ファイル操作」という共通のドメインがあったので統合が自然でした。逆に、全く独立したツールを無理にまとめるとルーティングが複雑になるだけなので、そこは判断が必要です。
Office ファイルを扱う Claude Code スキルを作っている方の参考になれば幸いです。




