🗣️

プロジェクト固有のAI呼び出し言語 - C3L

に公開

サマリー

  • AI呼び出し言語 C3L Specification v0.3 を作成しました。
  • 英語の自然文のように、CLIなPrompt実行を可能にします。
  • 言語定義してプロンプトを呼び出すため、単純かつシンプルな構成です。

C3L - Climpt 3-word Language とは

基本原則: 3単語によるコマンド構成

開発現場のサイクルは、基本的に同じルーティンです。「新しい機能を実装しよう」「テスト失敗の原因はなんだ?調べよう」といった、類似のワークフローで動いています。

AI Agentic Codingしていると、類似のプロンプトを少し書き換えて、何度も打っていることに気づきます。

C3L(Climpt 3-word Language)は、そんな課題を解決するために設計した言語です。すべてのコマンドが一貫して以下の3つの要素で構成されます。

climpt-<ドメイン> <アクション> <ターゲット>

これを分解すると:

  1. ドメイン (climpt-code): 命令が対象とする領域を定義します。コード、データ、インフラなど、どの分野の作業なのかを明確にします。
  2. アクション (create): 実行したい操作を定義します。作成、ビルド、分析など、何をするのかを表現します。
  3. ターゲット (api): 操作が適用される対象を定義します。API、サービス、ファイルなど、何に対して作業するのかを指定します。

つまり、「コード開発でAPIを作成する」という命令は、こんなふうに表現されます:

climpt-code create api

実際の開発現場ではもう少し複雑な要求があります。

例えば「"安全な" APIを "サービスとして" 作成する」といったニュアンスを伝えたい場合はどうでしょうか?

ハイフンによる意味の拡張: より自然な表現を目指して

そこでハイフン(-)を用いた複合語というアプローチを取り入れました。

3単語という制約の中で表現力を確保するため、アクションとターゲットに修飾子を付与することで、コマンドの意味を拡張できるようにしました。(3単語の制約は、CLIコマンドであるClimptの仕様です。)

実際にコマンドがどのように進化していくのか、段階的に見てみましょう:

# パターンA: 基本形
# 解釈: 「コードエージェント、APIを作成せよ」
climpt-code create api

# パターンB: アクションの修飾
# 解釈: 「コードエージェント、"安全な"APIを作成せよ」
climpt-code create-secure api

# パターンC: ターゲットの修飾
# 解釈: 「コードエージェント、"APIサービス"を作成せよ」
climpt-code create api-service

# パターンD: 双方の修飾(v0.3の推奨形式)
# 解釈: 「コードエージェント、"安全なAPIサービス"を作成せよ」
climpt-code create-secure api-service

ハイフンを用いることで、コマンドはより詳細かつ自然言語に近い表現になっています。まるで英語で「create a secure API service」と言っているような感覚ですね。

設計ガイドライン: 表現力と可読性のバランス

表現力が高まる一方で、可読性を損なわないための設計ガイドラインを設けています。

推奨される利用法

  • 品質の修飾: build-robust (堅牢にビルド), create-secure (安全に作成)
  • 対象の特定: api-service (APIサービス), test-suite (テストスイート)

非推奨な利用法: 過度な複合化

# 非推奨: 複数の概念を詰め込みすぎている
climpt-code create-secure-fast-scalable api-gateway-service-v2

上記のような過度な複合化は、可読性を低下させます。複雑な属性情報は、オプション(--)を用いて明示的に指定することを推奨します。

# 推奨: 複雑な属性はオプションで分離
climpt-code create-secure api-gateway --uv-version=2 --uv-ctx=scalable

C3L まとめ

C3L v0.3は、CLIとしての厳格なシステム要件と、人間にとっての直感的な分かりやすさという2つの目標を両立させるための、具体的な解決策を提示します。

  • 構造の一貫性: 常に「ドメイン、アクション、ターゲット」の3要素で構成。
  • 表現力の拡張: ハイフンによる複合語が、制約の中で意味論を実現。
  • 意味の明確性: コマンド自体がその意図を明確に語る自己記述性を獲得。

この言語仕様が、今後の開発プロセスにおいて、より高い効率性と生産性をもたらす一助となることを期待しています。

C3Lの実装: プロンプトを呼び出す仕組み

さて、ここまでC3Lの「言語仕様」について説明してきましたが、実際のところ、一つひとつの実行はプロンプトです。

平たく言うと、C3Lは「プロンプトの呼び出し言語」です。CLIコマンドの形式で書くと、背後でプロンプトが呼び出され、その結果として具体的な指示が表示される仕組みになっています。一応、オプション指定やSTDINからの入力値も受け付けるため、ある程度の汎用性も確保されています。

例えば、実際の開発では次のような感じで実行します:

未完了の状況をもとに、
足りない機能をFILENAME=tmp/something_feature_name.mdで保存し、
その後  
`climpt-build robust api -f=FILENAME <<<"E2Eの認証を含めた一貫プロセスの完成を行うまで実施。"` 
を実行する。実行結果の指示に従うこと。 

(これはC3L v0.3定義前の用法ですが、使い方のイメージは掴めるかと思います。)

CLAUDE.mdへの組み込み方法

私のプロジェクトでは、climpt-*で命名を統一しているため、CLAUDE.mdには以下のように記載しています:

- `climpt-*`: bash実行する。実行結果の出力は指示プロンプトである。従うこと。(CLI Prompt=Climpt)
  - `climpt-speak climpt lang` は、`climpt-*` を話すための実行である。
    `climpt-speak climpt lang`の指示に従い`climpt-*`を生成したあと、その生成された指示に含まれる `climpt-*` を再帰的に実行すること。

ちなみに、climpt-*はDenoで実装しているので、.deno/bin/*を自由に命名できます。別にclimpt-*以外の名前でも構いません。

動的言語リスト: AIに「何ができるか」を教える

動的な会話のために、プロジェクトで「話せる言葉」をリスト化して管理しています。このリストは動的に生成され、climpt-speakに読み込ませることで「今どんなコマンドが実行できるのか」をAIに判断させる材料にしています。

記載内容は、各プロンプトのFront Matterから自動取得される仕組みにしています:

tools-list.md
**climpt-build robust api**:
APIを強固に構築する
ドメイン駆動設計と全域性(Totality)原則に基づいた、強固で堅牢なAPI構築を行う。
input_text_file: 強固に構築すべき機能要件
input_text: 強固な構築に向けた追加指示

**climpt-build robust repository**:
リポジトリ層の強固構築
ドメイン駆動設計と全域性(Totality)原則に基づいた、堅牢なリポジトリ層の実装を行う。
input_text_file: 強固に構築すべき機能要件
input_text: 強固な構築に向けた追加指示

現在は選択をClaude Codeに任せていますが、もっと効率的にできるはずです。Sub Agent + SerenaのようなMCP経由でできるかもしれませんね。

なぜAI呼び出し言語が必要だと感じたか

ここで、「そもそもなぜこんな仕組みが必要になったのか?」という疑問が湧くかもしれません。

実は、AI Agentic Codingを本格的に始めると、いくつかの課題にぶつかります。これらの課題は、単純なCLAUDE.mdファイルだけでは解決できない、より根深い問題でした。

1. 毎回長いプロンプトを打つのはダルい・・・

ソロ開発なので、メンバー間での共有という文脈はそれほど重要ではありません。しかし、プロジェクトは技術スタックが混在しています。

バックエンド: Go API、フロントエンド: React + Vite、古いシステム: Ruby on Rails、一部のツール: Python、CLIツール: Deno

どのプロジェクトでも、Gitのブランチやコミットには、ほぼ共通のルールが適用できます。しかし、構成や考え方が微妙に異なるため、全く同じ・・・というわけではありません。

例えば、Agentが開発したコードは散らばりがちなので、コミットをまとめるために以下のようなプロンプトを使っています。git commitの頻度で、climpt-commit semantic unitsを実行します:

climpt-commit semantic units
---
title: 意味的近さでコミットを分けて実施する
---

# 指示
Gitコミットを、ファイルの変更内容の近さ単位でグループ化し、
近い単位にまとめてコミットする。

まったく異なる内容を1つのコミットへ含めることを避けつつ、
複数回のコミット処理を連続して実行することが目的である。

意味的に近いとは、

 : 

(正直なところ、climpt-commit semantic unitsと書くより、climpt-git commit .で実行したいです。C3L v0.3では、climpt-git commitになります。)

プロジェクトごとの違いがあるため、コミットにも依存度判定があります。Migration/Docker有無で判断軸を分けるケースもあります。

コミット以外にも、プロジェクト差分はたくさんあります。この差分調整をサボると後述の散らかる問題を誘発するため、丁寧に定義します。結果、指示がダルい・・・

2. CLAUDE.mdだけでは限界がある・・・

プロジェクトが複雑になると、CLAUDE.mdだけでは制御しきれなくなります。

そもそも、Claude Code(Claude Sonnet 4)は全てのMarkdownファイルを読んでくれるわけではありません。Serenaなどを使っても、全てのファイルを読まない以上、文脈理解には限界があります。

本来なら、指示した瞬間に必要な内容が展開され、Claude Codeが完全に理解してくれることが理想ですよね。

言語とは、背景知識の圧縮である

Agentic処理において、言語とは背景知識の圧縮だと考えています。

言語を使うということは、その定義に対応する背景知識が必要です。これが文脈を形成するわけです。

だからこそ、ClimptはCLIからPromptを呼び出すツールでありながら、コマンド自体を言語化することを試みました。それがC3L (Climpt 3-word Language) Specificationです。

3. ドメイン固有の用法が理解されない・・・

ドメインごとに、同じ単語でも意味が変わってしまうんですよね。

「価格」や「履歴」といっても、ECサイトとサービス料金ページとランディングページと株価システムでは、まったく異なります。

そのために用語集を作るわけですが、抽象度の高い言葉ほど解釈に幅があるため、使い方にブレが生じます。また、用語集のような「離れた場所」を読ませることの難しさも募ります。

4. 同じ階層へ異なる指示をしたい・・・

同じsrc/配下や、同じinternal/配下でも、実施しているタスクに応じて意味合いが変わります。

コードを書いているときと、テストを実施しているときと、仕様書を作っているときでは、読み方も理解の仕方も変わるはずです。それらを全てCLAUDE.mdに置くと、異なる文脈を1つのファイルで解決しているように見えてしまいます。

理想的には:

  • 実装するときはCLAUDE_coding.md
  • 仕様書を作るときはCLAUDE_doc.md

を読んでほしいわけです。仕様書作成時に「ドメイン駆動設計で、TDDで...」は不要ですからね。

5. コードは、散らばるものである・・・

私の感覚では、エントロピー増大の法則はAIコーディングにも当てはまるようです。

外界からのエネルギー投入(AIによるコード量の増加)に対し、ある程度の質的変化(品質の低いコードの混入)が起こると、徐々に均質化していく(質の低い方へ引っ張られる)ようです。

そこで、私はいくつかの対策を講じています。まず境界を閉じるためにドメイン境界線を必ず引きます。
境界線の中でエントロピー増大(という比喩)を抑えるために、圧力をかけ続けます。ドメイン中心からの引力と言っても良いです(比喩です)。

対策は数式や方程式として表現されており、各所で利用されるため、開発したコードは必ずドメインの中心地に収束します。

これをやらないと、必ずコードが散らばるので、必要なシーンでは指示に含めたいのです。

一方、ドキュメント化や調査のときには不要(むしろ邪魔)なため、必ず読まれるCLAUDE.mdでは、不便です。

6. テストでウソをつかれる・・・

開発速度が上がるのと比例して、「テストが成功したと言いながら実施されていないなんて・・このやろう」と打ちたくなるのを、グッと堪えるシーンが増えます。
この問題は、前の2番と5番の複合問題なのですが、開発では大きな課題です。
時々、テスト自体の成果を検証することが必要ですので、その術を持っておく必要があります。

AI呼び出し言語による課題解決のアプローチ

上述の課題は、AI呼び出し言語によってほぼ解決できると考えています(コードの散らかり問題だけは、小さいスコープでも「抽象度の高いAIコーディングのハンドリング」に成功していることが前提ですが)。

なぜAI呼び出し言語で解決できるのか

開発時に行うことって、ほぼ決まっていますよね。

不具合があれば、原因を調査します。調査する場所も、ほぼ決まっています。まずログを見て、再現させて...という流れです。

原因が分かれば、対策も決まります。修正案を考え、仕様にも影響するなら影響範囲を調べて...と、これも定型的な流れです。

AI Agentic Codingへの要求は、まさに「これら手間のかかるステップを、効率よく、短い指示で行いたい」ということです。

ところが、狭く詳細に実施すれば成功することを、「Agentへ任せよう」と広くに端的に実施すると、荒れます。

そこで、この間を見つけていくことになります。
つまり、言語体系が完成すれば、指示の即時詳細化が叶うため、端的な指示でもAgentic Codingがスムーズに実現できるはずです(そう信じています)。

プロジェクト単位である必要性

ただし、その言語の適用範囲が課題です。

問題のスコープは可変で、スコープに応じて意味や手順が変わるため、プロジェクト単位の言語でなければなりません。言い方を変えると、プロジェクトに精通している必要があります。

プロジェクトは、必ずしもGitレポジトリ単位とは限りません。小さいレポジトリばかりなら良いのですが、現実はそうもいきません。大きなレポジトリの小さな範囲に特化させる必要があるかもしれません。

あるいは、小さなレポジトリ(サブ的なもの)は横断してもよいかもしれません。
いずれにしても「言葉と手順がセットで通用する範囲」に準じている必要があります。

現段階での留意事項

チーム開発では、まだ試していません。

考えとしては、プロジェクト内部で異なるAI呼び出し言語が必要になるケースは想像しにくいので、おそらくチーム固有の問題はないだろうと思っています。

そもそもAIが開発の主体になるなら、大きなチームである必要もありません。ソロ開発でいくつものプロジェクトを並行して進めることを想定すれば、言語体系を定義するには十分だろうと考えました。

この辺りは、どこかでフィードバックを得られると良いなと、うっすら思っている部分です。

まとめ

C3Lは、まだ発展途上の、初期段階です。しかし、AI Agentic Codingが普及していく中で、「プロジェクト固有の知識をどう言語化し、自動的な指示に繋げるか」という課題は、ますます重要になってくると感じています。
汎用的な部分では、多くの部分が共通ツールとして洗練されていくでしょう。そのうち、プロンプトも動的生成されるに違いありません。一方で、アプリケーションやサービスが独自の何かを有しているのなら、そのユニーク性を明確な指示体系にする要求は途絶えないだろうとも思っています。

個人的には、この取り組みを通じて開発効率が大幅に向上しており、手応えを感じています。C3Lを使うかはともかく、開発のための独自言語作りも意外とできそうだな、と感じていただけたら幸いです。

Discussion