Skip to main content
Glama
bdelanghe

flake-verbs

by bdelanghe

flake-verbs

型付きの verbspec スペックとして一度だけ書き、CLI、MCP、Anthropic tool-use、OpenAPI へ投影する、flake 構造の動詞群。

このツールが答える質問は2つです。どちらも、従来は flake を手で読む必要がありました。

動詞

質問

inputs

自分の入力のうち、実際にどこかが使っているのはどれか?

input-drift

各ロック済み入力は上流からどれだけ乖離しているか?それともそもそも取得できるのか?

実行

bun install
bun run src/cli.ts inputs ~/.config/home-manager
bun run src/cli.ts input-drift ~/.config/home-manager --problemsOnly
bun run src/cli.ts --mcp-tools          # the agent-facing surface, derived

どちらの動詞も flake ルートを位置引数(デフォルト .)として受け取り、JSON を出力します。CLI はテキストビューを表示し、それ以外のすべてのインターフェースは output を消費します。

Related MCP server: mcp-supply-guard

inputs — 使用とただの言及

素朴な実装は grep <input-name> *.nix で、その場合すべての入力が「使われている」と報告されます。しかし、入力に依存せず入力に言及するものが3つあります:

  • すべての入力に名前を付ける outputs = { a, b, … }: パラメータリスト

  • コメント

  • パスリテラルと文字列リテラル — ./programs/lnzr.nix、"lnzr/.keep"

文字列の補間(interpolation) は例外で、フィルタを通過しなければなりません。"${dx-compose}/path/to/module" は本物の参照だからです。この非対称性があるため、これは grep では代用できません。

スキャンは _module.args のエイリアスも追跡します。synoptic = config._module.args.synoptic-github を束縛する flake は、入力をまったく別の語で使っています。それを見逃すと、実際に使われている入力を刈り落としてしまいます。

3つの判定

referenced と unused は、文字どおりの意味です。面白いのは module-import-only で、これが意図的に unused と呼ばれていません。Home Manager モジュールのインポートは、完全に機能を担っている場合(モジュール自身が config を設定する)もあれば、完全に何もしない場合(すべてのオプションが既定で false で、有効にするものがない)もあります。

--deep(デフォルトでオン)にすると、判別できる場合はそのケースを確定させます。nix flake archive で入力をストアパスに解決し、インポートされているモジュールを読み取り、そこで宣言されているオプション名前空間を復元し、消費側の flake 内でその名前空間が設定されているかを確認します。これで「首をひねるだけ」が「確定した事実」になります。

DEAD dx-compose          github:bdelanghe/dx-compose
     imports a module declaring programs.devcontainers-cli, which nothing in this flake sets

名前空間を解決できない場合、推測せず module-import-only のままにします。誤った unused は高くつくミスです。動いている入力を削除してしまうからです。そのため、どの段階でも確信がなければ「人間が確認すべき」という判定に倒れます。

input-drift — 元が取れる動詞

behind は普通の状態であり、失敗ではありません。重要なステータスは2つです。

  • unportable — path: 入力です。Nix は評価時に path 入力をディスクから読み直すため、作者のマシンにしか存在しないディレクトリを指すロックは、flake をどこか他のマシンでも評価不能にします。これは、2台目のマシンでビルドしようとするまでまったく見えない、ブートストラップの行き止まりです。

  • orphaned — ロックされたリビジョンに、リモートのデフォルトブランチには存在しないコミットが含まれているか、リモートがそのリビジョンをまったく知らない状態です。そのコミットはローカルのチェックアウトにしか存在せず、マシンの再ビルドで静かに捨てられてしまう、プッシュされていない作業です。

この2つは非ゼロで終了するため、CI のゲートになります。behind はゲートになりません。

上流への問い合わせは gh api 経由で行われるため、プライベート入力も、このツールがトークンを扱うことなく解決できます。

この動詞が存在する理由

実際に失われたので、その後で書かれました。ある home-manager flake は、~/.local の下を指す4つの path: 入力を持っていました。新しいマシンでは、その flake はまったく評価できませんでした。それらの入力を GitHub のリポジトリに差し替えたところ、そのうちの1つ lnzr が、リモートの main より3か月先進んだローカルチェックアウトを持っていました——それは他どこにも存在しない作業であり、古いディスクとともに消えました。

ロックは当初からその2つの事実を記録していました。しかし、それに問い合わせる手段はありませんでした。

知っておくべき制約

  • 参照スキャンはテキスト処理であり、評価ではありません。.nix ソースを読み取りますが、flake を評価しないため、動的または生成後に構成される属性パス経由でのみ到達できる入力は、まだ見落とされることがあります。

  • --deep は cfg = config.<ns> と options.<ns> のイディオムを認識します。それ以外の書き方をされたモジュールは、module-import-only へフォールバックします。

  • input-drift は github: 入力だけを上流と照合します。git: と tarball: の入力には、間違った回答の代わりに unknown を報告します。

  • 検査されるのは直接の入力のみです。推移的な入力は誰か他の人が選んだものであり、各自のリポジトリで監査すべきものです。

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables MCP-compatible clients to inspect Next.js codebases, analyze App Router and Pages Router structure, discover API routes, and audit build performance through controlled tools.
    8 npm
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables supply-chain integrity for MCP tools by locking tool-definition hashes after review and detecting added, removed, modified, or risky tool definitions.
    MIT