なんちゃってAI駆動開発で作ってるシェルをIT系メディアの記事風にAIに書かせてみた
Rustで開発されている新しいシェル「psh」が、設計志向の強いアプローチで注目を集めている。従来のBash互換を前提としたシェルとは異なり、pshは「構造の明快さ」と「拡張性」を重視したアーキテクチャを採用しているのが特徴だ。
従来のシェルが抱える構造的課題
bashやzshといった既存シェルは長い歴史の中で多くの機能を取り込んできた一方で、内部構造の複雑化という課題を抱えている。
具体的には、以下のような問題が指摘されてきた。
- parserと実行系(evaluator)が密結合している
- 歴史的互換性により仕様が一貫しにくい
- UIと実行ロジックが混在しやすい
- 機能追加時に設計の整合性が崩れやすい
pshは、こうした課題を前提に「最初から分離された構造で設計する」ことを出発点としている。
parser / evaluator / UI を分離した設計
pshの最大の特徴は、コマンド実行に関わる各レイヤを明確に分離している点にある。
全体は大きく以下の構成で整理されている。
- CLI / main:実行モードの分岐(REPL / script / -c)
- REPL:対話入力と表示
- script / config:ファイル実行とポリシー管理
- shell:コマンド実行の中核
- expand:変数や引数の展開
- resolve:alias解決
- exec:外部コマンド実行
このように、UI・実行・補助機構が層として分離されており、責務が交差しない構造になっている。
特に「script実行のポリシーはscript層に閉じる」といった設計は、従来のシェルにはあまり見られない明確な分離だ。
状態管理は最小限に限定
pshでは、ShellStateの役割も意図的に限定されている。
保持するのは以下のようなグローバル状態のみだ。
- カレントディレクトリ
- 環境変数・ユーザ変数
- alias
- function定義
- 履歴
一方で、以下のような情報はあえて持たせていない。
- UIの状態
- script実行コンテキスト
- function引数
- completion状態
function引数などの一時的な情報は、CallFrameとして実行時コンテキスト側で管理される。この設計により、状態の責務が混在することを防いでいる。
function引数やstrict modeも“置き場所”を意識して実装
pshでは最近、function引数($1, $2, $10など)やscript実行時のstrict modeが追加されている。
例えばfunction引数は、ShellStateではなくCallFrameスタックとして管理され、現在のフレームのみを参照する形で展開される。
またstrict modeは以下のように利用できる。
$ psh --strict script.psh
このモードでは、スクリプト実行中にエラーが発生した時点で処理を停止する。
重要なのは、これらの機能がいずれも「既存構造に無理やりねじ込まれていない」点だ。
function引数はevaluator側、strict modeはscript runner側と、責務に応じた層に実装されている。
行単位のエラー診断も導入
さらにpshでは、scriptや設定ファイル実行時の可観測性向上として、行単位のエラー診断機能も追加されている。
エラー発生時には、以下のような形式で出力される。
script `build.psh` line 12 failed
この診断情報も、ShellStateやparserではなく、file runner層が管理している。
将来的な構造化エラーハンドリングへの拡張も見据えた設計となっている。
機能よりも「構造の持続性」を重視
pshの特徴は、機能そのものよりも「構造を壊さないこと」を優先している点にある。
一般的なシェル開発では、新機能の追加とともに条件分岐や特例処理が増え、設計が徐々に複雑化していくことが多い。
pshではこれを避けるため、以下の原則が一貫して守られている。
- parserに実行意味を持ち込まない
- ShellStateに一時情報を入れない
- 実行ポリシーはrunner層に閉じる
- UIと実行ロジックを分離する
今後の展開
現時点でpshは、基本的なコマンド実行、関数、変数展開、スクリプト実行などの基盤機能を備えている。
今後は以下のような機能拡張が予定されている。
-
&&/||の実装 - scriptの制御構文
- completionの高度化
- plugin / extensionの導入
構造を維持したまま機能を拡張できるかどうかが、今後のポイントになりそうだ。
まとめ
pshは、既存シェルの課題を踏まえ、「最初から整理された構造で作る」という思想のもと設計されたシェルである。
Bash互換をあえて外し、責務分離と拡張性を優先したアプローチは、今後のシェル設計の一つの方向性を示すものと言えるだろう。
今後の機能拡張とともに、この構造がどこまで維持されるのか注目される。