gh CLI × Claude Code で Gist 操作をチャット1行で完結させる

ども!最近 Gist の出番が増えた龍ちゃんです。スニペットの保存はもちろん、プロジェクト横断で使い回すプロンプトテンプレートとか、ちょっとした設定ファイルとか。操作が面倒で使ってなかったんですけど、チャットで完結するようにしたら話が変わりました。

.claude/skills/gh-gist/SKILL.md という Markdown ファイル1枚で、Gist の検索・取得・保存・更新がチャットの一言で動きます。この記事ではスキルの使い方と、CRUD をスキル化するときのトークン効率・安全設計の考え方を解説します。

GitHub Gist の課題 — 検索性と保存コスト

Gist 自体は優秀な仕組みなんですよね。URL 一つでコードを共有できて、バージョン管理もついてくる。複数ファイルをまとめられるし、secret / public の切り替えもできます。「ちょっとしたコードの保存と共有」にちょうどいい粒度で設計されています。

でも実態、使いこなせてなくないですか?

僕の場合がまさにそうでした。問題は2つあります。

検索性が弱い。 Gist が増えてくると、Web UI では目視スクロールで探すことになります。「あのスニペットどこだっけ」が頻発して、見つからないとそのまま諦めてしまう。

保存のハードルが高い。 ブラウザで gist.github.com を開いて、ファイル名を入力して、コードを貼り付けて、description を書いて、public か secret を選んで、Create ボタンを押す。コードを書いてる最中にこの手順をやる気にはなれないんですよね。

結果どうなるかというと、「保存するほどでもないか」→ 使わなくなる → 存在を忘れる。もったいない。

操作コストが下がれば話は変わる

「Gist に保存して」「Python のスニペット取ってきて」で済むなら話は別です。VS Code のチャットで完結するなら、コーディングの流れも切れません。

スニペットの保存・取得だけじゃなくて、操作コストが下がると 使い方の発想自体が変わる んですよね。たとえばプロジェクト横断で使い回すファイル(人格設定、プロンプトテンプレートなど)を Gist で一元管理して、必要なプロジェクトにスキルで引っ張ってくるとか。1ファイル完結 × 複数プロジェクトで共有 × バージョン管理つき、という Gist の粒度にぴったりハマります。「Gist = ちょっとしたコード置き場」から「プロジェクト横断のファイル管理」へ。

これを Claude Code の Skills(SKILL.md)と GitHub CLI(gh コマンド) で作りました。この記事ではスキルの使い方と作り方を解説します。SKILL.md の全文は付録に載せているので、すぐ試したい人はそちらもどうぞ。

なぜ gh CLI + スキルを選んだか

Gist をエディタ内で操作する方法は他にもあります。

GitHub の Web UI は Gist の作成・閲覧・編集が一通りできますが、前述のとおり検索性が弱い。何よりコードを書いてる最中にブラウザに切り替えると作業の流れが切れます。

GitHub MCP Server には Gist 関連のツールがありません(2026年2月時点)。仮に対応していたとしても、MCP はツールの戻り値が大きくなりがちでトークン消費が膨らみやすいのはわりとあるあるな話です。

その上で gh CLI + SKILL.md を選んだのは、Gist の操作に合っていたからです。

  • gh CLI が Gist のサブコマンドを持っている。 gh gist list / view / create / edit / delete で CRUD 全部できます。--filter--raw --filename で出力を絞れるので、トークン効率のルールを設計しやすい
  • 認証が gh auth で済む。 devcontainer の postCreateCommand に入れておけば環境構築時に自動で認証できる
  • SKILL.md 一枚で完結する。 .claude/skills/gh-gist/SKILL.md に Markdown で手順を書くだけで動きます。Skills は description だけが常時コンテキストに入り、本文は呼び出し時のみロードされるので、普段の会話を圧迫しません

選択肢が複数ある中で gh CLI を選んだのは優劣の話ではなく、自分の環境と用途に合っていたからです。

gh CLI × Claude Code で Gist を操作する(デモ)

ここからは実際のデモです。検証用に Gist を事前に作成して、Claude Code のチャットで操作しました。前提として、gh CLI がインストール済みで認証が完了している必要があります。

認証方法について: とりあえず試すなら gh auth login でブラウザ認証するのが一番手軽です。ただし OAuth はスコープが広くなりがちなので、運用するなら PAT(Personal Access Token)で最小限のスコープに絞るのがおすすめです。Classic PAT なら gist スコープだけで Gist の全操作が動きます。

# PAT を使った認証
echo "<your-pat>" | gh auth login --with-token

SKILL.md は5モード対応(一覧 / 取得 / 保存 / 更新 / データ管理)ですが、よく使う3モードをデモで見ていきます。

取得 —「Python のスニペット取ってきて」

「Gist から Python のスニペット取ってきて」と打つと、スキルが以下のステップを自動で実行します。

Step 1: キーワードで Gist を検索

gh gist list --filter "Python"
e7236579...  Python useful snippets (updated)  2 files  secret  2026-02-26T14:20:47Z

Step 2: ファイル一覧を確認

gh gist view e72365796014c25d70629f6d8cfe01bc --files
snippets.py
todo.md

Step 3: 目的のファイルを取得

gh gist view e72365796014c25d70629f6d8cfe01bc --raw --filename snippets.py
"""Python useful snippets - よく使うコードスニペット集"""
# --- flatten nested list ---
def flatten(nested: list) -> list:
    ...

「Python のスニペット」という曖昧な指示から、3ステップで目的のファイルに辿り着いています。--filter で絞り → --files でファイル一覧 → --filename で中身取得。この 段階的な絞り込み がトークン効率のルールと連動していて、各ステップで情報量を削っています。このあたりの工夫は SKILL.md の解説セクションで詳しく説明します。

保存 —「このコードを Gist に保存して」

コードを渡して「Gist に保存して、description は Verification test で」と打ちます。

Step 1: 一時ファイルに書き出し

ユーザーが指定したコードを application/tools/tmp/hello.py に書き出します。gh gist create はファイルパスを引数に取るので、一時ファイル経由で作成する形です。

Step 2: Gist を作成

gh gist create application/tools/tmp/hello.py -d "Verification test"
https://gist.github.com/user/xxxx

デフォルトは secret で作成されます。public にしたい場合は「public で」と明示する必要があり、SKILL.md にそのルールを書いてあります。書き込み操作をスキル化するときに入れておきたい安全策の一つです。

更新 —「さっきの Gist にファイル追加して」

「さっき保存した Gist に README.md を追加して」と打つと、スキルが直前の会話のコンテキストから Gist ID を拾い、gh gist edit でファイルを追加します。

ファイル追加

gh gist edit <gist-id> --add application/tools/tmp/README.md

description 変更

gh gist edit <gist-id> --desc "Verification test (updated)"

gh gist edit はデフォルトだとエディタが開いて対話的な編集になります。Claude Code から使うにはオプション引数で非対話的に更新する必要があって、このあたりも SKILL.md に手順を書いてあります。

SKILL.md の設計 — トークン効率と安全策

ここからは「どうやって作ったか」の話です。スキルの実体は .claude/skills/gh-gist/SKILL.md という Markdown ファイル1枚(全文は付録参照)。中身をパートごとに見ていきます。

メタデータ(--- で囲まれたヘッダー部分)

---
name: gh-gist
description: |
  This skill should be used when the user asks to "Gist一覧", "Gistに保存して",
  "Gistから取ってきて", "Gistを更新して", "コードをGistに",
  "Gist確認して", "/gh-gist",
  or needs to manage GitHub Gists via gh CLI.
allowed-tools: Bash, Read
---

description にスキルの起動条件を書いておくと、Claude がユーザーの発言を見て自動的にスキルを呼び出します。「Gist に保存して」のような日本語のトリガーも列挙できます。allowed-tools: Bash, Read で、このスキルが使えるツールを制限しています。

Skills は description だけが常時コンテキストに入っていて、本文はスキルが呼び出されたときにだけロードされるので、普段の会話には影響しません。

モード判定

| モード | トリガー例 | 主なコマンド |
|--------|-----------|-------------|
| 一覧 | 「Gist一覧」 | `gh gist list` |
| 取得 | 「Gistから取ってきて」 | `gh gist view --raw --filename` |
| 保存 | 「Gistに保存して」 | `gh gist create` |
| 更新 | 「Gistを更新して」 | `gh gist edit` |
| データ管理 | 「Gistのデータ更新して」 | `gh gist view` + jq + `gh gist edit` |

ユーザーの一言からどのモードを実行するかを、このテーブルで Claude に判断させています。CI 編が読み取り中心の4モードだったのに対して、Gist 編は CRUD 操作を含む5モード構成です。

トークン効率のルール

ここが SKILL.md で一番重要なパートです。CI 編では --log--job 必須・watch 禁止というルールでしたが、Gist 編ではサブコマンドが違う分、ルールの中身も変わります。ただし 「必要な情報だけに絞り込む」 という設計思想は共通です。

**必ず守ること:**

- `gh gist list --include-content` は使用禁止(全 Gist の中身を取得してトークンを大量消費する)
- `gh gist view` で複数ファイル Gist を扱う場合は必ず `--filename` で絞る
- `gh gist view --files` でファイル一覧を先に確認してから `--raw --filename` で中身取得

--include-content を禁止しているのは、gh gist list に付けると全 Gist の中身まで取得してしまうからです。--filter だけで description とファイル名は検索できるので、中身を全部取る必要はありません。

--filename を必須にしているのは、複数ファイルの Gist で --filename なしだと全ファイルが連結出力されるからです。検証では2ファイルの Gist で --filename ありだと6行、なしだと37行の出力差がありました。ファイル数が多い Gist だとこの差はさらに開きます。

デモで見た「--filter--files--raw --filename」という段階的な絞り込みも、このルールに基づいています。最初から全部取るのではなく、ステップを分けて必要な情報だけに辿り着く設計です。

--raw の落とし穴

検証で見つけた話なんですが、gh gist view <id> --raw--filename なしで実行すると、description が出力の先頭行に入ります。

$ gh gist view e72365796014c25d70629f6d8cfe01bc --raw
Python useful snippets        ← description が1行目に出る

"""Python useful snippets - よく使うコードスニペット集"""
...

ターミナルで見る分には気にならないんですけど、> file.json でリダイレクトすると JSON の先頭に description が混入してパースが壊れます。後述するデータ管理モードで JSON を取得→更新するフローがあるので、SKILL.md に --raw は必ず --filename と併用する」 というルールを明記して、Claude が --filename なしで実行するのを防いでいます。

書き込み操作の安全策

CI 編のスキルは読み取り専用でしたが、Gist 編は CRUD 全操作を含むので、安全策の設計が必要になります。

  • secret デフォルト: --public はユーザーが「public で」と明示した場合のみ使う。意図せず公開されるのを防ぐ
  • 削除前確認: gh gist delete はユーザーに確認を取ってから実行する
  • --yes フラグ: 非インタラクティブ環境(Claude Code)では削除時に --yes が必須。検証中に --yes なしで実行してエラーになって気づいた
  • 一時ファイル経由: 保存・更新は application/tools/tmp/ に一時ファイルを書き出してからコマンドに渡す

読み取り専用のスキルにはない設計ですが、CRUD をスキル化するなら、こういう安全策のセットはテンプレートとして使い回せると思います。

データ管理モード

SKILL.md には5つ目のモードとして「データ管理」を入れています。description に [data] プレフィックスを付けてデータ用 Gist を識別する規約で、JSON の取得 → jq で変換 → Gist に反映、というフローを定義しています。Gist を簡易 DB 的に使う発想ですね。実用レベルかはまだ試行中ですが、仕組みとしては動きます。興味がある人は付録の SKILL.md 全文を参照してください。

改善の余地

gh CLI には gh gist clone でローカルに落として編集→ push するフローや、gh gist rename でのファイル名変更もあります。SKILL.md にはまだ組み込んでいませんが、使いながら必要になったら足していく予定です。

まとめ

ざっくり振り返ると、Before / After はこうなりました。

Before: Gist は便利な仕組みだけど、操作コストが高くて使いこなせていなかった。保存するにもブラウザ、探すにもブラウザ。結局「保存するほどでもないか」で使わなくなる。

After: 「Gist に保存して」「スニペット取ってきて」とチャットで打つだけ。VS Code から離れない。操作コストが下がると、Gist を「使おう」と思えるようになる。

これを実現しているのは .claude/skills/gh-gist/SKILL.md という Markdown ファイル1枚です。特別なインフラもサーバーも不要で、プロジェクトにファイルを1つ追加するだけで動きます。

トークン効率のルール(--include-content 禁止、--filename 必須、段階的絞り込み)は gh CLI スキル共通のパターンとして使えます。書き込み操作の安全策(secret デフォルト、削除前確認、--yes)は CRUD をスキル化するときの設計テンプレートになると思います。

ほなまた〜

シリーズ記事

記事内容
概要編 — ブラウザなし GitHub 操作を実現する問題提起と解決策の全体像
CI 編 — GitHub Actions 失敗ログをチャットで即解決失敗ログの取得から原因分析まで
この記事(Gist 編)Gist の検索・保存・更新

付録

SKILL.md 全文

.claude/skills/gh-gist/SKILL.md の内容です。

---
name: gh-gist
description: |
  This skill should be used when the user asks to "Gist一覧", "Gistに保存して",
  "Gistから取ってきて", "Gistを更新して", "コードをGistに",
  "Gist確認して", "/gh-gist",
  or needs to manage GitHub Gists via gh CLI.
allowed-tools: Bash, Read
---

# GitHub Gist Management

gh CLI を使って GitHub Gist の管理(一覧・取得・保存・更新・データ管理)を行います。

## Mode Selection

ユーザーの指示から以下の5モードを自動判定して実行する。

| モード | トリガー例 | 主なコマンド |
|--------|-----------|-------------|
| 一覧 | 「Gist一覧」「Gist確認して」 | `gh gist list` |
| 取得 | 「Gistから取ってきて」「Gistの中身見せて」 | `gh gist view --raw --filename` |
| 保存 | 「Gistに保存して」「コードをGistに」 | `gh gist create` |
| 更新 | 「Gistを更新して」「Gistに追加して」 | `gh gist edit` |
| データ管理 | 「Gistのデータ更新して」「Gistの設定を変更」 | `gh gist view --raw` + jq + `gh gist edit` |

## Token Efficiency Rules

**必ず守ること:**

- `gh gist list --include-content` は使用禁止(全 Gist の中身を取得してトークンを大量消費する)
- `gh gist view --raw` を `--filename` なしで使うと description が先頭行に混入する。特にリダイレクトで JSON/YAML を取得する場合は **必ず `--filename` を指定する**(パースが壊れる)
- `gh gist view` で複数ファイル Gist を扱う場合は必ず `--filename` で絞る(全ファイル連結出力になる)
- `gh gist view --files` でファイル一覧を先に確認してから `--raw --filename` で中身を取得する
- 新規作成時はデフォルト secret(`--public` はユーザーの明示的指示がある場合のみ)
- データ管理モードでは `application/tools/tmp/` に一時ファイルを書き出して `gh gist edit` で反映

---

## Mode 1: 一覧

自分の Gist 一覧を表示する。

### Step 1: Gist 一覧の取得

```bash
# 最新10件
gh gist list --limit 10

# フィルタ付き(description / ファイル名で検索)
gh gist list --filter "keyword"

# public のみ / secret のみ
gh gist list --public
gh gist list --secret
```

### Step 2: 結果を報告テンプレートで表示

## Mode 2: 取得

特定の Gist からファイル内容を取得する。

### Step 1: 対象 Gist の特定

ユーザーが Gist ID / URL を指定していない場合は一覧から検索する。

```bash
# キーワードで検索
gh gist list --filter "keyword"
```

### Step 2: ファイル一覧の確認

```bash
# Gist 内のファイル名を確認
gh gist view <gist-id> --files
```

### Step 3: ファイル内容の取得

```bash
# 特定ファイルの内容を raw で取得
gh gist view <gist-id> --raw --filename <filename>
```

**重要:** 複数ファイル Gist では必ず `--filename` を指定する。省略すると全ファイルが出力されトークンを大量消費する。

## Mode 3: 保存

新しい Gist を作成する。

### Step 1: ファイルの準備

ユーザーが指定したコードやテキストを `application/tools/tmp/` に一時ファイルとして書き出す。

### Step 2: Gist の作成

```bash
# 単一ファイル(secret、デフォルト)
gh gist create application/tools/tmp/<filename> -d "description"

# 複数ファイル
gh gist create application/tools/tmp/file1 application/tools/tmp/file2 -d "description"

# public(ユーザーが明示的に指示した場合のみ)
gh gist create application/tools/tmp/<filename> -d "description" --public

# stdin から作成
echo "content" | gh gist create -f <filename> -d "description"
```

**重要:** デフォルトは secret。`--public` はユーザーが「public で」「公開で」と明示した場合のみ使用する。

### Step 3: 結果を報告テンプレートで表示

## Mode 4: 更新

既存の Gist を更新する。

### Step 1: 対象 Gist の特定

ユーザーが Gist ID / URL を指定していない場合は一覧から検索する。

```bash
gh gist list --filter "keyword"
```

### Step 2: 現在の内容を確認

```bash
gh gist view <gist-id> --files
gh gist view <gist-id> --raw --filename <filename>
```

### Step 3: 更新の実行

```bash
# ファイル内容の上書き(一時ファイル経由)
gh gist edit <gist-id> --filename <target> application/tools/tmp/<local-file>

# ファイルの追加
gh gist edit <gist-id> --add application/tools/tmp/<new-file>

# description の変更
gh gist edit <gist-id> --desc "new description"

# ファイルの削除(ユーザーの明示的指示がある場合のみ)
gh gist edit <gist-id> --remove <filename>
```

### Step 4: 結果を報告テンプレートで表示

## Mode 5: データ管理

JSON / YAML などの構造化データを Gist に保存し、DB 的に管理する。

### データ用 Gist の識別

description に `[data]` プレフィックスを付けてデータ用 Gist を識別する。

```bash
# データ用 Gist の検索
gh gist list --filter "\\[data\\]"
```

### データの取得と更新

```bash
# 1. 現在のデータを取得
gh gist view <gist-id> --raw --filename <filename> > application/tools/tmp/<filename>

# 2. jq で変換(JSON の場合)
jq '.key = "new_value"' application/tools/tmp/<filename> > application/tools/tmp/<filename>.updated

# 3. Gist に反映
gh gist edit <gist-id> --filename <filename> application/tools/tmp/<filename>.updated
```

### データ用 Gist の新規作成

```bash
# JSON データ
gh gist create application/tools/tmp/data.json -d "[data] project-config"

# YAML データ
gh gist create application/tools/tmp/data.yaml -d "[data] settings"
```

**削除操作:** ユーザーの明示的指示がある場合のみ実行。必ず確認を取る。

```bash
# 削除(非インタラクティブ環境では --yes が必須)
gh gist delete <gist-id> --yes
```

## Report Templates

以下のテンプレートを使って結果を報告する。

### 一覧

```
## Gist 一覧

| # | Description | Files | Visibility | Updated |
|---|-------------|-------|------------|---------|
| 1 | <description> | <file-count> | <public/secret> | <date> |
```

### 取得結果

```
## Gist 内容

**Gist:** <description>
**ID:** <gist-id>
**File:** <filename>

<ファイル内容をコードブロックで表示>
```

### 保存完了

```
## Gist 作成完了

**URL:** <gist-url>
**Description:** <description>
**Visibility:** <public/secret>
**Files:** <file-list>
```

### データ管理

```
## データ更新完了

**Gist:** <description>
**File:** <filename>
**変更内容:** <変更のサマリ>
```

## Important Notes

- **gh CLI 未認証の場合**: `gh auth status` で認証状態を確認し、未認証ならユーザーに通知
- **`--include-content` は絶対に使わない**: トークン効率のため。`--filter` だけで description とファイル名は検索可能
- **secret がデフォルト**: ユーザーが明示的に public を指定しない限り secret で作成する
- **削除操作は慎重に**: `gh gist delete` はユーザーの明示的な指示 + 確認の上でのみ実行。非インタラクティブ環境では `--yes` フラグが必須
- **一時ファイルの場所**: 必ず `application/tools/tmp/` を使用する(`/tmp/` は使わない)
ご覧いただきありがとうございます! この投稿はお役に立ちましたか?

役に立った 役に立たなかった

0人がこの投稿は役に立ったと言っています。
エンジニア募集中!

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です