flake-verbs

flake-verbs

Enables analyzing Nix flakes to identify which inputs are actually used and to detect locked-input drift, including unportable or orphaned inputs, through MCP tools.

Category
访问服务器

README

flake-verbs

Flake-structure verbs, authored once as typed verbspec specs and projected to CLI, MCP, Anthropic tool-use and OpenAPI.

Two questions this answers, both of which used to require reading a flake by hand:

verb question
inputs Which of my inputs does anything actually use?
input-drift How far has each locked input drifted from its upstream — and can it still be fetched at all?

Run

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

Both verbs take the flake root as a positional (default .) and emit JSON; the CLI renders a text view, every other surface consumes output.

inputs — use vs. mention

The naive version of this is grep <input-name> *.nix, and it reports that every input is used. Three things mention an input without depending on it:

  • the outputs = { a, b, … }: parameter list, which names every input
  • comments
  • path and string literals — ./programs/lnzr.nix, "lnzr/.keep"

String interpolations are the exception and must survive the filter, because "${dx-compose}/path/to/module" is a genuine reference. That asymmetry is why this can't be a grep.

The scan also follows _module.args aliases. A flake that binds synoptic = config._module.args.synoptic-github uses the input under a different word entirely, and missing that is how a live input gets pruned.

The three verdicts

referenced and unused mean what they say. module-import-only is the interesting one, and it is deliberately not called "unused": importing a Home Manager module can be entirely load-bearing (the module sets config itself) or a complete no-op (every option defaults false and nothing enables them).

With --deep (default on) the verb settles the case where it can: it resolves the input to its store path via nix flake archive, reads the imported module, recovers the option namespace it declares, and checks whether anything in the consuming flake sets it. That turns a shrug into a fact:

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

Where it can't resolve a namespace it stays module-import-only rather than guessing. A false unused is the expensive mistake — it deletes a working input — so every step degrades toward "a human should look".

input-drift — the one that pays for itself

behind is ordinary and not a failure. Two statuses are:

  • unportable — a path: input. Nix re-reads path inputs from disk at evaluation time, so a lock pointing at a directory that exists only on the authoring machine makes the flake unevaluable anywhere else. This is a bootstrap dead-end that stays completely invisible until you try to build on a second machine.
  • orphaned — the locked revision carries commits that are not on the remote's default branch, or the remote has never heard of it. The commit exists only in a local checkout: unpushed work that a machine rebuild discards silently.

Both exit non-zero, so this gates CI. behind does not.

Upstream queries go through gh api, so private inputs resolve without this tool ever handling a token.

Why it exists

Written after a real loss. A home-manager flake carried four path: inputs pointing under ~/.local; on a fresh machine the flake could not evaluate at all. Repointing them at GitHub revealed that one, lnzr, had a local checkout three months ahead of its remote main — work that existed nowhere else and went with the old disk.

The lock had recorded both facts the whole time. Nothing could ask it.

Limits worth knowing

  • The reference scan is textual, not an evaluation. It reads .nix sources; it does not evaluate the flake, so an input reached only through generated or dynamically-constructed attribute paths can still be missed.
  • --deep recognises the cfg = config.<ns> and options.<ns> idioms. A module written some other way falls back to module-import-only.
  • input-drift only checks github: inputs against their upstream. git: and tarball: inputs report unknown rather than a wrong answer.
  • Only direct inputs are examined. A transitive input is someone else's choice, to audit in their own repo.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选