specrails-desktop 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (455) hide show
  1. package/.claude/commands/specrails/batch-implement.md +287 -0
  2. package/.claude/commands/specrails/compat-check.md +271 -0
  3. package/.claude/commands/specrails/doctor.md +62 -0
  4. package/.claude/commands/specrails/enrich.md +1635 -0
  5. package/.claude/commands/specrails/explore-spec.md +173 -0
  6. package/.claude/commands/specrails/health-check.md +527 -0
  7. package/.claude/commands/specrails/implement.md +1457 -0
  8. package/.claude/commands/specrails/memory-inspect.md +259 -0
  9. package/.claude/commands/specrails/opsx-diff.md +419 -0
  10. package/.claude/commands/specrails/propose-spec.md +102 -0
  11. package/.claude/commands/specrails/reconfig.md +89 -0
  12. package/.claude/commands/specrails/refactor-recommender.md +212 -0
  13. package/.claude/commands/specrails/retry.md +363 -0
  14. package/.claude/commands/specrails/telemetry.md +552 -0
  15. package/.claude/commands/specrails/why.md +96 -0
  16. package/LICENSE +21 -0
  17. package/README.md +290 -0
  18. package/cli/dist/specrails-desktop.js +1098 -0
  19. package/client/dist/assets/ActivityFeedPage-Gy4x8dBt.js +1 -0
  20. package/client/dist/assets/AgentsPage-CPgu--Fb.js +86 -0
  21. package/client/dist/assets/AnalyticsPage-B5sJEee2.js +1 -0
  22. package/client/dist/assets/BarChart-7IMQ8HY1.js +33 -0
  23. package/client/dist/assets/CodePage-CBdFvbwe.js +2 -0
  24. package/client/dist/assets/DesktopAnalyticsPage-w0rdTq4w.js +1 -0
  25. package/client/dist/assets/DocsDialog-BZUYM7wm.js +11 -0
  26. package/client/dist/assets/DocsPage-9QglWl46.js +11 -0
  27. package/client/dist/assets/ExportDropdown-BLZFXtNi.js +1 -0
  28. package/client/dist/assets/IntegrationsPage-BxBE4y99.js +3 -0
  29. package/client/dist/assets/JobDetailPage-DydWx_5S.js +16 -0
  30. package/client/dist/assets/JobsPage-20ibw0IO.js +1 -0
  31. package/client/dist/assets/abap-Bw6f2wDG.js +1 -0
  32. package/client/dist/assets/activity-BEIp_Y1A.js +1 -0
  33. package/client/dist/assets/activity-BdrPln96.js +1 -0
  34. package/client/dist/assets/activity-CpkRS8Sx.js +1 -0
  35. package/client/dist/assets/activity-DKCpESPt.js +1 -0
  36. package/client/dist/assets/activity-DOUVEjJi.js +1 -0
  37. package/client/dist/assets/activity-DRwkql_y.js +1 -0
  38. package/client/dist/assets/activity-DcDQ7tjw.js +1 -0
  39. package/client/dist/assets/activity-Dv6H7wEr.js +1 -0
  40. package/client/dist/assets/addon-image-3WCl5Vhd.js +1 -0
  41. package/client/dist/assets/addon-ligatures-C5OdliKs.js +2 -0
  42. package/client/dist/assets/addon-webgl-BbX6pSjl.js +44 -0
  43. package/client/dist/assets/addspec-B5yl4Loj.js +1 -0
  44. package/client/dist/assets/addspec-BEeF5-zc.js +1 -0
  45. package/client/dist/assets/addspec-D33ocMxf.js +1 -0
  46. package/client/dist/assets/addspec-DFswZ0jK.js +1 -0
  47. package/client/dist/assets/addspec-DRE-jZv7.js +1 -0
  48. package/client/dist/assets/addspec-DVZ15Jp8.js +1 -0
  49. package/client/dist/assets/addspec-Fkv91Opc.js +1 -0
  50. package/client/dist/assets/addspec-GWm4ffKl.js +1 -0
  51. package/client/dist/assets/agents-1nCDWRmP.js +1 -0
  52. package/client/dist/assets/agents-Bm9rPqnt.js +1 -0
  53. package/client/dist/assets/agents-CMxtJMLD.js +1 -0
  54. package/client/dist/assets/agents-DK-Dlc0i.js +1 -0
  55. package/client/dist/assets/agents-Q6Ldfpxx.js +1 -0
  56. package/client/dist/assets/agents-TeOSy-ax.js +1 -0
  57. package/client/dist/assets/agents-iTqjRajS.js +1 -0
  58. package/client/dist/assets/agents-s87sMGzL.js +1 -0
  59. package/client/dist/assets/agentstudio-B6Wb59E7.js +1 -0
  60. package/client/dist/assets/agentstudio-BADhZ41e.js +1 -0
  61. package/client/dist/assets/agentstudio-BSnWLR63.js +1 -0
  62. package/client/dist/assets/agentstudio-BdidyBzZ.js +1 -0
  63. package/client/dist/assets/agentstudio-CxlUllqI.js +1 -0
  64. package/client/dist/assets/agentstudio-D3I62TLJ.js +1 -0
  65. package/client/dist/assets/agentstudio-DuH9TogZ.js +1 -0
  66. package/client/dist/assets/agentstudio-Kw88_dUF.js +1 -0
  67. package/client/dist/assets/aiedit-BWxHGsYA.js +1 -0
  68. package/client/dist/assets/aiedit-D2ji6Qy0.js +1 -0
  69. package/client/dist/assets/aiedit-DAhZTvtk.js +1 -0
  70. package/client/dist/assets/aiedit-DJMny-D5.js +1 -0
  71. package/client/dist/assets/aiedit-DOcxERkU.js +1 -0
  72. package/client/dist/assets/aiedit-DvrcbwGv.js +1 -0
  73. package/client/dist/assets/aiedit-TTwzL1TS.js +1 -0
  74. package/client/dist/assets/aiedit-WBSjT_C1.js +1 -0
  75. package/client/dist/assets/analytics-BIdr0YfL.js +1 -0
  76. package/client/dist/assets/analytics-C6EzgtdE.js +1 -0
  77. package/client/dist/assets/analytics-C9Zc-rkM.js +1 -0
  78. package/client/dist/assets/analytics-CVx3YOc0.js +1 -0
  79. package/client/dist/assets/analytics-CYj0tfj7.js +1 -0
  80. package/client/dist/assets/analytics-CnY4kNG3.js +1 -0
  81. package/client/dist/assets/analytics-CrPCZRJ-.js +1 -0
  82. package/client/dist/assets/analytics-DMCto-TF.js +1 -0
  83. package/client/dist/assets/apex-Cw8_REBo.js +1 -0
  84. package/client/dist/assets/atom-one-dark-B-oHczHB.css +1 -0
  85. package/client/dist/assets/attachments-BIsSSnHJ.js +1 -0
  86. package/client/dist/assets/attachments-BW4L3l2L.js +1 -0
  87. package/client/dist/assets/attachments-Bcf6BG6V.js +1 -0
  88. package/client/dist/assets/attachments-Bke8sCU4.js +1 -0
  89. package/client/dist/assets/attachments-COcrGRFz.js +1 -0
  90. package/client/dist/assets/attachments-DYHGA2Dj.js +1 -0
  91. package/client/dist/assets/attachments-Dd92KpUH.js +1 -0
  92. package/client/dist/assets/attachments-DzdU6DV6.js +1 -0
  93. package/client/dist/assets/azcli-Cz6HAoOw.js +1 -0
  94. package/client/dist/assets/bat-CcJ-xyqL.js +1 -0
  95. package/client/dist/assets/bicep-z1WDCKYz.js +2 -0
  96. package/client/dist/assets/browser-5ErDlJoR.js +1 -0
  97. package/client/dist/assets/browser-Bc-YdlVg.js +1 -0
  98. package/client/dist/assets/browser-BlYF4OOq.js +1 -0
  99. package/client/dist/assets/browser-CT-ReZGt.js +1 -0
  100. package/client/dist/assets/browser-DGITz3fC.js +1 -0
  101. package/client/dist/assets/browser-JsAIGCEW.js +1 -0
  102. package/client/dist/assets/browser-M5-rbPlw.js +1 -0
  103. package/client/dist/assets/browser-Qya9cARy.js +1 -0
  104. package/client/dist/assets/cameligo-BRewOpfa.js +1 -0
  105. package/client/dist/assets/chat-BEGuC03z.js +1 -0
  106. package/client/dist/assets/chat-BEW60P_u.js +1 -0
  107. package/client/dist/assets/chat-BQNMD0PL.js +1 -0
  108. package/client/dist/assets/chat-BsbNGPW9.js +1 -0
  109. package/client/dist/assets/chat-CboQguCi.js +1 -0
  110. package/client/dist/assets/chat-DRCa9pOt.js +1 -0
  111. package/client/dist/assets/chat-DwUm6W9z.js +1 -0
  112. package/client/dist/assets/chat-yoXwguQu.js +1 -0
  113. package/client/dist/assets/chunk-CilyBKbf.js +1 -0
  114. package/client/dist/assets/clojure-DBjRWN6g.js +1 -0
  115. package/client/dist/assets/clsx-DnqN-uhr.js +1 -0
  116. package/client/dist/assets/code-AL1rVIMb.js +1 -0
  117. package/client/dist/assets/code-C0BKpkht.js +1 -0
  118. package/client/dist/assets/code-C0FTS3ew.js +1 -0
  119. package/client/dist/assets/code-CPcHxzxw.js +1 -0
  120. package/client/dist/assets/code-D3ryDniw.js +1 -0
  121. package/client/dist/assets/code-D3zVVQTj.js +1 -0
  122. package/client/dist/assets/code-PCmfS3dn.js +1 -0
  123. package/client/dist/assets/code-exI0G5Wd.js +1 -0
  124. package/client/dist/assets/codicon-ngg6Pgfi.ttf +0 -0
  125. package/client/dist/assets/coffee-Cfk_XHGR.js +1 -0
  126. package/client/dist/assets/commands-B772IyDa.js +1 -0
  127. package/client/dist/assets/commands-BDDp6xFG.js +1 -0
  128. package/client/dist/assets/commands-CJxCry-o.js +1 -0
  129. package/client/dist/assets/commands-CfgY-_of.js +1 -0
  130. package/client/dist/assets/commands-DLrvnPNg.js +1 -0
  131. package/client/dist/assets/commands-IXMOKBYt.js +1 -0
  132. package/client/dist/assets/commands-UD1NzmwX.js +1 -0
  133. package/client/dist/assets/commands-sqrqsxyE.js +1 -0
  134. package/client/dist/assets/common-DCr6VzJ7.js +1 -0
  135. package/client/dist/assets/common-Dard9UNH.js +1 -0
  136. package/client/dist/assets/common-DeDELLZJ.js +1 -0
  137. package/client/dist/assets/common-DltqHaAe.js +1 -0
  138. package/client/dist/assets/common-Dmm1GhdD.js +1 -0
  139. package/client/dist/assets/common-DnjcgkPH.js +1 -0
  140. package/client/dist/assets/common-GbpxfPG8.js +1 -0
  141. package/client/dist/assets/common-wA36jmj1.js +1 -0
  142. package/client/dist/assets/cpp-BVob6BaP.js +1 -0
  143. package/client/dist/assets/csharp-C4fbRuOu.js +1 -0
  144. package/client/dist/assets/csp-DthFP_vT.js +1 -0
  145. package/client/dist/assets/css-CGMH0hcW.js +3 -0
  146. package/client/dist/assets/css.worker-Wv5dxAWO.js +89 -0
  147. package/client/dist/assets/cssMode-Cc6ozl-J.js +1 -0
  148. package/client/dist/assets/cypher-Pnf68BRV.js +1 -0
  149. package/client/dist/assets/dart-PMMOtxZX.js +1 -0
  150. package/client/dist/assets/dashboard-B4ixDVk8.js +1 -0
  151. package/client/dist/assets/dashboard-BZBADHSj.js +1 -0
  152. package/client/dist/assets/dashboard-C1MfeUHs.js +1 -0
  153. package/client/dist/assets/dashboard-C7SK6xu5.js +1 -0
  154. package/client/dist/assets/dashboard-CB6Le1yN.js +1 -0
  155. package/client/dist/assets/dashboard-CoTpMOBM.js +1 -0
  156. package/client/dist/assets/dashboard-Duo4DDCW.js +1 -0
  157. package/client/dist/assets/dashboard-I19DXBxw.js +1 -0
  158. package/client/dist/assets/dist-js-BY-Fv_fg.js +1 -0
  159. package/client/dist/assets/dist-js-Bakc4uxT.js +1 -0
  160. package/client/dist/assets/dockerfile-di1nsJCc.js +1 -0
  161. package/client/dist/assets/ecl-D_WVcB5M.js +1 -0
  162. package/client/dist/assets/editor-Br_kD0ds.css +1 -0
  163. package/client/dist/assets/editor.api2-XLGzZfbc.js +872 -0
  164. package/client/dist/assets/editor.main-CfXxHimg.js +6 -0
  165. package/client/dist/assets/editor.worker-Bd9IXS8d.js +26 -0
  166. package/client/dist/assets/elixir-OAdJEMOn.js +1 -0
  167. package/client/dist/assets/explore-4mFpnrKU.js +1 -0
  168. package/client/dist/assets/explore-A8Ltoblq.js +1 -0
  169. package/client/dist/assets/explore-B9A3iN2W.js +1 -0
  170. package/client/dist/assets/explore-BV5Xxlsn.js +1 -0
  171. package/client/dist/assets/explore-BrBJvfjP.js +1 -0
  172. package/client/dist/assets/explore-C3FSE42C.js +1 -0
  173. package/client/dist/assets/explore-D2EFgt8J.js +1 -0
  174. package/client/dist/assets/explore-hFc3HFcp.js +1 -0
  175. package/client/dist/assets/flow9-D3QEZjgn.js +1 -0
  176. package/client/dist/assets/format-command-CwGuwzGA.js +1 -0
  177. package/client/dist/assets/freemarker2-DP7J1gG3.js +3 -0
  178. package/client/dist/assets/fsharp-BF0k_8N8.js +1 -0
  179. package/client/dist/assets/go-BAQO5Jsz.js +1 -0
  180. package/client/dist/assets/graphql-hdFVFkiV.js +1 -0
  181. package/client/dist/assets/handlebars-BjRlucw6.js +1 -0
  182. package/client/dist/assets/hcl-DWnl1o-X.js +1 -0
  183. package/client/dist/assets/html-OumBQJ-U.js +1 -0
  184. package/client/dist/assets/html.worker-CQP8QQsS.js +502 -0
  185. package/client/dist/assets/htmlMode-CStc3zXM.js +1 -0
  186. package/client/dist/assets/index-CimDRRi7.css +2 -0
  187. package/client/dist/assets/index-XGZaKl_u.js +142 -0
  188. package/client/dist/assets/ini-CB-6OVu3.js +1 -0
  189. package/client/dist/assets/integrations-C3p12Ms6.js +1 -0
  190. package/client/dist/assets/integrations-Cr6hH7XR.js +1 -0
  191. package/client/dist/assets/integrations-Cublz3m6.js +1 -0
  192. package/client/dist/assets/integrations-D28q1kF6.js +1 -0
  193. package/client/dist/assets/integrations-DRdbki5W.js +1 -0
  194. package/client/dist/assets/integrations-DaC4SzzL.js +1 -0
  195. package/client/dist/assets/integrations-DmQYCUvN.js +1 -0
  196. package/client/dist/assets/integrations-HIlUxXVs.js +1 -0
  197. package/client/dist/assets/java-d1CmfiHX.js +1 -0
  198. package/client/dist/assets/javascript-CMk--e7g.js +1 -0
  199. package/client/dist/assets/jobs-BE1siB0M.js +1 -0
  200. package/client/dist/assets/jobs-BHcQ_Faf.js +1 -0
  201. package/client/dist/assets/jobs-CFfc2dNX.js +1 -0
  202. package/client/dist/assets/jobs-CSi5n8X_.js +1 -0
  203. package/client/dist/assets/jobs-Dc3X86PY.js +1 -0
  204. package/client/dist/assets/jobs-De5tASex.js +1 -0
  205. package/client/dist/assets/jobs-DsoXEdo7.js +1 -0
  206. package/client/dist/assets/jobs-Wl-ApPMb.js +1 -0
  207. package/client/dist/assets/json.worker-DzV-CpCQ.js +58 -0
  208. package/client/dist/assets/jsonMode-C2h3ZcjZ.js +7 -0
  209. package/client/dist/assets/julia-Bgv08lKa.js +1 -0
  210. package/client/dist/assets/kotlin-u98kaVTf.js +1 -0
  211. package/client/dist/assets/less-CjYwpgg5.js +2 -0
  212. package/client/dist/assets/lexon-YTjaAFBB.js +1 -0
  213. package/client/dist/assets/lib-CPxTMOAq.js +7 -0
  214. package/client/dist/assets/liquid-mI3KJrBE.js +1 -0
  215. package/client/dist/assets/lspLanguageFeatures-DU09ggWi.js +4 -0
  216. package/client/dist/assets/lua-BzmkWv27.js +1 -0
  217. package/client/dist/assets/m3-CFwk9fw0.js +1 -0
  218. package/client/dist/assets/markdown-CR5iMpSZ.js +1 -0
  219. package/client/dist/assets/mdx-C41VDTR_.js +1 -0
  220. package/client/dist/assets/mips-CcEalc17.js +1 -0
  221. package/client/dist/assets/monaco.contribution-CPObAXMC.js +2 -0
  222. package/client/dist/assets/msdax-BQbkawnr.js +1 -0
  223. package/client/dist/assets/mysql-GTlaaW_P.js +1 -0
  224. package/client/dist/assets/nav-0fwkrgHt.js +1 -0
  225. package/client/dist/assets/nav-BEL3MTwK.js +1 -0
  226. package/client/dist/assets/nav-B_G-TJDW.js +1 -0
  227. package/client/dist/assets/nav-C2YXcbZS.js +1 -0
  228. package/client/dist/assets/nav-ClzOE4mA.js +1 -0
  229. package/client/dist/assets/nav-CtYwmMgu.js +1 -0
  230. package/client/dist/assets/nav-D2bOGSEg.js +1 -0
  231. package/client/dist/assets/nav-iH1V5j6o.js +1 -0
  232. package/client/dist/assets/objective-c-Byu1T5if.js +1 -0
  233. package/client/dist/assets/pascal-BrfzBfRm.js +1 -0
  234. package/client/dist/assets/pascaligo-BXXKFUeo.js +1 -0
  235. package/client/dist/assets/perl-B3OikKq-.js +1 -0
  236. package/client/dist/assets/pgsql-CTsa0Acc.js +1 -0
  237. package/client/dist/assets/php-DiQh3FUW.js +1 -0
  238. package/client/dist/assets/pla-92uH8Fzm.js +1 -0
  239. package/client/dist/assets/postiats-BbeWkKUr.js +1 -0
  240. package/client/dist/assets/powerquery-DgDMzpsm.js +1 -0
  241. package/client/dist/assets/powershell-BfdUUzaG.js +1 -0
  242. package/client/dist/assets/preload-helper-DSXbuxSR.js +1 -0
  243. package/client/dist/assets/protobuf-BojW2ftW.js +2 -0
  244. package/client/dist/assets/pug-BxqTg3IU.js +1 -0
  245. package/client/dist/assets/python-Y27rKQtk.js +1 -0
  246. package/client/dist/assets/qsharp-BX_A-MW9.js +1 -0
  247. package/client/dist/assets/r-D9BMnxvJ.js +1 -0
  248. package/client/dist/assets/razor-Cd5-q9Bp.js +1 -0
  249. package/client/dist/assets/redis-5cJqEQJJ.js +1 -0
  250. package/client/dist/assets/redshift-d8BBqiwb.js +1 -0
  251. package/client/dist/assets/restructuredtext-C8a6yIcZ.js +1 -0
  252. package/client/dist/assets/ruby-egeh-6KX.js +1 -0
  253. package/client/dist/assets/rust-a3r9IInB.js +1 -0
  254. package/client/dist/assets/sb-y8iRIDei.js +1 -0
  255. package/client/dist/assets/scala-BPDK2AmK.js +1 -0
  256. package/client/dist/assets/scheme-BIWUEoOs.js +1 -0
  257. package/client/dist/assets/scss-CA-PSzwg.js +3 -0
  258. package/client/dist/assets/settings-55oDcbSh.js +1 -0
  259. package/client/dist/assets/settings-Bd4Tq1RB.js +1 -0
  260. package/client/dist/assets/settings-CCSM-Fhn.js +1 -0
  261. package/client/dist/assets/settings-D3e_bDoW.js +1 -0
  262. package/client/dist/assets/settings-DKbTkbn7.js +1 -0
  263. package/client/dist/assets/settings-Dxpo6_w7.js +1 -0
  264. package/client/dist/assets/settings-bt84e3Aa.js +1 -0
  265. package/client/dist/assets/settings-nu68QukM.js +1 -0
  266. package/client/dist/assets/setup-BMqwfbW9.js +1 -0
  267. package/client/dist/assets/setup-Bb5LcG28.js +1 -0
  268. package/client/dist/assets/setup-BeEx2_da.js +1 -0
  269. package/client/dist/assets/setup-CCCrB53Q.js +1 -0
  270. package/client/dist/assets/setup-CJA0ATmd.js +1 -0
  271. package/client/dist/assets/setup-CeiDbZcb.js +1 -0
  272. package/client/dist/assets/setup-Cus7TApA.js +1 -0
  273. package/client/dist/assets/setup-D9qOs2Xo.js +1 -0
  274. package/client/dist/assets/shell--LiT1Bja.js +1 -0
  275. package/client/dist/assets/solidity-DdqZccZg.js +1 -0
  276. package/client/dist/assets/sophia-S6-YxNG_.js +1 -0
  277. package/client/dist/assets/sparql-BSf5kMp2.js +1 -0
  278. package/client/dist/assets/specs-BFfu3u-a.js +1 -0
  279. package/client/dist/assets/specs-B__C8-8a.js +1 -0
  280. package/client/dist/assets/specs-CZ1PsXsC.js +1 -0
  281. package/client/dist/assets/specs-D2FzlLn9.js +1 -0
  282. package/client/dist/assets/specs-DaUTrNF9.js +1 -0
  283. package/client/dist/assets/specs-Dyc5hYeE.js +1 -0
  284. package/client/dist/assets/specs-cKEh2LXt.js +1 -0
  285. package/client/dist/assets/specs-k0PyLDVt.js +1 -0
  286. package/client/dist/assets/sql-D7KgjR8G.js +1 -0
  287. package/client/dist/assets/st-BnoDa-Ml.js +1 -0
  288. package/client/dist/assets/swift-DEUHTkUX.js +1 -0
  289. package/client/dist/assets/systemverilog-Tqb_KPnW.js +1 -0
  290. package/client/dist/assets/tcl-BmBFS2qq.js +1 -0
  291. package/client/dist/assets/terminal-80yDMgMF.js +1 -0
  292. package/client/dist/assets/terminal-Bje4ziIa.js +1 -0
  293. package/client/dist/assets/terminal-C2WYcFHF.js +1 -0
  294. package/client/dist/assets/terminal-CSONJOex.js +1 -0
  295. package/client/dist/assets/terminal-DEqzGtcr.js +1 -0
  296. package/client/dist/assets/terminal-DeWzh6ys.js +1 -0
  297. package/client/dist/assets/terminal-YOlsJCQj.js +1 -0
  298. package/client/dist/assets/terminal-lkZYR4wJ.js +1 -0
  299. package/client/dist/assets/tickets-CB7N30gm.js +1 -0
  300. package/client/dist/assets/tickets-CF2PYelu.js +1 -0
  301. package/client/dist/assets/tickets-DNOANUXr.js +1 -0
  302. package/client/dist/assets/tickets-DU1aqsbr.js +1 -0
  303. package/client/dist/assets/tickets-DYvafSaY.js +1 -0
  304. package/client/dist/assets/tickets-DlpC_iTg.js +1 -0
  305. package/client/dist/assets/tickets-DucYgtdl.js +1 -0
  306. package/client/dist/assets/tickets-clefmXLv.js +1 -0
  307. package/client/dist/assets/ts.worker-METxwbDZ.js +67719 -0
  308. package/client/dist/assets/tsMode-B0y_xEci.js +11 -0
  309. package/client/dist/assets/twig-BQV8igWC.js +1 -0
  310. package/client/dist/assets/typescript-BzK0OgwW.js +1 -0
  311. package/client/dist/assets/typespec-DlFroUGY.js +1 -0
  312. package/client/dist/assets/useProjectCache-DSaiGFjV.js +1 -0
  313. package/client/dist/assets/vb-BlrJpIMX.js +1 -0
  314. package/client/dist/assets/wgsl-BWgIc6FZ.js +298 -0
  315. package/client/dist/assets/workers-rt--R2Qy.js +1 -0
  316. package/client/dist/assets/xml-eX9QXAmI.js +1 -0
  317. package/client/dist/assets/yaml-fcsNkpOt.js +1 -0
  318. package/client/dist/index.html +246 -0
  319. package/docs/README.md +54 -0
  320. package/docs/cli.md +198 -0
  321. package/docs/codex.md +210 -0
  322. package/docs/creating-specs.md +197 -0
  323. package/docs/customizing.md +197 -0
  324. package/docs/getting-started.md +140 -0
  325. package/docs/internals/README.md +25 -0
  326. package/docs/internals/adding-a-provider.md +238 -0
  327. package/docs/internals/api-reference.md +634 -0
  328. package/docs/internals/architecture.md +332 -0
  329. package/docs/internals/configuration.md +172 -0
  330. package/docs/internals/openspec-workflow.md +282 -0
  331. package/docs/internals/operations-runbook.md +198 -0
  332. package/docs/internals/profiles.md +152 -0
  333. package/docs/platforms/macos.md +130 -0
  334. package/docs/platforms/windows.md +81 -0
  335. package/docs/running-pipelines.md +240 -0
  336. package/docs/terminal.md +138 -0
  337. package/docs/tracking-cost.md +155 -0
  338. package/package.json +82 -0
  339. package/server/dist/agent-generator.js +232 -0
  340. package/server/dist/agent-refine-db.js +124 -0
  341. package/server/dist/agent-refine-manager.js +526 -0
  342. package/server/dist/ai-invocations.js +111 -0
  343. package/server/dist/attachment-manager.js +299 -0
  344. package/server/dist/auth.js +207 -0
  345. package/server/dist/binary-probe.js +35 -0
  346. package/server/dist/browser-capture-manager.js +576 -0
  347. package/server/dist/browser-capture-types.js +28 -0
  348. package/server/dist/browser-network.js +149 -0
  349. package/server/dist/browser-playwright.js +888 -0
  350. package/server/dist/build-dirs.js +44 -0
  351. package/server/dist/changes-reader.js +120 -0
  352. package/server/dist/chat-manager.js +1060 -0
  353. package/server/dist/chromium-resolver.js +311 -0
  354. package/server/dist/code-explorer-router.js +788 -0
  355. package/server/dist/codex-otel-bridge.js +235 -0
  356. package/server/dist/command-resolver.js +102 -0
  357. package/server/dist/config.js +306 -0
  358. package/server/dist/context-budget.js +113 -0
  359. package/server/dist/context-scope.js +279 -0
  360. package/server/dist/contract-refine-runner.js +521 -0
  361. package/server/dist/core-compat.js +207 -0
  362. package/server/dist/core-package.js +14 -0
  363. package/server/dist/db.js +1034 -0
  364. package/server/dist/desktop-analytics.js +156 -0
  365. package/server/dist/desktop-db.js +456 -0
  366. package/server/dist/desktop-router.js +735 -0
  367. package/server/dist/docs-router.js +207 -0
  368. package/server/dist/explore-contract-refine.js +421 -0
  369. package/server/dist/explore-cwd-manager.js +242 -0
  370. package/server/dist/explore-draft-title.js +47 -0
  371. package/server/dist/explore-smash.js +450 -0
  372. package/server/dist/feature-flags.js +17 -0
  373. package/server/dist/file-provenance.js +382 -0
  374. package/server/dist/file-summary-generator.js +221 -0
  375. package/server/dist/file-summary-manager.js +689 -0
  376. package/server/dist/hooks.js +102 -0
  377. package/server/dist/ids.js +7 -0
  378. package/server/dist/index.js +586 -0
  379. package/server/dist/metrics.js +136 -0
  380. package/server/dist/mobile/index.js +16 -0
  381. package/server/dist/mobile/mobile-admin-router.js +84 -0
  382. package/server/dist/mobile/mobile-auth.js +67 -0
  383. package/server/dist/mobile/mobile-devices.js +80 -0
  384. package/server/dist/mobile/mobile-event-bus.js +39 -0
  385. package/server/dist/mobile/mobile-gateway.js +285 -0
  386. package/server/dist/mobile/mobile-mdns.js +81 -0
  387. package/server/dist/mobile/mobile-pairing.js +179 -0
  388. package/server/dist/mobile/mobile-redact.js +53 -0
  389. package/server/dist/mobile/mobile-router.js +411 -0
  390. package/server/dist/mobile/mobile-tls.js +86 -0
  391. package/server/dist/mobile/mobile-types.js +9 -0
  392. package/server/dist/mobile/mobile-ws.js +275 -0
  393. package/server/dist/path-resolver.js +298 -0
  394. package/server/dist/plugin-manager.js +617 -0
  395. package/server/dist/plugins/claude-approval.js +179 -0
  396. package/server/dist/plugins/claude-md-mutation.js +146 -0
  397. package/server/dist/plugins/codex-mcp.js +108 -0
  398. package/server/dist/plugins/contributors.js +72 -0
  399. package/server/dist/plugins/drift.js +58 -0
  400. package/server/dist/plugins/index.js +14 -0
  401. package/server/dist/plugins/json-mutation.js +120 -0
  402. package/server/dist/plugins/manager.js +32 -0
  403. package/server/dist/plugins/ownership.js +86 -0
  404. package/server/dist/plugins/paths.js +37 -0
  405. package/server/dist/plugins/prereq-installer.js +104 -0
  406. package/server/dist/plugins/rail-integration.js +79 -0
  407. package/server/dist/plugins/serena/index.js +13 -0
  408. package/server/dist/plugins/serena/install.js +91 -0
  409. package/server/dist/plugins/serena/instructions-content.js +21 -0
  410. package/server/dist/plugins/serena/manifest.js +111 -0
  411. package/server/dist/plugins/serena/verify.js +78 -0
  412. package/server/dist/plugins-router.js +215 -0
  413. package/server/dist/pricing.js +89 -0
  414. package/server/dist/profile-manager.js +310 -0
  415. package/server/dist/profiles-router.js +759 -0
  416. package/server/dist/project-registry.js +443 -0
  417. package/server/dist/project-router.js +4016 -0
  418. package/server/dist/proposal-manager.js +291 -0
  419. package/server/dist/provider-selection.js +69 -0
  420. package/server/dist/providers/claude-adapter.js +281 -0
  421. package/server/dist/providers/codex-adapter.js +264 -0
  422. package/server/dist/providers/index.js +23 -0
  423. package/server/dist/providers/registry.js +37 -0
  424. package/server/dist/providers/types.js +22 -0
  425. package/server/dist/queue-manager.js +1511 -0
  426. package/server/dist/rails-router.js +362 -0
  427. package/server/dist/rails-store.js +116 -0
  428. package/server/dist/result-event.js +106 -0
  429. package/server/dist/schemas/profile.v1.json +151 -0
  430. package/server/dist/setup-manager.js +1165 -0
  431. package/server/dist/setup-prerequisites.js +372 -0
  432. package/server/dist/smash-runner.js +663 -0
  433. package/server/dist/spec-draft-parser.js +133 -0
  434. package/server/dist/spec-launcher-manager.js +174 -0
  435. package/server/dist/spec-models.js +32 -0
  436. package/server/dist/specrails-tech-client.js +82 -0
  437. package/server/dist/spending.js +448 -0
  438. package/server/dist/telemetry-compactor.js +180 -0
  439. package/server/dist/telemetry-export.js +317 -0
  440. package/server/dist/telemetry-receiver.js +224 -0
  441. package/server/dist/terminal-manager.js +633 -0
  442. package/server/dist/terminal-marks-store.js +117 -0
  443. package/server/dist/terminal-osc-parser.js +159 -0
  444. package/server/dist/terminal-settings.js +282 -0
  445. package/server/dist/terminal-shell-integration.js +196 -0
  446. package/server/dist/ticket-broadcast.js +47 -0
  447. package/server/dist/ticket-store.js +397 -0
  448. package/server/dist/ticket-watcher.js +117 -0
  449. package/server/dist/types.js +10 -0
  450. package/server/dist/user-mcp-config.js +117 -0
  451. package/server/dist/util/cli-prompt.js +181 -0
  452. package/server/dist/util/secure-fs.js +50 -0
  453. package/server/dist/util/win-spawn.js +43 -0
  454. package/server/dist/webhook-manager.js +89 -0
  455. package/server/dist/ws-routing.js +47 -0
@@ -0,0 +1,634 @@
1
+ # API reference
2
+
3
+ REST and WebSocket endpoints exposed by the app server. The server binds to `127.0.0.1` only (loopback); the default port is `4200` but it can be overridden with `--port <n>` on the server command line.
4
+
5
+ ## Authentication
6
+
7
+ An app token is **auto-generated on first run** (two concatenated UUIDs) and persisted to `~/.specrails/desktop.token` with mode `0600`. It is **mandatory**, not optional. Every `/api/*` route is protected by it, with two exceptions that are mounted before the auth middleware: `/api/health` and `/api/token`.
8
+
9
+ Send the token either as a Bearer header or an `X-Desktop-Token` header:
10
+
11
+ ```http
12
+ Authorization: Bearer <token>
13
+ X-Desktop-Token: <token>
14
+ ```
15
+
16
+ The CLI and the desktop client read the token automatically. The browser client fetches it same-origin from `GET /api/token`. WebSocket upgrades carry it as the `token` query parameter.
17
+
18
+ There is no UI to set or clear the token, and it is not an app setting.
19
+
20
+ This page is hand-maintained against the route declarations in `server/*-router.ts`. If you spot a discrepancy, please file an issue.
21
+
22
+ ---
23
+
24
+ ## Top-level mounts
25
+
26
+ | Prefix | Router | Auth | Notes |
27
+ |--------|--------|------|-------|
28
+ | `/api/health` | direct | none | Liveness probe (`{ status, version, uptime, projects, mode }`) |
29
+ | `/api/token` | direct | none | Returns the auth token for local bootstrapping (loopback-only) |
30
+ | `/api/docs` | `docs-router` | none (mounted before auth) | Bundled documentation portal |
31
+ | `/api/mobile/*` | `mobile-admin-router` | Bearer / X-Desktop-Token + loopback | Mobile Gateway admin (enable/pair/devices) |
32
+ | `/api/*` | `desktop-router` | Bearer / X-Desktop-Token | Cross-project operations |
33
+ | `/api/projects/:projectId/*` | `project-router` | Bearer / X-Desktop-Token | Project-scoped operations |
34
+ | `/api/projects/:projectId/code/*` | `code-explorer-router` | Bearer / X-Desktop-Token | Read-only Code explorer |
35
+ | `/api/projects/:projectId/rails/*` | `rails-router` | Bearer / X-Desktop-Token | Rails (execution lanes) |
36
+ | `/api/projects/:projectId/profiles/*` | `profiles-router` | Bearer / X-Desktop-Token | Agent profiles + catalog studio |
37
+ | `/api/projects/:projectId/plugins/*` | `plugins-router` | Bearer / X-Desktop-Token | Plugin marketplace |
38
+ | `/otlp/v1/{traces,metrics,logs}` | `telemetry-receiver` | none (gated by job id) | OTLP/JSON receiver |
39
+ | `/ws` | WebSocket | token in query | Project + app event stream |
40
+ | `/ws/terminal/:id` | WebSocket | token in query | PTY traffic for the terminal panel |
41
+
42
+ **Mount order matters**: the `desktop-router` is mounted at `/api` **before** the project router, so exact routes such as `GET /api/projects` and `DELETE /api/projects/:id` are answered by the desktop router, while everything under `/api/projects/:projectId/*` falls through to the project router.
43
+
44
+ A non-localhost `Origin` header is rejected by the CORS middleware with `403 Forbidden: cross-origin requests not allowed`.
45
+
46
+ > **Breaking change (Specrails Desktop rebrand)**: the former `/api/hub/*` prefix is now `/api/*` (e.g. `/api/hub/state` → `/api/state`, `/api/hub/token` → `/api/token`, `/api/hub/projects` → `/api/projects`), the auth header `X-Hub-Token` is now `X-Desktop-Token`, the WebSocket auth subprotocol `hub-token.<token>` is now `desktop-token.<token>`, and the webhook/WS event `hub_daily_budget_exceeded` is now `desktop_daily_budget_exceeded`. There is no server-side alias for the old paths or header.
47
+
48
+ ---
49
+
50
+ ## `/api/*`
51
+
52
+ ### Projects
53
+
54
+ | Method | Path | Notes |
55
+ |--------|------|-------|
56
+ | `GET` | `/projects` | List registered projects |
57
+ | `POST` | `/projects` | Register a project. Body `{ path, name?, provider?, providers? }`. `providers: string[]` enables a multi-provider project (first entry = primary/default); legacy single `provider` still honoured; omit both to default to `["claude"]`. 409 if the path is already registered |
58
+ | `DELETE` | `/projects/:id` | Unregister (does not delete the project directory) |
59
+ | `GET` | `/resolve?path=…` | Find a project by **exact** canonical filesystem path. No parent-directory walking — a subdirectory returns 404 |
60
+
61
+ ### App state
62
+
63
+ | Method | Path | Notes |
64
+ |--------|------|-------|
65
+ | `GET` | `/state` | `{ projects, projectCount, …todayStats }` (today's cross-project cost/run aggregates spread into the response) |
66
+ | `GET` | `/cli-status` | Detected AI CLI provider + version (`{ provider, version }`), e.g. claude or codex — runs `<binary> --version` |
67
+ | `GET` | `/available-providers` | Provider catalogue (Claude, Codex) used by the setup wizard |
68
+ | `GET` | `/core-compat` | specrails-core version compatibility probe |
69
+ | `GET` | `/setup-prerequisites` | Tool checks (`node`/`npm`/`npx`/`git`, optionally `uv`). Add `?diagnostic=1` to nest a `diagnostic` object: `{ pathSegments, pathSources, loginShellStatus, whichResults, nodeEnv, platform }` |
70
+
71
+ ### Settings, budget, theme
72
+
73
+ | Method | Path | Notes |
74
+ |--------|------|-------|
75
+ | `GET` | `/settings` | App-wide settings |
76
+ | `PUT` | `/settings` | Update any subset of `{ port?, specrailsTechUrl?, costAlertThresholdUsd? }` |
77
+ | `GET` | `/budget` | App-wide budget config |
78
+ | `PATCH` | `/budget` | Update the app-wide daily budget |
79
+ | `GET` | `/theme` | Current UI theme (defaults to `specrails`) |
80
+ | `PATCH` | `/theme` | Set UI theme. Body `{ theme }`; one of `dracula`, `aurora-light`, `obsidian-dark`, `matrix`, `specrails`. 400 on an unknown value |
81
+ | `GET` | `/language` | Current UI language; `{ language: null }` when the user never chose one (the client then follows the OS language) |
82
+ | `PATCH` | `/language` | Set UI language. Body `{ language }`; one of `en`, `es`, `fr`, `de`, `pt`, `it`, `zh`, `ja`. 400 on an unknown value |
83
+ | `GET` | `/code-explorer-settings` | `{ language, monthlyBudgetUsd }` (summary language `en`/`es`, default budget $5) |
84
+ | `PATCH` | `/code-explorer-settings` | Update `{ language?, monthlyBudgetUsd? }` |
85
+ | `GET` | `/terminal-settings` | App-wide terminal panel defaults |
86
+ | `PATCH` | `/terminal-settings` | Update app-wide terminal defaults |
87
+
88
+ ### Analytics (app-wide)
89
+
90
+ | Method | Path | Notes |
91
+ |--------|------|-------|
92
+ | `GET` | `/analytics?period=&from=&to=` | Cross-project aggregated spending (the Desktop Analytics page; supports a custom `from`/`to` range) |
93
+ | `GET` | `/recent-jobs?limit=` | Recent jobs across all projects (1–50) |
94
+
95
+ ### Mobile Gateway admin (`/api/mobile/*`)
96
+
97
+ Loopback-only admin surface for the Mobile Gateway (the gateway itself is a separate HTTPS+WSS listener the phone talks to). The wire contract the phone consumes intentionally keeps the legacy `hub.*` names — see the frozen mobile wire-compat note in `CLAUDE.md`.
98
+
99
+ | Method | Path | Notes |
100
+ |--------|------|-------|
101
+ | `GET` | `/status` | Gateway status (`{ enabled, running, port, certFingerprint, lanAddresses, mdnsEnabled, desktopName }`) |
102
+ | `POST` | `/enable` | Start the gateway (generates the TLS identity on first run) |
103
+ | `POST` | `/disable` | Stop the gateway |
104
+ | `POST` | `/pairing-session` | Open a pairing session; returns the QR payload |
105
+ | `GET` | `/pairing-session` | Poll the current pairing session (pending claim, if any) |
106
+ | `POST` | `/pairing-session/approve` | Approve the pending claim (pairs the device) |
107
+ | `POST` | `/pairing-session/deny` | Deny the pending claim |
108
+ | `DELETE` | `/pairing-session` | Cancel the pairing session |
109
+ | `GET` | `/devices` | List paired devices |
110
+ | `DELETE` | `/devices/:id` | Revoke a paired device |
111
+ | `POST` | `/cert/rotate` | Rotate the gateway TLS identity (unpairs every device) |
112
+
113
+ ### specrails-tech proxy
114
+
115
+ Proxies the external specrails-tech agents service (base URL from `desktop_settings.specrails_tech_url`).
116
+
117
+ | Method | Path | Notes |
118
+ |--------|------|-------|
119
+ | `GET` | `/specrails-tech/status` | Health + connected flag |
120
+ | `GET` | `/specrails-tech/agents` | List remote agents |
121
+ | `GET` | `/specrails-tech/agents/:slug` | Agent detail |
122
+ | `GET` | `/specrails-tech/docs` | List remote docs |
123
+ | `GET` | `/specrails-tech/docs/:page` | Doc page detail |
124
+
125
+ ### Agents catalogue (app-wide)
126
+
127
+ | Method | Path | Notes |
128
+ |--------|------|-------|
129
+ | `GET` | `/agents` | List all configured agents |
130
+ | `GET` | `/agents/:id` | Get one agent |
131
+ | `POST` | `/agents` | Create an agent entry |
132
+ | `PATCH` | `/agents/:id` | Update |
133
+
134
+ ### Webhooks
135
+
136
+ | Method | Path | Notes |
137
+ |--------|------|-------|
138
+ | `GET` | `/webhooks` | List webhooks |
139
+ | `POST` | `/webhooks` | Create |
140
+ | `PATCH` | `/webhooks/:id` | Update |
141
+ | `DELETE` | `/webhooks/:id` | Delete |
142
+ | `POST` | `/webhooks/:id/test` | Fire a test payload |
143
+
144
+ Subscribable events: `job.completed`, `job.failed`, `job.canceled`, `daily_budget_exceeded`, `desktop_daily_budget_exceeded`. **Breaking**: the event formerly named `hub_daily_budget_exceeded` is now `desktop_daily_budget_exceeded` — stored webhook subscriptions are rewritten automatically by a one-time migration, but external consumers matching on the event name must update.
145
+
146
+ ---
147
+
148
+ ## `/api/projects/:projectId/*`
149
+
150
+ All routes below are prefixed with `/api/projects/:projectId/`. In the client, use `getApiBase()` as the prefix — it injects the active project ID for you and throws if no project is active.
151
+
152
+ ### Spawn / commands / config
153
+
154
+ | Method | Path | Notes |
155
+ |--------|------|-------|
156
+ | `POST` | `/spawn` | Queue a command job. Body `{ command, priority?, dependsOnJobId?, pipelineId?, profileName?, aiEngine? }`. `aiEngine` is a per-job provider override validated against installed providers (omit to use the primary). `profileName: null` forces legacy (no profile). Returns `202 { jobId, position }` |
157
+ | `GET` | `/config` | List discovered `/specrails:*` and `/opsx:*` commands |
158
+ | `POST` | `/config` | Force re-discovery |
159
+ | `GET` | `/default-spec-model?provider=` | Resolve the Quick-spec model for an engine. Returns `{ model, provider, allowed, providers }`; `provider` falls back to the primary if omitted/invalid |
160
+
161
+ ### Pipelines and jobs
162
+
163
+ | Method | Path | Notes |
164
+ |--------|------|-------|
165
+ | `GET` | `/pipelines/:pipelineId` | One pipeline (group of jobs) |
166
+ | `GET` | `/state` | Active job, queue depth, paused flag |
167
+ | `GET` | `/activity` | Chronological event log (`job_started`/`job_completed`/`job_failed`/`job_canceled` items) |
168
+ | `GET` | `/issues` | GitHub issues linked to the project |
169
+ | `GET` | `/jobs` | Job list (`?limit=&offset=&status=`) |
170
+ | `GET` | `/jobs/export` | CSV/JSON export |
171
+ | `GET` | `/jobs/compare` | Compare metrics between two jobs |
172
+ | `GET` | `/jobs/:id` | One job. Returns `{ job, events, phaseDefinitions }`; `job` is annotated with `hasTelemetry` and `tickets[]` (resolved from the command, powers the ticket header) |
173
+ | `DELETE` | `/jobs/:id` | Cancel a running or queued job |
174
+ | `DELETE` | `/jobs` | Purge completed jobs (optional `{ from, to }` window) |
175
+ | `PATCH` | `/jobs/:id/priority` | Re-rank a queued job |
176
+ | `GET` | `/jobs/:jobId/diagnostic` | Stream a diagnostic ZIP (telemetry + profile + plugins snapshots) |
177
+
178
+ ### Queue
179
+
180
+ Jobs within a project run **strictly one at a time** (serialized) — a single queue per project. Parallelism is across projects only.
181
+
182
+ | Method | Path | Notes |
183
+ |--------|------|-------|
184
+ | `GET` | `/queue` | Current queue state |
185
+ | `POST` | `/queue/pause` | Pause |
186
+ | `POST` | `/queue/resume` | Resume |
187
+ | `PUT` | `/queue/reorder` | Reorder. Body `{ jobIds: string[] }` |
188
+
189
+ ### Analytics + spending
190
+
191
+ Spending is tracked across six surfaces: `job`, `quick-spec`, `explore-spec`, `ai-edit`, `smash`, `file-summary`.
192
+
193
+ | Method | Path | Notes |
194
+ |--------|------|-------|
195
+ | `GET` | `/stats` | Summary (total jobs, tokens, cost) |
196
+ | `GET` | `/metrics` | Raw metrics |
197
+ | `GET` | `/spending` | Burn-rate / timeline / by-surface / by-model / top-tickets — powers the Analytics page |
198
+ | `GET` | `/invocations` | Paginated raw `ai_invocations` rows |
199
+ | `GET` | `/tickets/:id/spending-summary` | Per-ticket cross-surface aggregate (powers `TicketSpendingLine`) |
200
+ | `GET` | `/analytics/export?format=csv\|json&mode=summary\|raw&…` | Multi-section summary CSV/JSON, or raw rows (10 000 cap) |
201
+
202
+ ### Budget
203
+
204
+ | Method | Path | Notes |
205
+ |--------|------|-------|
206
+ | `GET` | `/budget` | Daily cap + per-job alert |
207
+ | `PATCH` | `/budget` | Update |
208
+
209
+ ### Tickets
210
+
211
+ | Method | Path | Notes |
212
+ |--------|------|-------|
213
+ | `GET` | `/tickets` | Filters: `?status=`, `?label=`, `?q=` |
214
+ | `GET` | `/tickets/:id` | One ticket |
215
+ | `POST` | `/tickets` | Create |
216
+ | `PATCH` | `/tickets/:id` | Update any subset of fields |
217
+ | `DELETE` | `/tickets/:id` | Delete (cascades the draft conversation if it is the last reference) |
218
+ | `POST` | `/tickets/generate-spec` | Quick-mode generation. Body `{ idea, model?, contractRefine?, aiEngine?, attachmentIds?, pendingSpecId?, contextScope? }` (the spec text is `idea`, not `title`). Streams progress over WS |
219
+ | `POST` | `/tickets/save-as-draft` | Persist an Explore conversation as a draft (idempotent on `conversationId`) |
220
+ | `POST` | `/tickets/from-draft` | Commit a draft (flip-in-place) or insert a new ticket |
221
+ | `POST` | `/tickets/from-prompt` | Create a ticket directly from a prompt |
222
+ | `POST` | `/tickets/:id/contract-refine` | Retry Contract Refine for an existing ticket (202 / 404 / 409) |
223
+ | `POST` | `/tickets/:id/smash` | SMASH an epic into sub-specs |
224
+ | `POST` | `/tickets/:id/smash/undo` | Undo a SMASH operation |
225
+ | `DELETE` | `/tickets/:id/children` | Delete all children of an epic |
226
+ | `POST` | `/tickets/:id/ai-edit` | Open an AI edit (Refine) session against the ticket |
227
+ | `DELETE` | `/tickets/:id/ai-edit` | Cancel an AI edit session |
228
+ | `POST` | `/tickets/:ticketId/attachments` | Upload an attachment (multipart) |
229
+ | `GET` | `/tickets/:ticketId/attachments` | List attachments |
230
+ | `GET` | `/tickets/:ticketId/attachments/:attachmentId` | Download one |
231
+ | `DELETE` | `/tickets/:ticketId/attachments/:attachmentId` | Delete one |
232
+ | `DELETE` | `/tickets/:ticketId/attachments` | Delete all |
233
+
234
+ ### Chat / Explore
235
+
236
+ | Method | Path | Notes |
237
+ |--------|------|-------|
238
+ | `GET` | `/chat/conversations` | List (filter by `?kind=sidebar\|explore`) |
239
+ | `POST` | `/chat/conversations` | Create. Body `{ kind?, model?, aiEngine? (alias provider), contextScope? }`. `contextScope` is only allowed for `kind=explore` |
240
+ | `GET` | `/chat/conversations/:id` | One conversation (with messages) |
241
+ | `PATCH` | `/chat/conversations/:id` | Update metadata (title, contextScope, etc.) |
242
+ | `DELETE` | `/chat/conversations/:id` | Delete (clears `origin_conversation_id` on linked draft tickets) |
243
+ | `GET` | `/chat/conversations/:id/messages` | List messages |
244
+ | `POST` | `/chat/conversations/:id/messages` | Send a turn; streams over WS |
245
+ | `DELETE` | `/chat/conversations/:id/messages/stream` | Cancel an in-progress turn |
246
+ | `GET` | `/chat/conversations/:id/spec-draft` | Live spec-draft state |
247
+ | `POST` | `/chat/conversations/:id/minimize` | Park the session (arms the idle-kill timer) |
248
+ | `POST` | `/chat/conversations/:id/restore` | Cancel the idle-kill timer |
249
+
250
+ ### Setup wizard
251
+
252
+ The setup wizard is a three-step flow (Configure / Install / Done). The `enrich/*` and `setup/start`+`setup/message` endpoints back the legacy AI-enriched flow that the app UI does not expose; they remain mounted for forward compatibility.
253
+
254
+ | Method | Path | Notes |
255
+ |--------|------|-------|
256
+ | `POST` | `/setup/install-config` | Write `.specrails/install-config.yaml` to the project |
257
+ | `POST` | `/setup/install` | Run `npx … specrails-core@^4.6.0 init --from-config <file>` |
258
+ | `POST` | `/setup/start` | Legacy setup-chat session start |
259
+ | `POST` | `/setup/message` | Legacy setup-chat turn |
260
+ | `POST` | `/enrich/start` | Legacy AI-enrich session start |
261
+ | `POST` | `/enrich/message` | Legacy AI-enrich turn |
262
+ | `GET` | `/setup/checkpoints` | Checkpoint state + last log lines |
263
+ | `POST` | `/setup/abort` | Abort the wizard |
264
+
265
+ ### Proposals
266
+
267
+ | Method | Path | Notes |
268
+ |--------|------|-------|
269
+ | `GET` | `/propose` | List spec proposals |
270
+ | `POST` | `/propose` | Create |
271
+ | `GET` | `/propose/:id` | One proposal |
272
+ | `POST` | `/propose/:id/refine` | Refine with feedback |
273
+ | `POST` | `/propose/:id/create-issue` | Convert a proposal to a GitHub issue |
274
+ | `DELETE` | `/propose/:id` | Delete |
275
+
276
+ ### OpenSpec changes
277
+
278
+ OpenSpec changes are read from `openspec/changes/<name>/` (active) and `openspec/changes/archive/<YYYY-MM-DD-name>/` (archived).
279
+
280
+ | Method | Path | Notes |
281
+ |--------|------|-------|
282
+ | `GET` | `/changes` | List changes under `openspec/changes/` |
283
+ | `GET` | `/changes/:changeId/artifacts/:artifact` | Read one artifact. Allowed names: `proposal.md`, `design.md`, `tasks.md`, `delta-spec.md`, `context-bundle.md` |
284
+
285
+ ### Spec launcher
286
+
287
+ | Method | Path | Notes |
288
+ |--------|------|-------|
289
+ | `POST` | `/spec-launcher/start` | Launch a spec-generation run |
290
+ | `DELETE` | `/spec-launcher/:launchId` | Cancel a launch |
291
+
292
+ ### Templates
293
+
294
+ | Method | Path | Notes |
295
+ |--------|------|-------|
296
+ | `GET` | `/templates` | List templates |
297
+ | `POST` | `/templates` | Create |
298
+ | `GET` | `/templates/:templateId` | One template |
299
+ | `PATCH` | `/templates/:templateId` | Update |
300
+ | `DELETE` | `/templates/:templateId` | Delete |
301
+ | `POST` | `/templates/:templateId/run` | Run the template against the project |
302
+
303
+ ### Integration contract
304
+
305
+ | Method | Path | Notes |
306
+ |--------|------|-------|
307
+ | `GET` | `/integration-contract` | Read the project's `integration-contract.json` |
308
+
309
+ ### Browser capture
310
+
311
+ Gated by `requireBrowserCaptureEnabled` — returns 404 when the feature is disabled.
312
+
313
+ | Method | Path | Notes |
314
+ |--------|------|-------|
315
+ | `GET` | `/browser/sessions` | List capture sessions |
316
+ | `POST` | `/browser/sessions` | Start a capture session |
317
+ | `POST` | `/browser/sessions/:id/navigate` | Navigate the embedded browser |
318
+ | `POST` | `/browser/sessions/:id/capture` | Capture the current page/selection |
319
+ | `POST` | `/browser/sessions/:id/capture-breakpoints` | Capture across responsive breakpoints |
320
+ | `POST` | `/browser/sessions/:id/element` | Capture a picked element |
321
+ | `POST` | `/browser/sessions/:id/clipboard` | Read/write the session clipboard |
322
+ | `DELETE` | `/browser/sessions/:id` | Close a session |
323
+
324
+ ### Terminals
325
+
326
+ | Method | Path | Notes |
327
+ |--------|------|-------|
328
+ | `GET` | `/terminals` | List PTY sessions |
329
+ | `POST` | `/terminals` | Create a session |
330
+ | `PATCH` | `/terminals/:id` | Rename |
331
+ | `DELETE` | `/terminals/:id` | Kill |
332
+ | `GET` | `/terminals/:id/marks` | Persisted command marks (OSC 133) |
333
+
334
+ ### Project settings
335
+
336
+ | Method | Path | Notes |
337
+ |--------|------|-------|
338
+ | `GET` | `/settings` | Project settings |
339
+ | `PATCH` | `/settings` | Update |
340
+ | `GET` | `/terminal-settings` | Per-project terminal overrides |
341
+ | `PATCH` | `/terminal-settings` | Update |
342
+ | `GET` | `/agent-models` | Per-agent model overrides |
343
+ | `PATCH` | `/agent-models` | Update |
344
+ | `GET` | `/context-budget` | Context-window budget per surface |
345
+ | `GET` | `/context-scope-last` | Last-used context scope per surface (sticky preset) |
346
+ | `PATCH` | `/context-scope-last` | Update the sticky preset |
347
+ | `GET` | `/add-spec-quick-contract-refine-last` | Last-used Quick-mode Contract Refine toggle |
348
+ | `PATCH` | `/add-spec-quick-contract-refine-last` | Update the toggle |
349
+
350
+ ---
351
+
352
+ ## `/api/projects/:projectId/code/*`
353
+
354
+ Read-only Code explorer (mounted via `code-explorer-router`; 404 when the server gate is off).
355
+
356
+ | Method | Path | Notes |
357
+ |--------|------|-------|
358
+ | `GET` | `/tree?withProvenance=1&filter=touched-by-ai\|all&cursor=…` | Virtualised file tree (pagination cap 2000, `.gitignore`-aware) |
359
+ | `GET` | `/file?path=…` | File contents (binary refusal, 2 MB cap, path-traversal guard) |
360
+ | `GET` | `/summary?path=…` | Plain-language AI summary for a file |
361
+ | `POST` | `/file/regenerate-summary?path=…` | Enqueue a summary regeneration. Body `{ overrideBudget? }` → `202 { enqueued: true }` |
362
+ | `GET` | `/provenance?ticketId=…` | Files touched by a ticket |
363
+ | `GET` | `/diff` | File-change diff data |
364
+
365
+ ---
366
+
367
+ ## `/api/projects/:projectId/rails/*`
368
+
369
+ | Method | Path | Notes |
370
+ |--------|------|-------|
371
+ | `GET` | `/` | List rails |
372
+ | `PUT` | `/:railIndex/tickets` | Assign tickets to a rail. Body `{ ticketIds: number[] }` |
373
+ | `PUT` | `/:railIndex/profile` | Set the rail's default profile |
374
+ | `PUT` | `/:railIndex/engine` | Set the rail's AI engine override. Body `{ aiEngine }` (string or `null` to clear) |
375
+ | `POST` | `/:railIndex/launch` | Launch the rail. Body `{ mode?, profileName?, aiEngine?, model? }`; `mode` is `implement` / `batch-implement` / `ultracode`; `model` (haiku/sonnet/opus) applies to ultracode only |
376
+ | `POST` | `/:railIndex/stop` | Stop the rail's running job |
377
+
378
+ ---
379
+
380
+ ## `/api/projects/:projectId/profiles/*`
381
+
382
+ Gated by `SPECRAILS_AGENTS_SECTION !== 'false'`. Profiles are effectively Claude-only — a non-Claude rail engine runs in legacy mode.
383
+
384
+ ### Profile CRUD
385
+
386
+ | Method | Path | Notes |
387
+ |--------|------|-------|
388
+ | `GET` | `/` | List profiles |
389
+ | `POST` | `/` | Create (validator enforces the baseline trio + routing ordering) |
390
+ | `GET` | `/:name` | One profile |
391
+ | `PATCH` | `/:name` | Update |
392
+ | `DELETE` | `/:name` | Delete |
393
+ | `POST` | `/:name/duplicate` | Duplicate. Body `{ newName }` |
394
+ | `POST` | `/:name/rename` | Rename. Body `{ newName }` |
395
+ | `GET` | `/resolve?profile=…` | Preview which profile would run given a selection |
396
+
397
+ ### Bootstrap and analytics
398
+
399
+ | Method | Path | Notes |
400
+ |--------|------|-------|
401
+ | `POST` | `/migrate-from-settings` | Seed `default.json` from existing agent frontmatter |
402
+ | `GET` | `/analytics?windowDays=30` | Per-profile usage analytics |
403
+ | `GET` | `/core-version` | specrails-core version probe (drives the upgrade banner) |
404
+
405
+ ### Agents catalogue + studio
406
+
407
+ | Method | Path | Notes |
408
+ |--------|------|-------|
409
+ | `GET` | `/catalog` | Read upstream `sr-*` + custom `custom-*` agents |
410
+ | `GET` | `/catalog/:agentId` | One agent |
411
+ | `POST` | `/catalog` | Create a custom agent (template/blank/duplicate) |
412
+ | `PATCH` | `/catalog/:agentId` | Update a custom agent |
413
+ | `DELETE` | `/catalog/:agentId` | Delete a custom agent |
414
+ | `POST` | `/catalog/test` | Test-run a draft against a sample task (no FS writes) |
415
+ | `POST` | `/catalog/generate` | Generate an agent `.md` via Claude from a natural-language description |
416
+ | `GET` | `/catalog/:agentId/versions` | Version history |
417
+
418
+ ### Agent refine sessions
419
+
420
+ | Method | Path | Notes |
421
+ |--------|------|-------|
422
+ | `POST` | `/catalog/:agentId/refine` | Open a refine session |
423
+ | `GET` | `/catalog/:agentId/refine` | List sessions |
424
+ | `GET` | `/catalog/:agentId/refine/:refineId` | One session |
425
+ | `PATCH` | `/catalog/:agentId/refine/:refineId` | Update |
426
+ | `DELETE` | `/catalog/:agentId/refine/:refineId` | Cancel |
427
+ | `POST` | `/catalog/:agentId/refine/:refineId/turn` | Send a turn |
428
+ | `POST` | `/catalog/:agentId/refine/:refineId/apply` | Apply the diff to the agent file |
429
+
430
+ ---
431
+
432
+ ## `/api/projects/:projectId/plugins/*`
433
+
434
+ Gated by `SPECRAILS_PLUGINS_SECTION !== 'false'`.
435
+
436
+ | Method | Path | Notes |
437
+ |--------|------|-------|
438
+ | `GET` | `/` | List bundled plugins with installed/orphan/degraded state |
439
+ | `GET` | `/:name/preview-install` | Diff of what would be added to `.mcp.json` and `agents/` |
440
+ | `POST` | `/:name/install` | Install (streams progress over WS) |
441
+ | `DELETE` | `/:name` | Uninstall or remove an orphan |
442
+ | `POST` | `/:name/activate` | Activate (post-install) |
443
+ | `POST` | `/:name/deactivate` | Deactivate |
444
+ | `POST` | `/:name/update` | Update to the latest bundled version |
445
+ | `GET` | `/:name/health` | On-demand verify (2 s timeout) |
446
+ | `POST` | `/_prerequisites/:prereq/install` | Install a plugin prerequisite (e.g. `uv` for Serena) |
447
+ | `POST` | `/_marketplace/disable` | Hide the integrations marketplace for this project |
448
+
449
+ ---
450
+
451
+ ## `/api/docs/*`
452
+
453
+ The bundled documentation portal (served by `docs-router`, public — mounted before auth).
454
+
455
+ | Method | Path | Notes |
456
+ |--------|------|-------|
457
+ | `GET` | `/` | List categories. Top-level `.md` files → a synthetic `guides` category; each subdirectory becomes its own category |
458
+ | `GET` | `/:category/:slug` | Fetch one document (`{ title, content, category, slug }`) |
459
+
460
+ Source resolution: `~/.specrails/docs/` (user-editable) wins if present; otherwise the bundled `docs/` from the install.
461
+
462
+ ---
463
+
464
+ ## `/otlp/v1/{traces,metrics,logs}`
465
+
466
+ OTLP/JSON receiver (`telemetry-receiver`) used by the pipeline-telemetry feature. Reads `specrails.job_id` and `specrails.project_id` from `resource.attributes`. Returns:
467
+
468
+ - `400` — attributes missing
469
+ - `404` — unknown project or job
470
+ - `200` — payload accepted
471
+
472
+ 10 MB cap per blob. Once a log payload pushes a blob over the cap, further logs are dropped (a one-shot `logs_truncated` control line is written).
473
+
474
+ ---
475
+
476
+ ## WebSocket — `/ws`
477
+
478
+ A single connection at `ws://127.0.0.1:4200/ws?token=<authToken>` multiplexes every project and app-level event. The token query param is required.
479
+
480
+ Every project-scoped message includes a `projectId` field. App-level messages have no `projectId` and reach every handler.
481
+
482
+ ### Job, queue & pipeline
483
+
484
+ | Type | Scope | Notes |
485
+ |------|-------|-------|
486
+ | `init` | project | Per-connection dashboard snapshot sent on (re)connect: `{ projectName, phases, phaseDefinitions, logBuffer, recentJobs, queue }` |
487
+ | `log` | project | Streaming log line |
488
+ | `event` | project | Structured job event |
489
+ | `phase` | project | Pipeline phase transition |
490
+ | `queue` | project | Queue snapshot (`{ jobs, activeJobId, paused, timestamp }`) — job-exit state changes reach the client here |
491
+ | `pipeline_status` | project | Pipeline finished (`completed` / `failed`) |
492
+ | `exit` | both | Replay of a process exit (`{ code, signal, early }`); also emitted on the terminal stream |
493
+
494
+ ### Budget & cost
495
+
496
+ | Type | Scope | Notes |
497
+ |------|-------|-------|
498
+ | `cost_alert` | project | Job exceeded the per-job alert threshold |
499
+ | `daily_budget_exceeded` | project | Project daily budget hit; queue paused |
500
+ | `desktop_daily_budget_exceeded` | app | App-wide daily budget hit |
501
+ | `spending.invalidated` | project | Analytics cache should refetch (no payload) |
502
+
503
+ ### Tickets, specs & drafts
504
+
505
+ | Type | Scope | Notes |
506
+ |------|-------|-------|
507
+ | `ticket_created` | project | New ticket |
508
+ | `ticket_updated` | project | Ticket changed (`ticket.id === 0` signals a full external refetch) |
509
+ | `ticket_deleted` | project | Ticket removed |
510
+ | `spec_gen_stream` / `spec_gen_done` / `spec_gen_error` | project | Quick generation lifecycle |
511
+ | `spec_draft.update` | project | Live Explore spec-draft update |
512
+ | `ticket_ai_edit_stream` / `ticket_ai_edit_done` / `ticket_ai_edit_error` | project | AI Edit (Refine) session lifecycle |
513
+ | `smash.started` / `smash.progress` / `smash.completed` / `smash.failed` / `smash.undone` | project | SMASH epic-split lifecycle |
514
+
515
+ ### Chat & Explore
516
+
517
+ | Type | Scope | Notes |
518
+ |------|-------|-------|
519
+ | `chat_stream` | project | Streaming assistant chunk |
520
+ | `chat_done` | project | Turn finished |
521
+ | `chat_error` | project | Turn failed |
522
+ | `chat_title_update` | project | Auto-titled a conversation |
523
+ | `chat_command_proposal` | project | The assistant proposed a command |
524
+ | `explore.contract_refine_started` / `explore.contract_refine_failed` | project | Contract Refine lifecycle |
525
+
526
+ ### Proposals & spec launcher
527
+
528
+ | Type | Scope | Notes |
529
+ |------|-------|-------|
530
+ | `proposal_stream` / `proposal_ready` / `proposal_refined` / `proposal_issue_created` / `proposal_error` | project | Proposal lifecycle |
531
+ | `spec_launcher_stream` / `spec_launcher_done` / `spec_launcher_error` | project | Spec launcher lifecycle |
532
+
533
+ ### Agents & profiles
534
+
535
+ | Type | Scope | Notes |
536
+ |------|-------|-------|
537
+ | `agent.changed` | project | Agent catalog updated |
538
+ | `profile.changed` | project | Profile catalog updated |
539
+ | `agent_refine_stream` / `agent_refine_ready` / `agent_refine_phase` / `agent_refine_applied` / `agent_refine_cancelled` / `agent_refine_error` | project | Agent refine session lifecycle |
540
+
541
+ ### Rails
542
+
543
+ | Type | Scope | Notes |
544
+ |------|-------|-------|
545
+ | `rail.job_started` / `rail.job_completed` / `rail.job_stopped` | project | Rail job lifecycle |
546
+
547
+ ### Plugins
548
+
549
+ | Type | Scope | Notes |
550
+ |------|-------|-------|
551
+ | `plugin.installed` / `plugin.uninstalled` | project | Install/uninstall completed |
552
+ | `plugin.health_changed` / `plugin.degraded` | project | Health flipped |
553
+ | `plugin.install_progress` | project | Streaming install progress |
554
+ | `plugin.prereq_install_progress` / `plugin.prereq_installed` | project | Prerequisite install lifecycle |
555
+
556
+ ### Files (Code explorer)
557
+
558
+ | Type | Scope | Notes |
559
+ |------|-------|-------|
560
+ | `file.provenance_updated` | project | A job touched files |
561
+ | `file.summary_updated` / `file.summary_failed` / `file.summary_skipped` | project | Summary lifecycle |
562
+
563
+ ### Setup wizard
564
+
565
+ | Type | Scope | Notes |
566
+ |------|-------|-------|
567
+ | `setup_log` | project | Streaming install log line |
568
+ | `setup_chat` | project | Setup-chat assistant chunk |
569
+ | `setup_checkpoint` | project | Checkpoint state change |
570
+ | `setup_install_done` | project | `npx … init` finished |
571
+ | `setup_turn_done` | project | One setup-chat turn finished |
572
+ | `setup_complete` | project | Setup wrapping up |
573
+ | `setup_error` | project | Setup failed |
574
+
575
+ ### App-level
576
+
577
+ | Type | Scope | Notes |
578
+ |------|-------|-------|
579
+ | `desktop.project_added` | app | New project registered |
580
+ | `desktop.project_removed` | app | Project unregistered |
581
+ | `desktop.projects` | app | Bulk project list refresh |
582
+
583
+ ### Client filtering pattern
584
+
585
+ WS handlers use a ref (not state) to avoid stale closures:
586
+
587
+ ```tsx
588
+ const activeProjectIdRef = useRef(activeProjectId)
589
+ useEffect(() => { activeProjectIdRef.current = activeProjectId }, [activeProjectId])
590
+
591
+ // In the WS message handler:
592
+ if (msg.projectId && msg.projectId !== activeProjectIdRef.current) return
593
+ ```
594
+
595
+ App-level messages (no `projectId`) are processed by every handler.
596
+
597
+ ---
598
+
599
+ ## WebSocket — `/ws/terminal/:id`
600
+
601
+ A dedicated WebSocket for terminal PTY traffic, separate from `/ws` so a chatty shell can never starve project events.
602
+
603
+ Connect with `?token=<authToken>&projectId=<id>`.
604
+
605
+ Attach protocol:
606
+
607
+ 1. Server sends the existing scrollback as one binary frame.
608
+ 2. Server sends a `{ type: "ready", cols, rows }` JSON frame.
609
+ 3. Live PTY output streams as binary frames.
610
+ 4. Shell-integration marks (OSC 133/1337) parsed server-side stream as JSON `{ type: "mark", kind, … }` frames.
611
+
612
+ Client → server: text input as binary; `{ type: "resize", cols, rows }` JSON on viewport changes.
613
+
614
+ ---
615
+
616
+ ## Errors
617
+
618
+ The app uses standard HTTP status codes. Notable conventions:
619
+
620
+ - `400` — malformed body / invalid params
621
+ - `401` — missing or invalid token (Bearer or `X-Desktop-Token`)
622
+ - `403` — cross-origin request (a non-localhost `Origin` header)
623
+ - `404` — resource not found (including a project resolved from an unregistered path)
624
+ - `409` — write conflict (file-lock contention on tickets, plugin name collision, project path already registered)
625
+ - `500` — unhandled exception (logged to stdout)
626
+
627
+ Error responses are `{ "error": "<message>" }`.
628
+
629
+ ---
630
+
631
+ ## Caveats
632
+
633
+ - **Surface drift**: this file is hand-maintained against the route declarations in `server/*-router.ts` and `server/code-explorer-router.ts`. The app adds endpoints regularly; if a route exists in code but not here, please open an issue.
634
+ - **Stability**: routes under `/api/*` and `/api/projects/:projectId/*` are considered stable. A few legacy setup endpoints (`setup/start`, `setup/message`, `enrich/*`) back a flow the UI does not expose and remain only for forward compatibility.