silvio-l/loam
GitHub: silvio-l/loam
一款专为 Dart/Flutter 打造的语义级代码分析工具,通过基线/棘轮门禁机制检测死代码、循环依赖与 AI 生成的垃圾代码。
Stars: 0 | Forks: 0
专为 Dart 和 Flutter 打造的代码库智能分析与 AI 垃圾代码检测工具。
捕获 dart analyze 无法察觉的结构漂移和AI 生成的垃圾代码——依托于基线/棘轮(ratchet)CI 门禁,绝不会在第一天就让成熟的代码库亮起红灯。
getloam.dev
·
github.com/silvio-l/loam
## 为什么选择 loam.dev?
AI 编码 agent 生成 Dart/Flutter 代码的速度超出了人类的审查能力。有两类破坏会直接绕过内置的 `dart analyze`:
1. **结构漂移** —— 死代码、重复代码、循环依赖、复杂度热点以及被破坏的架构边界。
2. **AI 垃圾代码** —— 空的 `catch` 块、无意义的填充注释、毫无根据的 `// ignore:`、重复的辅助函数、无效的守卫子句以及幻觉产生的抽象。
JS/TS 在这方面拥有成熟的工具。**而 Dart/Flutter 一直缺乏免费且具备垃圾代码检测意识的工具** —— 最接近的是 DCM,但其最佳规则受限于商业许可,且不支持基于 LLM 的垃圾代码检测。loam.dev 正是为了填补这一空白。
## 检测内容
**现已提供 (0.1.10) —— 四项生效规则:** 项目范围内的**未使用的公共 API**(死导出、类、方法、getter/setter 和字段),第一方库之间的**循环依赖**,**代码重复**(基于 AST 归一化的 token 哈希 —— 检测完全一致及结构相同的副本;每个集群输出一个包含所有位置的发现),以及**复杂度热点**(圈复杂度/认知复杂度,聚合成 `loam health` 分数;默认扫描 `lib/` 和 `bin/` —— 可通过 `loam.yaml` 中的 `source_dirs` 进行配置)。所有检测均基于已解析的 Dart 元素模型 —— 而非正则表达式 —— 并受基线/棘轮门禁控制。
其余部分均为**目标范畴**:每一项都将作为插件接入,统一受限于单一且稳定的 `Rule` 接口,因此添加新功能绝不会改变流水线 (🚧 = 计划中)。
| 结构漂移(确定性,语义级) | AI 垃圾代码(确定性 **+** 可选 LLM) |
|---|---|
| ✅ 未使用的公共导出、文件、成员 | 🚧 空的 / 吞没异常的 `catch` 块 |
| ✅ 循环依赖 | 🚧 无意义的填充注释 |
| ✅ 代码重复(基于 AST 归一化) | 🚧 毫无根据的 `// ignore:` |
| ✅ 复杂度热点 + 健康分数 | 🚧 重复的辅助函数、无效的守卫子句 |
| 🚧 架构边界违规 | 🚧 幻觉 / 多余的抽象 |
## 独有特性
- **🌱 语义级,而非正则表达式。** 结构规则使用已解析的 Dart 元素模型和项目级图表 —— 真正的全程序解析,而非启发式算法。*(已生效)*
- **🔒 基线 / 棘轮门禁(默认)。** 冻结当前已接受的发现;此后只有**新增**的异常才会导致 CI 失败。实现单调改进,杜绝首日即红灯。*(已生效)*
- **📦 原生 Dart 支持。** 通过 `dart pub global activate loam` 安装。遵循 SemVer;`ruleset@ver` 是基线身份的一部分(在 LLM 层中还会加入 `prompt@ver`)。*(已生效)*
- **♻️ 可复现,即使使用 LLM。** LLM 提出 `{score, label}` → 通过 `sha(code)+prompt@ver` 缓存 → 由固定阈值判定。相同的代码 = 缓存命中 = 稳定的结论 = 零 token 成本。告别不稳定的门禁。*(🚧 计划中)*
- **📄 独立 HTML 报告。** 单个离线 `.html` 产物:按规则、严重程度或文件浏览检测结果 —— 无需服务器,无需托管。`loam scan --format html` 会生成 `loam-report.html` 并在浏览器中打开;使用 `--output
` 指定路径,使用 `--no-open` 跳过浏览器(在管道输出或 CI 环境下会自动禁止打开)。*(自 0.1.3 起生效;在 0.1.6 中重新设计)*
## 快速开始
### 安装
**Homebrew (Apple Silicon macOS 与 Linux —— 推荐)。** 无需设置 `PATH`,直接安装到系统已在 `PATH` 中包含的目录:
```
brew install silvio-l/loam/loam
```
使用 `brew upgrade loam` 进行更新。(Intel Mac:请使用下方的 Dart pub 路径。)
**Dart pub (全平台)。** pub.dev 包:
```
dart pub global activate loam
```
这会将其安装到 `$HOME/.pub-cache/bin`,该目录默认**不在**你的 `PATH` 中 —— 如果不在,Dart 会打印提醒。它显示的 `export` 行仅对当前 shell 有效;请将其添加到你的 shell 配置文件中以**永久**生效:
将 ~/.pub-cache/bin 永久加入你的 PATH
```
# zsh (macOS 默认)
echo 'export PATH="$PATH:$HOME/.pub-cache/bin"' >> ~/.zshrc && source ~/.zshrc
# bash
echo 'export PATH="$PATH:$HOME/.pub-cache/bin"' >> ~/.bashrc && source ~/.bashrc
```
**如需更新**,请重新运行 `dart pub global activate loam`。
改为安装未发布的 dev 分支
```
dart pub global activate --source git https://github.com/silvio-l/loam.git \
--git-path packages/loam_cli --git-ref dev
```
### 使用
现已提供(四项生效规则 —— 未使用的导出、循环依赖、代码重复、复杂度热点):
```
loam scan # full audit: all active rules, whole repo
loam scan /path/to/project # same, positional path to project root
loam baseline --write # freeze the remaining, accepted state
loam gate # CI from now on — ratchet: only new findings fail
loam gate /path/to/project # same, positional path to project root
```
初始化配置:
```
loam init # scaffold loam.yaml config in the project
loam init /path/to/project # same, positional path to project root
```
复杂度健康分数:
```
loam health # cyclomatic/cognitive complexity distribution view
loam health /path/to/project # same, positional path to project root
```
所有五个命令(`scan`、`gate`、`health`、`init`、`baseline`)均接受一个可选的位置参数 `[path]` 作为项目根目录。如果同时提供,显式的 `-p`/`--project-root` 选项将覆盖位置路径。
即将推出(已接入 `loam --help`,尚未实现):
```
loam slop # AI-slop audit: slop-focused rules only
loam fix --safe # apply mechanical fixes
```
**接入现有代码库**(让成熟的代码库变绿,并保持下去):`scan` → 清理 → `baseline --write` → 在 CI 中运行 `gate`。后续的清理只需重复此过程。全新项目?`loam gate --absolute` 无需基线。
**更新通知。** loam.dev 每天最多检查一次 pub.dev,当存在较新版本时,会在命令输出*之后*向 stderr 打印一行信息 —— 绝不输出到 stdout,也绝不更改退出码。该信息会根据 loam 的安装方式标明相应的升级命令(如果是 Homebrew 二进制文件则为 `brew upgrade loam`,否则为 `dart pub global activate loam`),确保更新应用到您实际运行的二进制文件上。要确认更新是否成功,请运行 `loam --version`:它会打印当前运行版本、安装渠道以及解析出的可执行文件路径。可以通过 `--no-update-check` 针对单次运行静默此通知,通过 `LOAM_NO_UPDATE_CHECK` 环境变量在全局静默,或者通过 `loam.yaml` 中的 `update_check: false` 在代码库级别静默。CI 环境始终保持静默。
## 专为终端打造
为 CI 和 agent 提供机器可读的输出,为您提供人类可读的报告:
```
--format human # default, readable terminal output (available)
--format sarif # CI / code-scanning (available)
--format json # agent / tooling integration (available)
--format markdown # PR / docs embedding (available)
--format html # interactive, self-contained report (available)
# human/sarif/json/markdown 流输出到 stdout;html 写入文件并打开它。
--output # write the report to (html: overrides loam-report.html)
--no-open # html only: don't open the browser (auto-off when piped/CI)
```
## 状态与路线图
**0.1.10** —— 四项规则已端到端生效(`unused-public-exports`、`circular-dependencies`、`code-duplicates`、`complexity-hotspots`)以及 `loam health` 视图;其余功能将作为独立的规则接入同一 `Rule` 接口。
有关概念、CLI 命令、输出格式和代码生成处理的详细说明,请参阅 **[开发者与工具指南](./docs/developer-guide.md)**。
## 仓库结构
这是一个 monorepo —— 包含了构成 loam.dev 的所有内容:
| 路径 | 说明 |
|---|---|
| [`packages/loam_cli/`](./packages/loam_cli/) | Dart CLI(pub.dev 包 `loam`)。实际的工具。 |
| [`web/`](./web/) | 推广 / 文档网站(静态、多页、EN/DE、免费层)。详见其 [README](./web/README.md)。 |
| [`skill/`](./skill/) | 为 agent 驱动 `loam` 的 Claude 技能/插件。脚手架。 |
| [`assets/brand/`](./assets/brand/) | Logo、颜色、终端横幅。详见其 [README](./assets/brand/README.md)。 |
| [`docs/`](./docs/) | 开发者与工具指南。 |
### 网站路由 (`web/`)
该网站是多语言的(根目录默认为 EN,DE 位于 `/de/` 下),共 10 个页面:
| EN 路由 | DE 路由 | 内容 |
|---|---|---|
| `/` | `/de/` | 首页 —— Hero、安装、GitHub Stars CTA |
| `/how-it-works` | `/de/how-it-works` | 流水线演示 |
| `/rules` | `/de/rules` | 规则目录(已生效 + 计划中) |
| `/privacy` | `/de/privacy` | 隐私政策 |
| `/developer-guide` | `/de/developer-guide` | 开发者与工具指南(根据 `docs/developer-guide.md` 在站点内渲染) |
所有页面共享同一个 `Layout.astro`(品牌 token、hreflang 备用链接、页脚)。
字体:自行托管的 `@fontsource/spline-sans-mono`(无 Google CDN)。
Sitemap:`@astrojs/sitemap`(已记录在案的例外情况 —— 确定性的静态 XML,无运行时服务)。
## 开发
Dart 包位于 `packages/loam_cli/` 中:
```
cd packages/loam_cli
dart pub get
dart format --output=none --set-exit-if-changed bin lib test
dart analyze --fatal-infos --fatal-warnings
dart test
dart run bin/loam.dart scan
```
loam.dev 的第一个测试目标就是**它自己的代码库** —— 一个用于发现垃圾代码和漂移的工具,自身绝不能带有这些问题。
## License
MIT © 2026 Silvio Lindstedt标签:Dart, Flutter, 云安全监控, 文档结构分析, 架构约束, 死代码检测, 聊天机器人, 静态分析