Zenn CLIで記事管理できるようにしてみる + AIによる誤字脱字チェック機能(おまけ)
TRUSTART株式会社でエンジニアとして働いているnagashunです!
大学は経営系の学部を卒業し、新卒1年目はWebの広告代理店で広告運用の仕事をしていました。
昨年、新卒2年目の秋からエンジニアに転職し、現在は不動産データを扱うR.E.DATA plusというサービスを作っています!
今回は弊社でテックブログの執筆が始まったため、GitHub上での記事管理とAIを活用した簡単な記事執筆ワークフローのようなものを作れないかとチャレンジしてみました!
やりたいこと
- 作成した記事をGitHubリポジトリで管理できるようにする
- その際、強制的にAIによる記事添削を挟み、レビューの工数を削減する
- 会社で定めた技術ブログのルール(禁止テーマ)などに抵触していないかAIにチェックしてもらう(今回は実装しません)
使用した技術やツール
- Zenn CLI
- 技術ブログは今のところZennのみに投稿予定のため
- VSCode or Cursor
- 弊社標準のエディタのため
- Cursorなどもほぼ同様にセットアップできるため
- Gemini API
- 弊社では試験導入で各メンバーにAPIキーが配布されているため
- Google Gen AI SDK for Python
- 「generativeai」は2025年8月31日にサポート終了予定のためこちらを利用
- GitHub Actions
- CI上でPythonスクリプトを実行し、PRのコメントに添削結果を出力してもらう
リポジトリをZennと連携させて執筆環境を作る
GitHubとZennのアカウントを連携する
Zennのページを開き、GitHubからのデプロイを選択します。
「リポジトリを連携する」をクリックします。
連携へ進む→連携するリポジトリを選択します。
※同時に紐付けられるリポジトリは2つまでのようです。
※チーム全体で1つのリポジトリを使って記事を管理する場合は、ZennのProプランが必要です。
Zenn CLIを使用して、執筆環境を作成
-
Zenn用のリポジトリを作成する
組織でも個人でもお好きなところでリポジトリを作り、ローカルにクローンしましょう。
公開設定はプライベートでも問題ないようです! -
Zenn CLIをインストールする
npm install zenn-cli
- リポジトリ内でZenn CLIを初期化する
npx zenn init
下記のような表示が出て、articlesディレクトリやbookディレクトリが作成されました!
Generating README.md skipped.
🎉 Done!
早速コンテンツを作成しましょう
👇 新しい記事を作成する
$ npx zenn new:article
👇 新しい本を作成する
$ npx zenn new:book
👇 投稿をプレビューする
$ npx zenn preview
READMEも作成してくれるようなのですが、使い方のリンクを貼ってくれるだけでした。
(大事だけど!)
- 記事ファイルを作成する
npx zenn new:article
すると、articlesディレクトリに.mdファイルが作成されます。
ちなみに、.mdファイルのファイル名に含まれるIDのような部分は「slug」といい、記事や本のユニークなIDのようなもののようです。
また、作成されたファイルの内容は以下のようになり、基本的なフロントマターが生成されました!
YAML形式でタイトルやタグなどを設定していき、本文は---の下から記述していきます。
---
title: ""
emoji: "🔖"
type: "tech" # tech: 技術記事 / idea: アイデア
topics: []
published: false # 下書きで投稿するにはfalseを選択
---
# 本文はここから
ああテスト ああああテスト ああテスト
これでVSCode上でZennの記事を作成する準備が整いました!!
これで開発の時と同じようにmainブランチからブランチを切って記事を作成します。
PR作成→mainにマージされるタイミングで記事が公開されるようです!
▼参考
【おまけ】PR作成したら、勝手に誤字脱字チェックをしてくれる仕組みを作る
執筆途中や執筆後に行う個別の添削はGitHub CopilotやCursorのチャットで行います。
しかし、人にレビューしてもらう前に誤字脱字や会社で取り決めた記事作成ルールに沿っているかどうかは、AIにチェックしてもらった方が手間も減るかと思います。
そのため、ここでは完成した記事を人がレビューする前にAIで添削し、誤字脱字を発見する方法を実践してみました!
GitHub Actionsワークフローファイルの作成
- GitHub Actionsのワークフローのディレクトリにファイルを作成
# GitHub Actionsのワークフローファイルを格納するディレクトリを作成
mkdir -p .github/workflows
# ワークフローファイル(ここでは.github/workflows/article_review.yml)の作成
touch .github/workflows/article_review.yml
- ワークフローファイルの中身を書く
※下記はあくまでも一部を抜粋したサンプルコードです
name: Spellcheck with Gemini
on:
pull_request:
paths:
- 'articles/**.md'
jobs:
spellcheck:
runs-on: ubuntu-latest
permissions:
pull-requests: write
contents: read
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Get changed Markdown files
id: changed_files
run: |
FILES=$(git diff --name-only ${{ github.event.pull_request.base.sha }} ${{ github.sha }} -- '*.md')
echo "files=$FILES" >> $GITHUB_OUTPUT
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.10'
- name: Install Dependencies
run: pip install google-genai
- name: Run Gemini Review
env:
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
CHANGED_FILES: ${{ steps.changed_files.outputs.files }}
run: python .github/scripts/review_article.py
- name: Comment PR with AI review
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
// PRにAIレビュー結果をコメントとして投稿
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: "AI校正結果をここに表示"
});
レビュー用Pythonスクリプトの作成
- レビュー用スクリプトを格納するディレクトリを作成
mkdir -p .github/scripts
- レビュー用のPythonスクリプトファイルを作成
touch .github/scripts/review_article.py
- google-genaiをインストールする
# 依存関係にgoogle-genaiを追加
poetry add google-genai python-dotenv
# poetryでインストール
poetry install
# プロジェクト自体をインストールせずに依存関係のみインストール
poetry install --no-root
# 仮想環境に入る
poetry shell
- Gemini APIを使用した誤字脱字チェック用のコードを書く
※下記はあくまでも一部を抜粋したサンプルコードです
class ArticleReviewer:
def __init__(self):
api_key = os.getenv("GEMINI_API_KEY")
self.client = genai.Client(api_key=api_key)
def review_content(self, article_content: str) -> str:
"""記事をGemini APIでレビューする"""
prompt = SPELLCHECK_PROMPT_TEMPLATE.format(
article_content=article_content
)
response = self.client.models.generate_content(
model='gemini-2.5-pro-preview-05-06',
contents=prompt
)
candidate = response.candidates[0]
if (hasattr(candidate, 'content') and candidate.content and
candidate.content.parts):
text_parts = []
for part in candidate.content.parts:
if hasattr(part, 'text') and part.text:
text_parts.append(part.text)
if text_parts:
return '\n'.join(text_parts)
ちなみにGeminiに添削を依頼する際のプロンプトは、以下のようにしてみました。
SPELLCHECK_PROMPT_TEMPLATE = """
あなたはプロの校正者です。以下のMarkdown形式のテキストから誤字脱字、文法的な誤り、不自然な日本語表現を細かくチェックしてください。
指摘箇所とその修正案を具体的に提示してください。修正が必要な箇所がない場合は、「誤字脱字や文法的な誤りは特に見つかりませんでした。」と明確に回答してください。
出力は、以下のような箇条書き形式でお願いします。
例:
* 元の文: 「これはテストです、こんにちわ。」
* 指摘: 「こんにちわ」は「こんにちは」が正しいです。
* 修正案: 「これはテストです、こんにちは。」
* 元の文: 「ユーザーフレンドリなインターフェース。」
* 指摘: 「ユーザーフレンドリな」はより自然な日本語「利用しやすい」や「使いやすい」にできます。
* 修正案: 「利用しやすいインターフェース。」または「使いやすいインターフェース。」
- GitHub SecretsにAPIキーを設定
GeminiのAPIキーはハードコーディングするわけにはいかないので、GitHub Secretsに格納しておきます。
GitHubで対象のリポジトリページを開く
↓
Settings
↓
Secrets and variables
↓
Actions
↓
New repository secret
上記で設定することができます。
これで完成!!
実際に記事を作成し、PRを作成してみると...
誤字脱字チェックをしてくれました!!
個人的にもっと試行錯誤できると思った点
- 適切なGeminiのモデルはどれかを検証する
- プロンプトの改善や生成の際の文体の制御設定を見直して、適切なフィードバックを得られるようにする
- 必要なトークン数の見積もりや制御方法
まだ誤字脱字チェックのプロンプトしか組み込んでいませんが、今後は会社で決めたルールに沿って記事を添削してくれるように改造していきたいです。
最後に
TRUSTART株式会社は、一緒に働くメンバーを募集しています!
インターンメンバーも大募集中です!
興味を持っていただいた方は、ぜひ弊社のページをご確認ください!!!

「人とデータで全てを可能にする」 不動産領域に関連する、あらゆるビジネスのDX化にチャレンジし、「テクノロジー×人」の力で社会課題を解決するTRUSTART株式会社のテックブログです! 採用情報はこちら:trustart.co.jp/recruit/
Discussion