← ミライズ労務コンサルティング開発知識シリーズ 目次(全6部)
第 3 部
hokama@mirise ~/project $ tail -n +2 employees.csv | awk -F, '$5 >= 20'

実例編

第1部と第2部で扱った層構造を、実際に動くコマンドと出力で追います。
掲載しているコマンドと結果は、すべて実行して確認したものです。

$ npm run dev

npm run dev を7層で追う

毎日打っているこの1行が、7つの層をどう通り抜けているか。

  1. シェル

    npm という名前のファイルを探す

    bash が PATH に並んだフォルダを先頭から順に見て、npm という名前のファイルを探します。見つかったら自分の複製を作り、その中身を上書きしようとします。第1部の第4章そのままです。

    $ which npm /usr/local/bin/npm
  2. OS カーネル

    ファイルの先頭2文字を見る

    カーネルがそのファイルを開いて先頭を確認すると、こう書かれています。

    #!/usr/bin/env node

    先頭の #!シバン(shebang)と呼ばれる印で、「これは機械語の実行ファイルではない。後ろに書いたプログラムに読ませてくれ」という指示です。

    だからカーネルは npm を直接動かすのではなく、node を起動して npm のファイルを引数として渡します。npm 自体が JavaScript で書かれたプログラムであり、Node の上で動いているということです。

  3. Node.js

    JavaScript として解釈する

    node が起動し、V8 エンジンが npm のコードを読み込んで実行を始めます。ここで初めて「JavaScript が動いている」状態になります。

  4. npm

    package.json を読んで、dev の中身を取り出す

    npm が今いるフォルダの package.json を開き、scripts の中の dev という項目を探します。

    "scripts": { "dev": "next dev" }

    つまり npm run dev それ自体は何もしません。package.json に書いてある別のコマンドを呼び出す代理人です。実際に動くのは next dev です。

    ここで npm がもう一仕事します。node_modules/.bin というフォルダを PATH の先頭に一時的に付け加えます。これがあるから、next をパソコン全体にインストールしていなくても next という名前で呼べます。

  5. npm

    next を子プロセスとして起動する

    npm がさらに自分の複製を作り、その中身を next で上書きします。ここでも fork と exec が起きています。プロセスの親子関係は bash → node(npm) → node(next) という三段になります。

  6. Next.js

    URL とファイルの対応表を作る

    nextapp/ フォルダの中を走査し、どのファイルがどの URL に対応するかの表を組み立てます。

    app/page.tsx → / app/staff/page.tsx → /staff app/api/csv/route.ts → /api/csv

    置き場所がそのまま URL になる。第1部の原則1「すべてはファイルである」の直系です。

  7. OS カーネル

    ポートを確保する

    Next.js がカーネルに「3000 番ポートで待ち受けたい」と依頼します。空いていればカーネルが割り当て、すでに他のプロセスが使っていれば拒否されます。

    Error: listen EADDRINUSE: address already in use :::3000

    あの見慣れたエラーは、この段階で出ています。Next.js の問題でもコードの問題でもなく、OS がポートを渡せなかったという報告です。

  8. Next.js

    終わらずに待ち続ける

    準備が終わっても Next.js は終了しません。リクエストを待つことが仕事なので、意図的に生き続けます。

    だからターミナルにプロンプトが戻ってきません。第1部で見た「親が子の終了を待つ」状態のまま、子が永遠に終わらないためです。Ctrl+C を押すと、その待機を強制的に打ち切ることになります。

この1行が説明していること

なぜターミナルが戻ってこないのか ─ 子プロセスが終わらない設計だから。異常ではない。

なぜ next を単体で入れていないのに動くのか ─ npm が node_modules/.bin を PATH に一時追加しているから。

なぜ EADDRINUSE が出るのか ─ 前回のプロセスが生き残ってポートを掴んでいるから。OS 層の問題なので、コードをいくら直しても解決しない。

$ cat employees.csv

同じ仕事を3つの層でやってみる

同じ結果を、シェル・Node スクリプト・Next.js の3通りで出します。

題材として、こういう従業員データがあるとします。employees.csv という名前のテキストファイルです。

employee_id,name,department,monthly_wage,weekly_hours,hire_date 1001,山田太郎,営業,320000,40,2023-04-01 1002,佐藤花子,管理,180000,25,2024-01-15 1003,鈴木一郎,営業,95000,15,2024-06-01 1004,高橋美咲,製造,265000,40,2022-10-01 1005,田中健二,製造,86000,20,2025-02-01 1006,伊藤さくら,管理,142000,30,2023-07-01 1007,渡辺大輔,営業,410000,40,2021-04-01 1008,山本結衣,製造,78000,12,2025-05-01

やりたいことは「週の所定労働時間が20時間以上の人を抽出し、賃金の高い順に並べる」です。

方法1 ─ シェルで1行

$ tail -n +2 employees.csv | awk -F, '$5 >= 20' | sort -t, -k4 -nr 1007,渡辺大輔,営業,410000,40,2021-04-01 1001,山田太郎,営業,320000,40,2023-04-01 1004,高橋美咲,製造,265000,40,2022-10-01 1002,佐藤花子,管理,180000,25,2024-01-15 1006,伊藤さくら,管理,142000,30,2023-07-01 1005,田中健二,製造,86000,20,2025-02-01

3つの独立したプログラムが、パイプでつながっているだけです。

部分役割
tail -n +21行目のヘッダを飛ばして、2行目以降を出す
awk -F, '$5 >= 20'カンマ区切りの5列目が20以上の行だけを通す
sort -t, -k4 -nr4列目を数値として、降順に並べる

awk は絞り込みしかしません。sort は並べ替えしかしません。それぞれが一つのことしかしないから、順番を入れ替えたり別のものに差し替えたりできます。第1部の原則2と原則3が、そのまま目に見える形で現れています。

部品を入れ替えると、別の集計になります。

$ tail -n +2 employees.csv | cut -d, -f3 | sort | uniq -c | sort -nr 3 製造 3 営業 2 管理

部署の列だけ取り出し、並べ、同じものを数え、多い順に並べる。4つつないだだけで部署別人数が出ます。新しいプログラムは1行も書いていません。

向いている場面は、今この場で1回確認したいとき。所要1分、作るものはゼロです。限界は、条件が複雑になると誰も読めなくなること、そして人に渡しにくいことです。

方法2 ─ Node スクリプト

判定条件が複数の組み合わせになると、シェルでは苦しくなります。そこで一段上げます。

// check.mjs import fs from 'node:fs'; const rows = fs.readFileSync('employees.csv', 'utf-8') .trim().split('\n').slice(1) .map(line => { const [id, name, dept, wage, hours, hireDate] = line.split(','); return { id, name, dept, wage: Number(wage), hours: Number(hours), hireDate }; }); const targets = rows.filter(r => r.hours >= 20 && r.wage >= 88000); console.log(`従業員 ${rows.length}名 / 該当 ${targets.length}名\n`); for (const r of targets) { console.log(` ${r.name} ${r.dept} ${r.wage.toLocaleString()}円 週${r.hours}h`); }
$ node check.mjs 従業員 8名 / 該当 5名 山田太郎 営業 320,000円 週40h 佐藤花子 管理 180,000円 週25h 高橋美咲 製造 265,000円 週40h 伊藤さくら 管理 142,000円 週30h 渡辺大輔 営業 410,000円 週40h
お断り

上の判定条件(週20時間以上・月額8.8万円以上)は、コードの構造を示すために単純化したものです。実際の適用要件は制度ごとに異なりますので、filter の中身は各要件に合わせて差し替えてください。

ここで見ていただきたいのは、条件が構造として書けるようになるという点です。r.hours >= 20 && r.wage >= 88000 は、条件が3つ4つに増えても読めます。awk ではこうはいきません。

向いている場面は、毎月繰り返す作業。ファイルとして保存できるので、来月も同じものが動きます。限界は、ターミナルを使える人しか回せないことです。

方法3 ─ Next.js の画面

職員が使うなら、ブラウザで完結させる必要があります。ファイルをこう置きます。

app/ ├── page.tsx → / トップ画面 ├── staff/ │ └── page.tsx → /staff 従業員一覧 └── api/ └── check/ └── route.ts → /api/check 判定処理

判定ロジックは方法2で書いたものがそのまま流用できます。変わるのは、結果を console.log で出すか、画面に表として描くかだけです。

向いている場面は、自分以外の人が使うとき。代償は、作る手間、保守の責任、そして誰がどこまで見られるかという設計です。

$ 判断

どの層で作るかの判断

3つの方法に優劣はありません。適する場面が違うだけです。

↑ 作る手間 使える人の範囲 → シェル 1行 自分が1回だけ Node スクリプト 自分が毎月回す Next.js 画面 職員が使う 認証付きアプリ 顧問先が使う
右上へ行くほど多くの人が使えますが、作る手間と保守の責任も比例して増えます。
状況適切な層理由
今1回だけ確認したいシェル1行作るものがゼロ。1分で終わる
毎月自分が回すNode スクリプト保存できて、条件が読める形で残る
職員が使うNext.js の画面ターミナルを教える必要がない
顧問先が使う認証付きの Web アプリ誰が何を見られるかの制御が必須になる

一段上げるたびの取引

層を一段上げるたびに、作る手間は増え、使う人の負担は減ります。この交換をどこで止めるかが設計判断です。

そして重要なのは、いきなり上から作らないことです。

まずシェル1行で確かめる。繰り返すことが分かってからスクリプトにする。他人が使うと決まってから画面をつける。この順番を守ると、要らないものを作らずに済みます。逆にいきなり Next.js から始めると、月1回しか使わない機能に数日かけることになります。

ここは AI が決められない

「誰が使うのか」「何回やるのか」「間違ったときに誰が困るのか」。この3つを知っているのは人間だけです。

AI に「従業員データを抽出する仕組みを作って」と頼めば、たいてい Next.js のアプリが出てきます。悪意ではなく、文脈を与えなければ最も一般的な答えを返すからです。「1回確認したいだけ」と伝えれば、awk の1行が返ってきます。

実装の速さが AI の側に移った結果、人間の側に残った仕事はどの層で解くかを指定することになりました。

$ python3 shinsei.py

「Python で作れ」と言われたとき

Excel の申請書を自動化したい、という場面でよく出る助言です。

「アプリを作るより Python のほうがいい」という言い方は、3つの別々の話を1つに束ねています。ほどくと見通しがよくなります。

選択肢
1. 画面を作るか作らない(スクリプト) ↔ 作る(アプリ)
2. どこで動かすか手元の PC ↔ サーバー
3. 何語で書くかPython ↔ JavaScript

この助言の実質は、たいてい軸1と軸2の話です。「画面を作らず、手元で動かせ」と言っている。Python という言語名は、その結論に付いてきただけのことが多い。

同じことは Node.js でも書けます。ですので最初に立てるべき問いは「アプリか Python か」ではなく、「アプリか、スクリプトか」です。

Excel の場合、往復が丸ごと無駄になる

Excel の申請書は、すでに手元のファイルとして存在しています。ここが決定的です。

Web アプリ 手元の Excel サーバーで処理 手元の Excel アップロード ダウンロード この2回の受け渡しは、Web にしたから生まれた工程 スクリプト 手元の Excel その場で処理 手元の Excel
金色の処理そのものは同じです。違いは、その前後に運搬工程が挟まるかどうかだけです。

上の往復は、Web アプリにしたせいで発生した工事であって、元の仕事とは無関係です。しかもアップロードとダウンロードのぶん、職員の操作手順はむしろ増えます。「自動化したのに手数が増えた」という結果になりがちなのは、この構造のためです。

ただし Excel だけは、言語の差も独立に効く

軸3(何語で書くか)が本当に効く数少ない領域が、まさに Excel です。

ライブラリできること
openpyxlxlsx の読み書き。書式・数式・条件付き書式を保ったまま編集できる
pandas表としての集計・結合・整形
xlsxwriter書き出し専用。書式の作り込みが得意
xlwings起動中の Excel 本体を外から操縦する
pywin32Windows の COM 経由で Excel を直接操作する

JavaScript にも SheetJS があり、読み書き自体は十分できます。ただし書式まわりは無償版だと制約があり、「元のブックの体裁を崩さずに値だけ埋める」という申請書の用途では Python のほうが素直です。

VBA の後継という位置づけ

決定的な差は最後の2つです。xlwingspywin32 は、起動している Excel そのものを操作できます。Excel の計算エンジンをそのまま使い、既存の VBA マクロを呼び出し、印刷まで指示できる。Web アプリには原理的にできないことです。

VBA でマクロを組んだ経験があるなら、Python はその自然な後継にあたります。同じことを Excel の外から、より強力な道具立てで行う。

ただし条件が2つあります。Excel 本体がインストールされている必要があることと、pywin32 は Windows 専用であることです。サーバー上では動きません。「手元で動かす」という前提とセットの手法です。

判断表

状況適する形
手元の Excel を加工して手元に戻すスクリプト
担当者1〜数人が回すスクリプト
毎月同じ処理を繰り返すスクリプト
職員が複数人、同時に使うWeb アプリ
顧問先に使わせるWeb アプリ(認証付き)
結果を蓄積して後から検索・集計するWeb アプリ + データベース
承認フローや履歴が要るWeb アプリ
スマホからも使いたいWeb アプリ

分かれ目はファイルが最終形かどうかです。Excel を作って終わりならスクリプト。データを溜めて後から使い回すならアプリ。この一問で、たいていの場合は決まります。

中間形態がある

いきなり画面を作らずに済ませる手が2つあります。

手法内容
実行だけボタン化スクリプトをバッチファイルやショートカットにする。職員はダブルクリックするだけ。ターミナルを教える必要がない
Streamlit / GradioPython のまま、数十行で簡単な画面が付く。手元で起動してブラウザから使う

「画面が要る」ことと「Web アプリにする」ことは別です。ここを分けて考えられると、選択肢がかなり広がります。

前章の図との対応

Python スクリプトは、前章の図の「Node スクリプト」とまったく同じ位置にあります。言語が違うだけで、層としては同一です。

ですので判断基準も変わりません。誰が何回使うかに尽きます。Excel の申請書は、たいてい「担当者が毎月」なのでスクリプトの領域に落ちる。冒頭の助言は、経験則として当たっているということです。

ただし理由が「Python だから」ではなく「その仕事はスクリプトの層だから」だと理解しておくと、条件が変わったとき ─ たとえば顧問先にも使わせることになったとき ─ に判断をやり直せます。

$ echo $?

エラーを層で追う

実際によく出る4つを、層に対応づけて読みます。

CASE 1 ─ シェル層
zsh: command not found: next

何が起きているか ─ シェルが PATH に並んだフォルダを全部見たが、next という名前のファイルが無かった。nextnode_modules/.bin の中にありますが、そこは PATH に入っていません。

だから npm run dev なら動く ─ npm が実行時に node_modules/.bin を PATH へ一時追加するためです。第1章の第4段階で見たとおりです。

対処npx next devnpm run dev を使う。

CASE 2 ─ OS 層
Error: listen EADDRINUSE: address already in use :::3000

何が起きているか ─ 3000 番ポートを他のプロセスが既に握っている。ほとんどの場合、前回起動した Node が終了せずに残っています。

コードを直しても解決しない ─ これは OS がポートを渡せなかったという報告で、アプリの中身とは無関係です。

# 誰が掴んでいるか調べる $ lsof -i :3000 # PID を指定して止める $ kill -9 <PID> # PowerShell PS> Get-Process node | Stop-Process -Force
CASE 3 ─ npm 層
Module not found: Can't resolve 'react'

何が起きているかpackage.json には react が必要だと書いてあるが、node_modules の中に実物が無い。取り寄せていないか、途中で壊れています。

$ rm -rf node_modules package-lock.json $ npm install

なぜ lock ファイルも消すのか ─ lock ファイル自体が壊れている可能性があるためです。ただし本番環境では消してはいけません。バージョンが変わって再現性が崩れます。

CASE 4 ─ 環境差
TypeError: Cannot read properties of undefined (DATABASE_URL is not defined) # ローカルでは動く。Vercel でのみ失敗する

何が起きているか ─ 接続情報は .env.local に書いてあるが、このファイルは Git に含まれていません。だから Vercel 側には存在しません。

これは不具合ではなく設計 ─ 秘密情報をリポジトリに入れないのは、意図的な取り決めです。.gitignore.env.local が書かれているのはそのためです。

対処 ─ Vercel の管理画面で環境変数を別途登録する。ローカルと本番は別の環境だという前提を持っておくと、この種の問題は最初から想定できます。

切り分けの原則

下から上へ確認する。上の層で悩む前に、下が正常であることを確かめます。

$ node -v # Node は入っているか $ which next # コマンドは見つかるか $ ls node_modules # 部品は揃っているか $ lsof -i :3000 # ポートは空いているか $ cat .env.local # 設定値は入っているか

この5行を先に流すだけで、原因の大半がどの層にあるか判明します。そしてその情報を持って AI に相談すると、返答の精度が変わります

# 情報が無い依頼 デプロイできません。直してください。 # 切り分け済みの依頼 ローカルの npm run dev は正常に起動する。 Vercel のビルドログで DATABASE_URL が undefined と出て停止。 .env.local には設定済みだが .gitignore に入っている。

後者に対して AI は、Vercel 側の環境変数登録が抜けているという結論に一手で到達します。前者に対しては、可能性を10個並べるしかありません。効いているのは技術力ではなく、どの層で止まったかを言語化する能力です。

$ ls -a

プロジェクトの構成を読む

Next.js プロジェクトの標準形。ファイルが20個以上並んでいても、種類は3つしかありません。

miraise-crm/ ├── .claude/ Claude Code の設定 ├── .next/ ビルド結果(自動生成) ├── .vercel/ Vercel との紐付け(自動生成) ├── data/ docs/ scripts/ 自作の作業フォルダ ├── deliverables/ scratchpad/ ├── node_modules/ 取り寄せた部品(自動生成) ├── src/ ソース本体 ← 中心 ├── .env.example 環境変数の見本 ├── .env.local 環境変数の実物(秘密) ├── .gitignore 記録しないものの一覧 ├── AGENTS.md CLAUDE.md AI への指示書 ├── README.md 人間向けの説明 ├── drizzle.config.ts Drizzle ORM の設定 ├── next.config.mjs Next.js の設定 ├── next-env.d.ts 型定義の参照(自動生成) ├── package.json 部品表 ├── package-lock.json 版の記録(自動生成) ├── postcss.config.mjs PostCSS の設定 ├── tailwind.config.ts Tailwind CSS の設定 ├── tsconfig.json TypeScript の設定 └── tsconfig.tsbuildinfo ビルドキャッシュ(自動生成)

分類は3つだけ

自分が書いたもの(資産。消えたら困る)、機械が自動生成したもの(消しても再生成される)、設定ファイル(自分が書くが、中身は道具への指示)。この3つです。

ドットで始まる名前の意味

.claude .next .env.local のように先頭がドットの名前は、Unix の慣習で隠しファイルを意味します。ls では表示されず、ls -a で初めて見えます。

技術的な仕掛けは何もありません。「普段は意識しなくていいもの」という印にすぎません。VS Code は設定に関わらず全部表示するので、エディタ上では見えています。

① 自動生成されるもの

名前中身git
node_modules/npm が取り寄せた部品の実物入れない
.next/Next.js のビルド結果とキャッシュ入れない
.vercel/Vercel との紐付け情報入れない
tsconfig.tsbuildinfoTypeScript の差分ビルド用キャッシュ入れない
package-lock.json実際に入った正確なバージョンの記録入れる
next-env.d.tsNext.js が用意する型定義の参照入れる

下2つが例外です。package-lock.json は「他の環境でも同じものが再現される」ための唯一の保証なので必ず記録します。next-env.d.ts は編集しても上書きされますが、記録する慣例です。

② 設定ファイル

名前どの道具の設定か
package.jsonnpm ─ 部品表とスクリプトの登録簿
next.config.mjsNext.js ─ 画像の許可ドメイン、リダイレクト等
tsconfig.jsonTypeScript ─ 厳格さの度合い、@/ などのパス別名
tailwind.config.tsTailwind CSS ─ 色、フォント、対象ファイルの範囲
postcss.config.mjsPostCSS ─ CSS の変換工程。Tailwind はここのプラグインとして動く
drizzle.config.tsDrizzle ORM ─ スキーマの場所、DB 接続、マイグレーション出力先
.gitignoreGit ─ 記録から除外するものの一覧

③ 自分が書いたもの

名前性格
src/ソース本体。この中に app/ があり、置き場所が URL になる
scripts/ data/ docs/自作の作業フォルダ。Next.js は関知しない
deliverables/ scratchpad/同上。成果物と作業場の分離
README.md人間向けの説明
CLAUDE.mdClaude Code への指示書
AGENTS.mdAI エージェント全般に向けた指示書。ツールをまたいで共通に読ませる想定の書き方
.claude/Claude Code のプロジェクト設定(権限、カスタムコマンド等)

なぜ設定ファイルが7つもあるのか

ここが第1部の原則に直接つながります。

ルート直下に設定が散らばっているのは、道具が独立して7つあるからです。Next.js、TypeScript、Tailwind、PostCSS、Drizzle。それぞれ別の作者が作った部品で、互いのことを知りません。だから設定もそれぞれ持ちます。

全部入りの一枚岩なら設定は1ファイルで済みます。ただし Tailwind を別の CSS ツールに差し替えることも、Drizzle を Prisma に替えることもできなくなります。

散らばっているのは混乱ではなく、原則2「一つのことをうまくやる」と原則3「組み合わせて使う」の代償です。差し替えられる自由の対価として、組み合わせを記述する手間を払っている。第1部で見た一枚岩と部品の対比が、そのままファイル一覧に現れています。

ルート直下に置く理由も単純で、各道具は起動時にカレントディレクトリから親方向へ設定を探しに上がるためです。プロジェクトの根に置くのが約束事になっています。

.env が2枚ある理由

これは第4章の CASE 4(Vercel で DATABASE_URL が undefined)に対する予防策そのものです。

ファイル役割git
.env.example何を設定する必要があるかの一覧。キー名だけで値は空入れる
.env.local実際の値。接続情報や API キー入れない

新しい環境で立ち上げるとき、example を見れば必要な項目が全部わかります。値そのものは漏れません。「秘密は共有しないが、秘密の一覧は共有する」という分離です。この2枚組を作っておくと、環境を移すときの事故が減ります。

.gitignore が引いている境界線

この1ファイルが、プロジェクトの中に見えない線を引いています。

プロジェクトフォルダ git に記録する src/ ── 自分のコード package.json ── 部品表 package-lock.json ── 版の記録 各種 config ── 道具の設定 README.md / CLAUDE.md 記録しない node_modules/ ── 再取得できる .next/ ── 再ビルドできる .vercel/ ── 環境ごとに違う .env.local ── 秘密情報 tsbuildinfo ── キャッシュ
判断基準は一つ。「壊れたときに作り直せるか」です。node_modules は npm install で作り直せます。src は作り直せません。

線の外側に置かれる理由は3つに整理できます。再生成できる(node_modules、.next)、秘密である(.env.local)、環境ごとに違う(.vercel)。この3つのどれかに当てはまるものは、記録しません。

困ったときの初期化

動作が怪しいときの定番手順です。①の自動生成物のうち3つを消すだけです。

$ rm -rf .next node_modules tsconfig.tsbuildinfo $ npm install $ npm run dev

消えたものはすべて自動生成物なので、失うものはありません。node_modules の再取得に数分かかるだけです。

第4章の CASE 3 で挙げた package-lock.json の削除は、ここには含めていません。あれは lock ファイル自体が壊れている疑いがあるときの最後の手段で、通常は残します。消すとバージョンが変わりうるので、再現性を捨てる操作だと理解しておくのが安全です。

$ claude

エージェント型 CLI の構造

Claude Code や Codex CLI は、シェルではありません。

これらはシェルの上で動くプログラムであり、同時にシェルを使う側でもあります。二重の立場を持っているのが特徴です。

従来 人間 シェル プログラム エージェント型 人間 エージェント シェル プログラム エージェントは、人間がシェルに向かっていた位置にそのまま入る
上下を見比べると、シェルが1つ右へずれています。空いた席にエージェントが座っています。

エージェントは、これまで人間が座っていた席に座っています。第1部で見た「シェルに翻訳を頼む」という立場そのものを代行している。

だから設計上の中心問題が権限になります。人間の席に座った以上、原理的には rm -rf も打てるからです。エージェント型 CLI の機能一覧が権限まわりに偏っているのは、この構造から必然的に出てきます。

4つのツールに共通する骨格

主要なエージェント型 CLI は、いずれもほぼ同じ仕組みを持つところへ収束しました。

仕組み何のためにあるか
指示書ファイル席に座る前に業務の文脈を渡す(CLAUDE.md / AGENTS.md
plan モード実行前に計画を人間に承認させる
サンドボックス触れる範囲を OS レベルで制限する
差分表示実行後に人間が検算できる形で出す
サブエージェント作業を分割して並列で走らせる
MCP外部システムへの接続口
ヘッドレスモードCI やスクリプトから呼べるようにする(-p 等)
フック特定の場面で処理を自動実行する

骨格が共通化した結果、各ツールの差はモデルの質・価格・エコシステムへ移りました。そこは週単位で動くのでこの資料には書きません。骨格を知っていれば、どのツールへ移っても同じ場所を探せば設定できます。

厳密には CLI ではない

これらは全画面を占有し、カーソルキーで項目を選び、状態を表示し続けます。第2部第0章の分類でいう TUI(Text User Interface)です。

純粋な CLI は「1行打って、結果が返って、終わる」形式です。エージェント型はセッションを維持し続けるので、その意味では GUI に近い性質を持っています。

miraise-crm の現物との対応

前章で見たルート直下のファイルが、そのままこの構造に対応しています。

ファイル構造上の役割
CLAUDE.mdClaude Code 向けの指示書
AGENTS.mdツール横断を想定した指示書
.claude/権限設定、カスタムコマンド

指示書を書くという行為の意味も、ここで定まります。席に座らせる前に、業務の文脈を渡しているということです。第2部第0章で挙げた「AI は事務所の業務も顧問先の事情も知らない」という制約に対する、唯一の実務的な対処がこれにあたります。

2026年6月の実例 ─ 依存の外側は制御できない

Google は2026年6月18日をもって、Gemini CLI の個人向け提供を終了し、Antigravity CLI に置き換えました。旧 Gemini CLI は Apache 2.0 の公開ソフトウェアで10万を超える GitHub スターを集めていましたが、後継は非公開です。

これは第2部第6章に書いた「依存を増やすということは、他人の責任範囲を増やすこと」の実例です。層の下側は自分で決められません。手元のコードは残っても、それを動かす道具は他社の判断で消えます。

裏返すと、指示書を CLAUDE.mdAGENTS.md の2枚で持っておくことは移行可能性を残す設計になっています。後者はツール横断を想定した書き方なので、乗り換えが必要になったときに効きます。.env.example.env.local を分けるのと同じ発想です。

この章の内容のうち、製品名と提供状況は2026年7月時点のものです。骨格の部分は当面変わらないと見ていますが、個別の製品情報は都度確認してください。

$ history

ゼロから公開までの全コマンド

各コマンドが、どの層に触っているかを対応させます。

$ npx create-next-app@latest my-app $ cd my-app $ npm run dev # ここで動作確認 $ git add -A $ git commit -m "初期構成" $ git remote add origin https://github.com/xxx/my-app.git $ git push -u origin main # Vercel が push を検知して自動でビルド・公開
コマンド触る層何が起きるか
npx create-next-appnpm雛形を取り寄せ、依存を install し、git init までやる
cd my-appシェル(ビルトイン)シェル自身の現在位置を変える。子プロセスは作られない
npm run dev全層第1章の8段階すべてを通る
git add -Aファイル変更を記録の候補として登録する
git commitファイルその時点の状態に名前を付けて保存する
git pushネットワーク手元の記録を GitHub へ送る
(自動)Vercelpush を検知し、ビルドして公開する
npx とは

npx は npm に付属するコマンドで、インストールせずに一度だけ実行するためのものです。

create-next-app は最初の1回しか使いません。それをパソコンに常駐させるのは無駄なので、npx が一時的に取り寄せて実行し、終わったら捨てます。

最後に ─ 3部を通して

第1部でシェルの仕組みと設計原則を見て、第2部で層の全体像を見て、第3部で実際のコマンドに落としました。

結局のところ、覚えておくべきことは多くありません。

問い答え
コマンドを打つとはシェルに翻訳を頼むこと。シェル自身はほとんど何もしていない
層が7つある意味下の層に依存し、上の層には複雑さを隠す。隠れているが無くなっていない
エラーが出たら下から上へ確認する。層を特定してから対処する
どの層で作るか誰が何回使うかで決める。いきなり上から作らない
AI との分担並べるのは AI、決めるのは人間

実装の速さは AI の側に移りました。だからこそ人間の側に残るのは、何を作るかを決める力と、出てきたものを疑う力です。そのどちらも、土台の構造を知っていることを前提にしています。