opencode-idea 0.0.16 → 0.0.17

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.
package/README.md CHANGED
@@ -7,9 +7,10 @@ OpenCode 插件,面向 JetBrains 项目 (IntelliJ IDEA / PyCharm / WebStorm 等)
7
7
  2. **优先使用 IDE 工具** —— IDE 可用时,向模型注入"项目内操作优先使用 IDEA MCP"的系统提示引导 + 能力映射;IDE 不可用时回退原生工具
8
8
  (正常回退,无需声明)。
9
9
 
10
- > **项目命令走 IDE 终端**:跑 `java` / `python` / `npm` 这类项目命令时,引导模型用 `idea_execute_terminal_command`
11
- > (`executeInShell: true`)而不是原生 shell —— 它在 IDE 集成终端里执行,**天然继承用户在 IDE 里配好的 JDK / Node / Python 版本**
12
- > (含 fnm / SDKMAN 这类靠 shell init 切版本的场景)。详见「项目命令执行」。
10
+ > **需要项目环境的命令走 Run Configuration**:跑 `java` / `python` / `npm` 这类依赖项目配好的 JDK / Node / Python 版本的
11
+ > 命令时,引导模型用 `idea_execute_run_configuration`(配置**由用户**先在 IDEA 里建好),而不是原生 shell;不需要项目
12
+ > 环境的命令照常走原生 shell。**IDE 内置终端 (`idea_execute_terminal_command`) 已被隐藏** —— 实测它并不继承项目环境,
13
+ > 对原生 shell 没有任何优势。详见「项目命令执行」。
13
14
 
14
15
  非 JetBrains 项目完全不受影响。 **手动接入**:插件启动不探测、不连接 IDE,只有跑 `/open-in-idea` 才接入。跑过一次后,该**项目**
15
16
  被「标记」(持久化在 `ctx.storage`,重启 OpenCode 后仍在)。之后**没有任何后台轮询**——恢复完全靠请求驱动:插件发现"该有 `idea_*`
@@ -29,7 +30,7 @@ setup(启动, 每项目一次):
29
30
  不探测、不注册 MCP
30
31
 
31
32
  /open-in-idea(手动触发, 阻塞到就绪):
32
- 1. 写项目标记 = true + 同步内存缓存;注册 `idea-run-config` skill
33
+ 1. 写项目标记 = true + 同步内存缓存;按 IDE 实际提供的工具同步 skill
33
34
  2. 探测本地 JetBrains IDE MCP 服务(/stream)
34
35
  - 已就绪 → 再问 IDE「当前项目是否已打开」(`get_project_modules`,带项目路径)
35
36
  · 已打开 → 不重复 open;未打开 → open -a 打开
@@ -93,88 +94,183 @@ Brave Mode 后再次执行 `/open-in-idea` 即可接上。
93
94
  输入 `/close-in-idea`:**注销当前项目的 IDE MCP** + 删除项目标记(持久化 + 内存缓存一并清),并清空注入的环境变量。
94
95
  之后 `idea_*` 工具不再可用,也不会再因失败自动接入。想重新接入,再次执行 `/open-in-idea`。
95
96
 
96
- ## IDE 工具优先 (直接调用引导)
97
+ ## 按能力选工具 (直接调用引导)
97
98
 
98
- IDE MCP 可用时,插件通过 **系统提示注入**提高模型主动使用 IDEA MCP 的概率;不修改任何工具 (原生或 IDEA)
99
+ IDE MCP 可用时,插件通过 **系统提示注入**告诉模型**哪些事该走 IDE**;不修改任何工具 (原生或 IDEA)
99
100
  的定义、描述或可用性:
100
101
 
101
- 1. **系统提示注入**:通过 `ctx.session.hook("context", …)` 往每次请求的 system 里追加一段「项目内操作优先使用 IDEA
102
- MCP」的直接调用引导 + 能力映射表 (`src/ide-guidance.js`),含工具名 (`idea_<name>`)与关键参数名:
103
- - 检索 → `idea_search_text` / `idea_search_regex` / `idea_search_file`(参数 `q`,可带 `paths` 收窄)
104
- - 读文件 → `idea_read_file`(`file_path` / `offset` / `limit`);目录 → `idea_list_directory_tree`
105
- - 改文件 → `idea_apply_patch`(`input`);新建 → `idea_create_new_file`(`pathInProject`)
106
- - 校验 → `idea_lint_files` / `idea_get_file_problems`
107
- - 重构/格式化 → `idea_rename_refactoring` / `idea_reformat_file`
108
- - 数据库 → `idea_list_database_connections` / `idea_execute_sql_query` / `idea_preview_table_data` 等;没有数据源时先建议用户在
109
- IDEA 里配置
110
- - 边界:只约束 **代码与文件操作**;未暴露的领域 (版本控制、shell/终端等) 工具表里没有 `idea_*` 选项,模型自然走原生
102
+ 1. **系统提示注入**:通过 `ctx.session.hook("context", …)` 往每次请求的 system 里追加一段引导 + 能力映射表。**文本本身在
103
+ `src/ide-guidance.template.md`**——它是一份要给人 review 的提示词文档,条件直接用 `{{#if …}}` 写在那几行外面,所以打开模板
104
+ 就能看到最终渲染成什么样;`src/template.js` 是渲染器(支持 `{{var}}` / `{{#if}}` / `{{else}}`,**不做 HTML 转义**——
105
+ 输出是 Markdown,`<jar>!/<entry>` 和反引号必须原样过)。含工具名 (`idea_<name>`)与关键参数名:
106
+ - **只有 IDE 才有的能力才写进去** —— 符号级检索、项目模型、检查与构建、重构与格式化、运行配置:
107
+ - 符号 → `idea_search_symbol` / `idea_get_symbol_info` / `idea_analyze_calls`
108
+ - 项目与编辑器 → `idea_get_project_modules` / `idea_get_project_dependencies` / `idea_list_directory_tree` /
109
+ `idea_get_all_open_file_paths` / `idea_open_file_in_editor`
110
+ - 重构/格式化 → `idea_rename_refactoring` / `idea_reformat_file`
111
+ - 校验 → `idea_lint_files` / `idea_get_file_problems` / `idea_build_project`
112
+ - 运行配置 → `idea_get_run_configurations` / `idea_execute_run_configuration`(+ 配套插件的启停工具)
113
+ - **读、写、找文本、找文件用原生工具**(`read` / `write` / `edit` / `grep` / `glob`)—— 这几件事走 IDE 只是多一跳,
114
+ 所以映射表里**不出现** `idea_search_text` / `idea_search_regex` / `idea_search_file` / `idea_apply_patch` /
115
+ `idea_create_new_file`,也不再禁止它们的原生对应物。
116
+ - **唯一例外是 `idea_read_file`**:它是读**包内文件**的唯一手段(`<jar>!/<entry>` 的依赖 jar 内文件、`jrt://` 的
117
+ JDK 镜像),引导只在这个用途上点名它,并写明普通文件一律用 `read`。
111
118
 
112
119
  不会把整份工具目录重复塞进 system prompt,也不要求模型先写编排代码。IDEA MCP 工具自身的
113
120
  description/schema 仍是参数使用的权威来源;工具返回业务错误时先修正参数,不要误判成工具不可用。MCP 不可用时立即
114
121
  提示用户执行 `/open-in-idea`,不重复探测或等待。
115
122
 
123
+ **总则里最靠前的两条是 Code Mode 规则**,而且第一条是**通用**的,不是 `idea_*` 特例:`工具列表里已经直接列出的原生工具,
124
+ 直接调用,不需要也不应该用 Code Mode 的 `search` 去找`;第二条才落到 `idea_*`(它就是原生工具,且不在 Code Mode 目录里)。
125
+ 放在所有路由规则之前,因为它们是前提 —— 模型拿不到工具,后面写什么都没用。理由是实测过的失效:工具明明在原生工具
126
+ 列表里,模型却进 Code Mode 跑了一次工具搜索(Code Mode 自己的指令「用 `search` 找工具」读起来像是访问任何东西的通用
127
+ 姿势,而原文没有任何一句说明这些工具在哪),白绕一圈之后还可能得出"工具不可用"的错误结论。同一条约束也写在
128
+ 「工具已消失」的恢复提示里,避免掉线时又去 Code Mode 里找。
129
+
116
130
  引导只在 **IDE MCP 可用**时生效;MCP 不可用时仅保留 fast-fail 恢复提示。`injectGuidance: false` 可关闭系统提示注入。
117
131
 
118
- ## Run Configuration 管理 (skill)
132
+ **条件注入**:映射表里只有内置 MCP Server 自带的那批工具是「永远写死」的。如果 IDE 里另外装了配套的
133
+ [`idea-mcp-enhance`](https://github.com/syllr/idea-mcp-enhance) 插件,它提供的 run configuration 启停工具也会被加进
134
+ 下面的「运行配置」段。判据是**这次请求的工具快照里真的有这些工具** —— 没装的 IDE 上这段一个字都不会出现,模型不会去调
135
+ 一个不存在的工具。
119
136
 
120
- IDE MCP 只能 **查**(`get_run_configurations`)和 **执行**(`execute_run_configuration`)run configuration, **没有增删改**
121
- 。插件在**被标记的项目**里注册一个 `idea-run-config` skill 来补上这块:
137
+ ## 工具参数 (schema 收敛 + `execute.before`)
122
138
 
123
- - 只操作 **项目级** `.run/<name>.run.xml`(可提交 git、团队共享), **不碰** `.idea/workspace.xml`;
124
- - 不内置任何按类型的模板 —— 先找项目里的 **真实样本**(`**/*.run.xml`,或让用户在 IDEA 里勾 "Store as project file"
125
- 建一个)当参照,再写;
126
- - 写完必须用 `idea_get_run_configurations` **校验它能被列出**、并用 `idea_execute_run_configuration` **实跑确认**;
127
- - 改配置用 `idea_apply_patch` **定向改 option**,不整文件重写。
139
+ 有些 IDEA 工具**不传某个参数就会回答一个你没问的问题**。这种参数由本插件完全掌管,所以要**两半一起做** —— 只做一半都是错的:
128
140
 
129
- **skill 的生命周期跟随项目标记**:`/open-in-idea` 打标记时注册、`/close-in-idea` 清标记时注销;曾被标记过的项目在
130
- `setup` 时(读回标记)就会注册。未标记的项目不受影响。文档放在 `skills/<id>/SKILL.md`(每个 skill 一个目录,`name` /
131
- `description` 走 YAML frontmatter),由 `src/skill/loader.js` 扫描加载 —— **加新 skill 只需加一个目录,不用改代码**。
141
+ | 一半 | 做法 | 不做会怎样 |
142
+ | ------------------------------ | ------------------------------------ | ------------------------------------------ |
143
+ | 从模型的工具 schema 里**删掉** | `ctx.tool.transform` 改 input schema | 模型会设它、会据此推理,而那个值被无声丢弃 |
144
+ | 每次调用**设成固定值** | `ctx.tool.hook("execute.before")` | 模型不传时拿到的是那个可能出错的默认值本身 |
132
145
 
133
- ## Standalone 模式纪律 (skill)
146
+ 两半由 `src/mcp/idea-tool-defaults.js` 的**同一张表** `FORCED_ARGUMENTS` 驱动,所以不会漂移。目前一条:
147
+
148
+ | 工具 | 参数 | 值 | 为什么 |
149
+ | -------------------- | --------- | ------ | -------------------------------------------------------------------------------------------------------------- |
150
+ | `idea_build_project` | `rebuild` | `true` | 增量构建比对的是 **IDE 自己那份文件新鲜度**;IDE 外部改的代码可能被判成"没有脏文件",构建于是变成 no-op 并报成功 |
151
+
152
+ - **强制**而不是"缺省才补":`rebuild: false` 请求的正是那个可能出错的答案,而且调用方从结果里分辨不出来;`rebuild: true`
153
+ 唯一的代价是时间。
154
+ - 依据是实测(IntelliJ 2026.2.3):`build_project` 落到
155
+ `ProjectTaskManager.createAllModulesBuildTask(project, isIncrementalBuild = !rebuild)`;用 `rebuild: true` 跑的 6 个场景
156
+ (改已有文件 / 新增文件、任意包、在编辑器里打开与否)**全部**识别到外部改动。
157
+ - 调用方自己也传了非空 `filesToRebuild` 时,IDE 走的是另一条分支、根本不读 `rebuild`,所以设不设都无副作用。
158
+ - **引导文本里一个字都不提 `rebuild`** —— schema 都不暴露了,再写进提示词等于把刚拿掉的旋钮又放回去。
159
+ - 只对**点名的工具**生效,其余工具的参数一字不改(测试里专门有一条:另一个恰好也有 `rebuild` 属性的工具不受影响)。
160
+
161
+ 安全性照着 OpenCode 源码确认过:一次工具调用**先**按该请求发布出去的 schema 校验,**然后**才进 `execute`,而
162
+ `execute.before` 在真正的工具逻辑之前触发。所以"schema 里没有、钩子里补上"这个组合不会撞校验。
163
+
164
+ **这是对早先「绝不改工具定义」那条规则的一次有意例外**(见 `141b1bd`),且刻意收得很窄:这里**只做减法,不发明、不解释**。
165
+ IDE 自己的 `build_project` 工具描述本来就没提这个参数(只有属性级描述提),所以删掉属性之后 schema 依然自洽、也依然完全是
166
+ IDE 的。schema 变换**绝不能**用来加建议 —— 那是引导文本的职责。
167
+
168
+ 两半都**不依赖项目标记**:它们修的是工具调用本身,与"这个项目是否接入 IDE"无关。
169
+
170
+ ## Run Configuration 全套 (配套插件 `idea-mcp-enhance`)
171
+
172
+ IDE 内置的 MCP Server 只能 **启动已有**的 run configuration(`execute_run_configuration`),**不能新建、不能停止、不能重启、
173
+ 也查不到运行状态**。配套的 IDEA 插件 [`idea-mcp-enhance`](https://github.com/syllr/idea-mcp-enhance)(IDEA 2026.2+,另装)
174
+ 补齐这四件事 —— 正好是「建 → 看 → 停 → 重启」一条链:
175
+
176
+ | 工具 (OpenCode 里叫 `idea_*`) | 作用 |
177
+ | ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
178
+ | `idea_create_shell_run_configuration` | 新建**项目级** Shell 配置(写 `.run/<name>.run.xml`);只支持 Shell 类型。**重操作 —— 只给固定流程建,且必须先取得用户同意** |
179
+ | `idea_list_running_configurations` | **当前真正在跑**的配置:几个实例 / 各自 pid / 退出码。`>1` 个实例就是端口漂移的信号 |
180
+ | `idea_stop_run_configuration` | 停掉该配置的**全部**实例并等它们退出;没在跑也返回成功(幂等) |
181
+ | `idea_rerun_run_configuration` | 等同 IDE 的 **Rerun** 按钮:在跑就重启、没在跑就启动,读 `started` 判断是否真起来了 |
182
+
183
+ opencode-idea 对这一组工具做三件事:
184
+
185
+ 1. **透传**:IDE MCP server 以 `codemode: false` 注册,工具目录整体转发,所以这四个工具自动以 `idea_*` 出现在模型的
186
+ 工具表里 —— 插件侧不需要单独声明(也因此**装不装这个 IDEA 插件,插件侧的代码都不用改**);
187
+ 2. **条件引导**:只有这次请求的工具快照里真的有它们,才在「运行配置(配套插件 … 提供,装了才有)」**自己那一节**里逐个点名 ——
188
+ 和 IDE 自带的 `### 运行配置` 分开:两个来源,两节,读者要能分清"IDE 给我的"和"我额外装的"。没装插件时**整节连同标题一起消失**。
189
+ 两个地方会跟着变:
190
+ - 「运行配置」段写明**改完代码要重启无热重载的进程就用 `idea_rerun_run_configuration`,不要用 `pkill` / `kill` / shell**
191
+ —— 这正是它要解决的问题:外部杀掉的进程 IDE 并不知道,Run 窗口仍显示运行中,下次启动就会撞端口;
192
+ - 「命令执行」段把**新建 run configuration 定性成重操作**:一个项目通常只建几个(固定要跑的构建 / 装依赖 / dev server),
193
+ **不是随手一条命令就建一个**,而且要**先告诉用户建什么、为什么,取得同意再动手**。只有最后"用哪条路建"才按工具是否
194
+ 分成两条**无条件 + 有条件**:「配置一律不由你写」永远在;只有「Shell 例外,用 `idea_create_shell_run_configuration`」那一行
195
+ 按工具是否存在分流,没有就换成「缺配置请用户在 IDEA 里建」。**没装插件时绝不会提到那个工具。**
196
+ 3. **工具名清单**写在 `src/mcp/enhance.js`(与原生 IDE 的 `src/mcp/idea.js` 分开放:原生走原生,插件的走插件的),
197
+ 与该仓库的 `RunLifecycleSchemas.kt` 保持同步。工具按**存在的子集**逐个点名(而不是「有就全写」),这样旧版本的配套
198
+ 插件少给一两个工具时,引导也不会提到它们。
199
+
200
+ > 没装 `idea-mcp-enhance` 的 IDE 一切照旧:工具不存在,引导也不提,模型继续按原来的方式工作。
134
201
 
135
- 本机直跑应用的**项目级纪律**由 `idea-standalone` skill 固化:它为项目生成/维护一份 rule,落在项目根
136
- **`.opencode/rules/idea-standalone.md`**,四段结构固定 ——
202
+ ## Run Configuration:能建就用工具,不能建就交给用户
137
203
 
138
- 1. **什么是 standalone 模式**:**standalone = 通过 IDEA 启动**(每个应用的入口是 IDEA run configuration),应用在本机进程
139
- 直跑(不容器化、不部署),只启动其中一部分是常态;启停一律由用户在 IDEA 里手动完成,AI 不得代为启停(含经
140
- `idea_execute_run_configuration`),判断需要重启时先取得用户明确授权;
204
+ 内置 MCP 只能 **查**(`get_run_configurations`)和 **执行**(`execute_run_configuration`)run configuration;新建靠配套插件的
205
+ `idea_create_shell_run_configuration`(只有 Shell 类型,见上面的「Run Configuration 全套」);**修改和删除永远没有工具**。
206
+
207
+ 所以插件的立场是:
208
+
209
+ - **配置一律不由 AI 动手** —— 不手写 `.run/*.run.xml`,也不手搓启动命令。这条无条件;
210
+ - **Shell 类型**且装了配套插件 → 用 `idea_create_shell_run_configuration`(新建是重操作,**必须先取得用户同意**);
211
+ - **其他类型,或没装插件** → **请用户在 IDEA 里建**,AI 只负责说明要建什么、为什么。
212
+
213
+ > **曾经有一个 `idea-run-config` skill 教模型手写 `.run/*.run.xml`,已经删掉。** 理由:手写那条路很脆 —— `type` 写错 IDE 会
214
+ > **静默忽略整个文件、日志里也不报**,模型的唯一判据只有"`idea_get_run_configurations` 里看不看得到";而它想补的"新建"能力现在
215
+ > 由配套插件提供。要配置但没有工具,就**交给用户**,比让模型猜 option 名可靠。
216
+
217
+ **skill 的生命周期跟随两道门,缺一不可**:
218
+
219
+ 1. **项目标记** —— `/open-in-idea` 打标记时注册、`/close-in-idea` 清标记时注销;曾被标记过的项目在 `setup` 时(读回标记)
220
+ 也会走这一步。未标记的项目不受影响。
221
+ 2. **IDE 真的在提供这个 skill 依赖的工具** —— skill 在自己的 frontmatter 里用 `requires:` 声明它绕着哪个工具写(例如
222
+ `idea-standalone` 声明 `idea_rerun_run_configuration`,那个工具只有配套插件提供)。**没这个工具就不注册这个 skill**:
223
+ 一个教模型去调"它根本看不到的工具"的 skill,不是知识,是一次注定的失败调用。工具的可见性是双向跟随的 —— `setup` 时还没
224
+ 连过 IDE、目录未知,所以那时**不注册**;等 IDE 应答(`/open-in-idea` 或重连)后目录才算已知,该出现的才出现;反过来,某个
225
+ 请求里工具没了,skill 也跟着撤(不需要等重连)。
226
+ `requires` 必须写 **OpenCode 侧的名字**(IDE 工具带 `idea_` 服务器前缀),因为门就是拿它跟 `ctx.tool.list()` 比;
227
+ 写成 IDE 的原始名(`rerun_run_configuration`)会让这个 skill 在任何机器上都不出现,而且没有任何报错。
228
+
229
+ 文档放在 `skills/<id>/SKILL.md`(每个 skill 一个目录,`name` / `description` / `requires` 走 YAML frontmatter,`requires` 由
230
+ loader 消费、**不会进入注册给 OpenCode 的定义**),由 `src/skill/loader.js` 扫描加载 —— **加新 skill 只需加一个目录,不用改代码**。
231
+
232
+ ## Standalone 模式纪律 (skill)
233
+
234
+ 本机直跑应用的**项目级纪律**由 `idea-standalone` skill 固化:它把这份纪律写进**项目根 `AGENTS.md`** 里由
235
+ `<!-- idea-standalone:begin -->` 与 `<!-- idea-standalone:end -->` 包裹的**标记块**(根 `AGENTS.md` 本来就是 AI 在本项目
236
+ 工作时必读的文件,所以不需要另建规则文件、也不需要 always-apply 开关;标记块是"以后改没改过"的判据)。骨架与各段写作规范在
237
+ `skills/idea-standalone/assets/AGENTS.template.md`,**SKILL.md 只写流程、指向模板**,不重复骨架。三段固定 ——
238
+
239
+ 1. **什么是 standalone 模式**:**standalone = 启动收口只有 IDEA run configuration**(每个应用的启动入口是 run configuration,不是手搓命令行;
240
+ 至于配置内部怎么起 —— 本机进程 / 容器 / 部署到远端 —— 由它自己决定,本段不预设),只启动其中一部分是常态;
241
+ **跑应用只用 `idea_rerun_run_configuration`**(在跑就重启、没在跑就启动)
242
+ —— 不必分辨启动还是重启,直接 rerun 就完事,常驻进程化 / 服务化的配置一律走这条;
243
+ **`idea_execute_run_configuration` 不用于这里**(它是给命令 / Job 类型的配置跑的,对常驻进程只会起重复实例);也不绕开 IDEA 用
244
+ `go run` / `pnpm dev` 这类裸命令或 `kill` / `pkill`;**重启不必先问** —— 改完代码要重启就直接 rerun,这条链是无人化的;
141
245
  2. **启动哪些应用**:一行一个应用,启动路径**只能是 IDEA run configuration**(配置名必须能在 `idea_get_run_configurations`
142
- 里查到;缺配置先走 `idea-run-config` skill 建 `.run/*.run.xml`),端口与被依赖的先后顺序一并写明;
246
+ 里查到;**缺配置就交给用户**去 IDEA 里建),端口与被依赖的先后顺序一并写明;
143
247
  3. **热重载矩阵**:逐应用标"是 / 否" —— 带 HMR 的 dev server 改动后**不用**提示重启;`go run .` 这类无热重载的进程改动后
144
248
  **必须**显式点名「需要重启 <应用>」,不得在未提示的情况下宣称"改完可验证";
145
249
  4. **项目补充条款**:文件写入位置、测试纪律、访问归属、dev 模式特有限制等,按用户给的条款逐条续写、保留原意。
146
250
 
147
251
  事实一律先查后写:配置名来自 `idea_get_run_configurations`,热重载列来自运行方式,端口读不到就问用户 —— 不猜。
252
+ **只动自己的标记块**:根 `AGENTS.md` 是共享文件(`project-scaffold` 的宪法、项目自己的内容都在里面),标记之外一字不改。
148
253
 
149
- ## 项目命令执行 (IDE 终端)
254
+ ## 项目命令执行 (Run Configuration)
150
255
 
151
- 跑项目相关的命令时,模型使用 **`idea_execute_terminal_command`**,而不是 OpenCode 原生 shell。判据是**白名单**:命令用于本项目
152
- 自身的构建 / 测试 / 运行,且首个可执行文件命中下表,才走 IDE 终端;其余一律走原生 shell。
256
+ 需要**项目环境**的命令(依赖用户在 IDE 里配好的 JDK / Node / Python 版本等),模型使用 **`idea_execute_run_configuration`**
257
+ 执行 —— 走 run configuration,不用原生 shell。
153
258
 
154
- - **Node / 前端**(`package.json`):`node` / `npm` / `npx` / `pnpm` / `yarn` / `vite` / `webpack` / `esbuild` / `tsc` /
155
- `jest` / `vitest`。
156
- - **Java**(`pom.xml` / `build.gradle`):`java` / `javac` / `mvn` / `mvnw` / `gradle` / `gradlew`。
157
- - **Python**(`pyproject.toml` / `requirements.txt`):`python` / `python3` / `pip` / `pip3` / `uv` / `poetry` / `pytest`。
158
- - **Go**(`go.mod`):`go` / `gofmt` / `golangci-lint`。
159
- - 白名单未覆盖的语言暂走原生 shell,遇到后再补进上表。
259
+ - 判据是:这条命令**依赖项目的运行时版本**。是 → run configuration;不是(看文件、git、临时脚本)→ 原生 shell。
260
+ - run configuration 会继承开发时具体配的那套运行时,或者干脆是你那个应用配好的运行时,所以这就是个应用。
261
+ - 配置必须**先在 IDEA 里存在**(项目级 `.run/*.run.xml`,**由用户建**)。没有就请用户建一个,再跑;
160
262
 
161
- 原因:
263
+ > 为什么不再用 IDE 终端:`idea_execute_terminal_command` 之前被当成"自动继承 IDE 项目环境"的通道而保留暴露,但实测
264
+ > **它拿不到项目配好的 JDK / Node / Python 版本**,和原生 shell 没有区别。既然没有优势,就把它从模型可见的工具表里
265
+ > 隐藏掉(`HIDDEN_IDEA_TOOLS`),命令执行的路由改由 run configuration 承担。
162
266
 
163
- - **`executeInShell: true`**(必开):命令在用户真实 shell(`zsh`/`bash`)里执行,**继承 IDE 集成终端的环境** —— 也就是用户在
164
- IDE 里配好的 JDK / Node / Python / Go / Maven / uv 等。原生 shell 未必能拿到同一套版本,尤其是 fnm / SDKMAN / pyenv 这类
165
- "选择写在 shell init 里"的版本管理器,靠几个环境变量复现不出来。
166
- - `timeout`(毫秒)按预期耗时给足;`maxLinesCount` 控制返回行数,超 2000 行会截断。
167
- - `reuseExistingTerminalWindow: true` 复用同一个 IDE 终端窗口,不刷屏。
168
- - 返回 `command_exit_code` + `command_output`;`cd` **不跨调用保留**,多步操作用 `&&` 串在一条命令里。
169
- - 需要 IDE 里开启 **Brave Mode**,否则每条命令都要用户确认一次。
170
-
171
- 引导文本由 `src/ide-guidance.js` 注入(`### 终端` 段),只在 IDE MCP 可用时生效。
267
+ 引导文本由 `src/ide-guidance.js` 注入(`### 命令执行` 段),只在 IDE MCP 可用时生效。
172
268
 
173
269
  ## 前置条件
174
270
 
175
271
  - JetBrains IDE 已开启 MCP 服务 (IDE 设置里的 MCP Server / AI Assistant MCP),版本需 **2026.2+**(提供 Streamable HTTP 端点
176
272
  `/stream`);若关闭,`/open-in-idea` 会立即提示如何重新开启。
177
- - 要读 IDE 终端环境,需要在 IDE 里开启 **Brave Mode**(否则 `execute_terminal_command` 会等确认);MCP 未就绪时通知会同时提醒开启它。
273
+ - IDE 侧需开启 **Brave Mode**(否则需要确认的 MCP 工具调用会停下来等用户确认);MCP 未就绪时通知会同时提醒开启它。
178
274
  - 插件注册给 OpenCode 的 MCP 配置(**只支持 Streamable HTTP**):
179
275
 
180
276
  ```jsonc
@@ -283,8 +379,8 @@ export { default } from "/Users/yutao/Projects/opencode-idea/src/index.js";
283
379
 
284
380
  ## 行为
285
381
 
286
- - **被标记的项目**:启动读回标记后挂上 shell 环境钩子 (环境值待接入后填充)、注册 `idea-run-config` skill;IDE MCP 由
287
- `/open-in-idea` 注册。
382
+ - **被标记的项目**:启动读回标记后挂上 shell 环境钩子 (环境值待接入后填充)、按 IDE 实际提供的工具同步 skill(IDE 还没应答时
383
+ 依赖配套工具的 skill 不注册);IDE MCP 由 `/open-in-idea` 注册。
288
384
  - **未标记的项目**:不改环境、不注册、不注入任何 IDEA 提示 (每请求零开销;setup 时只做一次项目标记读取)。
289
385
  - **手动接入 + 就绪即返回**:`/open-in-idea` 会 `open -a` 拉起 IDEA 并**等 IDE MCP 就绪**(冷启动数十秒,上限 60s);就绪后
290
386
  **先注销旧的 `idea` → 再重新注册**(远程 Streamable HTTP),等 `idea_*` 工具就绪,最后才通知。**每次执行都重建**。命令返回即可用;
@@ -299,7 +395,7 @@ export { default } from "/Users/yutao/Projects/opencode-idea/src/index.js";
299
395
  恢复引导会**明确禁止**调用 `idea_*`(此前复用"重试一次"的文案,反而诱导模型去调一个不在工具表里的工具,得到
300
396
  `No tool named ... available`)。
301
397
  - **`execute.after` 钩子**:见下一条。
302
- 恢复是**每个 Location(项目)各一份**;没有任何定时器,插件在不使用时完全静止。
398
+ 恢复是**每个 Location(项目)各一份**;没有任何定时器,插件在不使用时完全静止。
303
399
  - **失败触发的自动接入(仅被标记项目)**:`tool.execute.after` 钩子监听 `idea_*` 工具报错并**分类**:
304
400
  - IDE MCP 不可用(掉了)→ 重跑 `/open-in-idea` 的接入流程;
305
401
  - IDE 在、但项目没打开(`Unable to determine the target project` / `doesn't correspond to any open project`)→ 让 IDEA 重新打开该项目;
@@ -319,11 +415,18 @@ export { default } from "/Users/yutao/Projects/opencode-idea/src/index.js";
319
415
  - skill 定义的字段名**以 schema 为准**,不要照官方文档:`Skill.Info` 需要 `path` (AbsolutePath),文档里写的 `location`
320
416
  不存在 —— 用错会让 `ctx.skill.transform` 抛 `SchemaError`,而**任何 transform 失败都会禁用整个插件**(0.0.6 就是这样丢了
321
417
  `/open-in-idea`)。同理,`Skill.Info` 的完整字段是 `id` / `name` / `description?` / `autoinvoke?` / `path` / `content`。
322
- - 项目命令走 `idea_execute_terminal_command` + **Brave Mode**;没开 Brave Mode 时每条命令都要用户确认一次。
323
- - 一批用不到的 IDEA MCP 工具被硬编码隐藏 (`src/plugin.js` 的 `HIDDEN_IDEA_TOOLS`,共 31 个):VCS (`idea_git_status` /
418
+ - 需要项目环境的命令走 `idea_execute_run_configuration`(run configuration 要先在 IDEA 里配好),不用原生 shell。
419
+ - 一批用不到的 IDEA MCP 工具被硬编码隐藏 (`src/plugin.js` 的 `HIDDEN_IDEA_TOOLS`,**共 48 个**):VCS (`idea_git_status` /
324
420
  `idea_get_repositories`,版本控制走原生 `git`)、Router 派发工具 (`idea_execute_tool`,未启用 router-only 时冗余)、Debugger
325
- (全部 `idea_xdebug_*`)、Dev Kit MCP、Inspection KTS MCP、解释器环境 MCP、以及数据库的建/改数据源 (数据源由用户在
326
- IDEA 里配置,AI 只读和查询)。**`idea_execute_terminal_command` 不隐藏**:项目命令要在 IDE 环境里跑,模型需要它。
421
+ (全部 `idea_xdebug_*`)、Dev Kit MCP、Inspection KTS MCP、解释器环境 MCP、**IDE 内置终端
422
+ (`idea_execute_terminal_command`:实测不继承项目环境,对原生 shell 没有优势)**、**整个 Database 组**(数据源由用户在
423
+ IDEA 里配置,而 IDE 也不是本插件设想的数据库客户端),以及**有原生对应的文件读写**
424
+ (`idea_search_text` / `idea_search_regex` / `idea_search_file` / `idea_apply_patch` / `idea_create_new_file`
425
+ 分别对应 `grep` / `grep -E` / `glob` / `edit` / `write`)。
426
+
427
+ 实测数字(拿运行中的 IDE MCP 拉 `tools/list`):IDE 暴露 **64** 个 → 隐藏 48 → **模型可见 16 个**,
428
+ 而且这 16 个**恰好等于引导里点名的 16 个** —— 没有"能看见但没人告诉它用途"的残留。
429
+
327
430
  - 探测只确认「MCP 服务是否在监听」;**「当前项目是否已在 IDE 打开」靠一次项目作用域的 MCP 调用判断**
328
431
  (`get_project_modules`,带 `IJ_MCP_SERVER_PROJECT_PATH`):返回模块 = 已打开 → 跳过 `open -a`;报
329
432
  `Unable to determine the target project` = 未打开 → `open -a` 打开。MCP 关闭时会用一次短探测并立即给出设置提示。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-idea",
3
- "version": "0.0.16",
3
+ "version": "0.0.17",
4
4
  "description": "OpenCode plugin that connects to JetBrains IDE MCP servers and prefers IDE tools when the current project is open in the IDE",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -8,7 +8,11 @@
8
8
  "index.js",
9
9
  "src/index.js",
10
10
  "src/plugin.js",
11
+ "src/template.js",
12
+ "src/ide-guidance.template.md",
11
13
  "src/mcp/idea.js",
14
+ "src/mcp/enhance.js",
15
+ "src/mcp/idea-tool-defaults.js",
12
16
  "src/project.js",
13
17
  "src/ide-launcher.js",
14
18
  "src/ide-guidance.js",
@@ -1,93 +1,41 @@
1
1
  ---
2
2
  name: idea-standalone
3
- description: "为项目生成/维护 standalone(经 IDEA 启动、本机进程直跑)模式的纪律 rule,写在项目根 `.opencode/rules/idea-standalone.md`。当用户要做 standalone 规范、要固化「本机跑哪几个应用」「哪些应用热重载、哪些改了必须重启」「AI 能不能启停本机进程」这类项目级纪律时使用。产出必须写清四段:standalone 是什么、standalone 下经 IDEA run configuration 启动哪些应用、逐应用的热重载与重启提示纪律、以及用户补充的其它条款。"
3
+ requires: idea_rerun_run_configuration
4
+ description: "为项目生成/维护 standalone(启动收口只有 IDEA run configuration)模式的纪律,写进**项目根 `AGENTS.md`** 里由 `<!-- idea-standalone:begin -->` 与 `<!-- idea-standalone:end -->` 包裹的标记块。当用户要做 standalone 规范、要固化「本机跑哪几个应用」「哪些应用热重载、哪些改了必须重启」「启停走哪个工具」这类项目级纪律时使用。产物固定三段:standalone 是什么、经 IDEA run configuration 启动哪些应用、逐应用的热重载与重启提示纪律。"
4
5
  ---
5
6
 
6
- # Standalone 模式纪律 rule 生成器
7
-
8
- ## 产出物
9
-
10
- 一份 **项目级 rule**:`<项目根>/.opencode/rules/idea-standalone.md`,把这个项目在 **本机 standalone 模式**下怎么跑、AI
11
- 能做什么不能做什么固化下来。
12
-
13
- - 位置固定:`.opencode/rules/`(项目级规则目录),文件名 `idea-standalone.md`。
14
- - frontmatter 照抄项目里既有 rule 的格式 (`description` + `alwaysApply: true`)。
15
- - 只对这个项目生效; **不写**全局规则目录 (`~/.config/opencode/rules/`)。
16
-
17
- ## 四段结构 (缺一不可)
18
-
19
- ### 第一段:什么是 standalone 模式
20
-
21
- **standalone = 通过 IDEA 启动** —— 应用在本机进程直跑,不容器化、不部署到远端。给"本项目在本机的运行形态"下定义,至少覆盖:
22
-
23
- - **通过 IDEA 启动**:每个应用的启动入口就是 IDEA 的 run configuration(Run / Debug),不是手搓命令行。
24
- - **应用在本机进程直跑**:不容器化、不部署到远端。本机 **不跑**什么也要写明 (例如需要 GPU 的服务、或本机直连的远端数据库)。
25
- - **只启动其中一部分是常态** —— standalone 不要求所有应用都起来,用户可能只开一两个。
26
- - **启停一律由用户在 IDEA 手动完成**:AI 不得代为启停本机进程 —— 包括 `go run` / `pnpm dev` / `uvicorn` /
27
- `python -m ...` 这类起进程、`kill` / `pkill` 业务进程,以及经 `idea_execute_run_configuration` 启停。AI 若判断需要重启,
28
- **先向用户说明并取得明确授权**,绝不自行执行。
29
- - **与部署链纪律互不构成许可**:standalone 的禁令不适用于部署流程,部署链的步骤也不构成"可以动本机进程"的许可 —— 两阶段纪律互相独立。
30
-
31
- ### 第二段:standalone 下启动哪些应用 (必须经 IDEA run configuration)
32
-
33
- 表格,一行一个应用:
34
-
35
- | 应用 | run configuration | 目录 | 端口 | 说明 |
36
- |------|-------------------|------|------|------|
37
-
38
- 要点:
39
-
40
- - `run configuration` 列 **必须是 `idea_get_run_configurations` 里真实存在的名字**(不凭印象写);缺配置时先用
41
- `idea-run-config` skill 建项目级 `.run/*.run.xml`,不要手搓启动命令。
42
- - **启动路径只能是 IDEA run configuration**:不写 `pnpm dev &`、`nohup ... &` 这类后台命令,也不建议用户这么干。
43
- - 端口写清"固定 / 默认 / 被占用即启动失败"; **哪个应用必须先起来**也要写 (例如前端 dev server 的 proxy 指向本机后端)。
44
- - 端口读不到 (配置里没有、也没写在项目配置里)就 **问用户**,不要编。
45
-
46
- ### 第三段:热重载矩阵 + 改代码后要不要提醒重启
47
-
48
- 逐应用写清 **是 / 不是**热重载,以及对应的提醒纪律:
49
-
50
- | 应用 | 热重载 | AI 改代码后 |
51
- |-------------------------------------------------------|--------|-------------------------------------------------------|
52
- | 带 HMR 的 dev server(如 Vite) | 是 | 不提醒重启 |
53
- | 编译型 / 无热重载进程(如 `go run .`、`python -m ...`) | 否 | **必须**在回复里显式点名「需要重启 <应用>」并说明原因 |
54
- | 只能跑在远端、本机起不来的服务 | 不适用 | 本机无法验证,按部署链部署后再验证 |
55
-
56
- 铁律:
57
-
58
- - 非热重载的应用改动后, **不得**在没有提示的情况下宣称"改动完成 / 可以去验证了";重启动作由用户手动做。
59
- - 热重载列必须有依据 (运行方式 → 有没有 HMR),不确定就问用户,不猜。
60
- - `go run .` 这类 **没有热重载**的写法要写进 rule,别让 AI 以为改了代码就自动生效。
61
-
62
- ### 第四段起:项目补充条款
63
-
64
- 用户针对这个项目给的其它纪律, **按顺序续写在后面**(第四段、第五段……),例如:
65
-
66
- - 文件写入位置 (禁止写哪些目录、跑测/调试产物必须落在哪儿)
67
- - 测试纪律 (用例归属、什么时候才允许新增 UT、端到端测试在哪台机器上跑)
68
- - 访问归属 (数据库 / 第三方接口只经哪个工具,不旁路直连)
69
- - dev 模式特有限制 (会真实计费的操作、凭据存储方式等)
70
-
71
- 处理方式:用户给的条款 **逐条保留原意**、编号连续, **不合并不改写语义**。
72
-
73
- ## 流程
74
-
75
- 1. **收集事实 (不猜)**:
76
- - `idea_get_run_configurations` → 真实存在的配置名 (第二段"run configuration"列只能来自这里)。
77
- - `idea_search_file` 传 `q="*.run.xml"` + `paths: [".run"]` → 每个配置实际干什么 (命令 / 脚本 / npm script)。
78
- - `package.json` / `pom.xml` / `go.mod` / `pyproject.toml` / `Cargo.toml` → 项目类型 → 决定第三段的热重载列。
79
- - 端口:从 run configuration 的 option 或项目自身配置里读。
80
- 2. **补齐缺口**:哪些应用进 standalone、哪些配置名对不上、端口与热重载不确定 —— 逐条向用户确认,不编。
81
- 3. **写文件**:首次用 `idea_create_new_file` 写 `.opencode/rules/idea-standalone.md`;后续更新用 `idea_apply_patch`
82
- **定向改**,不整文件重写。
83
- 4. **校验**:第二段表格里每个配置名都能在 `idea_get_run_configurations` 里查到 —— **查不到就是错的**,不许用
84
- "应该生效了"结案。
85
-
86
- ## 铁律 (汇总)
87
-
88
- 1. 四段结构不能缺:standalone 定义 → 应用与 run configuration → 热重载与重启提醒 → 用户补充条款。
89
- 2. 第二段的启动方式 **只能是 IDEA run configuration**;不写手搓启动命令。
90
- 3. AI 不启停本机进程 (含 `idea_execute_run_configuration`);判断需要重启时先取得用户明确授权。
91
- 4. 配置名、端口、热重载三项都必须有依据;不确定就问用户。
92
- 5. 用户补充条款保留原意、编号连续,不合并不改写。
93
- 6. rule 只写项目级 `.opencode/rules/idea-standalone.md`,不写全局规则目录。
7
+ # idea-standalone — standalone 模式纪律
8
+
9
+ ## 定位与管辖文档
10
+
11
+ 本 skill 为项目固化它 **standalone 模式**(启动收口只有 IDEA run configuration)下怎么跑、AI 能做什么不能做什么。
12
+
13
+ - **产物位置固定:项目根 `AGENTS.md`**,作为其中一块,用 `<!-- idea-standalone:begin -->` 与 `<!-- idea-standalone:end -->` 包裹。
14
+ 项目根 `AGENTS.md` 是 AI 在本项目工作时必读的文件,所以写在这里天然"总是生效",不需要额外的规则文件与开关。
15
+ - **标记之内由本 skill 生成与维护;标记之外的项目内容一律不动。**
16
+ - **目标产物的骨架、各段内容约定与写作规范以 [assets/AGENTS.template.md](assets/AGENTS.template.md) 为准**,本 skill 不另行维护
17
+ 章节骨架或逐段规则;生成或更新前必须先读该文件,并严格沿用其中的标题层级、标记与生成提示。
18
+ - 只对这个项目生效; **不写**全局配置目录 (`~/.config/opencode/`),也不另建规则文件。
19
+
20
+ ## 读取
21
+
22
+ - 读 `<项目根>/AGENTS.md`,确认是否已存在 `idea-standalone` 标记块(更新)或需要在文件末尾追加(新增)。
23
+ - **`idea_get_run_configurations` 直接调用,不传任何参数** → 项目里已有的 run configuration 就是**用户已经在 IDEA 里配好的那些**,
24
+ 这一次调用会把它们的名字连同启动细节(程序参数、工作目录、环境变量、是否支持启动时覆盖)一并给出。
25
+ 第二段的 `run configuration` 列、以及端口,**只能来自这里** —— 不需要再去逐个翻 `.run/*.run.xml`,那份列表已经是配置的结果。
26
+ - 项目类型(`package.json` / `pom.xml` / `go.mod` / `pyproject.toml` / `Cargo.toml`)→ 决定第三段的热重载列。
27
+ - 端口:先看上面那份启动细节里有没有;项目自身配置里也读不到就**问用户**,不要编。
28
+ - `run configuration` 列表里缺某个应用:**交给用户** —— 请他在 IDEA 里自己建一个,然后**重新查一次**。不要手搓启动命令,也不要自己写 `.run/*.run.xml`。
29
+ - 补齐缺口:哪些应用进 standalone、哪些配置名对不上、端口与热重载不确定 —— **逐条向用户确认**,不猜。
30
+ - 生成或更新前先读 [assets/AGENTS.template.md](assets/AGENTS.template.md),确认三段与各段生成提示。
31
+
32
+ ## 生成与更新
33
+
34
+ 1. 归属判断:属于三段骨架的内容写进 `idea-standalone` 标记块;不属于的(项目自己的其它纪律)留在标记外,本 skill 不写。
35
+ 2. 先读 [assets/AGENTS.template.md](assets/AGENTS.template.md),按其中的生成提示逐段填充。**`<!-- 生成提示:begin -->…<!-- 生成提示:end -->` 是给生成过程的说明,产物里整块删掉** —— 产物是给 AI 当规则读的,里面不该留指令。
36
+ 同时:**未涉及的表格行与小节整块删掉**,不留空标题、不留 `{...}`。
37
+ 3. **新增**(文件里还没有标记块):在 `AGENTS.md` **末尾追加**标记块,文件既有内容原样保留;文件不存在则创建它。
38
+ 只替换标记内内容、不动标记外 —— 尤其**不要触碰**其他 skill 的标记块(例如 `project-scaffold`)。
39
+ 4. **更新**(已有标记块):只替换 `<!-- idea-standalone:begin -->` 与 `<!-- idea-standalone:end -->` 之间的内容,块外一字不动。
40
+ 5. 用原生 `edit` 做定向替换;文件不存在时才用 `write` 创建。**不要整文件重写**。
41
+ 6. 复读并核对:标记块内逐段与模板一致,块外内容与改动前逐字一致,报告产物清单。
@@ -0,0 +1,66 @@
1
+ <!-- idea-standalone:begin -->
2
+
3
+ # Standalone 模式纪律
4
+
5
+ <!-- 生成提示:begin -->
6
+
7
+ 本块由 `idea-standalone` skill 生成与维护。标记内只写 standalone 模式的纪律;标记之外是项目自己在 `AGENTS.md` 里维护的内容,本 skill 一律不动。
8
+ `{...}` 是待替换的元变量,不留进产物。未涉及的表格行与小节整块删掉,不留空标题。
9
+ **`<!-- 生成提示:… -->` 是给生成过程的说明,产物里整块删掉** —— 产物是给 AI 当规则读的,里面不该留指令。
10
+ <!-- 生成提示:end -->
11
+
12
+ ## 一、什么是 standalone 模式
13
+
14
+ **standalone = 启动收口只有 IDEA run configuration** —— 每个应用的启动入口是 IDEA 的 run configuration(Run / Debug),不是手搓命令行;至于配置内部怎么起(**本机进程 / 容器 / 部署到远端**),由它自己决定,本段不预设。给"本项目怎么起、起在哪"下定义,至少覆盖:
15
+
16
+ - **入口唯一(唯一绝对的约束)**:每个应用的启动入口就是 IDEA 的 run configuration,**不是手搓命令行**。
17
+ - **形态不限**:配置可以起本机进程,也可以是容器(Compose / K8s)、或部署到远端 —— 怎么起是配置的事,**不要假设它一定在本机直跑**。相应地,哪些应用**不在本机跑、或本机起不来**要单独写明(需要 GPU 的服务、本机直连的远端数据库、只能部署后验证的服务),别当成"本机直跑"来验证。
18
+ - **只启动其中一部分是常态** —— 不要求所有应用都起来,用户可能只开一两个。
19
+ - **跑应用只用 `idea_rerun_run_configuration`**:在跑就重启、没在跑就启动 —— 不必分辨"这是启动还是重启",直接 rerun 就完事。
20
+ 常驻进程化 / 服务化的 run configuration 一律走这一条。
21
+ - **不要用 `idea_execute_run_configuration` 跑这些应用**:它是给**命令 / Job 类型**的配置跑的,standalone 的配置是**常驻型**(起来就不退),
22
+ 用它只会起出重复实例。
23
+ - **也不要绕过 IDEA**:不用 `go run` / `pnpm dev` / `uvicorn` / `python -m ...` 这类裸命令起进程,更不要 `kill` / `pkill` 业务进程 ——
24
+ 外部杀掉的进程 IDE 并不知道(Run 窗口仍显示运行中,下次启动就撞端口)。
25
+ - **重启不必先问**:改完代码要重启哪个应用,直接 `idea_rerun_run_configuration` —— 这条链是无人化的,先征求同意只会把重启卡住。
26
+ - 工具列表里没有 `idea_rerun_run_configuration` 时(没装配套插件):交回用户,请他在 IDEA 里手动跑,AI 不动手。
27
+ - **与部署链纪律互不构成许可**:本段管的是 **standalone 跑应用的方式**,不适用于部署流程;反过来,部署链里的步骤也不构成"可以绕开本段、用裸命令在本机起应用"的许可 —— 两阶段纪律互相独立。
28
+
29
+ ## 二、standalone 下启动哪些应用(必须经 IDEA run configuration)
30
+
31
+ <!-- 生成提示:begin -->
32
+
33
+ 一行一个应用,**按操作系统分成两张表**:macOS / Linux 一张,Windows 一张。同一份项目在不同平台上的启动方式往往不一样(解释器路径、脚本、
34
+ 甚至该用哪个配置都不同 —— 比如某个配置的 `INTERPRETER_PATH` 指向 Windows PowerShell,在 macOS 上根本起不来),
35
+ 所以**每张表里的 `run configuration` 必须是该平台上真正存在、真正能跑的那个名字**,不要把 Windows 上能用的配置写进 macOS 那张表。
36
+ 某个应用在某平台上起不来,就在该表里注明(或干脆不列),别让 AI 在一个平台上去跑另一个平台的配置。
37
+
38
+ `run configuration` 列**必须是 `idea_get_run_configurations` 里真实存在的名字**,不凭印象写;缺配置就**交给用户**:
39
+ 请他在 IDEA 里自己建一个,不要手搓启动命令,也不要自己写 `.run/*.run.xml`。端口写清"固定 / 默认 / 被占用即启动失败",读不到就**问用户**,不要编。
40
+ **启动前流程**列:**多数应用留空**。只有确实"得先做点什么才能起"时才写,而且**按顺序写清第 1 步、第 2 步、第 3 步**(例如 `1. 装依赖 2. 构建 3. 起前置服务`);
41
+ 这些事**用文字写出来**(AI 照这段文本自己按序去做)。这类前置事项往往没被写成 run configuration,所以必须在这里说明,否则 AI 直接 rerun 会拿到一个起不来的进程。
42
+ **哪个应用必须先起来**也要写明(例如前端 dev server 的 proxy 指向本机后端)。与本项目无关的应用不写。
43
+ <!-- 生成提示:end -->
44
+
45
+ ### macOS / Linux
46
+
47
+ | 应用 | run configuration | 目录 | 端口 | 启动前流程 | 说明 |
48
+ | ---- | ----------------- | ---- | ---- | ---------- | ---- |
49
+
50
+ ### Windows
51
+
52
+ | 应用 | run configuration | 目录 | 端口 | 启动前流程 | 说明 |
53
+ | ---- | ----------------- | ---- | ---- | ---------- | ---- |
54
+
55
+ ## 三、热重载矩阵:改代码后要不要提醒重启
56
+
57
+ <!-- 生成提示:begin -->
58
+
59
+ 逐应用判定。热重载列必须有依据(运行方式 → 有没有 HMR),不确定就问用户,不猜。非热重载的应用改动后,**不得**在没有提示的情况下宣称
60
+ "改动完成 / 可以去验证了";重启动作由用户手动做。`go run .` 这类**没有热重载**的写法要写进来,别让 AI 以为改了代码就自动生效。
61
+ <!-- 生成提示:end -->
62
+
63
+ | 应用 | 热重载 | AI 改代码后 |
64
+ | ---- | ------ | ----------- |
65
+
66
+ <!-- idea-standalone:end -->