@ibotor/smart-trellis 0.5.22 → 0.5.24

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 (30) hide show
  1. package/README.md +176 -153
  2. package/dist/cli/smart.js +3 -1
  3. package/dist/cli/smart.js.map +1 -1
  4. package/dist/commands/smart-init.d.ts +4 -1
  5. package/dist/commands/smart-init.d.ts.map +1 -1
  6. package/dist/commands/smart-init.js +96 -1
  7. package/dist/commands/smart-init.js.map +1 -1
  8. package/dist/configurators/shared.d.ts.map +1 -1
  9. package/dist/configurators/shared.js +2 -0
  10. package/dist/configurators/shared.js.map +1 -1
  11. package/dist/migrations/manifests/0.5.23.json +9 -0
  12. package/dist/templates/common/bundled-skills/trellis-dev-preflight/SKILL.md +162 -0
  13. package/dist/templates/common/bundled-skills/trellis-quality-review/SKILL.md +82 -0
  14. package/dist/templates/common/bundled-skills/trellis-quality-review/docs/overview.md +331 -0
  15. package/dist/templates/common/bundled-skills/trellis-quality-review/evals/evals.json +50 -0
  16. package/dist/templates/common/bundled-skills/trellis-quality-review/references/copy-fidelity.md +56 -0
  17. package/dist/templates/common/bundled-skills/trellis-quality-review/references/decision-tree.md +102 -0
  18. package/dist/templates/common/bundled-skills/trellis-quality-review/references/formatting-fidelity.md +37 -0
  19. package/dist/templates/common/bundled-skills/trellis-quality-review/references/framework-rules.md +59 -0
  20. package/dist/templates/common/bundled-skills/trellis-quality-review/references/report-format.md +23 -0
  21. package/dist/templates/common/bundled-skills/trellis-quality-review/references/safe-refactor-boundaries.md +158 -0
  22. package/dist/templates/common/bundled-skills/trellis-quality-review/references/scope-control.md +49 -0
  23. package/dist/templates/common/bundled-skills/trellis-quality-review/references/severity.md +105 -0
  24. package/dist/templates/common/bundled-skills/trellis-quality-review/references/small-change-fast-path.md +51 -0
  25. package/dist/templates/common/bundled-skills/trellis-quality-review/references/verification-selection.md +81 -0
  26. package/dist/templates/common/bundled-skills/trellis-quality-review/scripts/diff_scans.sh +145 -0
  27. package/dist/templates/common/bundled-skills/verification-before-completion/SKILL.md +139 -0
  28. package/dist/templates/common/commands/micro-task.md +33 -0
  29. package/dist/templates/trellis/workflow.md +1 -1
  30. package/package.json +1 -1
package/README.md CHANGED
@@ -1,113 +1,208 @@
1
1
  # Smart Trellis
2
2
 
3
- `smart-trellis` 是基于 Trellis 原始能力扩展出来的智能初始化入口。
3
+ `smart-trellis` Trellis 的智能初始化与联调增强包。它保留原 Trellis 的完整项目结构,同时把常见初始化选项收束成更少、更明确的配置入口。
4
4
 
5
- 它不会替换 `trellis init` 的核心逻辑,而是在执行前自动推断项目配置,并把原本需要反复确认的大量问题转换为默认行为。你通常只需要确认要配置哪些 AI 工具,例如 Codex、Cursor、Claude Code 等。
5
+ 这个 npm 包提供三个命令:
6
6
 
7
- ## 新增命令
7
+ ```text
8
+ smart-trellis # 智能初始化入口
9
+ trellis # 原 Trellis CLI
10
+ tl # trellis 的短别名
11
+ ```
12
+
13
+ 当前 npm latest:`0.5.23`。
14
+
15
+ ## 安装
16
+
17
+ ```bash
18
+ npm install -g @ibotor/smart-trellis@latest
19
+ ```
20
+
21
+ 安装后,在项目根目录执行:
8
22
 
9
23
  ```bash
10
24
  smart-trellis init
11
25
  ```
12
26
 
13
- 这个命令等价于一个更省心的 `trellis init`:
27
+ 如果希望临时使用,也可以不全局安装:
14
28
 
15
- - 自动调用原始 Trellis 初始化流程。
16
- - 自动开启非交互初始化,跳过 monorepo 和 spec source 的大量选择。
17
- - 自动检测 monorepo 项目结构。
18
- - 自动检测开发者名称,优先使用 `--user`,其次使用 `git config user.name`,最后使用系统用户名。
19
- - 默认工具为 `codex,cursor`。
20
- - 如果没有传 `--tools`、没有传具体工具参数、也没有传 `--yes`,只会弹出一次工具选择。
29
+ ```bash
30
+ npx -p @ibotor/smart-trellis smart-trellis init
31
+ ```
21
32
 
22
- ## 和 `trellis init` 的区别
33
+ ## smart-trellis 迭代功能
23
34
 
24
- | 命令 | 适合场景 | 交互量 |
25
- | --- | --- | --- |
26
- | `trellis init` | 需要完整手动控制 Trellis 初始化选项 | 会询问 monorepo、每个包的 spec source、工具等 |
27
- | `smart-trellis init` | 希望快速初始化一个项目,并保留 Trellis 原完整结构 | 通常只确认工具,或完全无交互 |
35
+ ### 1. `smart-trellis init`
36
+
37
+ `smart-trellis init` 用来简化 Trellis 初始化配置。它会调用原始 `trellis init`,但提前帮你处理常见默认值,让新项目更快进入可用状态。
28
38
 
29
- `smart-trellis init` 仍然会生成 Trellis 的完整结构,包括 `.trellis/`、`.agents/skills/`、平台配置目录和 `AGENTS.md`。
39
+ 核心能力:
30
40
 
31
- ## 新设备安装
41
+ | 能力 | 说明 | 常用参数 |
42
+ | --- | --- | --- |
43
+ | 简化 Trellis 初始化配置 | 默认启用非交互初始化,自动检测 monorepo、开发者名称和常用 AI 工具 | `--yes`、`--tools`、`--user` |
44
+ | 配置触发方式 | 支持用户主动触发,或让 Trellis 在开发请求中自动判断是否进入任务流程 | `--trellis-activation explicit`、`--trellis-activation auto` |
45
+ | 配置 `.gitignore` | 初始化时可选择是否把 `.trellis/` 和 AI 工具生成目录加入 `.gitignore` | `--gitignore-config`、`--no-gitignore-config` |
32
46
 
33
- 新设备只需要安装一次 npm 包:
47
+ 推荐的新项目初始化方式:
34
48
 
35
49
  ```bash
36
- npm install -g @ibotor/smart-trellis
50
+ smart-trellis init \
51
+ --tools codex,cursor \
52
+ --user <developer-name> \
53
+ --trellis-activation explicit \
54
+ --gitignore-config
37
55
  ```
38
56
 
39
- 安装后,在任意新项目根目录执行:
57
+ 如果希望完全使用默认配置:
40
58
 
41
59
  ```bash
42
- smart-trellis init
60
+ smart-trellis init --yes
43
61
  ```
44
62
 
45
- 如果你暂时不想全局安装,也可以用 npm exec:
63
+ `--yes` 会使用默认工具 `codex,cursor`,并把 `.trellis/`、`.codex/`、`.cursor/`、`.agents/skills/` 等生成目录写入 `.gitignore`。
64
+
65
+ #### 初始化时会生成什么
66
+
67
+ 根据选择的工具不同,生成内容会略有差异。常见输出包括:
68
+
69
+ | 路径 | 作用 |
70
+ | --- | --- |
71
+ | `.trellis/` | Trellis workflow、spec、tasks、workspace、脚本等核心目录 |
72
+ | `.agents/skills/` | 跨工具复用的 Trellis skills |
73
+ | `.codex/` | Codex 专用配置、agents、hooks、skills |
74
+ | `.cursor/` | Cursor 专用 commands、skills、agents、hooks |
75
+ | `.github/` | GitHub Copilot prompts、agents、hooks 等 |
76
+ | `AGENTS.md` | 项目级 AI 助手协作说明 |
77
+
78
+ #### 触发方式配置
79
+
80
+ `smart-trellis init` 支持配置 Trellis 的 activation mode:
81
+
82
+ | 模式 | 行为 | 适合场景 |
83
+ | --- | --- | --- |
84
+ | `explicit` | 用户明确说 `/trellis start`、`$trellis-start`、`走 Trellis` 等才启动任务流程 | 希望普通问答和小改动不被 Trellis 接管 |
85
+ | `auto` | Trellis 根据当前开发请求自动判断是否进入任务流程 | 希望 AI 主动进入 Trellis 工作流 |
86
+
87
+ 示例:
46
88
 
47
89
  ```bash
48
- npm exec --package @ibotor/smart-trellis -- smart-trellis init
90
+ smart-trellis init --tools codex,cursor --trellis-activation explicit
49
91
  ```
50
92
 
51
- 也可以在 CI 或临时环境里使用 `npx`:
93
+ 旧项目可以先更新模板,再在 `.trellis/config.yaml` 里设置:
52
94
 
53
95
  ```bash
54
- npx -p @ibotor/smart-trellis smart-trellis init
96
+ trellis update
97
+ ```
98
+
99
+ ```yaml
100
+ trellis:
101
+ activation_mode: explicit
55
102
  ```
56
103
 
57
- ## 基础用法
104
+ #### `.gitignore` 配置
58
105
 
59
- 进入项目根目录后执行:
106
+ 初始化时可以选择是否把生成目录加入项目 `.gitignore`。以 `codex,cursor` 为例,候选项通常是:
107
+
108
+ ```text
109
+ .trellis/
110
+ .codex/
111
+ .agents/skills/
112
+ .cursor/
113
+ ```
114
+
115
+ 规则:
116
+
117
+ - 交互模式下会显示多选项,默认全选。
118
+ - 没有 `.gitignore` 时会创建。
119
+ - 已有 `.codex` 或 `.codex/` 时不会重复添加 `.codex/`。
120
+ - 已有 `.agents/` 时,不会再重复添加 `.agents/skills/`。
121
+ - 候选目录来自 Trellis 的 AI 工具注册表,不手写平台清单。
122
+
123
+ 脚本模式下直接全选:
60
124
 
61
125
  ```bash
62
- smart-trellis init
126
+ smart-trellis init --tools codex,cursor --gitignore-config
63
127
  ```
64
128
 
65
- 如果你希望完全不出现交互,并使用默认工具 `codex,cursor`:
129
+ 完全不修改 `.gitignore`:
66
130
 
67
131
  ```bash
68
- smart-trellis init --yes
132
+ smart-trellis init --tools codex,cursor --no-gitignore-config
69
133
  ```
70
134
 
71
- 不加 `--yes` 时,初始化过程会提示你选择 AI 工具,并选择 Trellis activation mode:
135
+ 注意:如果把 `.trellis/` 加入 `.gitignore`,Trellis spec、tasks、workspace 等状态默认不会被 Git 跟踪。适合把 Trellis 配置当本地工作区的团队;如果团队希望提交 `.trellis/spec/` 或任务记录,请在多选时取消 `.trellis/`。
72
136
 
73
- - `auto`:默认行为,Trellis 可以为开发/重构需求自动启动任务流程。
74
- - `explicit`:Trellis 只在你明确使用 `/trellis start` / `$trellis-start` / “走 Trellis” 时启动。
137
+ ### 2. 前后端联调
75
138
 
76
- 如果你希望直接指定工具:
139
+ 前后端联调用来让 AI 根据 Apifox 接口链接读取接口详情,并和当前项目里的 API 封装、请求参数、响应字段、代理配置进行对照。
77
140
 
78
- ```bash
79
- smart-trellis init --tools codex,cursor
141
+ 当前真实入口名是 `trellis-joint-debugger`:
142
+
143
+ ```text
144
+ Cursor: /trellis-joint-debugger
145
+ Codex / .agents/skills: $trellis-joint-debugger
146
+ ```
147
+
148
+ 使用场景:
149
+
150
+ - 前端已经有页面或 API wrapper,但接口参数对不上。
151
+ - 后端接口文档在 Apifox,想让 AI 自动读取 method、path、query、body、response。
152
+ - 只想提供 Apifox 链接,让 AI 帮你定位本地代码里该改哪里。
153
+
154
+ 支持的 Apifox 链接格式:
155
+
156
+ ```text
157
+ app.apifox.com/link/project/{projectId}/apis/api-{apiId}
158
+ app.apifox.com/project/{projectId}/apis/api-{apiId}
80
159
  ```
81
160
 
82
- 如果你希望指定开发者名称:
161
+ 第一次使用前,可以保存 Apifox token:
83
162
 
84
163
  ```bash
85
- smart-trellis init --tools codex,cursor --user adong
164
+ python3 ./.trellis/scripts/apifox_token.py save
86
165
  ```
87
166
 
88
- 如果你希望 Trellis 不主动接管普通开发需求,而是必须显式使用 `/trellis start` / `$trellis-start` / “走 Trellis” 才启动:
167
+ 也可以检查当前是否已配置:
89
168
 
90
169
  ```bash
91
- smart-trellis init --tools codex,cursor --trellis-activation explicit
170
+ python3 ./.trellis/scripts/apifox_token.py check
92
171
  ```
93
172
 
94
- 上面的命令大致等价于:
173
+ token 读取优先级:
174
+
175
+ 1. `APIFOX_ACCESS_TOKEN` 环境变量
176
+ 2. `~/.trellis/apifox.env`
177
+ 3. 旧项目内 `.trellis/.runtime/apifox.env`
178
+
179
+ 联调流程会做什么:
180
+
181
+ 1. 从 Apifox 链接解析 `projectId` 和 `apiId`。
182
+ 2. 请求 Apifox Web API 读取接口详情。
183
+ 3. 提取 method、path、query/path/header/body、responses。
184
+ 4. 展开请求体或响应体里的 schema 引用。
185
+ 5. 搜索当前项目里的 API 封装、请求客户端、代理配置和环境配置。
186
+ 6. 对比 Apifox 字段和本地代码字段。
187
+ 7. 如需真实请求业务后端,会根据项目代理和环境配置执行;如果返回 `401` 或缺少登录态,会明确报告。
188
+
189
+ 旧项目先运行:
95
190
 
96
191
  ```bash
97
- trellis init --yes --codex --cursor --user adong
192
+ trellis update
98
193
  ```
99
194
 
100
- ## 工具选择
195
+ ## 常用参数
101
196
 
102
- 支持两种写法。
197
+ ### 指定工具
103
198
 
104
- 第一种,使用 `--tools` 传逗号分隔的工具名:
199
+ 逗号形式:
105
200
 
106
201
  ```bash
107
202
  smart-trellis init --tools codex,cursor,claude
108
203
  ```
109
204
 
110
- 第二种,使用独立工具参数:
205
+ 独立参数形式:
111
206
 
112
207
  ```bash
113
208
  smart-trellis init --codex --cursor --claude
@@ -132,21 +227,25 @@ droid
132
227
  pi
133
228
  ```
134
229
 
135
- ## Registry 用法
230
+ ### 指定开发者名称
136
231
 
137
- `smart-trellis init` 兼容原 `trellis init --registry` 能力,可以从自定义 GitHub、GitLab、Bitbucket 仓库拉取 spec。
232
+ ```bash
233
+ smart-trellis init --tools codex,cursor --user adong
234
+ ```
138
235
 
139
- ### 直接下载 spec 目录
236
+ 如果不传 `--user`,会优先读取 `git config user.name`,再回退到系统用户名。
140
237
 
141
- 仓库目录会被下载到当前项目的 `.trellis/spec/`:
238
+ ### Registry 和模板
239
+
240
+ `smart-trellis init` 兼容原 `trellis init --registry` 能力,可以从自定义 GitHub、GitLab、Bitbucket 仓库拉取 spec。
142
241
 
143
242
  ```bash
144
- smart-trellis init --tools codex,cursor --registry gh:myorg/myrepo/my-team-spec
243
+ smart-trellis init \
244
+ --tools codex,cursor \
245
+ --registry gh:myorg/myrepo/my-team-spec
145
246
  ```
146
247
 
147
- ### Marketplace 模式指定模板
148
-
149
- 如果 registry 目录里有 `index.json`,并且里面定义了多个模板,非交互模式下必须指定 `--template`:
248
+ Marketplace 模式:
150
249
 
151
250
  ```bash
152
251
  smart-trellis init \
@@ -155,9 +254,7 @@ smart-trellis init \
155
254
  --template my-template
156
255
  ```
157
256
 
158
- 如果不指定 `--template`,Trellis 无法在非交互模式下自动判断要使用哪个模板。
159
-
160
- ### 指定分支
257
+ 指定分支:
161
258
 
162
259
  ```bash
163
260
  smart-trellis init \
@@ -165,122 +262,66 @@ smart-trellis init \
165
262
  --registry gh:myorg/myrepo/specs#develop
166
263
  ```
167
264
 
168
- ### GitLab 和 Bitbucket
265
+ GitLab 和 Bitbucket
169
266
 
170
267
  ```bash
171
268
  smart-trellis init --tools codex,cursor --registry gitlab:myorg/myrepo/specs
172
269
  smart-trellis init --tools codex,cursor --registry bitbucket:myorg/myrepo/specs
173
270
  ```
174
271
 
175
- ## 文件覆盖策略
176
-
177
- `smart-trellis init` 默认会以安全方式写入文件。因为它内部会启用非交互模式,所以遇到已经存在的文件时默认跳过,避免覆盖已有配置。
178
-
179
- 如果你要强制覆盖已有文件:
180
-
181
- ```bash
182
- smart-trellis init --tools codex,cursor --force
183
- ```
184
-
185
- 如果你希望明确跳过已有文件:
186
-
187
- ```bash
188
- smart-trellis init --tools codex,cursor --skip-existing
189
- ```
190
-
191
- 使用远程模板时,也可以控制 spec 目录写入方式:
272
+ 远程模板写入策略:
192
273
 
193
274
  ```bash
194
275
  smart-trellis init --tools codex,cursor --registry gh:myorg/myrepo/specs --overwrite
195
276
  smart-trellis init --tools codex,cursor --registry gh:myorg/myrepo/specs --append
196
277
  ```
197
278
 
198
- ## Monorepo 控制
199
-
200
- 默认情况下,`smart-trellis init` 会让 Trellis 自动检测当前项目是否为 monorepo。
279
+ ### 文件覆盖和 Monorepo
201
280
 
202
- 强制启用 monorepo:
281
+ 默认写入策略偏安全:遇到已有文件会跳过,避免覆盖本地配置。
203
282
 
204
283
  ```bash
205
- smart-trellis init --tools codex,cursor --monorepo
284
+ smart-trellis init --tools codex,cursor --force
285
+ smart-trellis init --tools codex,cursor --skip-existing
206
286
  ```
207
287
 
208
- 跳过 monorepo 检测:
288
+ Monorepo 默认自动检测。也可以手动指定:
209
289
 
210
290
  ```bash
291
+ smart-trellis init --tools codex,cursor --monorepo
211
292
  smart-trellis init --tools codex,cursor --no-monorepo
212
293
  ```
213
294
 
214
- ## 初始化后会生成什么
215
-
216
- 根据选择的工具不同,生成内容会略有差异。常见输出包括:
217
-
218
- - `.trellis/`:Trellis workflow、spec、tasks、workspace 等核心目录。
219
- - `.agents/skills/`:跨工具复用的 Trellis skills。
220
- - `.codex/`:Codex 专用配置、skills、agents、hooks。
221
- - `.cursor/`:Cursor 专用配置、commands、skills、agents、hooks。
222
- - `AGENTS.md`:项目级 AI 助手协作说明。
223
-
224
- 所以,`smart-trellis init` 的目标不是只生成一个轻量配置,而是用更少确认步骤生成原 Trellis 初始化应有的完整结果。
225
-
226
- ## Apifox 前后端联调入口
227
-
228
- 初始化 Cursor / Codex 等平台后,会生成 `trellis-joint-debugger` 入口,用于根据 Apifox 接口链接自动解析接口详情并辅助前后端联调。
295
+ ## 更新已有项目
229
296
 
230
- 常见触发方式:
297
+ 已初始化项目通常只需要:
231
298
 
232
- - Cursor:`/trellis-joint-debugger`
233
- - Codex / `.agents/skills`:`$trellis-joint-debugger`
234
-
235
- 当用户提供以下 Apifox 链接,并提到“联调”“接口”“参数”“详情”“完成它”等开发意图时,入口会优先走 Apifox Web API,而不是默认打开浏览器页面:
236
-
237
- ```text
238
- app.apifox.com/link/project/{projectId}/apis/api-{apiId}
239
- app.apifox.com/project/{projectId}/apis/api-{apiId}
299
+ ```bash
300
+ npm install -g @ibotor/smart-trellis@latest
301
+ trellis update
240
302
  ```
241
303
 
242
- 第一次使用前,需要配置 Apifox access token:
304
+ 如果要使用 Apifox 联调能力,再配置一次用户级 token:
243
305
 
244
306
  ```bash
245
- python3 ./.trellis/scripts/apifox_token.py check
246
307
  python3 ./.trellis/scripts/apifox_token.py save
247
308
  ```
248
309
 
249
- `save` 会使用隐藏输入,并把 token 保存到用户级配置:
250
-
251
- ```text
252
- ~/.trellis/apifox.env
253
- ```
254
-
255
- 因此同一台机器上只需要配置一次,后续所有 Trellis 项目都可以复用。运行时读取优先级为:
256
-
257
- 1. `APIFOX_ACCESS_TOKEN` 环境变量
258
- 2. `~/.trellis/apifox.env`
259
- 3. 旧项目内 `.trellis/.runtime/apifox.env`(仅兼容读取)
260
-
261
- token 只用于请求 header,不会被命令打印。接口详情会通过:
262
-
263
- ```text
264
- GET https://api.apifox.com/api/v1/projects/{projectId}/http-apis/{apiId}
265
- ```
266
-
267
- 如请求体或响应中出现 `$ref: #/definitions/{schemaId}`,会继续根据接口详情里的 `moduleId` 请求 data-schemas 并解析入参/出参字段。随后 Trellis 会将 method、path、入参、出参与当前项目中的 API 封装核对;如果要联调真实后端,再根据项目代理和环境配置请求业务后端。若缺少业务登录态,应明确报告 `401` / 未登录,不猜测数据。
268
-
269
310
  ## 本地开发验证
270
311
 
271
- 在本仓库开发时,可以先构建 CLI:
312
+ 在本仓库开发时,先构建 CLI:
272
313
 
273
314
  ```bash
274
315
  pnpm --filter @ibotor/smart-trellis build
275
316
  ```
276
317
 
277
- 然后直接用本地 bin 测试:
318
+ 直接用本地 bin 测试:
278
319
 
279
320
  ```bash
280
321
  node packages/cli/bin/smart-trellis.js init --tools codex,cursor --user adong
281
322
  ```
282
323
 
283
- 也可以在一个临时项目里验证:
324
+ 也可以在临时项目里验证:
284
325
 
285
326
  ```bash
286
327
  mkdir /tmp/smart-trellis-demo
@@ -289,29 +330,11 @@ echo '{"name":"smart-trellis-demo"}' > package.json
289
330
  node /path/to/smart-trellis/packages/cli/bin/smart-trellis.js init --tools codex,cursor --user adong
290
331
  ```
291
332
 
292
- ## 推荐团队用法
293
-
294
- 团队成员在新项目里只需要执行:
295
-
296
- ```bash
297
- smart-trellis init --tools codex,cursor --user <developer-name>
298
- ```
299
-
300
- 如果你维护了团队统一 spec registry,则推荐:
301
-
302
- ```bash
303
- smart-trellis init \
304
- --tools codex,cursor \
305
- --user <developer-name> \
306
- --registry gh:<org>/<repo>/<spec-path>
307
- ```
308
-
309
- 如果 registry 是 marketplace:
333
+ 发布前建议至少运行:
310
334
 
311
335
  ```bash
312
- smart-trellis init \
313
- --tools codex,cursor \
314
- --user <developer-name> \
315
- --registry gh:<org>/<repo>/<marketplace-path> \
316
- --template <template-id>
336
+ pnpm --filter @ibotor/smart-trellis test
337
+ pnpm --filter @ibotor/smart-trellis build
338
+ pnpm --filter @ibotor/smart-trellis lint
339
+ pnpm --filter @ibotor/smart-trellis typecheck
317
340
  ```
package/dist/cli/smart.js CHANGED
@@ -22,7 +22,9 @@ const initCommand = program
22
22
  .option("--overwrite", "Overwrite existing spec directory when using template")
23
23
  .option("--append", "Only add missing files when using template")
24
24
  .option("-r, --registry <source>", "Use a custom template registry (e.g., gh:myorg/myrepo/specs)")
25
- .option("--trellis-activation <mode>", "Set no-task Trellis activation mode: auto or explicit");
25
+ .option("--trellis-activation <mode>", "Set no-task Trellis activation mode: auto or explicit")
26
+ .option("--gitignore-config", "Add generated config directories to .gitignore without prompting")
27
+ .option("--no-gitignore-config", "Do not add generated config directories to .gitignore");
26
28
  for (const tool of getInitToolChoices()) {
27
29
  initCommand.option(`--${tool.key}`, `Include ${tool.name}`);
28
30
  }
@@ -1 +1 @@
1
- {"version":3,"file":"smart.js","sourceRoot":"","sources":["../../src/cli/smart.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,SAAS,EAAyB,MAAM,2BAA2B,CAAC;AAC7E,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAElD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,eAAe,CAAC;KACrB,WAAW,CAAC,wCAAwC,CAAC;KACrD,OAAO,CAAC,OAAO,EAAE,eAAe,EAAE,2BAA2B,CAAC,CAAC;AAElE,MAAM,WAAW,GAAG,OAAO;KACxB,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,gEAAgE,CAAC;KAC7E,MAAM,CAAC,iBAAiB,EAAE,6CAA6C,CAAC;KACxE,MAAM,CAAC,WAAW,EAAE,6CAA6C,CAAC;KAClE,MAAM,CACL,mBAAmB,EACnB,mDAAmD,CACpD;KACA,MAAM,CAAC,aAAa,EAAE,yCAAyC,CAAC;KAChE,MAAM,CAAC,qBAAqB,EAAE,oCAAoC,CAAC;KACnE,MAAM,CAAC,YAAY,EAAE,qBAAqB,CAAC;KAC3C,MAAM,CAAC,eAAe,EAAE,yBAAyB,CAAC;KAClD,MAAM,CACL,uBAAuB,EACvB,uDAAuD,CACxD;KACA,MAAM,CACL,aAAa,EACb,uDAAuD,CACxD;KACA,MAAM,CAAC,UAAU,EAAE,4CAA4C,CAAC;KAChE,MAAM,CACL,yBAAyB,EACzB,8DAA8D,CAC/D;KACA,MAAM,CACL,6BAA6B,EAC7B,uDAAuD,CACxD,CAAC;AAEJ,KAAK,MAAM,IAAI,IAAI,kBAAkB,EAAE,EAAE,CAAC;IACxC,WAAW,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,GAAG,EAAE,EAAE,WAAW,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;AAC9D,CAAC;AAED,WAAW,CAAC,MAAM,CAAC,KAAK,EAAE,OAAyB,EAAE,EAAE;IACrD,IAAI,CAAC;QACH,MAAM,SAAS,CAAC,OAAO,CAAC,CAAC;IAC3B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CACX,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,EACnB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAC/C,CAAC;QACF,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;YACnD,OAAO,CAAC,KAAK,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAC9D,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,OAAO,CAAC,KAAK,EAAE,CAAC"}
1
+ {"version":3,"file":"smart.js","sourceRoot":"","sources":["../../src/cli/smart.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,SAAS,EAAyB,MAAM,2BAA2B,CAAC;AAC7E,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAElD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,eAAe,CAAC;KACrB,WAAW,CAAC,wCAAwC,CAAC;KACrD,OAAO,CAAC,OAAO,EAAE,eAAe,EAAE,2BAA2B,CAAC,CAAC;AAElE,MAAM,WAAW,GAAG,OAAO;KACxB,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,gEAAgE,CAAC;KAC7E,MAAM,CAAC,iBAAiB,EAAE,6CAA6C,CAAC;KACxE,MAAM,CAAC,WAAW,EAAE,6CAA6C,CAAC;KAClE,MAAM,CACL,mBAAmB,EACnB,mDAAmD,CACpD;KACA,MAAM,CAAC,aAAa,EAAE,yCAAyC,CAAC;KAChE,MAAM,CAAC,qBAAqB,EAAE,oCAAoC,CAAC;KACnE,MAAM,CAAC,YAAY,EAAE,qBAAqB,CAAC;KAC3C,MAAM,CAAC,eAAe,EAAE,yBAAyB,CAAC;KAClD,MAAM,CACL,uBAAuB,EACvB,uDAAuD,CACxD;KACA,MAAM,CACL,aAAa,EACb,uDAAuD,CACxD;KACA,MAAM,CAAC,UAAU,EAAE,4CAA4C,CAAC;KAChE,MAAM,CACL,yBAAyB,EACzB,8DAA8D,CAC/D;KACA,MAAM,CACL,6BAA6B,EAC7B,uDAAuD,CACxD;KACA,MAAM,CACL,oBAAoB,EACpB,kEAAkE,CACnE;KACA,MAAM,CACL,uBAAuB,EACvB,uDAAuD,CACxD,CAAC;AAEJ,KAAK,MAAM,IAAI,IAAI,kBAAkB,EAAE,EAAE,CAAC;IACxC,WAAW,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,GAAG,EAAE,EAAE,WAAW,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;AAC9D,CAAC;AAED,WAAW,CAAC,MAAM,CAAC,KAAK,EAAE,OAAyB,EAAE,EAAE;IACrD,IAAI,CAAC;QACH,MAAM,SAAS,CAAC,OAAO,CAAC,CAAC;IAC3B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CACX,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,EACnB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAC/C,CAAC;QACF,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;YACnD,OAAO,CAAC,KAAK,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAC9D,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,OAAO,CAAC,KAAK,EAAE,CAAC"}
@@ -1,10 +1,11 @@
1
1
  import { type InitOptions } from "./init.js";
2
- import type { CliFlag } from "../types/ai-tools.js";
2
+ import { type CliFlag } from "../types/ai-tools.js";
3
3
  type SmartToolFlagOptions = Partial<Record<CliFlag, boolean>>;
4
4
  export type TrellisActivationMode = "auto" | "explicit";
5
5
  export type SmartInitOptions = SmartToolFlagOptions & {
6
6
  append?: boolean;
7
7
  force?: boolean;
8
+ gitignoreConfig?: boolean;
8
9
  monorepo?: boolean;
9
10
  overwrite?: boolean;
10
11
  registry?: string;
@@ -19,6 +20,8 @@ export declare const SMART_DEFAULT_TOOLS: CliFlag[];
19
20
  export declare function parseSmartToolsOption(value: string): CliFlag[];
20
21
  export declare function parseSmartTrellisActivationMode(value: string | undefined): TrellisActivationMode | undefined;
21
22
  export declare function patchTrellisActivationConfig(content: string, mode: TrellisActivationMode): string;
23
+ export declare function getSmartGitignoreCandidates(tools: CliFlag[]): string[];
24
+ export declare function patchGitignoreConfigDirs(content: string, entries: string[]): string;
22
25
  export declare function createSmartInitOptions(options: SmartInitOptions, tools: CliFlag[], detectedUser?: string): InitOptions;
23
26
  export declare function detectDeveloperName(cwd?: string): string | undefined;
24
27
  export declare function smartInit(options: SmartInitOptions): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"smart-init.d.ts","sourceRoot":"","sources":["../../src/commands/smart-init.ts"],"names":[],"mappings":"AAMA,OAAO,EAAQ,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAEpD,KAAK,oBAAoB,GAAG,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;AAC9D,MAAM,MAAM,qBAAqB,GAAG,MAAM,GAAG,UAAU,CAAC;AAExD,MAAM,MAAM,gBAAgB,GAAG,oBAAoB,GAAG;IACpD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,OAAO,CAAC;CACf,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,OAAO,EAAwB,CAAC;AAgBlE,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,EAAE,CAkB9D;AAED,wBAAgB,+BAA+B,CAC7C,KAAK,EAAE,MAAM,GAAG,SAAS,GACxB,qBAAqB,GAAG,SAAS,CAWnC;AAED,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,qBAAqB,GAC1B,MAAM,CAwCR;AAmDD,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,gBAAgB,EACzB,KAAK,EAAE,OAAO,EAAE,EAChB,YAAY,CAAC,EAAE,MAAM,GACpB,WAAW,CA6Bb;AAED,wBAAgB,mBAAmB,CACjC,GAAG,GAAE,MAAsB,GAC1B,MAAM,GAAG,SAAS,CAoBpB;AAuED,wBAAsB,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAWxE"}
1
+ {"version":3,"file":"smart-init.d.ts","sourceRoot":"","sources":["../../src/commands/smart-init.ts"],"names":[],"mappings":"AASA,OAAO,EAAQ,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAmB,KAAK,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAErE,KAAK,oBAAoB,GAAG,OAAO,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;AAC9D,MAAM,MAAM,qBAAqB,GAAG,MAAM,GAAG,UAAU,CAAC;AAExD,MAAM,MAAM,gBAAgB,GAAG,oBAAoB,GAAG;IACpD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,OAAO,CAAC;CACf,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,OAAO,EAAwB,CAAC;AAiBlE,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,EAAE,CAkB9D;AAED,wBAAgB,+BAA+B,CAC7C,KAAK,EAAE,MAAM,GAAG,SAAS,GACxB,qBAAqB,GAAG,SAAS,CAWnC;AAED,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,qBAAqB,GAC1B,MAAM,CAwCR;AA2CD,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,MAAM,EAAE,CAUtE;AAED,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EAAE,GAChB,MAAM,CAmBR;AAiED,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,gBAAgB,EACzB,KAAK,EAAE,OAAO,EAAE,EAChB,YAAY,CAAC,EAAE,MAAM,GACpB,WAAW,CA6Bb;AAED,wBAAgB,mBAAmB,CACjC,GAAG,GAAE,MAAsB,GAC1B,MAAM,GAAG,SAAS,CAoBpB;AAmGD,wBAAsB,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAgBxE"}
@@ -3,9 +3,11 @@ import fs from "node:fs";
3
3
  import os from "node:os";
4
4
  import path from "node:path";
5
5
  import inquirer from "inquirer";
6
- import { getInitToolChoices } from "../configurators/index.js";
6
+ import { getInitToolChoices, resolveCliFlag, } from "../configurators/index.js";
7
7
  import { init } from "./init.js";
8
+ import { getManagedPaths } from "../types/ai-tools.js";
8
9
  export const SMART_DEFAULT_TOOLS = ["codex", "cursor"];
10
+ const TRELLIS_GITIGNORE_ENTRY = ".trellis/";
9
11
  function supportedToolFlags() {
10
12
  return getInitToolChoices().map((tool) => tool.key);
11
13
  }
@@ -71,6 +73,75 @@ export function patchTrellisActivationConfig(content, mode) {
71
73
  const separator = content.endsWith("\n") ? "\n" : "\n\n";
72
74
  return `${content}${separator}trellis:\n activation_mode: ${mode}\n`;
73
75
  }
76
+ function normalizeGitignoreDirEntry(value) {
77
+ const trimmed = value.trim();
78
+ if (!trimmed || trimmed.startsWith("#") || trimmed.startsWith("!")) {
79
+ return undefined;
80
+ }
81
+ const normalized = trimmed
82
+ .replace(/\\/g, "/")
83
+ .replace(/^\/+/, "")
84
+ .replace(/\/+$/g, "");
85
+ if (!normalized) {
86
+ return undefined;
87
+ }
88
+ return `${normalized}/`;
89
+ }
90
+ function uniqueDirEntries(entries) {
91
+ const seen = new Set();
92
+ const unique = [];
93
+ for (const entry of entries) {
94
+ const normalized = normalizeGitignoreDirEntry(entry);
95
+ if (!normalized || seen.has(normalized)) {
96
+ continue;
97
+ }
98
+ seen.add(normalized);
99
+ unique.push(normalized);
100
+ }
101
+ return unique;
102
+ }
103
+ function gitignoreEntryCoversCandidate(gitignoreEntry, candidate) {
104
+ const normalized = normalizeGitignoreDirEntry(gitignoreEntry);
105
+ return (normalized === candidate ||
106
+ Boolean(normalized && candidate.startsWith(normalized)));
107
+ }
108
+ export function getSmartGitignoreCandidates(tools) {
109
+ const entries = [TRELLIS_GITIGNORE_ENTRY];
110
+ for (const tool of tools) {
111
+ const platformId = resolveCliFlag(tool);
112
+ if (!platformId) {
113
+ throw new Error(`Unknown tool "${tool}".`);
114
+ }
115
+ entries.push(...getManagedPaths(platformId));
116
+ }
117
+ return uniqueDirEntries(entries);
118
+ }
119
+ export function patchGitignoreConfigDirs(content, entries) {
120
+ const candidates = uniqueDirEntries(entries);
121
+ if (candidates.length === 0) {
122
+ return content;
123
+ }
124
+ const existingLines = content.split(/\r?\n/);
125
+ const missing = candidates.filter((candidate) => !existingLines.some((line) => gitignoreEntryCoversCandidate(line, candidate)));
126
+ if (missing.length === 0) {
127
+ return content;
128
+ }
129
+ const prefix = content && !content.endsWith("\n") ? `${content}\n` : content;
130
+ return `${prefix}${missing.join("\n")}\n`;
131
+ }
132
+ function applyGitignoreConfigDirs(cwd, entries) {
133
+ if (entries.length === 0) {
134
+ return;
135
+ }
136
+ const gitignorePath = path.join(cwd, ".gitignore");
137
+ const content = fs.existsSync(gitignorePath)
138
+ ? fs.readFileSync(gitignorePath, "utf-8")
139
+ : "";
140
+ const patched = patchGitignoreConfigDirs(content, entries);
141
+ if (patched !== content) {
142
+ fs.writeFileSync(gitignorePath, patched, "utf-8");
143
+ }
144
+ }
74
145
  function applyTrellisActivationConfig(cwd, mode) {
75
146
  if (!mode) {
76
147
  return;
@@ -169,6 +240,28 @@ async function resolveSmartTools(options) {
169
240
  ]);
170
241
  return answers.tools;
171
242
  }
243
+ async function resolveSmartGitignoreConfigDirs(options, tools) {
244
+ const candidates = getSmartGitignoreCandidates(tools);
245
+ if (options.gitignoreConfig === false || candidates.length === 0) {
246
+ return [];
247
+ }
248
+ if (options.gitignoreConfig === true || options.yes) {
249
+ return candidates;
250
+ }
251
+ const answers = await inquirer.prompt([
252
+ {
253
+ type: "checkbox",
254
+ name: "gitignoreConfigDirs",
255
+ message: "Select generated config directories to add to .gitignore:",
256
+ choices: candidates.map((entry) => ({
257
+ checked: true,
258
+ name: entry,
259
+ value: entry,
260
+ })),
261
+ },
262
+ ]);
263
+ return answers.gitignoreConfigDirs ?? [];
264
+ }
172
265
  async function resolveSmartTrellisActivation(options) {
173
266
  const parsed = parseSmartTrellisActivationMode(options.trellisActivation);
174
267
  const hasExplicitTools = !!options.tools ||
@@ -198,9 +291,11 @@ async function resolveSmartTrellisActivation(options) {
198
291
  }
199
292
  export async function smartInit(options) {
200
293
  const tools = await resolveSmartTools(options);
294
+ const gitignoreConfigDirs = await resolveSmartGitignoreConfigDirs(options, tools);
201
295
  const activationMode = await resolveSmartTrellisActivation(options);
202
296
  const initOptions = createSmartInitOptions(options, tools, detectDeveloperName());
203
297
  await init(initOptions);
204
298
  applyTrellisActivationConfig(process.cwd(), activationMode);
299
+ applyGitignoreConfigDirs(process.cwd(), gitignoreConfigDirs);
205
300
  }
206
301
  //# sourceMappingURL=smart-init.js.map