@blxzer/cursor-trellis 0.1.0 → 0.1.2

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 (285) hide show
  1. package/README.md +124 -5
  2. package/README.zh-CN.md +170 -0
  3. package/dist/cli/index.d.ts.map +1 -1
  4. package/dist/cli/index.js +1 -33
  5. package/dist/cli/index.js.map +1 -1
  6. package/dist/commands/init.d.ts +0 -13
  7. package/dist/commands/init.d.ts.map +1 -1
  8. package/dist/commands/init.js +7 -14
  9. package/dist/commands/init.js.map +1 -1
  10. package/dist/commands/uninstall.d.ts.map +1 -1
  11. package/dist/commands/uninstall.js +3 -32
  12. package/dist/commands/uninstall.js.map +1 -1
  13. package/dist/commands/update.d.ts.map +1 -1
  14. package/dist/commands/update.js +7 -84
  15. package/dist/commands/update.js.map +1 -1
  16. package/dist/configurators/index.d.ts +7 -8
  17. package/dist/configurators/index.d.ts.map +1 -1
  18. package/dist/configurators/index.js +11 -236
  19. package/dist/configurators/index.js.map +1 -1
  20. package/dist/configurators/workflow.d.ts.map +1 -1
  21. package/dist/configurators/workflow.js +5 -1
  22. package/dist/configurators/workflow.js.map +1 -1
  23. package/dist/migrations/manifests/0.1.1.json +9 -0
  24. package/dist/migrations/manifests/0.1.2.json +9 -0
  25. package/dist/templates/common/bundled-skills/smart-search-cli/SKILL.md +3 -3
  26. package/dist/templates/common/bundled-skills/trellis-meta/SKILL.md +4 -2
  27. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-agents.md +8 -15
  28. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-hooks.md +7 -7
  29. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/change-skills-or-commands.md +18 -21
  30. package/dist/templates/common/bundled-skills/trellis-meta/references/customize-local/overview.md +2 -2
  31. package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/generated-files.md +10 -7
  32. package/dist/templates/common/bundled-skills/trellis-meta/references/local-architecture/overview.md +4 -4
  33. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/agents.md +20 -31
  34. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/hooks-and-settings.md +20 -31
  35. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/overview.md +24 -40
  36. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/platform-map.md +28 -59
  37. package/dist/templates/common/bundled-skills/trellis-meta/references/platform-files/skills-and-commands.md +12 -28
  38. package/dist/templates/common/bundled-skills/trellis-skill-creator/references/trellis-skill-locations.md +2 -2
  39. package/dist/templates/cursor/hooks.json +6 -0
  40. package/dist/templates/cursor/rules/retrieval-routing.mdc +57 -0
  41. package/dist/templates/extract.d.ts +0 -14
  42. package/dist/templates/extract.d.ts.map +1 -1
  43. package/dist/templates/extract.js +0 -34
  44. package/dist/templates/extract.js.map +1 -1
  45. package/dist/templates/markdown/agents.md +2 -6
  46. package/dist/templates/markdown/index.d.ts +1 -0
  47. package/dist/templates/markdown/index.d.ts.map +1 -1
  48. package/dist/templates/markdown/index.js +1 -0
  49. package/dist/templates/markdown/index.js.map +1 -1
  50. package/dist/templates/markdown/prompts/run-semantic-slice-12.md.txt +41 -0
  51. package/dist/templates/markdown/spec/guides/code-reuse-thinking-guide.md.txt +14 -14
  52. package/dist/templates/markdown/spec/guides/cross-layer-thinking-guide.md.txt +8 -20
  53. package/dist/templates/markdown/spec/guides/cross-platform-thinking-guide.md.txt +15 -14
  54. package/dist/templates/markdown/spec/guides/cursor-context-injection-guide.md.txt +4 -2
  55. package/dist/templates/markdown/spec/guides/cursor-semantic-compliance.md.txt +49 -0
  56. package/dist/templates/markdown/spec/guides/cursor-subagent-policy.md.txt +18 -5
  57. package/dist/templates/markdown/spec/guides/retrieval-daily-guide.md.txt +68 -20
  58. package/dist/templates/shared-hooks/index.d.ts +1 -1
  59. package/dist/templates/shared-hooks/index.d.ts.map +1 -1
  60. package/dist/templates/shared-hooks/index.js +1 -0
  61. package/dist/templates/shared-hooks/index.js.map +1 -1
  62. package/dist/templates/shared-hooks/inject-retrieval-plan.py +163 -0
  63. package/dist/templates/shared-hooks/inject-subagent-context.py +31 -567
  64. package/dist/templates/shared-hooks/research-end-retrieval-pack.py +2 -11
  65. package/dist/templates/trellis/index.d.ts +12 -0
  66. package/dist/templates/trellis/index.d.ts.map +1 -1
  67. package/dist/templates/trellis/index.js +24 -0
  68. package/dist/templates/trellis/index.js.map +1 -1
  69. package/dist/templates/trellis/scripts/aggregate_retrieval_telemetry.py +342 -0
  70. package/dist/templates/trellis/scripts/batch_plan_envelope.py +105 -0
  71. package/dist/templates/trellis/scripts/codegraph_session_smoke.py +76 -0
  72. package/dist/templates/trellis/scripts/common/active_task.py +116 -147
  73. package/dist/templates/trellis/scripts/common/cli_adapter.py +34 -710
  74. package/dist/templates/trellis/scripts/common/codebase_retrieval_router.py +49 -106
  75. package/dist/templates/trellis/scripts/common/git_context.py +17 -2
  76. package/dist/templates/trellis/scripts/common/project_file_stats.py +91 -0
  77. package/dist/templates/trellis/scripts/common/retrieval_adapter_metadata.py +9 -11
  78. package/dist/templates/trellis/scripts/common/retrieval_agent_instructions.py +313 -0
  79. package/dist/templates/trellis/scripts/common/retrieval_pack.py +0 -6
  80. package/dist/templates/trellis/scripts/common/retrieval_pack_context.py +0 -4
  81. package/dist/templates/trellis/scripts/common/retrieval_plan_gate.py +76 -0
  82. package/dist/templates/trellis/scripts/common/retrieval_result_ranking.py +253 -0
  83. package/dist/templates/trellis/scripts/common/retrieval_tool_classification.py +157 -0
  84. package/dist/templates/trellis/scripts/common/semantic_plan_gate.py +52 -0
  85. package/dist/templates/trellis/scripts/common/subagent_dispatch.py +527 -0
  86. package/dist/templates/trellis/scripts/common/task_store.py +32 -0
  87. package/dist/templates/trellis/scripts/common/workflow_phase.py +3 -24
  88. package/dist/templates/trellis/scripts/rank_retrieval_candidates.py +80 -0
  89. package/dist/templates/trellis/scripts/route_codebase_retrieval.py +38 -11
  90. package/dist/templates/trellis/scripts/score_evidence.py +112 -0
  91. package/dist/templates/trellis/scripts/task.py +26 -0
  92. package/dist/templates/trellis/workflow.md +844 -960
  93. package/dist/types/ai-tools.d.ts +13 -16
  94. package/dist/types/ai-tools.d.ts.map +1 -1
  95. package/dist/types/ai-tools.js +5 -238
  96. package/dist/types/ai-tools.js.map +1 -1
  97. package/dist/utils/codebase-retrieval-router.d.ts +1 -8
  98. package/dist/utils/codebase-retrieval-router.d.ts.map +1 -1
  99. package/dist/utils/codebase-retrieval-router.js +39 -180
  100. package/dist/utils/codebase-retrieval-router.js.map +1 -1
  101. package/dist/utils/project-capabilities.d.ts.map +1 -1
  102. package/dist/utils/project-capabilities.js +10 -24
  103. package/dist/utils/project-capabilities.js.map +1 -1
  104. package/dist/utils/retrieval-agent-instructions.d.ts +14 -0
  105. package/dist/utils/retrieval-agent-instructions.d.ts.map +1 -0
  106. package/dist/utils/retrieval-agent-instructions.js +221 -0
  107. package/dist/utils/retrieval-agent-instructions.js.map +1 -0
  108. package/dist/utils/retrieval-execution-telemetry.d.ts +43 -85
  109. package/dist/utils/retrieval-execution-telemetry.d.ts.map +1 -1
  110. package/dist/utils/retrieval-execution-telemetry.js +289 -22
  111. package/dist/utils/retrieval-execution-telemetry.js.map +1 -1
  112. package/dist/utils/retrieval-result-ranking.js +1 -1
  113. package/dist/utils/retrieval-result-ranking.js.map +1 -1
  114. package/dist/utils/retrieval-tool-classification.d.ts +32 -0
  115. package/dist/utils/retrieval-tool-classification.d.ts.map +1 -0
  116. package/dist/utils/retrieval-tool-classification.js +113 -0
  117. package/dist/utils/retrieval-tool-classification.js.map +1 -0
  118. package/dist/utils/uninstall-scrubbers.d.ts +0 -36
  119. package/dist/utils/uninstall-scrubbers.d.ts.map +1 -1
  120. package/dist/utils/uninstall-scrubbers.js +0 -184
  121. package/dist/utils/uninstall-scrubbers.js.map +1 -1
  122. package/package.json +4 -2
  123. package/dist/commands/mem.d.ts +0 -30
  124. package/dist/commands/mem.d.ts.map +0 -1
  125. package/dist/commands/mem.js +0 -424
  126. package/dist/commands/mem.js.map +0 -1
  127. package/dist/configurators/antigravity.d.ts +0 -7
  128. package/dist/configurators/antigravity.d.ts.map +0 -1
  129. package/dist/configurators/antigravity.js +0 -19
  130. package/dist/configurators/antigravity.js.map +0 -1
  131. package/dist/configurators/claude.d.ts +0 -9
  132. package/dist/configurators/claude.d.ts.map +0 -1
  133. package/dist/configurators/claude.js +0 -72
  134. package/dist/configurators/claude.js.map +0 -1
  135. package/dist/configurators/codebuddy.d.ts +0 -10
  136. package/dist/configurators/codebuddy.d.ts.map +0 -1
  137. package/dist/configurators/codebuddy.js +0 -30
  138. package/dist/configurators/codebuddy.js.map +0 -1
  139. package/dist/configurators/codex.d.ts +0 -8
  140. package/dist/configurators/codex.d.ts.map +0 -1
  141. package/dist/configurators/codex.js +0 -87
  142. package/dist/configurators/codex.js.map +0 -1
  143. package/dist/configurators/copilot.d.ts +0 -10
  144. package/dist/configurators/copilot.d.ts.map +0 -1
  145. package/dist/configurators/copilot.js +0 -51
  146. package/dist/configurators/copilot.js.map +0 -1
  147. package/dist/configurators/droid.d.ts +0 -10
  148. package/dist/configurators/droid.d.ts.map +0 -1
  149. package/dist/configurators/droid.js +0 -30
  150. package/dist/configurators/droid.js.map +0 -1
  151. package/dist/configurators/gemini.d.ts +0 -16
  152. package/dist/configurators/gemini.d.ts.map +0 -1
  153. package/dist/configurators/gemini.js +0 -38
  154. package/dist/configurators/gemini.js.map +0 -1
  155. package/dist/configurators/kilo.d.ts +0 -7
  156. package/dist/configurators/kilo.d.ts.map +0 -1
  157. package/dist/configurators/kilo.js +0 -19
  158. package/dist/configurators/kilo.js.map +0 -1
  159. package/dist/configurators/kiro.d.ts +0 -8
  160. package/dist/configurators/kiro.d.ts.map +0 -1
  161. package/dist/configurators/kiro.js +0 -24
  162. package/dist/configurators/kiro.js.map +0 -1
  163. package/dist/configurators/opencode.d.ts +0 -14
  164. package/dist/configurators/opencode.d.ts.map +0 -1
  165. package/dist/configurators/opencode.js +0 -96
  166. package/dist/configurators/opencode.js.map +0 -1
  167. package/dist/configurators/pi.d.ts +0 -3
  168. package/dist/configurators/pi.d.ts.map +0 -1
  169. package/dist/configurators/pi.js +0 -45
  170. package/dist/configurators/pi.js.map +0 -1
  171. package/dist/configurators/qoder.d.ts +0 -11
  172. package/dist/configurators/qoder.d.ts.map +0 -1
  173. package/dist/configurators/qoder.js +0 -31
  174. package/dist/configurators/qoder.js.map +0 -1
  175. package/dist/configurators/windsurf.d.ts +0 -7
  176. package/dist/configurators/windsurf.d.ts.map +0 -1
  177. package/dist/configurators/windsurf.js +0 -19
  178. package/dist/configurators/windsurf.js.map +0 -1
  179. package/dist/templates/claude/agents/trellis-check.md +0 -124
  180. package/dist/templates/claude/agents/trellis-implement.md +0 -110
  181. package/dist/templates/claude/agents/trellis-research.md +0 -137
  182. package/dist/templates/claude/index.d.ts +0 -22
  183. package/dist/templates/claude/index.d.ts.map +0 -1
  184. package/dist/templates/claude/index.js +0 -46
  185. package/dist/templates/claude/index.js.map +0 -1
  186. package/dist/templates/claude/settings.json +0 -84
  187. package/dist/templates/codebuddy/agents/trellis-check.md +0 -115
  188. package/dist/templates/codebuddy/agents/trellis-implement.md +0 -110
  189. package/dist/templates/codebuddy/agents/trellis-research.md +0 -137
  190. package/dist/templates/codebuddy/index.d.ts +0 -15
  191. package/dist/templates/codebuddy/index.d.ts.map +0 -1
  192. package/dist/templates/codebuddy/index.js +0 -15
  193. package/dist/templates/codebuddy/index.js.map +0 -1
  194. package/dist/templates/codebuddy/settings.json +0 -70
  195. package/dist/templates/codex/agents/trellis-check.toml +0 -67
  196. package/dist/templates/codex/agents/trellis-implement.toml +0 -40
  197. package/dist/templates/codex/agents/trellis-research.toml +0 -73
  198. package/dist/templates/codex/config.toml +0 -28
  199. package/dist/templates/codex/hooks/session-start.py +0 -575
  200. package/dist/templates/codex/hooks.json +0 -15
  201. package/dist/templates/codex/index.d.ts +0 -39
  202. package/dist/templates/codex/index.d.ts.map +0 -1
  203. package/dist/templates/codex/index.js +0 -85
  204. package/dist/templates/codex/index.js.map +0 -1
  205. package/dist/templates/codex/skills/before-dev/SKILL.md +0 -40
  206. package/dist/templates/codex/skills/brainstorm/SKILL.md +0 -112
  207. package/dist/templates/codex/skills/break-loop/SKILL.md +0 -130
  208. package/dist/templates/codex/skills/check/SKILL.md +0 -98
  209. package/dist/templates/codex/skills/check-cross-layer/SKILL.md +0 -158
  210. package/dist/templates/codex/skills/create-command/SKILL.md +0 -101
  211. package/dist/templates/codex/skills/finish-work/SKILL.md +0 -90
  212. package/dist/templates/codex/skills/improve-ut/SKILL.md +0 -69
  213. package/dist/templates/codex/skills/integrate-skill/SKILL.md +0 -221
  214. package/dist/templates/codex/skills/onboard/SKILL.md +0 -363
  215. package/dist/templates/codex/skills/record-session/SKILL.md +0 -67
  216. package/dist/templates/codex/skills/start/SKILL.md +0 -66
  217. package/dist/templates/codex/skills/update-spec/SKILL.md +0 -335
  218. package/dist/templates/copilot/hooks/session-start.py +0 -557
  219. package/dist/templates/copilot/hooks.json +0 -19
  220. package/dist/templates/copilot/index.d.ts +0 -23
  221. package/dist/templates/copilot/index.d.ts.map +0 -1
  222. package/dist/templates/copilot/index.js +0 -54
  223. package/dist/templates/copilot/index.js.map +0 -1
  224. package/dist/templates/copilot/prompts/before-dev.prompt.md +0 -39
  225. package/dist/templates/copilot/prompts/brainstorm.prompt.md +0 -111
  226. package/dist/templates/copilot/prompts/break-loop.prompt.md +0 -129
  227. package/dist/templates/copilot/prompts/check-cross-layer.prompt.md +0 -157
  228. package/dist/templates/copilot/prompts/check.prompt.md +0 -97
  229. package/dist/templates/copilot/prompts/create-command.prompt.md +0 -116
  230. package/dist/templates/copilot/prompts/finish-work.prompt.md +0 -99
  231. package/dist/templates/copilot/prompts/integrate-skill.prompt.md +0 -223
  232. package/dist/templates/copilot/prompts/onboard.prompt.md +0 -362
  233. package/dist/templates/copilot/prompts/parallel.prompt.md +0 -204
  234. package/dist/templates/copilot/prompts/record-session.prompt.md +0 -66
  235. package/dist/templates/copilot/prompts/start.prompt.md +0 -63
  236. package/dist/templates/copilot/prompts/update-spec.prompt.md +0 -358
  237. package/dist/templates/droid/droids/trellis-check.md +0 -107
  238. package/dist/templates/droid/droids/trellis-implement.md +0 -102
  239. package/dist/templates/droid/droids/trellis-research.md +0 -137
  240. package/dist/templates/droid/index.d.ts +0 -15
  241. package/dist/templates/droid/index.d.ts.map +0 -1
  242. package/dist/templates/droid/index.js +0 -15
  243. package/dist/templates/droid/index.js.map +0 -1
  244. package/dist/templates/droid/settings.json +0 -70
  245. package/dist/templates/gemini/agents/trellis-check.md +0 -107
  246. package/dist/templates/gemini/agents/trellis-implement.md +0 -102
  247. package/dist/templates/gemini/agents/trellis-research.md +0 -136
  248. package/dist/templates/gemini/index.d.ts +0 -13
  249. package/dist/templates/gemini/index.d.ts.map +0 -1
  250. package/dist/templates/gemini/index.js +0 -13
  251. package/dist/templates/gemini/index.js.map +0 -1
  252. package/dist/templates/gemini/settings.json +0 -28
  253. package/dist/templates/kiro/agents/trellis-check.json +0 -26
  254. package/dist/templates/kiro/agents/trellis-implement.json +0 -26
  255. package/dist/templates/kiro/agents/trellis-research.json +0 -30
  256. package/dist/templates/kiro/index.d.ts +0 -18
  257. package/dist/templates/kiro/index.d.ts.map +0 -1
  258. package/dist/templates/kiro/index.js +0 -18
  259. package/dist/templates/kiro/index.js.map +0 -1
  260. package/dist/templates/opencode/agents/trellis-check.md +0 -122
  261. package/dist/templates/opencode/agents/trellis-implement.md +0 -118
  262. package/dist/templates/opencode/agents/trellis-research.md +0 -145
  263. package/dist/templates/opencode/lib/session-utils.js +0 -667
  264. package/dist/templates/opencode/lib/trellis-context.js +0 -336
  265. package/dist/templates/opencode/package.json +0 -5
  266. package/dist/templates/opencode/plugins/inject-subagent-context.js +0 -495
  267. package/dist/templates/opencode/plugins/inject-workflow-state.js +0 -159
  268. package/dist/templates/opencode/plugins/session-start.js +0 -101
  269. package/dist/templates/pi/agents/trellis-check.md +0 -37
  270. package/dist/templates/pi/agents/trellis-implement.md +0 -42
  271. package/dist/templates/pi/agents/trellis-research.md +0 -25
  272. package/dist/templates/pi/extensions/trellis/index.ts.txt +0 -1600
  273. package/dist/templates/pi/index.d.ts +0 -5
  274. package/dist/templates/pi/index.d.ts.map +0 -1
  275. package/dist/templates/pi/index.js +0 -12
  276. package/dist/templates/pi/index.js.map +0 -1
  277. package/dist/templates/pi/settings.json +0 -12
  278. package/dist/templates/qoder/agents/trellis-check.md +0 -108
  279. package/dist/templates/qoder/agents/trellis-implement.md +0 -103
  280. package/dist/templates/qoder/agents/trellis-research.md +0 -137
  281. package/dist/templates/qoder/index.d.ts +0 -15
  282. package/dist/templates/qoder/index.d.ts.map +0 -1
  283. package/dist/templates/qoder/index.js +0 -15
  284. package/dist/templates/qoder/index.js.map +0 -1
  285. package/dist/templates/qoder/settings.json +0 -47
@@ -1,34 +1,12 @@
1
1
  """
2
- CLI Adapter for Multi-Platform Support.
3
-
4
- Abstracts differences between Claude Code, OpenCode, Cursor, iFlow, Codex, Kilo, Kiro Code, Gemini CLI, Antigravity, Windsurf, Qoder, CodeBuddy, GitHub Copilot, Factory Droid, and Pi Agent interfaces.
5
-
6
- Supported platforms:
7
- - claude: Claude Code (default)
8
- - opencode: OpenCode
9
- - cursor: Cursor IDE
10
- - iflow: iFlow CLI
11
- - codex: Codex CLI (skills-based)
12
- - kilo: Kilo CLI
13
- - kiro: Kiro Code (skills-based)
14
- - gemini: Gemini CLI
15
- - antigravity: Antigravity (workflow-based)
16
- - windsurf: Windsurf (workflow-based)
17
- - qoder: Qoder
18
- - codebuddy: CodeBuddy
19
- - copilot: GitHub Copilot (VS Code)
20
- - droid: Factory Droid (commands-based)
21
- - pi: Pi Agent (extension-backed)
2
+ CLI Adapter for Cursor.
3
+
4
+ Cursor-only fork: abstracts Trellis paths and command layout for Cursor IDE.
22
5
 
23
6
  Usage:
24
7
  from common.cli_adapter import CLIAdapter
25
8
 
26
- adapter = CLIAdapter("opencode")
27
- cmd = adapter.build_run_command(
28
- agent="dispatch",
29
- session_id="abc123",
30
- prompt="Start the pipeline"
31
- )
9
+ adapter = CLIAdapter("cursor")
32
10
  """
33
11
 
34
12
  from __future__ import annotations
@@ -37,280 +15,49 @@ from dataclasses import dataclass
37
15
  from pathlib import Path
38
16
  from typing import ClassVar, Literal
39
17
 
40
- Platform = Literal[
41
- "claude",
42
- "opencode",
43
- "cursor",
44
- "iflow",
45
- "codex",
46
- "kilo",
47
- "kiro",
48
- "gemini",
49
- "antigravity",
50
- "windsurf",
51
- "qoder",
52
- "codebuddy",
53
- "copilot",
54
- "droid",
55
- "pi",
56
- ]
18
+ Platform = Literal["cursor"]
57
19
 
58
20
 
59
21
  @dataclass
60
22
  class CLIAdapter:
61
- """Adapter for different AI coding CLI tools."""
23
+ """Adapter for Cursor IDE integration."""
62
24
 
63
25
  platform: Platform
64
26
 
65
- # =========================================================================
66
- # Agent Name Mapping
67
- # =========================================================================
68
-
69
- # OpenCode has built-in agents that cannot be overridden
70
- # See: https://github.com/sst/opencode/issues/4271
71
- # Note: Class-level constant, not a dataclass field
72
27
  _AGENT_NAME_MAP: ClassVar[dict[Platform, dict[str, str]]] = {
73
- "claude": {}, # No mapping needed
74
- "opencode": {
75
- "plan": "trellis-plan", # 'plan' is built-in in OpenCode
76
- },
28
+ "cursor": {},
77
29
  }
78
30
 
79
31
  def get_agent_name(self, agent: str) -> str:
80
- """Get platform-specific agent name.
81
-
82
- Args:
83
- agent: Original agent name (e.g., 'plan', 'dispatch')
84
-
85
- Returns:
86
- Platform-specific agent name (e.g., 'trellis-plan' for OpenCode)
87
- """
88
32
  mapping = self._AGENT_NAME_MAP.get(self.platform, {})
89
33
  return mapping.get(agent, agent)
90
34
 
91
- # =========================================================================
92
- # Agent Path
93
- # =========================================================================
94
-
95
35
  @property
96
36
  def config_dir_name(self) -> str:
97
- """Get platform-specific config directory name.
98
-
99
- Returns:
100
- Directory name ('.claude', '.opencode', '.cursor', '.iflow', '.codex', '.kilocode', '.kiro', '.gemini', '.agent', '.windsurf', '.qoder', '.codebuddy', '.github/copilot', '.factory', or '.pi')
101
- """
102
- if self.platform == "opencode":
103
- return ".opencode"
104
- elif self.platform == "cursor":
105
- return ".cursor"
106
- elif self.platform == "iflow":
107
- return ".iflow"
108
- elif self.platform == "codex":
109
- return ".codex"
110
- elif self.platform == "kilo":
111
- return ".kilocode"
112
- elif self.platform == "kiro":
113
- return ".kiro"
114
- elif self.platform == "gemini":
115
- return ".gemini"
116
- elif self.platform == "antigravity":
117
- return ".agent"
118
- elif self.platform == "windsurf":
119
- return ".windsurf"
120
- elif self.platform == "qoder":
121
- return ".qoder"
122
- elif self.platform == "codebuddy":
123
- return ".codebuddy"
124
- elif self.platform == "copilot":
125
- return ".github/copilot"
126
- elif self.platform == "droid":
127
- return ".factory"
128
- elif self.platform == "pi":
129
- return ".pi"
130
- else:
131
- return ".claude"
37
+ return ".cursor"
132
38
 
133
39
  def get_config_dir(self, project_root: Path) -> Path:
134
- """Get platform-specific config directory.
135
-
136
- Args:
137
- project_root: Project root directory
138
-
139
- Returns:
140
- Path to config directory (.claude, .opencode, .cursor, .iflow, .codex, .kilocode, .kiro, .gemini, .agent, .windsurf, .qoder, .codebuddy, .github/copilot, .factory, or .pi)
141
- """
142
40
  return project_root / self.config_dir_name
143
41
 
144
42
  def get_agent_path(self, agent: str, project_root: Path) -> Path:
145
- """Get path to agent definition file.
146
-
147
- Args:
148
- agent: Agent name (original, before mapping)
149
- project_root: Project root directory
150
-
151
- Returns:
152
- Path to agent definition file (.md for most platforms, .toml for Codex)
153
- """
154
43
  mapped_name = self.get_agent_name(agent)
155
- if self.platform == "codex":
156
- return self.get_config_dir(project_root) / "agents" / f"{mapped_name}.toml"
157
44
  return self.get_config_dir(project_root) / "agents" / f"{mapped_name}.md"
158
45
 
159
46
  def get_commands_path(self, project_root: Path, *parts: str) -> Path:
160
- """Get path to commands directory or specific command file.
161
-
162
- Args:
163
- project_root: Project root directory
164
- *parts: Additional path parts (e.g., 'trellis', 'finish-work.md')
165
-
166
- Returns:
167
- Path to commands directory or file
168
-
169
- Note:
170
- Cursor uses prefix naming: .cursor/commands/trellis-<name>.md
171
- Antigravity uses workflow directory: .agent/workflows/<name>.md
172
- Windsurf uses workflow directory: .windsurf/workflows/trellis-<name>.md
173
- Copilot uses prompt files: .github/prompts/<name>.prompt.md
174
- Pi uses prompt templates: .pi/prompts/trellis-<name>.md
175
- Claude/OpenCode use subdirectory: .claude/commands/trellis/<name>.md
176
- """
177
- if self.platform == "pi":
178
- prompts_dir = self.get_config_dir(project_root) / "prompts"
179
- if not parts:
180
- return prompts_dir
181
- if len(parts) >= 2 and parts[0] == "trellis":
182
- filename = parts[-1]
183
- if filename.endswith(".md"):
184
- filename = filename[:-3]
185
- return prompts_dir / f"trellis-{filename}.md"
186
- return prompts_dir / Path(*parts)
187
-
188
- if self.platform == "windsurf":
189
- workflow_dir = self.get_config_dir(project_root) / "workflows"
190
- if not parts:
191
- return workflow_dir
192
- if len(parts) >= 2 and parts[0] == "trellis":
193
- filename = parts[-1]
194
- return workflow_dir / f"trellis-{filename}"
195
- return workflow_dir / Path(*parts)
196
-
197
- if self.platform in ("antigravity", "kilo"):
198
- workflow_dir = self.get_config_dir(project_root) / "workflows"
199
- if not parts:
200
- return workflow_dir
201
- if len(parts) >= 2 and parts[0] == "trellis":
202
- filename = parts[-1]
203
- return workflow_dir / filename
204
- return workflow_dir / Path(*parts)
205
-
206
- if self.platform == "copilot":
207
- prompts_dir = project_root / ".github" / "prompts"
208
- if not parts:
209
- return prompts_dir
210
- if len(parts) >= 2 and parts[0] == "trellis":
211
- filename = parts[-1]
212
- if filename.endswith(".md"):
213
- filename = filename[:-3]
214
- return prompts_dir / f"{filename}.prompt.md"
215
- return prompts_dir / Path(*parts)
216
-
217
47
  if not parts:
218
48
  return self.get_config_dir(project_root) / "commands"
219
-
220
- # Cursor uses prefix naming instead of subdirectory
221
- if self.platform == "cursor" and len(parts) >= 2 and parts[0] == "trellis":
222
- # Convert trellis/<name>.md to trellis-<name>.md
49
+ if len(parts) >= 2 and parts[0] == "trellis":
223
50
  filename = parts[-1]
224
51
  return (
225
52
  self.get_config_dir(project_root) / "commands" / f"trellis-{filename}"
226
53
  )
227
-
228
54
  return self.get_config_dir(project_root) / "commands" / Path(*parts)
229
55
 
230
56
  def get_trellis_command_path(self, name: str) -> str:
231
- """Get relative path to a trellis command file.
232
-
233
- Args:
234
- name: Command name without extension (e.g., 'finish-work', 'check')
235
-
236
- Returns:
237
- Relative path string for use in JSONL entries
238
-
239
- Note:
240
- Cursor: .cursor/commands/trellis-<name>.md
241
- Codex: .agents/skills/trellis-<name>/SKILL.md
242
- Kiro: .kiro/skills/trellis-<name>/SKILL.md
243
- Gemini: .gemini/commands/trellis/<name>.toml
244
- Antigravity: .agent/workflows/<name>.md
245
- Windsurf: .windsurf/workflows/trellis-<name>.md
246
- Pi: .pi/prompts/trellis-<name>.md
247
- Others: .{platform}/commands/trellis/<name>.md
248
- """
249
- if self.platform == "cursor":
250
- return f".cursor/commands/trellis-{name}.md"
251
- elif self.platform == "codex":
252
- # 0.5.0-beta.0 renamed all skill dirs to add the `trellis-` prefix
253
- # (see that release's manifest for the 60+ rename entries).
254
- return f".agents/skills/trellis-{name}/SKILL.md"
255
- elif self.platform == "kiro":
256
- return f".kiro/skills/trellis-{name}/SKILL.md"
257
- elif self.platform == "gemini":
258
- return f".gemini/commands/trellis/{name}.toml"
259
- elif self.platform == "antigravity":
260
- return f".agent/workflows/{name}.md"
261
- elif self.platform == "windsurf":
262
- return f".windsurf/workflows/trellis-{name}.md"
263
- elif self.platform == "kilo":
264
- return f".kilocode/workflows/{name}.md"
265
- elif self.platform == "copilot":
266
- return f".github/prompts/{name}.prompt.md"
267
- elif self.platform == "droid":
268
- return f".factory/commands/trellis/{name}.md"
269
- elif self.platform == "pi":
270
- return f".pi/prompts/trellis-{name}.md"
271
- else:
272
- return f"{self.config_dir_name}/commands/trellis/{name}.md"
273
-
274
- # =========================================================================
275
- # Environment Variables
276
- # =========================================================================
57
+ return f".cursor/commands/trellis-{name}.md"
277
58
 
278
59
  def get_non_interactive_env(self) -> dict[str, str]:
279
- """Get environment variables for non-interactive mode.
280
-
281
- Returns:
282
- Dict of environment variables to set
283
- """
284
- if self.platform == "opencode":
285
- return {"OPENCODE_NON_INTERACTIVE": "1"}
286
- elif self.platform == "iflow":
287
- return {"IFLOW_NON_INTERACTIVE": "1"}
288
- elif self.platform == "codex":
289
- return {"CODEX_NON_INTERACTIVE": "1"}
290
- elif self.platform == "kiro":
291
- return {"KIRO_NON_INTERACTIVE": "1"}
292
- elif self.platform == "gemini":
293
- return {} # Gemini CLI doesn't have a non-interactive env var
294
- elif self.platform == "antigravity":
295
- return {}
296
- elif self.platform == "windsurf":
297
- return {}
298
- elif self.platform == "qoder":
299
- return {}
300
- elif self.platform == "codebuddy":
301
- return {}
302
- elif self.platform == "copilot":
303
- return {}
304
- elif self.platform == "droid":
305
- return {}
306
- elif self.platform == "pi":
307
- return {}
308
- else:
309
- return {"CLAUDE_NON_INTERACTIVE": "1"}
310
-
311
- # =========================================================================
312
- # CLI Command Building
313
- # =========================================================================
60
+ return {}
314
61
 
315
62
  def build_run_command(
316
63
  self,
@@ -321,337 +68,57 @@ class CLIAdapter:
321
68
  verbose: bool = True,
322
69
  json_output: bool = True,
323
70
  ) -> list[str]:
324
- """Build CLI command for running an agent.
325
-
326
- Args:
327
- agent: Agent name (will be mapped if needed)
328
- prompt: Prompt to send to the agent
329
- session_id: Optional session ID (Claude Code only for creation)
330
- skip_permissions: Whether to skip permission prompts
331
- verbose: Whether to enable verbose output
332
- json_output: Whether to use JSON output format
333
-
334
- Returns:
335
- List of command arguments
336
- """
337
- mapped_agent = self.get_agent_name(agent)
338
-
339
- if self.platform == "opencode":
340
- cmd = ["opencode", "run"]
341
- cmd.extend(["--agent", mapped_agent])
342
-
343
- # Note: OpenCode 'run' mode is non-interactive by default
344
- # No equivalent to Claude Code's --dangerously-skip-permissions
345
- # See: https://github.com/anomalyco/opencode/issues/9070
346
-
347
- if json_output:
348
- cmd.extend(["--format", "json"])
349
-
350
- if verbose:
351
- cmd.extend(["--log-level", "DEBUG", "--print-logs"])
352
-
353
- # Note: OpenCode doesn't support --session-id on creation
354
- # Session ID must be extracted from logs after startup
355
-
356
- cmd.append(prompt)
357
-
358
- elif self.platform == "iflow":
359
- cmd = ["iflow", "-y", "-p"]
360
- cmd.append(f"${mapped_agent} {prompt}")
361
- elif self.platform == "codex":
362
- cmd = ["codex", "exec"]
363
- cmd.append(prompt)
364
- elif self.platform == "kiro":
365
- cmd = ["kiro", "run", prompt]
366
- elif self.platform == "gemini":
367
- cmd = ["gemini"]
368
- cmd.append(prompt)
369
- elif self.platform == "antigravity":
370
- raise ValueError(
371
- "Antigravity workflows are UI slash commands; CLI agent run is not supported."
372
- )
373
- elif self.platform == "windsurf":
374
- raise ValueError(
375
- "Windsurf workflows are UI slash commands; CLI agent run is not supported."
376
- )
377
- elif self.platform == "qoder":
378
- cmd = ["qodercli", "-p", prompt]
379
- elif self.platform == "codebuddy":
380
- raise ValueError(
381
- "CodeBuddy does not support non-interactive mode (no CLI agent)"
382
- )
383
- elif self.platform == "copilot":
384
- raise ValueError(
385
- "GitHub Copilot is IDE-only; CLI agent run is not supported."
386
- )
387
- elif self.platform == "droid":
388
- raise ValueError(
389
- "Factory Droid CLI agent run is not yet supported."
390
- )
391
- elif self.platform == "pi":
392
- cmd = ["pi", "-p", prompt]
393
-
394
- else: # claude
395
- cmd = ["claude", "-p"]
396
- cmd.extend(["--agent", mapped_agent])
397
-
398
- if session_id:
399
- cmd.extend(["--session-id", session_id])
400
-
401
- if skip_permissions:
402
- cmd.append("--dangerously-skip-permissions")
403
-
404
- if json_output:
405
- cmd.extend(["--output-format", "stream-json"])
406
-
407
- if verbose:
408
- cmd.append("--verbose")
409
-
410
- cmd.append(prompt)
411
-
412
- return cmd
71
+ _ = (agent, prompt, session_id, skip_permissions, verbose, json_output)
72
+ raise ValueError(
73
+ "Cursor is IDE-only; CLI agent run is not supported. Use Cursor Agent in the IDE."
74
+ )
413
75
 
414
76
  def build_resume_command(self, session_id: str) -> list[str]:
415
- """Build CLI command for resuming a session.
416
-
417
- Args:
418
- session_id: Session ID to resume (ignored for iFlow)
419
-
420
- Returns:
421
- List of command arguments
422
- """
423
- if self.platform == "opencode":
424
- return ["opencode", "run", "--session", session_id]
425
- elif self.platform == "iflow":
426
- # iFlow uses -c to continue most recent conversation
427
- # session_id is ignored as iFlow doesn't support session IDs
428
- return ["iflow", "-c"]
429
- elif self.platform == "codex":
430
- return ["codex", "resume", session_id]
431
- elif self.platform == "kiro":
432
- return ["kiro", "resume", session_id]
433
- elif self.platform == "gemini":
434
- return ["gemini", "--resume", session_id]
435
- elif self.platform == "antigravity":
436
- raise ValueError(
437
- "Antigravity workflows are UI slash commands; CLI resume is not supported."
438
- )
439
- elif self.platform == "windsurf":
440
- raise ValueError(
441
- "Windsurf workflows are UI slash commands; CLI resume is not supported."
442
- )
443
- elif self.platform == "qoder":
444
- return ["qodercli", "--resume", session_id]
445
- elif self.platform == "codebuddy":
446
- raise ValueError(
447
- "CodeBuddy does not support non-interactive mode (no CLI agent)"
448
- )
449
- elif self.platform == "copilot":
450
- raise ValueError(
451
- "GitHub Copilot is IDE-only; CLI resume is not supported."
452
- )
453
- elif self.platform == "droid":
454
- raise ValueError(
455
- "Factory Droid CLI resume is not yet supported."
456
- )
457
- elif self.platform == "pi":
458
- return ["pi", "-c", session_id]
459
- else:
460
- return ["claude", "--resume", session_id]
77
+ _ = session_id
78
+ raise ValueError("Cursor is IDE-only; CLI resume is not supported.")
461
79
 
462
80
  def get_resume_command_str(self, session_id: str, cwd: str | None = None) -> str:
463
- """Get human-readable resume command string.
464
-
465
- Args:
466
- session_id: Session ID to resume
467
- cwd: Optional working directory to cd into
468
-
469
- Returns:
470
- Command string for display
471
- """
472
81
  cmd = self.build_resume_command(session_id)
473
82
  cmd_str = " ".join(cmd)
474
-
475
83
  if cwd:
476
84
  return f"cd {cwd} && {cmd_str}"
477
85
  return cmd_str
478
86
 
479
- # =========================================================================
480
- # Platform Detection Helpers
481
- # =========================================================================
482
-
483
- @property
484
- def is_opencode(self) -> bool:
485
- """Check if platform is OpenCode."""
486
- return self.platform == "opencode"
487
-
488
- @property
489
- def is_claude(self) -> bool:
490
- """Check if platform is Claude Code."""
491
- return self.platform == "claude"
492
-
493
87
  @property
494
88
  def is_cursor(self) -> bool:
495
- """Check if platform is Cursor."""
496
- return self.platform == "cursor"
497
-
498
- @property
499
- def is_iflow(self) -> bool:
500
- """Check if platform is iFlow CLI."""
501
- return self.platform == "iflow"
89
+ return True
502
90
 
503
91
  @property
504
92
  def cli_name(self) -> str:
505
- """Get CLI executable name.
506
-
507
- Note: Cursor doesn't have a CLI tool, returns None-like value.
508
- """
509
- if self.is_opencode:
510
- return "opencode"
511
- elif self.is_cursor:
512
- return "cursor" # Note: Cursor is IDE-only, no CLI
513
- elif self.platform == "iflow":
514
- return "iflow"
515
- elif self.platform == "kiro":
516
- return "kiro"
517
- elif self.platform == "gemini":
518
- return "gemini"
519
- elif self.platform == "antigravity":
520
- return "agy"
521
- elif self.platform == "windsurf":
522
- return "windsurf"
523
- elif self.platform == "qoder":
524
- return "qodercli"
525
- elif self.platform == "codebuddy":
526
- return "codebuddy"
527
- elif self.platform == "copilot":
528
- return "copilot"
529
- elif self.platform == "droid":
530
- return "droid"
531
- elif self.platform == "pi":
532
- return "pi"
533
- else:
534
- return "claude"
93
+ return "cursor"
535
94
 
536
95
  @property
537
96
  def supports_cli_agents(self) -> bool:
538
- """Check if platform supports running agents via CLI.
539
-
540
- Claude Code, OpenCode, iFlow, and Codex support CLI agent execution.
541
- Cursor is IDE-only and doesn't support CLI agents.
542
- """
543
- return self.platform in ("claude", "opencode", "iflow", "codex", "pi")
97
+ return False
544
98
 
545
99
  @property
546
100
  def requires_agent_definition_file(self) -> bool:
547
- """Check if platform requires an agent definition file (.md/.toml) to run.
548
-
549
- Claude Code, OpenCode, iFlow: require agent .md files (--agent flag).
550
- Codex: auto-discovers agents from .codex/agents/*.toml, no --agent flag.
551
- """
552
- return self.platform in ("claude", "opencode", "iflow")
553
-
554
- # =========================================================================
555
- # Session ID Handling
556
- # =========================================================================
101
+ return True
557
102
 
558
103
  @property
559
104
  def supports_session_id_on_create(self) -> bool:
560
- """Check if platform supports specifying session ID on creation.
561
-
562
- Claude Code: Yes (--session-id)
563
- OpenCode: No (auto-generated, extract from logs)
564
- iFlow: No (no session ID support)
565
- """
566
- return self.platform == "claude"
105
+ return False
567
106
 
568
107
  def extract_session_id_from_log(self, log_content: str) -> str | None:
569
- """Extract session ID from log output (OpenCode only).
570
-
571
- OpenCode generates session IDs in format: ses_xxx
572
-
573
- Args:
574
- log_content: Log file content
575
-
576
- Returns:
577
- Session ID if found, None otherwise
578
- """
579
- import re
580
-
581
- # OpenCode session ID pattern
582
- match = re.search(r"ses_[a-zA-Z0-9]+", log_content)
583
- if match:
584
- return match.group(0)
108
+ _ = log_content
585
109
  return None
586
110
 
587
111
 
588
- # =============================================================================
589
- # Factory Function
590
- # =============================================================================
591
-
592
-
593
- def get_cli_adapter(platform: str = "claude") -> CLIAdapter:
594
- """Get CLI adapter for the specified platform.
595
-
596
- Args:
597
- platform: Platform name ('claude', 'opencode', 'cursor', 'iflow', 'codex', 'kilo', 'kiro', 'gemini', 'antigravity', 'windsurf', 'qoder', 'codebuddy', 'copilot', 'droid', or 'pi')
598
-
599
- Returns:
600
- CLIAdapter instance
601
-
602
- Raises:
603
- ValueError: If platform is not supported
604
- """
605
- if platform not in (
606
- "claude",
607
- "opencode",
608
- "cursor",
609
- "iflow",
610
- "codex",
611
- "kilo",
612
- "kiro",
613
- "gemini",
614
- "antigravity",
615
- "windsurf",
616
- "qoder",
617
- "codebuddy",
618
- "copilot",
619
- "droid",
620
- "pi",
621
- ):
622
- raise ValueError(
623
- f"Unsupported platform: {platform} (must be 'claude', 'opencode', 'cursor', 'iflow', 'codex', 'kilo', 'kiro', 'gemini', 'antigravity', 'windsurf', 'qoder', 'codebuddy', 'copilot', 'droid', or 'pi')"
624
- )
112
+ def get_cli_adapter(platform: str = "cursor") -> CLIAdapter:
113
+ if platform != "cursor":
114
+ raise ValueError(f"Unsupported platform: {platform} (must be 'cursor')")
115
+ return CLIAdapter(platform="cursor")
625
116
 
626
- return CLIAdapter(platform=platform) # type: ignore
627
-
628
-
629
- _ALL_PLATFORM_CONFIG_DIRS = (
630
- ".claude",
631
- ".cursor",
632
- ".iflow",
633
- ".opencode",
634
- ".codex",
635
- ".kilocode",
636
- ".kiro",
637
- ".gemini",
638
- ".agent",
639
- ".windsurf",
640
- ".qoder",
641
- ".codebuddy",
642
- ".github/copilot",
643
- ".factory",
644
- ".pi",
645
- )
646
- """Platform-specific config directory names used by detect_platform exclusion
647
- checks. `.agents/skills/` is NOT listed here: it is a shared cross-platform
648
- layer (written by Codex, also consumed by Amp/Cline/Warp/etc. via the
649
- agentskills.io standard), not a single-platform signal. Its presence must not
650
- block detection of Kiro, Antigravity, Windsurf, or other platforms."""
117
+
118
+ _ALL_PLATFORM_CONFIG_DIRS = (".cursor",)
651
119
 
652
120
 
653
121
  def _has_other_platform_dir(project_root: Path, exclude: set[str]) -> bool:
654
- """Check if any platform config dir exists besides those in *exclude*."""
655
122
  return any(
656
123
  (project_root / d).is_dir()
657
124
  for d in _ALL_PLATFORM_CONFIG_DIRS
@@ -660,152 +127,9 @@ def _has_other_platform_dir(project_root: Path, exclude: set[str]) -> bool:
660
127
 
661
128
 
662
129
  def detect_platform(project_root: Path) -> Platform:
663
- """Auto-detect platform based on existing config directories.
664
-
665
- Detection order:
666
- 1. TRELLIS_PLATFORM environment variable (if set)
667
- 2. .opencode directory exists → opencode
668
- 3. .iflow directory exists → iflow
669
- 4. .cursor directory exists (without .claude) → cursor
670
- 5. .codex exists and no other platform dirs → codex
671
- 6. .kilocode directory exists → kilo
672
- 7. .kiro/skills exists and no other platform dirs → kiro
673
- 8. .gemini directory exists → gemini
674
- 9. .agent/workflows exists and no other platform dirs → antigravity
675
- 10. .windsurf/workflows exists and no other platform dirs → windsurf
676
- 11. .codebuddy directory exists → codebuddy
677
- 12. .qoder directory exists → qoder
678
- 13. .pi directory exists → pi
679
- 14. Default → claude
680
-
681
- Args:
682
- project_root: Project root directory
683
-
684
- Returns:
685
- Detected platform ('claude', 'opencode', 'cursor', 'iflow', 'codex', 'kilo', 'kiro', 'gemini', 'antigravity', 'windsurf', 'qoder', 'codebuddy', 'copilot', 'droid', 'pi', or default 'claude')
686
- """
687
- import os
688
-
689
- # Check environment variable first
690
- env_platform = os.environ.get("TRELLIS_PLATFORM", "").lower()
691
- if env_platform in (
692
- "claude",
693
- "opencode",
694
- "cursor",
695
- "iflow",
696
- "codex",
697
- "kilo",
698
- "kiro",
699
- "gemini",
700
- "antigravity",
701
- "windsurf",
702
- "qoder",
703
- "codebuddy",
704
- "copilot",
705
- "droid",
706
- "pi",
707
- ):
708
- return env_platform # type: ignore
709
-
710
- # Check for .opencode directory (OpenCode-specific)
711
- if (project_root / ".opencode").is_dir():
712
- return "opencode"
713
-
714
- # Check for .iflow directory (iFlow-specific)
715
- if (project_root / ".iflow").is_dir():
716
- return "iflow"
717
-
718
- # Check for .cursor directory (Cursor-specific)
719
- # Only detect as cursor if .claude doesn't exist (to avoid confusion)
720
- if (project_root / ".cursor").is_dir() and not (project_root / ".claude").is_dir():
130
+ override = __import__("os").environ.get("TRELLIS_PLATFORM", "").strip().lower()
131
+ if override == "cursor":
721
132
  return "cursor"
722
-
723
- # Check for .gemini directory (Gemini CLI-specific)
724
- if (project_root / ".gemini").is_dir():
725
- return "gemini"
726
-
727
- # Check for .codex directory (Codex-specific)
728
- # .agents/skills/ alone does NOT trigger codex detection (it's a shared standard)
729
- if (project_root / ".codex").is_dir() and not _has_other_platform_dir(
730
- project_root, {".codex", ".agents"}
731
- ):
732
- return "codex"
733
-
734
- # Check for .kilocode directory (Kilo-specific)
735
- if (project_root / ".kilocode").is_dir():
736
- return "kilo"
737
-
738
- # Check for Kiro skills directory only when no other platform config exists
739
- if (project_root / ".kiro" / "skills").is_dir() and not _has_other_platform_dir(
740
- project_root, {".kiro"}
741
- ):
742
- return "kiro"
743
-
744
- # Check for Antigravity workflow directory only when no other platform config exists
745
- if (
746
- project_root / ".agent" / "workflows"
747
- ).is_dir() and not _has_other_platform_dir(
748
- project_root, {".agent", ".gemini"}
749
- ):
750
- return "antigravity"
751
-
752
- # Check for Windsurf workflow directory only when no other platform config exists
753
- if (
754
- project_root / ".windsurf" / "workflows"
755
- ).is_dir() and not _has_other_platform_dir(
756
- project_root, {".windsurf"}
757
- ):
758
- return "windsurf"
759
-
760
- # Check for .codebuddy directory (CodeBuddy-specific)
761
- if (project_root / ".codebuddy").is_dir():
762
- return "codebuddy"
763
-
764
- # Check for .qoder directory (Qoder-specific)
765
- if (project_root / ".qoder").is_dir():
766
- return "qoder"
767
-
768
- # Check for .github/copilot directory (GitHub Copilot-specific)
769
- if (project_root / ".github" / "copilot").is_dir():
770
- return "copilot"
771
-
772
- # Check for .factory directory (Factory Droid-specific)
773
- if (project_root / ".factory").is_dir():
774
- return "droid"
775
-
776
- # Check for .pi directory (Pi Agent-specific)
777
- if (project_root / ".pi").is_dir():
778
- return "pi"
779
-
780
- # Fallback: checkout only has the Codex shared-skills layer
781
- # (.agents/skills/trellis-* dirs) and no explicit platform config dir.
782
- # Happens on fresh clones where .codex/ is gitignored/absent but the
783
- # shared skills were committed to git. Must guard against the case
784
- # where .claude/ or any other platform dir also exists — .agents/skills/
785
- # can legitimately coexist with any platform as a shared consumption
786
- # layer for Amp/Cline/Warp/etc.
787
- agents_skills = project_root / ".agents" / "skills"
788
- if agents_skills.is_dir() and not _has_other_platform_dir(
789
- project_root, set()
790
- ):
791
- try:
792
- for entry in agents_skills.iterdir():
793
- if entry.is_dir() and entry.name.startswith("trellis-"):
794
- return "codex"
795
- except OSError:
796
- pass
797
-
798
- return "claude"
799
-
800
-
801
- def get_cli_adapter_auto(project_root: Path) -> CLIAdapter:
802
- """Get CLI adapter with auto-detected platform.
803
-
804
- Args:
805
- project_root: Project root directory
806
-
807
- Returns:
808
- CLIAdapter instance for detected platform
809
- """
810
- platform = detect_platform(project_root)
811
- return CLIAdapter(platform=platform)
133
+ if (project_root / ".cursor").is_dir():
134
+ return "cursor"
135
+ return "cursor"