この記事でわかること・前提環境
Claude Code と Qiita CLI を組み合わせて、「ネタのメモ → 構成案 → 下書き → 機密チェック → プレビュー → 承認後に投稿」までを定型化した環境の作り方を紹介します。あわせて、その仕組みを Claude Code のプラグインにしてチームに配れるようにした話も書きます。
前提環境は以下のとおりです。
| ツール | バージョン |
|---|---|
| Node.js | v22.23.2 |
| npm | 10.9.8 |
| git | 2.40.1 |
Qiita CLI (@qiita/qiita-cli) |
1.10.0 |
| Claude Code | デスクトップアプリ |
やりたかったこと
技術記事を書きたい気持ちはあっても、「何を書くか整理する」「体裁を整える」「出してはいけない情報が混ざっていないか確認する」の3つが面倒で、なかなか手が動きませんでした。
そこで Claude Code に手伝ってもらうことにしたのですが、AI に記事を勝手に投稿されるのは怖いです。そのため、次の2つを両立させることをゴールにしました。
- 面倒な部分は Claude Code に任せる
- 外に出る操作(投稿・公開)は必ず人間が承認する
全体構成
リポジトリは2つに分けました。
① 記事リポジトリ(個人・private) ~/dev/qiita-articles
├── public/ 記事(Qiita CLI 管理)
├── notes/ 作業ログ・ネタ帳
├── .claude/settings.json 権限設定
└── CLAUDE.md 個人設定(Organization名・文体など)
② プラグインリポジトリ(チーム共有) my-team-plugins
├── .claude-plugin/marketplace.json
└── plugins/qiita-writer/
├── .claude-plugin/plugin.json
└── skills/
├── qiita-setup/ ①を作る
├── qiita-note/ ネタをメモする
└── qiita-post/ 書いて投稿する
分けた理由は、記事は個人のもの、スキルはチームの共有物で性質が違うからです。
- Qiita CLI はログインした1アカウントで投稿する作りなので、記事リポジトリは1人1つが自然です
- 記事リポジトリを GitHub に置くなら private にします。限定共有の記事も Markdown としてリポジトリに入るためです
- スキルは全員で同じものを使い、改善も共有したいので、プラグインとして配布します
Qiita CLI で記事リポジトリを作る
mkdir -p ~/dev/qiita-articles && cd ~/dev/qiita-articles
git init
npm init -y
npm i -D @qiita/qiita-cli
npx qiita init
mkdir -p public notes
npx qiita init を実行すると、.github/workflows/publish.yml、.gitignore、qiita.config.json が生成されます。
次にログインします。トークンは Qiita のアクセストークン発行ページ で、read_qiita と write_qiita のスコープを付けて発行します。
npx qiita login
ログインは必ず自分の手で行います。 トークンは Claude Code には渡しません。
ログインできたかは、npx qiita pull が通るかで確認できます。認証情報のファイルを開かずに確認できるので便利です。
$ npx qiita pull
Sync local articles from Qiita
Successful!
Claude Code のプラグインにする
マーケットプレイスとプラグインの定義
Claude Code のプラグインは、マーケットプレイスという単位で配布できます。Qiita 専用のリポジトリにはせず、チーム共通のプラグイン置き場として作り、qiita-writer をその最初のプラグインにしました。
{
"name": "my-team-plugins",
"owner": { "name": "<会社名>" },
"plugins": [
{
"name": "qiita-writer",
"source": "./plugins/qiita-writer",
"description": "Qiita CLI で技術記事を書く・投稿する"
}
]
}
{
"name": "qiita-writer",
"version": "0.1.0",
"description": "Qiita CLI で技術記事を書く・投稿する",
"author": { "name": "<会社名>" },
"keywords": ["qiita", "writing", "blog"]
}
claude plugin validate . で定義ファイルを検証できます。author がないと warning が出ました。
3つのスキル
| スキル | 役割 |
|---|---|
qiita-setup |
記事リポジトリの初期構築(Qiita CLI 導入、.gitignore、権限設定、CLAUDE.md) |
qiita-note |
作業中に「記事になりそう」な内容を notes/ に作業ログとして残す |
qiita-post |
構成案 → 下書き → 機密チェック → プレビュー → 承認後に投稿 |
qiita-setup を用意したことで、今回手作業でやった環境構築を、他のメンバーも同じ手順で再現できます。
各スキルにはパスや Organization 名を直接書かず、各自の記事リポジトリの CLAUDE.md から読むようにしました。
## qiita-writer 設定
- organization_url_name: <Organization URL名。なければ空>
- 文体: です・ます調
qiita-post の流れは次のとおりです(SKILL.md から抜粋)。
## 絶対ルール
- `~/.config/qiita-cli/`(認証情報)や `.env` は読まない・表示しない
- `npx qiita login` はユーザー自身に実行してもらう
- `npx qiita publish` はユーザーの明示的な「投稿してOK」の後にだけ実行する
- 記事は ローカル確認 → 限定共有 → 公開 の順に進め、段階を飛ばさない
- 新規記事は必ず `private: true`(限定共有)で初回投稿する
- 機密チェックで指摘ゼロ、またはユーザーが全件確認済みになるまで投稿しない
## 手順
1. 題材の整理(誰向けに/読後に何ができるか)
2. 構成案(タイトル案3つ・タグ・見出し)→ 承認
3. 下書き作成(npx qiita new)
4. 機密チェック(顧客名・社内URL・認証情報・個人名・絶対パスなど)
5. ローカル確認(npx qiita preview でユーザーが内容を確認)→ 承認
6. 限定共有で投稿(npx qiita publish)→ Qiita上で最終確認 → 承認
7. private: false にして公開
導入方法
プラグインのリポジトリを GitHub に置けば、メンバーは次の2行で導入できます。
/plugin marketplace add <org>/my-team-plugins
/plugin install qiita-writer@my-team-plugins
AI に投稿させるための安全策
1. 認証情報を読ませない
記事リポジトリの .claude/settings.json で、認証情報の読み取りを禁止しています。あわせて、外に出る操作は毎回確認が出るようにしています。
{
"permissions": {
"deny": [
"Read(~/.config/qiita-cli/**)",
"Read(./.env)",
"Read(./.env.*)",
"Bash(cat ~/.config/qiita-cli/*)"
],
"ask": [
"Bash(npx qiita publish:*)",
"Bash(npx qiita login:*)",
"Bash(git push:*)"
]
}
}
スキルに書いた「読まない」というルールに加えて、権限設定でも止めています。指示と設定の二重のガードです。
2. 「ローカル確認 → 限定共有 → 公開」の3段階で承認する
記事は3段階で進め、次の段階に進むたびに承認を挟みます。
| 段階 | 場所 | 確認すること | 次へ進む合図 |
|---|---|---|---|
| ローカル確認 | Markdown とプレビュー画面(npx qiita preview) |
内容そのもの | 「ローカルOK」 |
| 限定共有 | Qiita の限定共有 | 実際の Qiita での見た目 | 「公開OK」 |
| 公開 | Qiita の公開 | — | — |
最初は「下書きができたら限定共有で投稿 → 確認して公開」の2段階にしていました。ところが実際に使ってみると、私が内容を読む前に Claude Code が投稿の承認を求めてきました。そこで、ローカルで人間が読む段階を独立させ、「ローカルOK」が出るまで投稿に進まないようにスキルを直しました。
3. 機密チェック
下書きを全文チェックし、以下に当てはまる箇所を「行 / 内容 / 推奨対応」の表で報告させています。
- 顧客名・取引先名・案件名
- 社内の URL / ホスト名 / IP アドレス / 社内リポジトリ名
- トークン・API キー・メールアドレスなどの認証情報や個人情報
- 他者の個人名
- ユーザー名を含む絶対パス(
/Users/<名前>/→~/)
AI に勝手に消させず、置換案を出させて人間が判断するようにしています。
はまりどころ・気づき
npx qiita init が自動投稿のワークフローを作る
.github/workflows/publish.yml は、main ブランチに push すると記事を自動で投稿する GitHub Actions です。「承認してから投稿する」方針と合わず、うっかり投稿する原因になるので削除しました。GitHub はバックアップと履歴のために使い、投稿はローカルから行います。
npx qiita new の初期値は private: false
新規作成した記事ファイルは、初期状態で公開になっています。そのまま publish すると、いきなり公開されてしまいます。スキル側で必ず private: true に書き換えるようにしています。
Qiita CLI は起動時に .env を読み込む
コマンドを実行するたびに injected env (0) from .env と表示されます。dotenv で .env を読み込んでいるようなので、念のため .gitignore に .env と .env.* を追加しました。
Organization の指定は記事ごと
Organization は qiita.config.json では指定できず、記事ごとの front matter にある organization_url_name で指定します。そのため、スキルが CLAUDE.md から値を読んで、毎回 front matter に埋めるようにしました。
push する前のプラグインはローカルで試せる
GitHub に push する前でも、ローカルのディレクトリをマーケットプレイスとして登録すれば試せます。
claude plugin marketplace add ~/dev/my-team-plugins --scope local
claude plugin install qiita-writer@my-team-plugins --scope local
--scope local にすると設定が .claude/settings.local.json に入るので、ローカルのパスがコミットされません。登録したあと、セッションを開き直すとスキルが読み込まれます。
settings.local.json はリポジトリの .gitignore にも書く
私の環境では、グローバルの gitignore(~/.config/git/ignore)で .claude/settings.local.json が除外されていました。他のメンバーの環境では除外されていないかもしれないので、リポジトリの .gitignore にも明示的に追加しています。
まとめ
- Qiita CLI で記事を Markdown として git 管理し、Claude Code のスキルで「書く」部分を定型化しました
- 記事は個人のリポジトリ、スキルはチームで共有するプラグイン、と分けて管理しています
- AI に任せる範囲を広げる代わりに、認証情報を読ませない設定・ローカル確認 → 限定共有 → 公開の3段階承認・機密チェックで安全側に倒しています
これで、ネタを思いついたら qiita-note でメモし、書くときは qiita-post を呼ぶだけになりました。