0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

CodexからDocker版Qiita CLIを操作して、確認後に記事を公開した

0
Posted at

はじめに

ねこ宿研究所の技術発信を始めるにあたり、CodexにQiita CLIの環境構築から原稿作成、公開後確認まで手伝ってもらいました。

実際の分担は次のとおりです。

工程 担当
既存環境の調査 Codex
Docker構成の作成と検証 Codex
Qiitaのトークン発行・ログイン
原稿作成と機密情報検査 Codex
ブラウザでのプレビュー確認
対象記事だけを公開 Codex
公開APIとHTTPによる確認 Codex

ポイントは、認証情報をCodexとのチャットへ貼らず、外部公開の直前に人が内容を確認することです。

この記事では、実際に使ったファイルとコマンド、途中で詰まった点、CodexへCLIを渡すときに決めておくとよい境界をまとめます。

なぜQiita CLIをDockerで動かしたのか

最初にCodexがローカル環境を調べると、ホストのNode.jsはv20.11.1でした。一方、その時点で使ったQiita CLI 1.10.0には、より新しいNode.jsが必要でした。

ホスト全体のNode.jsを更新すると、別プロジェクトへ影響する可能性があります。そこでQiita記事の管理を独立したディレクトリへ分け、Node.js 22.22.1をDocker内に固定しました。

neko-yado-qiita/
├── Dockerfile
├── compose.yaml
├── package.json
├── qiita.config.json
├── README.md
└── public/
    ├── ai-wordpress-wp-cli-guardrails.md
    └── codex-qiita-cli-docker-workflow.md

これにより、Codexはプロジェクト内の同じコマンドだけを使えばよく、ホスト側のNode.jsバージョンへ依存しなくなりました。

Dockerfile

実際のDockerfileは次のような構成です。

FROM node:22.22.1-bookworm-slim

WORKDIR /app

COPY package.json ./
RUN npm install --no-audit --no-fund \
    && npm cache clean --force \
    && mkdir -p /home/node/.config/qiita-cli \
    && chown -R node:node /home/node/.config

USER node
WORKDIR /workspace

ENTRYPOINT ["/app/node_modules/.bin/qiita"]
CMD ["help"]

package.jsonでは、公式パッケージを固定しました。

{
  "name": "neko-yado-qiita",
  "private": true,
  "dependencies": {
    "@qiita/qiita-cli": "1.10.0"
  }
}

USER nodeにより、Qiita CLIをrootでは実行しません。認証情報の保存先も先に作り、nodeユーザーが書き込めるようにしています。

最初はENTRYPOINTで失敗した

初版では次のENTRYPOINTにしていました。

ENTRYPOINT ["npx", "--no-install", "qiita"]

しかし、依存パッケージは/app/node_modulesへインストールし、実行時のカレントディレクトリは/workspaceです。npxが実行ファイルを見つけられず、次のエラーになりました。

npm error could not determine executable to run

そこで、インストール済みバイナリの絶対パスをENTRYPOINTへ指定しました。

ENTRYPOINT ["/app/node_modules/.bin/qiita"]

修正後、Codexがコンテナ内でバージョンを確認しました。

docker compose run --rm qiita version
1.10.0

AIにCLIを使わせる場合、コマンドの入口と作業ディレクトリを固定すると、毎回の指示が短くなり、環境差による失敗も追いやすくなります。

Composeで認証情報と原稿を分ける

Composeは次のようにしました。

services:
  qiita:
    build:
      context: .
    init: true
    stdin_open: true
    tty: true
    volumes:
      - .:/workspace
      - qiita-credentials:/home/node/.config/qiita-cli
    ports:
      - "127.0.0.1:8888:8888"

volumes:
  qiita-credentials:

原稿と設定はホスト側のプロジェクトへ保存します。一方、Qiitaの認証情報は名前付きボリュームqiita-credentialsへ分離します。

この構成では、アクセストークンを次の場所へ入れません。

  • Markdown原稿
  • .env
  • Git管理対象ファイル
  • Codexとのチャット
  • シェルのコマンド引数

Qiita CLIが必要とするときだけ、コンテナから名前付きボリュームを読みます。

ログインは人が行う

イメージを作った後、ログインだけは人がターミナルで実行しました。

docker compose build
docker compose run --rm qiita login

表示された案内に従って、Qiitaで発行したトークンをCLIへ直接入力します。トークンをCodexへ渡す必要はありません。

ログイン後、Codexからは次のような認証済み操作を実行できます。

docker compose run --rm qiita version
docker compose run --rm qiita new article-name
docker compose run --rm --service-ports qiita preview
docker compose run --rm qiita publish article-name

認証情報そのものを見せることと、認証済みCLIの限定されたコマンドを使わせることは分けて考えられます。

qiita initが作った自動公開workflowを削除した

Codexが次を実行して初期設定を生成しました。

docker compose run --rm qiita init

qiita.config.jsonに加えて、GitHubへのpushで記事を公開するworkflowも生成されました。

今回は「人がプレビューを確認した後、指定した1記事だけを公開する」という方針です。pushを公開承認としては扱わないため、自動生成されたworkflowを削除しました。

さらに、通常の投稿では次を使いません。

docker compose run --rm qiita publish --all

代わりに記事名を指定します。

docker compose run --rm qiita publish ai-wordpress-wp-cli-guardrails

CLIを導入した直後は「動くこと」だけでなく、暗黙に追加された自動化がないかも確認したほうが安全です。

原稿作成から公開までの会話

実際には、次の流れで進めました。

1. Codexが実装を調査する

最初の記事は、ねこ宿研究所で実際に使っているWordPress運用ラッパーを題材にしました。Codexがローカルのシェルスクリプトや設計資料を読み、実装と記事の説明が一致するように原稿を作成しました。

架空の成功談にはせず、実装が厳密な許可リストではなく、高危険度コマンドを拒否する方式である点も明記しました。

2. 公開してはいけない情報を検査する

投稿前にCodexが次を確認しました。

  • 本番ホスト名
  • SSHユーザー名
  • サーバー内部パス
  • 資格情報の値
  • Markdownのコードフェンス
  • Qiita front matter
  • 参考リンクのHTTP応答

技術記事では、コードを正しくするだけでなく、実環境の情報をどこまで匿名化するかもレビュー対象になります。

3. 人がプレビューする

プレビューは次のコマンドで起動しました。

docker compose run --rm --service-ports qiita preview

ブラウザでhttp://localhost:8888を開き、人が表示と内容を確認します。

この段階では、まだQiitaへ公開していません。人が「確認できました」と返した後にだけ、Codexが投稿コマンドを実行しました。

4. Codexが対象記事だけを投稿する

docker compose run --rm qiita publish ai-wordpress-wp-cli-guardrails

Qiita CLIは成功時に記事IDを返し、Markdownのfront matterへidupdated_atを書き戻しました。

5. 公開結果を別経路で確認する

コマンドの終了コード0だけで完了とはしませんでした。CodexがQiita APIから公開記事を取得し、次を再確認しました。

  • 記事ID
  • タイトル
  • private: false
  • タグ
  • 公開URL
  • 作成日時と更新日時

最後に公開URLがHTTP 200で応答することも確認しました。

「投稿コマンドが成功した」と「読者が公開記事を取得できる」は別の確認です。

Codexへ依頼するときの例

最初から公開まで一度に任せるのではなく、停止地点を明示すると扱いやすくなります。

このディレクトリでDocker版Qiita CLIを構築してください。

- 公式Qiita CLIを使用する
- Node.jsのバージョンを固定する
- 認証情報はGit管理対象やチャットへ出さない
- 記事はpublic/*.mdで管理する
- publish --allとpush時の自動公開は使わない
- 原稿完成後はプレビューで止める
- 私が確認した後、指定した記事だけを公開する
- 公開後はAPIとHTTP応答を確認する

OpenAIの公式ユースケースでも、Codexが繰り返し使うCLIには、予測可能な出力、認証チェック、draft-before-write、書き込み操作の承認境界を持たせる考え方が紹介されています。

今回分けてよかった境界

Codexへ任せたこと

  • 必要バージョンの調査
  • DockerfileとComposeの作成
  • CLIの初期化
  • エラーの診断と修正
  • 原稿作成
  • 静的検査
  • 指定記事の投稿
  • 公開後確認

人が行ったこと

  • Qiitaトークンの発行
  • CLIへのログイン
  • ブラウザ上のプレビュー確認
  • 公開してよいという最終判断

認証操作をすべて人に残す必要がある、という意味ではありません。CIで公開する運用も可能です。ただし、誰がどのイベントを公開承認とみなすかは、最初に決める必要があります。

今回の小規模な運用では、「プレビューを見た人の明示的な返答」を公開承認にしました。

まとめ

CodexからQiita CLIを使う環境を作り、実際に記事を公開できました。

うまく機能したのは、次の点です。

  • Qiita用ディレクトリとDocker環境を独立させる
  • CLIとNode.jsのバージョンを固定する
  • 認証情報を名前付きボリュームへ分離する
  • publish --allやpush時の自動公開を使わない
  • 人のプレビュー確認を公開前の停止地点にする
  • 公開後にAPIとHTTPで結果を再確認する

Codexに外部サービスのCLIを渡すと、環境構築から検証まで一つの会話で進められます。ただし、便利さを活かすには「どのコマンドを使えるか」だけでなく、「どの時点で人が確認するか」「秘密情報をどこへ置くか」「成功をどう再確認するか」まで設計するのが大切でした。

前回公開した実例は、AIに本番WordPressを操作させるため、WP-CLIの実行経路を4層に分けたです。

参考資料

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?