跳到正文
Hacker News· ob4cl·· 6 天前AI 评分37

ConfigLens:一款用于排查 AI 编程工具为何忽略配置的 Rust CLI

ConfigLens: Figure out why your AI tool is ignore your settings

AI 导读

ConfigLens 是一款本地只读的 Rust CLI,可追踪 Claude Code 和 OpenCode 的配置键,展示实际生效的值及其来源文件、行号和原因,包括被覆盖的配置项。

正文 · AI 翻译

ConfigLens

网站与交互式演示 · 版本发布 · 文档

找出你的 AI 编程工具为何忽略你的配置。

ConfigLens 是一个小巧、本地、只读的 Rust CLI,它会针对 Claude Code 和 OpenCode,在受支持的配置来源中追踪某个受支持的配置键,并显示观察到的胜出者——包括每个贡献项所在的文件、行号和原因,也包括那些落败的贡献项。

它从不执行你的配置,从不运行客户端二进制文件,不打开任何套接字,也不读取任何凭据。除非适配器明确将其列入允许列表,否则值都会被脱敏处理。

预发布版,0.1.0-beta.3。 这是一个可用的原型,而非成品:两个适配器都经过固定样本验证,而非运行时一致性验证,无法读取的层会被报告为缺口,而不是靠猜测填补。状态准确说明了这意味着什么。

安装

每个版本都附带了预编译二进制文件。目前提供三个目标平台:

平台 发布归档
Windows (x86-64) configlens-<tag>-x86_64-pc-windows-msvc.zip
macOS (Apple Silicon) configlens-<tag>-aarch64-apple-darwin.tar.gz
Linux (x86-64, glibc) configlens-<tag>-x86_64-unknown-linux-gnu.tar.gz

每个版本还附带一个 SHA256SUMS 文件以及每个目标平台的 CycloneDX SBOM。这些二进制文件未签名,也没有安装程序或包管理器;请将下面的 <tag> 替换为你想要的版本(当前为 v0.1.0-beta.3)。

验证下载

Linux 和 macOS:

tag=v0.1.0-beta.3
target=x86_64-unknown-linux-gnu              # or aarch64-apple-darwin
base=https://github.com/ob4cl/configlens/releases/download/$tag
curl -LO $base/configlens-$tag-$target.tar.gz
curl -LO $base/SHA256SUMS
sha256sum -c --ignore-missing SHA256SUMS      # macOS: use shasum -a 256 -c
tar xzf configlens-$tag-$target.tar.gz
./configlens-$tag-$target/configlens --version

Windows (PowerShell):

$tag  = 'v0.1.0-beta.3'
$repo = 'ob4cl/configlens'
# With the GitHub CLI:
gh release download $tag --repo $repo --pattern '*windows-msvc.zip'
gh release download $tag --repo $repo --pattern 'SHA256SUMS'
# Without it: download both files from the release page in a browser.

$zip      = Get-ChildItem *windows-msvc.zip | Select-Object -First 1
$expected = (Get-Content .\SHA256SUMS | Select-String $zip.Name).Line.Split()[0]
$actual   = (Get-FileHash -Algorithm SHA256 $zip.FullName).Hash.ToLower()
if ($actual -ne $expected) { throw 'SHA256 mismatch - do not run this file' }
Expand-Archive $zip.FullName -DestinationPath unpacked
& .\unpacked\configlens-*\configlens.exe --version

预期得到 configlens 0.1.0-beta.3。在 macOS 上,归档文件未经公证,因此 Gatekeeper 会在首次运行时发出警告:右键点击 → 打开,或 xattr -d com.apple.quarantine <binary>。

从源码安装

任何装有 Rust 1.85 或更新版本的平台:

cargo install --locked --git https://github.com/ob4cl/configlens

或者从代码检出目录安装:cargo build --locked --release,这会将二进制文件留在 target/release/configlens。

尚不可用:macOS Intel、Linux arm64、crates.io、Homebrew、Scoop/winget。没有强制性的 curl-to-shell 安装程序,而且这里的一切在运行时都不会访问网络。

你的第一条命令

configlens explain /model --client claude --client-version 2.1.296

这会打印出 model 的观察到的胜出者,以及每个贡献项所在的文件、行号和原因。一个真实的终端示例展示了完整输出以及如何解读它。

这能回答的问题

你设置了一个模型、一项权限、一个 MCP 标志。工具却忽略了它。现在你有五个可能的文件、一个环境变量、一个会话标志和一项可能都牵涉其中的托管策略——而工具只是说“正在使用另一个”。ConfigLens 回答了随之而来的四个问题:

  • 哪个值胜出了? 在它能读取的所有内容中观察到的胜出者。
  • 每个值来自哪里? 每个贡献项所在的文件、行号和列号,按优先级顺序排列,包括那些被替换或跳过的定义。
  • 我应该编辑哪个文件? 胜出的来源会被指明,因此你可以编辑正确的那个。
  • 我能把这个粘贴到 issue 里吗? 报告会对受保护的值进行脱敏,--paths share 会减少可识别细节;configlens support-report --preview 正是为此构建共享模式报告。在分享之前,请查看输出和下方的隐私限制;脱敏报告并不保证匿名。

快速开始(从源码)

在软件包发布之前,请从此代码检出目录构建。无需安装任何客户端,运行时也不需要网络访问。

cargo build --locked --release
./target/release/configlens --help

如果你更想从代码检出目录将二进制文件安装到你的 PATH:

cargo install --locked --path .

运行隔离演示

demo/demo.sh 不读取任何真实配置。它会在临时目录下创建一个一次性的 home 和项目,只写入明显虚假的值,清空环境,并针对该沙盒运行 CLI。临时目录之外的任何内容都不会被写入,也不会使用网络或客户端子进程。

cargo build --locked --release
./demo/demo.sh

一个真实的终端示例

截取自上文中的隔离演示(仅使用合成值)。较长的覆盖行和末尾的两条 trust_unknown 诊断信息被省略——该工具会打印每一个缺口和每一条诊断信息。

$ configlens explain /model --client claude --client-version 2.1.296
/model = "local-model" (observed)
Observed winner: $PROJECT/.claude/settings.local.json:1:12  "local-model"  observed_winner
Losers:
  "project-model"  $PROJECT/.claude/settings.json:2:12  replaced_by_later_layer
Rule: claude.scalar.layer-override
Coverage: partial — cc.managed.hkcu — registry_not_read (expected_unobservable); … (3 more gaps)
Support: fixture_verified; confidence: evidence_class:fixture_verified
Conclusion: "local-model" wins among the observed applicable sources; effective value withheld.
Next inspection:
  - supply the managed settings file with --input-context to include it
  - remote/MDM layers are not observable here; re-run where the managed source is readable

这样理解:项目文件集 model 到 "project-model",后面的某一层将其替换为 "local-model",而 "local-model" 是 ConfigLens 观察到胜出的值。它有意不将其称为运行时值,因为某个它无法读取的更高层仍可能改变它——参见 有界语义。

命令

configlens <command> [options]
命令 示例 作用
clients configlens clients 列出已实现的适配器及其测试过的版本、始终不完整的层,以及明确不支持的客户端。
scan configlens scan --client claude 清点候选来源及其适用性和可读性,外加覆盖缺口。不进行递归爬取。
explain configlens explain /model --client claude --client-version 2.1.296 解释一个 RFC 6901 JSON Pointer:有序追踪、观察到的胜出者(或未解析的结果)以及覆盖缺口。
doctor configlens doctor --client opencode --format json --strict 解析 / schema / 适用性 / 覆盖诊断。绝不将配置认证为安全。
snapshot configlens snapshot --client claude --output before.json 将脱敏后的报告 JSON 写入显式路径。默认创建新文件;使用 --overwrite 进行替换。
diff configlens diff before.json after.json 比较来自同一客户端和 schema 的两份报告;受保护的值按 unknown_redacted 比较。
schema configlens schema --kind report 打印内置的报告 JSON Schema。无网络。
support-report configlens support-report --preview 构建用于粘贴到 issue 中的分享模式报告。始终为分享模式(无论 --paths 如何)。--preview 将其打印到 stdout 且不写入任何内容;--output <PATH> 将其写入(在 Unix 上为 0600)。没有上传。
completions configlens completions --shell bash 为 bash、zsh 或 fish 打印 shell 补全脚本,由实时命令树生成。不向磁盘写入任何内容。

运行 configlens --help(以及 configlens <command> --help)以获取当前权威列表——上表涵盖核心命令。

选项

解析需要 --client <opencode|claude>。共享选项:--cwd <PATH>(默认 .)、--client-version <VERSION>(一个声称的版本——ConfigLens 从不读取客户端二进制文件)、--format text|json、--strict、--no-env、--input-context <PATH>、--color auto|always|never、--paths local|share、--allow-read-root <PATH>(可重复)、--project-root <PATH>。此外,一个全局 --quiet(在每个子命令上以 configlens <cmd> --quiet 形式接受)仅抑制信息性 stderr 提示——即快照 wrote N bytes 行和支持报告的写入/--preview 提示。错误始终打印到 stderr,stdout 保持机器可读(JSON),退出码不变。snapshot 添加 --output/--overwrite;doctor 添加 --fail-on warning|error;support-report 接受 --preview 或 --output <PATH>;两者都不提供属于用法错误(退出码 2),如果两者都给出,则 --preview 胜出且不写入任何内容;completions 接受 --shell bash|zsh|fish。

退出码

代码 含义
0 已生成报告。允许存在非致命发现。
1 doctor 发现达到或高于 --fail-on(默认 error)。
2 用法错误或输入/报告不兼容。
3 请求的键/客户端语义不受支持,或 --strict 发现上下文不完整。
4 所需文件无法访问、格式错误或超出资源限制。

当多个条件适用时,优先级为 2 → 4 → 3 → 1 → 0。

“胜出”究竟意味着什么

每个报告中有三个术语承载着关键含义:

  • 观察到的胜出者——在 ConfigLens 能够读取的来源中优先级最高的定义。
  • fixture_verified——该规则已针对本项目的 fixtures 和上游文档进行了核对,而非针对正在运行的客户端。
  • 覆盖缺口——某个来源存在但无法读取,因此有效值被保留不给出。

ConfigLens 是一个针对其能够读取的输入的静态分析器。它不检查正在运行的会话,也从不假设不可读的层不存在。这有三个可见的后果:

  • 已观察,但未生效。当存在更高优先级的层但不可观察时(服务器管理的策略、MDM/注册表设置、OpenCode 远程默认值)——或者项目信任状态未知——结果会被标记为 partial,胜出者被标记为已观察胜出者,而有效值则与覆盖缺口列表一起被暂不披露。
  • 清点,而非猜测。未知键会作为不透明清单保留,绝不会被赋予凭空发明的合并规则。未知或未经测试的客户端版本会以临时方式报告;--strict 随后以 3 退出。
  • 来源,而非授权。对于 Claude 权限列表,ConfigLens 会展示列表条目如何组合,并明确提示这不是一项授权决定。

因此退出码 0 意味着“已生成报告”,而不是“这就是你的工具将使用的值”。

兼容性

目前提供两个有边界的适配器。两者最多都只是 fixture_verified——依据项目自身的测试夹具和当前上游文档进行验证,而非依据上游加载器,因此没有任何规则声称 upstream_conformance_verified。支持状态以 inventory_only < documented < fixture_verified < upstream_conformance_verified 运行。

客户端 适配器修订版 已测试/已记录版本 最大支持 始终不完整的层
OpenCode 0.1.0 已测试 1.18.35 / 已记录 1.19.0 fixture_verified 远程默认值、.opencode 目录、macOS 托管偏好设置
Claude Code 0.1.0 2.1.296 fixture_verified MDM 策略存储、服务器管理的设置、HKCU 注册表、托管文件缺失

逐键详情、证据 URL、检索日期和规则→测试 ID 位于适配器的注册表中: compatibility/opencode/registry.md 和 compatibility/claude/registry.md。

OpenCode 的 @opencode/cli 2.x 系列是一个单独的测试版,具有不同的已记录合并模型(目录遍历至文件系统根目录;每个 .opencode 配置覆盖每个直接配置)。它尚未实现;声称的版本若不在受支持集合内,会以 unsupported 报告,而不是凭猜测解析。请参阅适配器注册表。

这些客户端尚未实现,并被标记为 unsupported——不会仅凭共享文件名做出兼容性声明:Codex 和 Gemini(0.2 待办)、Aider(待办),以及 Cursor、Copilot CLI、Cline、Roo 和 Hermes(未调查)。运行 configlens clients 以获取当前矩阵。

隐私与注意事项

  • 离线且只读。无网络、无子进程、不执行客户端二进制文件;一项测试会扫描 src/ 以保持这一状态。$schema 引用永远不会被获取。
  • 除非列入允许列表,否则一律脱敏。只有脱敏投影会生成可报告的值;机密会显示为 {"redacted": true, "reason": "..."}。
  • 两种路径模式。--paths local(默认)显示配置位置和键名,以便你进行诊断;--paths share 会对路径进行假名化,将未知键名替换为不透明 ID,并剥离 URL 用户信息、查询和片段。
  • 快照。以创建新文件的方式原子写入,在 Unix 上使用 0600 仅所有者权限。在 Windows 上没有 0600 等价物:快照会作为同目录临时文件写入,然后重命名,因此它继承目标文件夹的 ACL——ConfigLens 无法收紧它。报告会说明这一点(redaction.snapshot_acl = "not_implemented"),而不是声称一种并不存在的保护。
  • 已知的 0.1 差距 / Windows 指南。 Windows 快照 ACL 限制未实现。 限制性 DACL 需要通过 unsafe FFI 或新依赖来调用 Win32 安全 API,而这两者都被本 crate 的 unsafe_code = "forbid" 及其最小依赖策略排除,因此不在 0.1 的范围内。请将快照保存在私有的、用户控制的目录中(例如 %USERPROFILE%,而不是共享或全局可读的文件夹),这样继承的 ACL 才是你想要的。
  • 报告仍会描述你的项目结构。切勿将原始凭据文件粘贴到 issue 中。

状态

0.1.0-beta.3,预发布版。诚实的总结:

  • 随附两个适配器——Claude Code 和 OpenCode——两者最多为 fixture_verified。没有任何规则 声称与上游一致,因为测试中未执行任何上游加载器。
  • 某些层始终被报告为覆盖缺口,而不是猜测;它们按客户端列在 Compatibility 中。
  • Windows 快照 ACL 限制未实现,报告如实说明,而不是暗示存在 实际并不存在的保护。
  • 引擎在键数量上是二次方的;真实配置只有几十个键,此时耗时 为亚毫秒级。实测的扩展性见 docs/implementation-status.md。
  • 已实现、已验证和未验证的内容逐项记录在 docs/implementation-status.md 中,实际运行的命令见 docs/verification-log.md。

要求

Rust,2021 版。rust-version = "1.85" 在 Cargo.toml 中声明并已验证: cargo +1.85.0 check --locked --all-targets --all-features 退出 0(docs/verification-log.md 的 §8.1),CI 的 msrv 任务运行相同的检查。 本地开发使用 1.99.0。确切命令和结果见验证日志。

贡献

适合初次贡献的内容包括合成夹具、更清晰的诊断信息和特定版本的规则 证据。每次适配器变更都需要一手来源、声明的兼容范围和 正/负测试——绝不能使用真实密钥或专有指令。开发 检查包括:

cargo fmt --all -- --check
cargo clippy --locked --all-targets --all-features -- -D warnings
cargo test --locked --no-fail-fast
python -m unittest discover -s scripts -p "test_*.py"

在打开拉取请求之前,请在本地运行这些检查。回归工作流见 CONTRIBUTING.md,维护者侧流程见 docs/maintaining.md。安全问题的报告方式见 SECURITY.md。

文档

许可证

以下任一许可证下授权

由你选择。

除非你明确声明 otherwise,否则你有意提交以纳入本项目的任何贡献, 如 Apache-2.0 许可证所定义,应按上述方式双重授权,且不附加 任何额外条款或条件。

来源:Hacker News · github.com