@devflow-tools/cli 0.3.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/README.md +50 -0
  2. package/dist/commands/doctor.d.ts +25 -0
  3. package/dist/commands/doctor.d.ts.map +1 -1
  4. package/dist/commands/doctor.js +77 -1
  5. package/dist/commands/doctor.js.map +1 -1
  6. package/dist/commands/init.d.ts +6 -2
  7. package/dist/commands/init.d.ts.map +1 -1
  8. package/dist/commands/init.js +53 -2
  9. package/dist/commands/init.js.map +1 -1
  10. package/dist/commands/session.d.ts +7 -0
  11. package/dist/commands/session.d.ts.map +1 -0
  12. package/dist/commands/session.js +20 -0
  13. package/dist/commands/session.js.map +1 -0
  14. package/dist/index.js +67 -3
  15. package/dist/index.js.map +1 -1
  16. package/dist/lib/plugin-setup.d.ts +23 -0
  17. package/dist/lib/plugin-setup.d.ts.map +1 -0
  18. package/dist/lib/plugin-setup.js +141 -0
  19. package/dist/lib/plugin-setup.js.map +1 -0
  20. package/dist/plugin-files/.claude-plugin/plugin.json +20 -0
  21. package/dist/plugin-files/CLAUDE.md +34 -0
  22. package/dist/plugin-files/dist/command-registry.json +235 -0
  23. package/dist/plugin-files/dist/skills/devflow:context/SKILL.md +29 -0
  24. package/dist/plugin-files/dist/skills/devflow:docker/SKILL.md +49 -0
  25. package/dist/plugin-files/dist/skills/devflow:electron/SKILL.md +49 -0
  26. package/dist/plugin-files/dist/skills/devflow:graph/SKILL.md +24 -0
  27. package/dist/plugin-files/dist/skills/devflow:graphql/SKILL.md +48 -0
  28. package/dist/plugin-files/dist/skills/devflow:knowledge/SKILL.md +24 -0
  29. package/dist/plugin-files/dist/skills/devflow:memory/SKILL.md +23 -0
  30. package/dist/plugin-files/dist/skills/devflow:nest/SKILL.md +48 -0
  31. package/dist/plugin-files/dist/skills/devflow:nextjs/SKILL.md +45 -0
  32. package/dist/plugin-files/dist/skills/devflow:performance/SKILL.md +49 -0
  33. package/dist/plugin-files/dist/skills/devflow:react/SKILL.md +57 -0
  34. package/dist/plugin-files/dist/skills/devflow:tailwind/SKILL.md +45 -0
  35. package/dist/plugin-files/dist/skills/devflow:taro/SKILL.md +48 -0
  36. package/dist/plugin-files/dist/skills/devflow:vue/SKILL.md +52 -0
  37. package/dist/plugin-files/dist/skills/devflow:workflow/SKILL.md +24 -0
  38. package/dist/plugin-files/hooks/constitution.md +20 -0
  39. package/dist/plugin-files/hooks/post-tool-use +106 -0
  40. package/dist/plugin-files/hooks/pre-tool-use +147 -0
  41. package/dist/plugin-files/hooks/session-start +96 -0
  42. package/dist/plugin-files/hooks/stop +31 -0
  43. package/dist/plugin-files/hooks.json +40 -0
  44. package/dist/plugin-files/package.json +29 -0
  45. package/package.json +25 -23
@@ -0,0 +1,23 @@
1
+ ---
2
+ name: devflow:memory
3
+ description: 项目记忆 — 技术栈、编码约定、历史决策、用户偏好
4
+ ---
5
+
6
+ <HARD-GATE>
7
+ 收到 devflow:memory 时,必须先调用以下 MCP 工具之一:
8
+ get_memory
9
+ </HARD-GATE>
10
+
11
+
12
+
13
+ # /devflow:memory
14
+
15
+ ## 执行
16
+
17
+ 调用 `get_memory` MCP 工具(无需参数):
18
+
19
+ ```
20
+ (无参数 — 返回技术栈、约定、偏好、历史决策)
21
+ ```
22
+
23
+ 项目记忆存储在 DevFlow 结构化数据库中,只有通过 MCP 工具才能获取完整数据。不要用 grep / Read 读取 .codegraph/ 目录下的缓存文件。
@@ -0,0 +1,48 @@
1
+ ---
2
+ name: devflow:nest
3
+ description: NestJS 专家 — 模块架构、守卫调试、微服务配置、Swagger 生成
4
+ ---
5
+
6
+ <HARD-GATE>
7
+ 收到 devflow:nest 时,必须先调用以下 MCP 工具之一:
8
+ nest_new_module / nest_diagnose_bug
9
+ </HARD-GATE>
10
+
11
+
12
+
13
+ # 🐱 NEST
14
+
15
+ 你是一个 NestJS 专家。使用装饰器模式、依赖注入和模块化架构。遵循 SOLID 原则。
16
+
17
+ ## 适用场景
18
+
19
+ **新建 NestJS 模块(Controller + Service + Module + DTO + 测试)**
20
+
21
+ **Bug 排查:** 接口 500、依赖注入失败 → 定位 Module/Controller/Provider,检查 DI 链条和守卫/拦截器,搜索 Nest 官方文档。
22
+
23
+ **Swagger 文档生成:扫描 API → 补充装饰器 → 验证**
24
+
25
+ **微服务端点配置:消息模式 → 传输层 → 客户端代理**
26
+
27
+ ## 核心规则
28
+
29
+ - 每个功能封装为独立 Module(Controller + Service + Module + DTO + Spec)
30
+ - 使用构造函数依赖注入,通过 interface 解耦
31
+ - 使用 class-validator + ValidationPipe 校验请求
32
+ - Controller 只处理路由和参数解析,业务逻辑在 Service 中
33
+ - 遇到问题先查 NestJS 官方文档再给方案
34
+ - 修复 Bug 前先追踪 DI 链和 Module 注册
35
+ - 使用 Prisma 作为 ORM,事务使用 $transaction
36
+
37
+ ## 当前版本
38
+
39
+ - nestjs-docs: 10.3.0 — https://docs.nestjs.com/
40
+
41
+ ## 工作流
42
+
43
+ | 场景 | 触发方式 |
44
+ |------|----------|
45
+ | 新建 NestJS 模块(Controller + Service + Module + DTO + 测试) | 调用 MCP 工具 `nest_new_module` |
46
+ | Bug 排查: | 调用 MCP 工具 `nest_diagnose_bug` |
47
+ | Swagger 文档生成:扫描 API → 补充装饰器 → 验证 | 调用 MCP 工具 `nest_generate:swagger` |
48
+ | 微服务端点配置:消息模式 → 传输层 → 客户端代理 | 调用 MCP 工具 `nest_setup:microservice` |
@@ -0,0 +1,45 @@
1
+ ---
2
+ name: devflow:nextjs
3
+ description: Next.js 专家 — App Router、SSR/SSG/ISR、Server Components、Middleware、部署
4
+ ---
5
+
6
+ <HARD-GATE>
7
+ 收到 devflow:nextjs 时,必须先调用以下 MCP 工具之一:
8
+ nextjs_new_page / nextjs_diagnose_bug
9
+ </HARD-GATE>
10
+
11
+
12
+
13
+ # ▲ NEXTJS
14
+
15
+ 你是一个 Next.js 14 专家。使用 App Router、React Server Components。默认服务端渲染,按需客户端交互。
16
+
17
+ ## 适用场景
18
+
19
+ **新建 Next.js 页面(路由 + 数据获取 + 渲染策略)**
20
+
21
+ **Pages Router → App Router 迁移:路由映射 → 数据获取 → 渐进迁移**
22
+
23
+ **Bug 排查:** SSR 报错、路由不匹配、API Route 500 → 区分 Client/Server Component 边界,检查数据获取方式。
24
+
25
+ ## 核心规则
26
+
27
+ - 组件默认 Server Components,需要交互时才加 'use client'
28
+ - 使用 App Router 文件系统路由(page/layout/loading/error)
29
+ - 服务端数据获取使用 async component + fetch + cache()
30
+ - 客户端数据获取使用 SWR 或 React Query
31
+ - 图片使用 next/image,链接使用 next/link
32
+ - 中间件在 Edge Runtime 执行,不能直接访问数据库
33
+ - 使用 generateStaticParams + ISR 优化静态页面
34
+
35
+ ## 当前版本
36
+
37
+ - nextjs-docs: 14.2.0 — https://nextjs.org/docs
38
+
39
+ ## 工作流
40
+
41
+ | 场景 | 触发方式 |
42
+ |------|----------|
43
+ | 新建 Next.js 页面(路由 + 数据获取 + 渲染策略) | 调用 MCP 工具 `nextjs_new_page` |
44
+ | Pages Router → App Router 迁移:路由映射 → 数据获取 → 渐进迁移 | 调用 MCP 工具 `nextjs_migrate:app-router` |
45
+ | Bug 排查: | 调用 MCP 工具 `nextjs_diagnose_bug` |
@@ -0,0 +1,49 @@
1
+ ---
2
+ name: devflow:performance
3
+ description: Web 性能专家 — Core Web Vitals、Bundle 优化、加载策略、渲染性能
4
+ ---
5
+
6
+ <HARD-GATE>
7
+ 收到 devflow:performance 时,必须先调用以下 MCP 工具之一:
8
+ performance_audit_performance
9
+ </HARD-GATE>
10
+
11
+
12
+
13
+ # ⚡ PERFORMANCE
14
+
15
+ 你是一个 Web 性能专家。精通 Core Web Vitals、Bundle 优化和运行时性能。所有优化建议必须有数据依据。
16
+
17
+ ## 适用场景
18
+
19
+ **性能审计:Lighthouse → Web Vitals → Bundle → 优化方案**
20
+
21
+ **Bundle 优化:分析 → 代码分割 → Tree Shaking → 验证**
22
+
23
+ **加载速度优化:资源加载策略 → 预加载 → 缓存**
24
+
25
+ **运行时性能优化:长任务 → 渲染卡顿 → 内存泄漏**
26
+
27
+ ## 核心规则
28
+
29
+ - Core Web Vitals 目标:LCP < 2.5s, INP < 200ms, CLS < 0.1
30
+ - 首屏 JS < 200KB, CSS < 50KB
31
+ - 图片使用 WebP/AVIF 格式 + srcset + loading=lazy
32
+ - 字体使用 font-display: swap + 子集化
33
+ - 关键资源使用 preload/preconnect 优先加载
34
+ - 使用代码分割和动态导入按需加载
35
+ - 所有优化建议必须有 Lighthouse/Performance 数据支持
36
+ - 不使用 setTimeout 做动画,使用 requestAnimationFrame
37
+
38
+ ## 当前版本
39
+
40
+ - web-vitals-docs: 2024 — https://web.dev/vitals/
41
+
42
+ ## 工作流
43
+
44
+ | 场景 | 触发方式 |
45
+ |------|----------|
46
+ | 性能审计:Lighthouse → Web Vitals → Bundle → 优化方案 | 调用 MCP 工具 `performance_audit_performance` |
47
+ | Bundle 优化:分析 → 代码分割 → Tree Shaking → 验证 | 调用 MCP 工具 `performance_optimize:bundle` |
48
+ | 加载速度优化:资源加载策略 → 预加载 → 缓存 | 调用 MCP 工具 `performance_optimize:load-speed` |
49
+ | 运行时性能优化:长任务 → 渲染卡顿 → 内存泄漏 | 调用 MCP 工具 `performance_optimize:runtime` |
@@ -0,0 +1,57 @@
1
+ ---
2
+ name: devflow:react
3
+ description: React 18 专家能力 — Bug 诊断、组件重构、性能优化、Hooks 审查
4
+ ---
5
+
6
+ <HARD-GATE>
7
+ 收到 devflow:react 时,必须先调用以下 MCP 工具之一:
8
+ react_diagnose_bug / react_new_feature / react_audit_performance / react_review_hooks / react_refactor_component / react_new_component
9
+ </HARD-GATE>
10
+
11
+
12
+
13
+ # ⚛️ REACT
14
+
15
+ 你是一个 React 18 专家。使用函数组件、Hooks 和 TypeScript。遇到问题先查文档再给方案,不凭空猜测 API 行为。
16
+
17
+ ## 适用场景
18
+
19
+ **Bug 排查:** 页面白屏、状态异常、渲染死循环 → 先定位源码文件,再查 git 最近变更,最后搜索 React 官方文档验证 API 用法是否匹配当前版本。
20
+
21
+ **新功能开发:** 需要加组件或页面 → 先确认现有实现模式,再做影响范围评估,然后生成符合项目约定的组件/Hook/类型代码,最后通过类型检查和测试。
22
+
23
+ **性能卡顿:** 列表页滚动掉帧、输入响应慢 → Profiler 分析渲染次数和耗时,检查 memo/useMemo/useCallback 使用情况,检测不必要重渲染,生成优化方案并对比前后基准。
24
+
25
+ **Hooks 审查:** lint 警告、useEffect 循环触发 → 全量扫描所有 Hooks 调用位置,检查顶层调用规则、依赖数组完整性、清理函数缺失、反模式(渲染中创建组件、过大 useEffect),自动修复安全项。
26
+
27
+ **组件拆分:** 单文件超 300 行、职责不清 → 评估复杂度(行数/props/Hooks/嵌套),识别代码异味,生成拆分方案(提取子组件、抽取自定义 Hooks、提取工具函数),重构后跑回归测试。
28
+
29
+ **新建组件:** 加弹窗/表单/列表 → 先确认有无现成组件可复用,定义 TypeScript Props interface,生成组件(含 React.memo、错误处理、加载态),附带样式、测试文件。
30
+
31
+ ## 核心规则
32
+
33
+ - 使用函数组件 + Hooks,不使用 Class 组件
34
+ - 每个文件只导出一个组件
35
+ - Props 使用 TypeScript interface 定义
36
+ - 使用 React.memo 优化纯展示组件
37
+ - 自定义 Hooks 命名以 use 开头
38
+ - 避免在渲染中创建新对象/函数(使用 useMemo / useCallback)
39
+ - 遇到不确定的 API 时先查 React 官方文档再回答
40
+ - 修复 Bug 前先查 git log 找最近变更
41
+ - 生成代码后必须通过 TypeScript 类型检查
42
+ - 不能凭记忆猜测 API 行为,必须基于当前项目版本
43
+
44
+ ## 当前版本
45
+
46
+ - react-docs: 18.3.1 — https://react.dev/reference/react
47
+
48
+ ## 工作流
49
+
50
+ | 场景 | 触发方式 |
51
+ |------|----------|
52
+ | Bug 排查: | 调用 MCP 工具 `react_diagnose_bug` |
53
+ | 新功能开发: | 调用 MCP 工具 `react_new_feature` |
54
+ | 性能卡顿: | 调用 MCP 工具 `react_audit_performance` |
55
+ | Hooks 审查: | 调用 MCP 工具 `react_review_hooks` |
56
+ | 组件拆分: | 调用 MCP 工具 `react_refactor_component` |
57
+ | 新建组件: | 调用 MCP 工具 `react_new_component` |
@@ -0,0 +1,45 @@
1
+ ---
2
+ name: devflow:tailwind
3
+ description: Tailwind 专家 — 响应式设计、主题定制、Purge 检查、Utility 审查
4
+ ---
5
+
6
+ <HARD-GATE>
7
+ 收到 devflow:tailwind 时,必须先调用以下 MCP 工具之一:
8
+ tailwind_new_component
9
+ </HARD-GATE>
10
+
11
+
12
+
13
+ # 🌊 TAILWIND
14
+
15
+ 你是一个 Tailwind CSS 专家。使用 utility-first 方法构建界面。遇到问题先查 Tailwind 官方文档。
16
+
17
+ ## 适用场景
18
+
19
+ **新建 Tailwind 组件:语义结构 → 样式 → 响应式 → 暗色模式**
20
+
21
+ **Utility 审查:清除自定义 CSS → 统一为 Tailwind utility**
22
+
23
+ **主题迁移:分析现有设计 → 提取 Design Token → 生成配置**
24
+
25
+ ## 核心规则
26
+
27
+ - 优先使用 Tailwind utility classes,避免自定义 CSS
28
+ - 使用 Tailwind 响应式断点(sm/md/lg/xl/2xl)
29
+ - 颜色和间距从 theme 配置中引用
30
+ - 复杂样式使用 @apply 抽取
31
+ - 使用 class 策略实现暗色模式
32
+ - 避免内联 style 和自定义 CSS
33
+ - 不确定 class 名称时先查 Tailwind 官方文档
34
+
35
+ ## 当前版本
36
+
37
+ - tailwind-docs: 3.4.0 — https://tailwindcss.com/docs
38
+
39
+ ## 工作流
40
+
41
+ | 场景 | 触发方式 |
42
+ |------|----------|
43
+ | 新建 Tailwind 组件:语义结构 → 样式 → 响应式 → 暗色模式 | 调用 MCP 工具 `tailwind_new_component` |
44
+ | Utility 审查:清除自定义 CSS → 统一为 Tailwind utility | 调用 MCP 工具 `tailwind_audit:utility` |
45
+ | 主题迁移:分析现有设计 → 提取 Design Token → 生成配置 | 调用 MCP 工具 `tailwind_migrate:theme` |
@@ -0,0 +1,48 @@
1
+ ---
2
+ name: devflow:taro
3
+ description: Taro 跨端专家 — 多端适配、小程序调试、性能优化、兼容方案
4
+ ---
5
+
6
+ <HARD-GATE>
7
+ 收到 devflow:taro 时,必须先调用以下 MCP 工具之一:
8
+ taro_new_page
9
+ </HARD-GATE>
10
+
11
+
12
+
13
+ # 🛠️ TARO
14
+
15
+ 你是一个 Taro 跨端开发专家。使用 Taro 内置组件和 API,确保多端兼容。遇到小程序问题先查文档,不凭经验猜测。
16
+
17
+ ## 适用场景
18
+
19
+ **新建页面:** Taro 跨端页面 → 生成页面组件(兼容 H5/微信小程序),配置路由和导航栏。
20
+
21
+ **跨端兼容检查:扫描平台 API → 识别风险点 → 建议兼容方案**
22
+
23
+ **小程序调试:错误排查 → 包体积分析 → 性能检测**
24
+
25
+ **小程序性能优化:包体积 → 渲染优化 → 加载速度**
26
+
27
+ ## 核心规则
28
+
29
+ - 使用 Taro 内置组件(View、Text、Image)替代 HTML 元素
30
+ - 使用 Taro API 替代浏览器 API
31
+ - 避免使用 window/document 等 DOM API
32
+ - 使用条件编译处理平台差异(process.env.TARO_ENV)
33
+ - 样式使用 px 单位(Taro 自动转换)
34
+ - 合理使用分包加载减少首屏体积
35
+ - 不确定跨端兼容性时先查 Taro 文档确认
36
+
37
+ ## 当前版本
38
+
39
+ - taro-docs: 3.6.0 — https://docs.taro.zone/docs/
40
+
41
+ ## 工作流
42
+
43
+ | 场景 | 触发方式 |
44
+ |------|----------|
45
+ | 新建页面: | 调用 MCP 工具 `taro_new_page` |
46
+ | 跨端兼容检查:扫描平台 API → 识别风险点 → 建议兼容方案 | 调用 MCP 工具 `taro_check:cross-platform` |
47
+ | 小程序调试:错误排查 → 包体积分析 → 性能检测 | 调用 MCP 工具 `taro_debug:miniapp` |
48
+ | 小程序性能优化:包体积 → 渲染优化 → 加载速度 | 调用 MCP 工具 `taro_optimize:performance` |
@@ -0,0 +1,52 @@
1
+ ---
2
+ name: devflow:vue
3
+ description: Vue 3 专家 — Bug 诊断、Composition API、响应式调试、组件重构
4
+ ---
5
+
6
+ <HARD-GATE>
7
+ 收到 devflow:vue 时,必须先调用以下 MCP 工具之一:
8
+ vue_diagnose_bug / vue_new_component / vue_debug_reactivity
9
+ </HARD-GATE>
10
+
11
+
12
+
13
+ # 💚 VUE
14
+
15
+ 你是一个 Vue 3 专家。使用 Composition API、<script setup> 和 TypeScript。遇到问题先查文档再给方案,不凭空猜测。
16
+
17
+ ## 适用场景
18
+
19
+ **Bug 排查:** 组件渲染异常、响应式数据不同步 → 定位源码,检查 computed/watch 逻辑,搜索 Vue 官方文档验证 API 用法。
20
+
21
+ **新建组件:** 按照项目 SFC 规范生成组件(template + script setup + style scoped),附带 Props/Emits/Slots 类型定义。
22
+
23
+ **响应式调试:追踪数据流 → 定位问题 → 修复**
24
+
25
+ **提取 Composable:识别重复逻辑 → 抽取 → 替换引用**
26
+
27
+ **Pinia Store 重构:结构审查 → 拆分/合并 → 类型安全**
28
+
29
+ ## 核心规则
30
+
31
+ - 使用 <script setup lang="ts"> 语法糖
32
+ - 使用 Composition API(ref、reactive、computed、watch)
33
+ - 状态管理使用 Pinia
34
+ - 可复用逻辑抽取为 composables
35
+ - 遇到不确定的 API 时先查 Vue 官方文档再回答
36
+ - 修复 Bug 前先排查响应式数据流
37
+ - 生成代码后必须通过 vue-tsc 类型检查
38
+ - 不能凭记忆猜测 API 行为,必须基于当前项目版本
39
+
40
+ ## 当前版本
41
+
42
+ - vue-docs: 3.4.0 — https://vuejs.org/guide/introduction.html
43
+
44
+ ## 工作流
45
+
46
+ | 场景 | 触发方式 |
47
+ |------|----------|
48
+ | Bug 排查: | 调用 MCP 工具 `vue_diagnose_bug` |
49
+ | 新建组件: | 调用 MCP 工具 `vue_new_component` |
50
+ | 响应式调试:追踪数据流 → 定位问题 → 修复 | 调用 MCP 工具 `vue_debug_reactivity` |
51
+ | 提取 Composable:识别重复逻辑 → 抽取 → 替换引用 | 调用 MCP 工具 `vue_extract:composable` |
52
+ | Pinia Store 重构:结构审查 → 拆分/合并 → 类型安全 | 调用 MCP 工具 `vue_refactor:pinia` |
@@ -0,0 +1,24 @@
1
+ ---
2
+ name: devflow:workflow
3
+ description: 执行标准化开发工作流 — Bug 修复、功能开发、代码审查
4
+ ---
5
+
6
+ <HARD-GATE>
7
+ 收到 devflow:workflow 时,必须先调用以下 MCP 工具之一:
8
+ run_workflow
9
+ </HARD-GATE>
10
+
11
+
12
+
13
+ # /devflow:workflow
14
+
15
+ ## 执行
16
+
17
+ 调用 `run_workflow` MCP 工具:
18
+
19
+ ```
20
+ type = "bugfix" | "feature" | "review"
21
+ input = 用户的查询内容
22
+ ```
23
+
24
+ MCP 工具提供标准化的 DAG 步骤编排、人工确认节点、执行追踪和遥测记录。工作流执行过程中,MCP 工具会返回需要你介入的步骤,此时才根据步骤指引执行具体操作。
@@ -0,0 +1,20 @@
1
+ <EXTREMELY_IMPORTANT>
2
+ 你正在使用 DevFlow MCP Gateway。
3
+
4
+ ## MCP 优先原则
5
+
6
+ 收到 /devflow:* 命令时,必须先调用 SKILL.md 中列出的 MCP 工具。
7
+ Hook 会自动拦截不符合规范的原生工具调用,并按提示引导你使用正确的 MCP 工具。
8
+
9
+ 正确流程:
10
+ 1. 调用 Skill 加载命令
11
+ 2. 立即调用 MCP 工具
12
+ 3. 基于 MCP 结果回答
13
+ 4. 如需补充信息,使用 Read 工具读取 MCP 未包含的关联文件
14
+
15
+ 绝对不要:
16
+ - 在调用 MCP 之前用 grep/find/Glob/Explore 搜索代码
17
+ - 用 WebSearch/WebFetch 替代 get_knowledge
18
+ - 用 Agent(Explore) 替代 MCP 工具
19
+ - 尝试绕过 Hook 拦截
20
+ </EXTREMELY_IMPORTANT>
@@ -0,0 +1,106 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # PostToolUse Hook — DevFlow post-correction
5
+ # After AI uses a native tool that could have been an MCP tool, inject a corrective reminder.
6
+
7
+ INPUT_JSON=$(cat)
8
+ TOOL_NAME=$(python3 -c "
9
+ import sys, json
10
+ try:
11
+ data = json.load(sys.stdin)
12
+ print(data.get('tool_name', ''))
13
+ except:
14
+ print('')
15
+ " <<< "$INPUT_JSON" 2>/dev/null || echo "")
16
+
17
+ # Only interested in tools that could bypass MCP
18
+ case "$TOOL_NAME" in
19
+ Agent|Bash|Glob|Grep|WebSearch|WebFetch)
20
+ ;;
21
+ *)
22
+ exit 0
23
+ ;;
24
+ esac
25
+
26
+ # Determine project root and receipt file
27
+ PROJECT_ROOT="${CLAUDE_PROJECT_DIR:-$(pwd)}"
28
+ RECEIPT_DIR="${TMPDIR:-/tmp}/.devflow-receipts"
29
+ mkdir -p "$RECEIPT_DIR"
30
+ SESSION_ID=$(echo -n "$PROJECT_ROOT" | shasum -a 256 2>/dev/null | cut -c1-16 || echo "default")
31
+ RECEIPT_FILE="$RECEIPT_DIR/${SESSION_ID}.json"
32
+
33
+ # Check if there was a recent MCP call (within 30s) — if yes, this native tool call is supplementary, not a bypass
34
+ HAS_RECENT_MCP=false
35
+ if [ -f "$RECEIPT_FILE" ]; then
36
+ last_call=$(python3 -c "
37
+ import json, sys, time
38
+ try:
39
+ with open('$RECEIPT_FILE') as f:
40
+ d = json.load(f)
41
+ ts = d.get('lastMcpCall', 0)
42
+ now = int(time.time())
43
+ if now - ts < 30:
44
+ print('valid')
45
+ except:
46
+ pass
47
+ " 2>/dev/null || echo "")
48
+ if [ "$last_call" = "valid" ]; then
49
+ exit 0
50
+ fi
51
+ fi
52
+
53
+ # Read current bypass count
54
+ BYPASS_COUNT=0
55
+ if [ -f "$RECEIPT_FILE" ]; then
56
+ BYPASS_COUNT=$(python3 -c "
57
+ import json
58
+ with open('$RECEIPT_FILE') as f:
59
+ d = json.load(f)
60
+ print(d.get('bypassCount', 0))
61
+ " 2>/dev/null || echo "0")
62
+ fi
63
+
64
+ # If no bypasses yet, nothing to correct
65
+ if [ "$BYPASS_COUNT" -eq 0 ]; then
66
+ exit 0
67
+ fi
68
+
69
+ # Build corrective message based on tool type and count
70
+ case "$TOOL_NAME" in
71
+ Agent)
72
+ MESSAGE="第 ${BYPASS_COUNT} 次违规:你刚才使用了 Agent 子代理执行搜索。下次请用 get_project_context MCP 工具替代。"
73
+ ;;
74
+ Bash)
75
+ MESSAGE="第 ${BYPASS_COUNT} 次违规:你刚才用了 Bash 命令搜索代码。下次请用 get_project_context MCP 工具替代。"
76
+ ;;
77
+ Glob)
78
+ MESSAGE="第 ${BYPASS_COUNT} 次违规:你刚才用了 Glob 匹配文件。下次请用 get_project_context MCP 工具替代。"
79
+ ;;
80
+ Grep)
81
+ MESSAGE="第 ${BYPASS_COUNT} 次违规:你刚才用了 Grep 搜索代码。下次请用 get_project_context MCP 工具替代。"
82
+ ;;
83
+ WebSearch|WebFetch)
84
+ MESSAGE="第 ${BYPASS_COUNT} 次违规:你刚才用了网络搜索。下次请用 get_knowledge MCP 工具替代。"
85
+ ;;
86
+ *)
87
+ exit 0
88
+ ;;
89
+ esac
90
+
91
+ # Add enforcement status
92
+ if [ "$BYPASS_COUNT" -ge 3 ]; then
93
+ MESSAGE="${MESSAGE} 已达到最大违规次数,后续绕过将被硬阻止。"
94
+ elif [ "$BYPASS_COUNT" -ge 2 ]; then
95
+ MESSAGE="${MESSAGE} 下次违规将被阻止。"
96
+ else
97
+ MESSAGE="${MESSAGE} 请立即纠正。"
98
+ fi
99
+
100
+ # Output as additionalContext injection
101
+ if [ -n "${CLAUDE_PLUGIN_ROOT:-}" ]; then
102
+ ESCAPED=$(printf '%s' "$MESSAGE" | python3 -c "import sys,json; print(json.dumps(sys.stdin.read()))")
103
+ printf '{"hookSpecificOutput":{"hookEventName":"PostToolUse","additionalContext":"%s"}}\n' "$ESCAPED"
104
+ fi
105
+
106
+ exit 0
@@ -0,0 +1,147 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # PreToolUse Hook — DevFlow unified command enforcement
5
+ # Reads command-registry.json and receipt to dynamically intercept
6
+ # native tool calls that bypass MCP Gateway.
7
+
8
+ # ---- Read stdin (Claude Code passes JSON via stdin) ----
9
+ INPUT_JSON=$(cat)
10
+ TOOL_NAME=$(python3 -c "
11
+ import sys, json
12
+ try:
13
+ data = json.load(sys.stdin)
14
+ print(data.get('tool_name', ''))
15
+ except:
16
+ print('')
17
+ " <<< "$INPUT_JSON" 2>/dev/null || echo "")
18
+
19
+ TOOL_INPUT=$(python3 -c "
20
+ import sys, json
21
+ try:
22
+ data = json.load(sys.stdin)
23
+ ti = data.get('tool_input', {})
24
+ if data.get('tool_name') == 'Agent':
25
+ out = {'subagent_type': ti.get('subagent_type',''),
26
+ 'description': ti.get('description',''),
27
+ 'prompt': ti.get('prompt','')}
28
+ print(json.dumps(out))
29
+ else:
30
+ print(ti.get('command') or ti.get('query') or ti.get('pattern') or json.dumps(ti))
31
+ except:
32
+ print('')
33
+ " <<< "$INPUT_JSON" 2>/dev/null || echo "")
34
+
35
+ # ---- Locate registry ----
36
+ PROJECT_ROOT="${CLAUDE_PROJECT_DIR:-$(pwd)}"
37
+ RECEIPT_DIR="${TMPDIR:-/tmp}/.devflow-receipts"
38
+ SESSION_ID=$(echo -n "$PROJECT_ROOT" | shasum -a 256 2>/dev/null | cut -c1-16 || echo "default")
39
+ RECEIPT_FILE="$RECEIPT_DIR/${SESSION_ID}.json"
40
+
41
+ REGISTRY="${CLAUDE_PLUGIN_ROOT:-}/dist/command-registry.json"
42
+ if [ ! -f "$REGISTRY" ]; then
43
+ REGISTRY="$HOME/.devflow/command-registry.json"
44
+ fi
45
+
46
+ # Fallback: built-in default rules when registry is missing
47
+ if [ ! -f "$REGISTRY" ]; then
48
+ REGISTRY_CONTENT='{"commands":{"devflow:context":{"mcpTools":["get_project_context","search_symbol"],"blockedNative":["Grep","grep","find","rg","ag","Glob","Explore","WebSearch","WebFetch"]},"devflow:knowledge":{"mcpTools":["get_knowledge"],"blockedNative":["WebSearch","WebFetch"]},"devflow:graph":{"mcpTools":["get_dependency_graph"],"blockedNative":["Glob","Explore"]},"devflow:memory":{"mcpTools":["get_memory"],"blockedNative":["Grep","grep","find"]}}}'
49
+ else
50
+ REGISTRY_CONTENT=$(cat "$REGISTRY")
51
+ fi
52
+
53
+ # ---- Phase 1: Is this tool devflow-relevant? ----
54
+ is_devflow_relevant() {
55
+ local tool="$1" input="$2"
56
+ case "$tool" in
57
+ Bash)
58
+ echo "$input" | grep -qE "^(grep|find|rg|ag) " || return 1
59
+ # Exclude test/build/git commands
60
+ echo "$input" | grep -qE "(npm test|npm run|npx |git |python -m pytest|cargo test)" && return 1
61
+ return 0 ;;
62
+ Grep|Glob) return 0 ;;
63
+ Agent)
64
+ echo "$input" | grep -qiE "explore|search|find|code" && return 0
65
+ return 1 ;;
66
+ WebSearch|WebFetch) return 0 ;;
67
+ *) return 1 ;;
68
+ esac
69
+ }
70
+
71
+ if ! is_devflow_relevant "$TOOL_NAME" "$TOOL_INPUT"; then
72
+ exit 0
73
+ fi
74
+
75
+ # ---- Phase 2: Read activeCommand from receipt ----
76
+ ACTIVE_CMD=$(RECEIPT_FILE="$RECEIPT_FILE" python3 -c "
77
+ import json, os
78
+ try:
79
+ with open(os.environ.get('RECEIPT_FILE','')) as f:
80
+ print(json.load(f).get('activeCommand',''))
81
+ except:
82
+ print('')
83
+ " 2>/dev/null || echo "")
84
+
85
+ # No activeCommand → no enforcement (user is not in a /devflow:* command)
86
+ [ -z "$ACTIVE_CMD" ] && exit 0
87
+
88
+ # ---- Phase 2.5: Dynamic interception from registry ----
89
+ MCP_INFO=$(ACTIVE_CMD="$ACTIVE_CMD" python3 -c "
90
+ import json, sys, os
91
+ try:
92
+ r = json.load(sys.stdin)
93
+ cmd = r['commands'].get(os.environ.get('ACTIVE_CMD',''), {})
94
+ tools = cmd.get('mcpTools', [])
95
+ blocked = cmd.get('blockedNative', [])
96
+ print(json.dumps({'tools': tools, 'blocked': blocked}))
97
+ except:
98
+ print('{}')
99
+ " <<< "$REGISTRY_CONTENT" 2>/dev/null || echo "{}")
100
+
101
+ MCP_TOOLS=$(echo "$MCP_INFO" | python3 -c "import sys,json; print(' / '.join(json.load(sys.stdin).get('tools',[])))" 2>/dev/null || echo "")
102
+
103
+ # Extract blocked list as newline-separated for membership check
104
+ BLOCKED=$(echo "$MCP_INFO" | python3 -c "
105
+ import sys, json
106
+ for item in json.load(sys.stdin).get('blocked', []):
107
+ print(item)
108
+ " 2>/dev/null || echo "")
109
+
110
+ # Check if current tool matches blockedNative from registry
111
+ IS_BLOCKED=false
112
+ case "$TOOL_NAME" in
113
+ Bash)
114
+ # Extract the base command (first word)
115
+ BASE_CMD=$(echo "$TOOL_INPUT" | awk '{print $1}')
116
+ case "$BASE_CMD" in
117
+ grep|find|rg|ag)
118
+ echo "$BLOCKED" | grep -qxF "$BASE_CMD" && IS_BLOCKED=true ;;
119
+ esac
120
+ ;;
121
+ Grep)
122
+ echo "$BLOCKED" | grep -qxF "Grep" && IS_BLOCKED=true ;;
123
+ Glob)
124
+ echo "$BLOCKED" | grep -qxF "Glob" && IS_BLOCKED=true ;;
125
+ Agent)
126
+ # Agent with explore/search intent → check Explore in blocked
127
+ if echo "$TOOL_INPUT" | grep -qiE "explore|search|find|code"; then
128
+ echo "$BLOCKED" | grep -qxF "Explore" && IS_BLOCKED=true
129
+ fi
130
+ ;;
131
+ WebSearch)
132
+ echo "$BLOCKED" | grep -qxF "WebSearch" && IS_BLOCKED=true ;;
133
+ WebFetch)
134
+ echo "$BLOCKED" | grep -qxF "WebFetch" && IS_BLOCKED=true ;;
135
+ esac
136
+
137
+ if [ "$IS_BLOCKED" = "true" ]; then
138
+ cat >&2 <<EOF
139
+ ━━━━━━ DevFlow Gateway ━━━━━━
140
+ 🛑 当前命令 ${ACTIVE_CMD} 禁止使用 ${TOOL_NAME}。
141
+ 请使用 MCP 工具: ${MCP_TOOLS}
142
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━
143
+ EOF
144
+ exit 2
145
+ fi
146
+
147
+ exit 0