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,332 @@
1
+ # Architecture
2
+
3
+ This document describes the technical architecture of specrails-desktop (v1.63.1): its layers, data layout, request flow, authentication, and the subsystems that make up the app. It is the entry point to the other internals docs — see the [See also](#see-also) block at the bottom.
4
+
5
+ ---
6
+
7
+ ## Three-layer monorepo
8
+
9
+ ```
10
+ specrails-desktop/
11
+ ├── server/ → Express 5 + WebSocket + SQLite (TypeScript, CommonJS)
12
+ ├── client/ → React 19 + Vite + Tailwind v4 (TypeScript, ESM)
13
+ ├── cli/ → specrails-desktop CLI bridge (TypeScript, CommonJS)
14
+ └── src-tauri/ → Tauri v2 desktop shell (Rust + bundled server sidecar)
15
+ ```
16
+
17
+ Server and CLI compile to **CommonJS** (root `tsconfig.json`). The client is **ESM** with its own `client/tsconfig.json`. The client has its own `package.json` and `node_modules`, so two separate `npm install` calls are required (root + `client/`).
18
+
19
+ The server persists with **better-sqlite3** (synchronous SQLite) and serves over **Express 5**; the WebSocket layer uses **ws**.
20
+
21
+ ### Everyday commands
22
+
23
+ ```bash
24
+ npm run dev # server (4200) + client (4201) concurrently
25
+ npm run dev:server # server only (tsx watch)
26
+ npm run dev:client # Vite dev client only
27
+ npm run build # production build: server → client → CLI
28
+ npm run typecheck # tsc --noEmit for server and client
29
+ npm test # vitest (server + CLI) + core-compat check
30
+ ```
31
+
32
+ Tests use vitest with `:memory:` SQLite databases.
33
+
34
+ ---
35
+
36
+ ## Data layout
37
+
38
+ ```
39
+ ~/.specrails/
40
+ desktop.sqlite # project registry (id, name, path, slug, provider…)
41
+ desktop.token # auth token, mode 0600 (auto-generated on first run)
42
+ manager.pid # server PID for clean shutdown
43
+ projects/
44
+ <slug>/
45
+ jobs.sqlite # per-project: jobs, rails, tickets, invocations, …
46
+ jobs/<jobId>/ # per-job snapshots (profile.json, plugins.json, …)
47
+ telemetry/ # OTEL blobs (compacted after 7 days)
48
+ explore-cwd/ # app-managed Explore spawn cwd (CLAUDE.md + ./project link)
49
+ terminals/ # per-session shell-integration shims
50
+ ```
51
+
52
+ The app SQLite (`desktop.sqlite`) stores only project metadata. All per-project data lives in an isolated `jobs.sqlite` under the project's slug directory — not just jobs and chat, but rails, tickets, agent profiles/versions, AI invocations (cost analytics), telemetry pointers, file provenance, terminal settings/marks, and more (see the `MIGRATIONS` array in `server/db.ts`). Projects can be removed and re-added without losing history, and the registry can be wiped without touching project data.
53
+
54
+ > The data root is hardcoded to `os.homedir()/.specrails`. There is no environment override for the data directory.
55
+ >
56
+ > **Rebrand migration:** installs upgraded from the Specrails Hub era are migrated automatically — on startup the server renames a legacy `hub.sqlite` (plus its `-wal`/`-shm` sidecars) to `desktop.sqlite` and a legacy `hub.token` to `desktop.token` before opening them, so no data or token is lost.
57
+
58
+ ---
59
+
60
+ ## Super-mode architecture
61
+
62
+ Super mode is the **only** supported mode — a single Express process manages every registered project. There is no legacy single-project runtime, and no mode detection.
63
+
64
+ ```
65
+ ┌─────────────────────────────────────────────────────┐
66
+ │ Express Server (port 4200, 127.0.0.1 only) │
67
+ │ │
68
+ │ ProjectRegistry │
69
+ │ ├── Project A → ProjectContext { db, queue, chat, │
70
+ │ ├── Project B → chatManager, setupManager, cwd } │
71
+ │ └── Project C → … │
72
+ │ │
73
+ │ Routes: │
74
+ │ /api/* → app-level operations │
75
+ │ /api/projects/:id/* → project-scoped actions │
76
+ │ /otlp/v1/* → OTLP telemetry receiver │
77
+ └─────────────────────────────────────────────────────┘
78
+ ```
79
+
80
+ ### Per-project isolation
81
+
82
+ Each project in the `ProjectRegistry` gets its own `ProjectContext`:
83
+
84
+ | Resource | Description |
85
+ |----------|-------------|
86
+ | `db` | SQLite connection to `projects/<slug>/jobs.sqlite` |
87
+ | `QueueManager` | Serialized job queue for this project (one active job at a time) |
88
+ | `ChatManager` | Isolated conversation manager (Explore + sidebar chat) |
89
+ | `SetupManager` | Wizard state for projects being onboarded |
90
+ | `cwd` | Absolute path to the project directory on disk |
91
+
92
+ The `boundBroadcast` closure injects `projectId` into all WebSocket messages, so managers don't need per-project constructor arguments.
93
+
94
+ ---
95
+
96
+ ## Key server modules
97
+
98
+ | Module | Responsibility |
99
+ |--------|---------------|
100
+ | `index.ts` | Entry point: PATH resolution, auth bootstrap, port binding, router mounts, WS server |
101
+ | `auth.ts` | Token bootstrap + `requireAuth` middleware + WS upgrade token check |
102
+ | `desktop-db.ts` | App-level SQLite: project registry CRUD, app settings |
103
+ | `project-registry.ts` | `ProjectRegistry` class: load/unload per-project `ProjectContext` |
104
+ | `desktop-router.ts` | `/api/*` routes: projects, settings, themes, specrails-tech proxy, cross-project analytics |
105
+ | `project-router.ts` | `/api/projects/:id/*` routes: all project-scoped operations |
106
+ | `db.ts` | Per-project SQLite: schema (`MIGRATIONS`) + queries |
107
+ | `queue-manager.ts` | Job queue: spawn provider CLI processes serially per project |
108
+ | `chat-manager.ts` | Chat/Explore: spawn provider CLI for conversational turns |
109
+ | `setup-manager.ts` | Setup wizard: orchestrate `specrails-core` install + `/setup` chat |
110
+ | `config.ts` | Command discovery: scan `<project>/.claude/commands/sr/*.md` |
111
+ | `hooks.ts` | Pipeline event handler: process phase transition events |
112
+ | `spending.ts` | Cost/analytics aggregation (single source of truth) |
113
+ | `ai-invocations.ts` | `recordInvocation` — writes one billable row per AI CLI call |
114
+ | `pricing.ts` | Rate-card cost fallback for providers without native billing |
115
+ | `result-event.ts` | `finaliseInvocationResult` — combines adapter result + pricing |
116
+ | `telemetry-receiver.ts` | OTLP/JSON receiver mounted at `/otlp` |
117
+ | `desktop-analytics.ts` | App-level analytics aggregated across all projects |
118
+ | `metrics.ts` | Per-project health metrics |
119
+ | `docs-router.ts` | Serve the embedded docs portal (`/api/docs`) |
120
+ | `path-resolver.ts` | Resolve a usable PATH for GUI-launched desktop spawns |
121
+ | `types.ts` | Shared TypeScript interfaces |
122
+
123
+ Provider, terminal, profile, plugin, code-explorer, and explore subsystems each live in their own modules — see [Feature subsystems](#feature-subsystems).
124
+
125
+ ---
126
+
127
+ ## Client architecture
128
+
129
+ ```
130
+ client/src/
131
+ ├── App.tsx # Mounts DesktopProvider + DesktopApp unconditionally
132
+ ├── components/
133
+ │ ├── TabBar.tsx # Project tab switcher
134
+ │ ├── ProjectLayout.tsx # Per-project three-panel wrapper
135
+ │ ├── ProjectNavbar.tsx # Left/right sidebar pin + collapse toggles
136
+ │ ├── ArcSidebar.tsx # Collapsible Arc-style left sidebar
137
+ │ ├── ProjectRightSidebar.tsx # Project nav (Jobs, Analytics, Agents, Code, …)
138
+ │ ├── TitleBar.tsx # Custom frameless titlebar (desktop)
139
+ │ ├── CommandGrid.tsx # Command launcher
140
+ │ ├── RecentJobs.tsx # Job history card list
141
+ │ ├── ProjectHealthWidget.tsx # Per-project health indicators
142
+ │ ├── AddProjectDialog.tsx # Register project modal (provider multi-select)
143
+ │ ├── WelcomeScreen.tsx # Zero-state landing
144
+ │ └── SetupWizard.tsx # Configure / Install / Done onboarding wizard
145
+ ├── hooks/
146
+ │ ├── useDesktop.tsx # DesktopProvider context: project list, active project
147
+ │ ├── useProjectCache.ts # Stale-while-revalidate per-project cache
148
+ │ ├── useSpecGenTracker.tsx # Quick-spec generation state (localStorage)
149
+ │ ├── usePipeline.ts # Pipeline phase state
150
+ │ └── useSharedWebSocket.tsx # Single WS connection, per-project filtering
151
+ ├── pages/
152
+ │ ├── DashboardPage.tsx # Specs board + Rails board + pipeline state
153
+ │ ├── AnalyticsPage.tsx # Per-project cost analytics
154
+ │ ├── DesktopAnalyticsPage.tsx # Cross-project spending roll-up
155
+ │ ├── AgentsPage.tsx # Agent profiles + catalog
156
+ │ ├── CodePage.tsx # Read-only code explorer (flag-gated)
157
+ │ ├── SettingsPage.tsx # Per-project settings
158
+ │ ├── GlobalSettingsPage.tsx # App settings
159
+ │ └── JobDetailPage.tsx # Full log viewer for a single job
160
+ └── lib/
161
+ ├── api.ts # getApiBase(): dynamic API prefix per active project
162
+ ├── pending-specs.ts # Quick-spec state persistence (localStorage)
163
+ └── route-memory.ts # Per-project URL route save/restore
164
+ ```
165
+
166
+ ### App bootstrap
167
+
168
+ `App.tsx` mounts `DesktopProvider` and `<DesktopApp />` **unconditionally** — there is no mode detection and no fallback layout. The client fetches its auth token same-origin from `/api/token` and then loads the project registry.
169
+
170
+ ### API base routing
171
+
172
+ `getApiBase()` (from `lib/api.ts`) always returns `${API_ORIGIN}/api/projects/<activeProjectId>` and **throws** when no active project is set — it never returns a bare `/api`. `DesktopProvider` updates the active project (via `setActiveProjectId`) on project switch; all API calls must go through `getApiBase()` rather than hardcoding `/api/projects/...`.
173
+
174
+ ### Per-project tab switch pattern
175
+
176
+ On project switch:
177
+ 1. `useDesktop` updates `activeProjectId`.
178
+ 2. `useProjectCache` returns cached data immediately (no flicker).
179
+ 3. A background fetch refreshes the cache for the new project.
180
+ 4. Never reset to empty state — always show the last-known data while loading.
181
+
182
+ State-bearing hooks key off `activeProjectId` as a `useEffect` dependency. `useSpecGenTracker` (via `lib/pending-specs.ts`) and `lib/route-memory.ts` persist Quick-spec progress and the active URL route per project to `localStorage`, surviving refreshes and project switches.
183
+
184
+ ---
185
+
186
+ ## Authentication
187
+
188
+ The app is local-first but **always authenticated** — auth is mandatory, not optional.
189
+
190
+ - On first run the server generates a token (two concatenated `randomUUID()`s) and persists it to `~/.specrails/desktop.token` with mode `0600` (`server/auth.ts`).
191
+ - `app.use('/api', requireAuth)` protects every `/api/*` route. The exceptions are `GET /api/health` and `GET /api/token` (both mounted before the middleware), plus `/api/docs` (the docs portal handlers respond before the auth fallthrough).
192
+ - `requireAuth` accepts the token as an `Authorization: Bearer <token>` header **or** an `X-Desktop-Token: <token>` header.
193
+ - WebSocket upgrades are authorized by `authorizeUpgrade`: the browser client sends the token as a subprotocol `desktop-token.<token>`; the CLI can pass it as a `Bearer` header.
194
+
195
+ There is no UI to set or clear the token and it is not an app setting. The browser client fetches it same-origin from `/api/token`, which is why that one route is public.
196
+
197
+ ---
198
+
199
+ ## WebSocket protocol
200
+
201
+ A single WebSocket connection at `ws://127.0.0.1:4200/ws` multiplexes all application messages. Terminal PTY output flows over a dedicated `/ws/terminal/:id` socket so high-throughput terminal data cannot starve the event stream.
202
+
203
+ Every project-scoped message includes a `projectId` field; app-level messages (`desktop.project_added`, `desktop.project_removed`, `desktop.projects`) have none.
204
+
205
+ ### Representative message types
206
+
207
+ Canonical shapes live in `server/types.ts`. The core dashboard messages:
208
+
209
+ | Type | Scope | Payload (key fields) |
210
+ |------|-------|----------------------|
211
+ | `init` | project | `{ projectName, phases, phaseDefinitions, logBuffer, recentJobs, queue, projectId }` — per-connection dashboard snapshot sent on (re)connect |
212
+ | `queue` | project | `{ jobs, activeJobId, paused, timestamp, projectId }` — full queue snapshot |
213
+ | `log` | project | `{ source: 'stdout'\|'stderr', line, timestamp, processId, projectId }` |
214
+ | `phase` | project | `{ phase, state, timestamp, projectId }` |
215
+ | `exit` | project | `{ code, signal, early }` — process exit replay on the WS upgrade |
216
+ | `desktop.project_added` | app | `{ project }` |
217
+ | `desktop.project_removed` | app | `{ projectId }` |
218
+ | `desktop.projects` | app | `{ projects }` |
219
+
220
+ Job lifecycle is reported by the message types `job_started`, `job_completed`, `job_failed`, and `job_canceled`. Feature subsystems add many more (`spending.invalidated`, `plugin.*`, `file.*`, `rail.job_started/completed/stopped`, `explore.contract_refine_failed`, chat/refine/SMASH/proposal streams). See [`api-reference.md`](api-reference.md) for the full outbound-event catalogue.
221
+
222
+ ### Client filtering pattern
223
+
224
+ WS handlers use a ref to avoid stale closures:
225
+
226
+ ```tsx
227
+ const activeProjectIdRef = useRef(activeProjectId)
228
+ useEffect(() => { activeProjectIdRef.current = activeProjectId }, [activeProjectId])
229
+
230
+ // In a WS message handler:
231
+ if (msg.projectId && msg.projectId !== activeProjectIdRef.current) return
232
+ ```
233
+
234
+ App-level messages (no `projectId`) are processed by all handlers.
235
+
236
+ ---
237
+
238
+ ## Process spawning and concurrency
239
+
240
+ `QueueManager` and `ChatManager` spawn the provider CLI (`claude` or `codex`) as subprocesses, always with `cwd` set so the process runs in the correct directory.
241
+
242
+ - **Within a project, jobs run strictly one at a time.** Each `ProjectContext` has exactly one `QueueManager` with a single `_activeJobId`; `_drainQueue()` early-returns while a job is active, so the next rail job queues behind the current one.
243
+ - **Parallelism is across projects only** — each project has its own `QueueManager`, so jobs in different projects run simultaneously. There is no "max concurrent jobs" setting; the only automatic queue-pause is budget-based (daily budget / per-job cost alert).
244
+ - **Cancelling a job** sends `SIGTERM`, waits **5 seconds**, then `SIGKILL`. (The terminal panel's 2-second shutdown grace is a separate subsystem.)
245
+ - A zombie-job watchdog terminates a stuck job after a default of **30 minutes**, overridable via `WM_ZOMBIE_TIMEOUT_MS`.
246
+ - Log lines stream back over WebSocket in real time.
247
+
248
+ ---
249
+
250
+ ## Feature subsystems
251
+
252
+ The app is more than the job pipeline. Each subsystem owns its modules; this is a map, not a duplication of [`CLAUDE.md`](../../CLAUDE.md).
253
+
254
+ | Subsystem | Server modules | Notes |
255
+ |-----------|---------------|-------|
256
+ | **Multi-provider adapters** | `server/providers/{types,claude-adapter,codex-adapter,registry,index}.ts`, `server/provider-selection.ts` | Claude (full native support) and Codex (≥ 0.128.0, estimated cost, synthesized OTEL) behind a `ProviderAdapter` contract. A project can install both; `providers[]` is a JSON column, the first entry is primary. Per-invocation provider is late-bound. See [`adding-a-provider.md`](adding-a-provider.md). |
257
+ | **Spending analytics** | `server/spending.ts`, `server/ai-invocations.ts`, `server/pricing.ts` | `recordInvocation` writes an `ai_invocations` row per AI CLI call across six surfaces (`job`, `quick-spec`, `explore-spec`, `ai-edit`, `smash`, `file-summary`); powers the Analytics page and `spending.invalidated`. |
258
+ | **Agent profiles** | `server/profile-manager.ts`, `server/profiles-router.ts` | Declarative JSON in `.specrails/profiles/*.json`, snapshot-per-job, `SPECRAILS_PROFILE_PATH` env injection. Requires `specrails-core ≥ 4.1.0`. |
259
+ | **Plugins (Integrations)** | `server/plugin-manager.ts`, `server/plugins/` | Bundled-only, MCP-based, additivity invariant, surgical `.mcp.json` merge, `plugin.*` WS events. Serena ships today. |
260
+ | **Terminal panel** | `server/terminal-manager.ts` | `node-pty` sessions over the dedicated `/ws/terminal/:id` socket, OSC shell-integration marks. See [`../terminal.md`](../terminal.md). |
261
+ | **Code explorer** | `server/code-explorer-router.ts`, `server/file-provenance.ts`, `server/file-summary-manager.ts` | Read-only file tree + Monaco viewer + AI summaries; provenance per ticket/job. |
262
+ | **Pipeline telemetry** | `server/telemetry-receiver.ts` + QueueManager OTEL injection | Opt-in OTLP/JSON signals to `POST /otlp/v1/{traces,metrics,logs}`; blobs compacted after 7 days; diagnostic ZIP export. |
263
+ | **Explore acceleration + Contract Refine** | `server/explore-cwd-manager.ts`, `server/contract-refine-runner.ts` | App-managed Explore spawn cwd for fast first-token; optional post-commit Contract Layer enrichment. Kill switches: `SPECRAILS_EXPLORE_CONTRACT_REFINE`, `SPECRAILS_EXPLORE_LEGACY_CWD`. |
264
+ | **Tickets / drafts** | `server/ticket-store.ts` | Spec tickets (incl. `draft` status) backing the Specs board and Save-as-Draft flow. |
265
+ | **Theme system** | `server/desktop-router.ts` (`GET/PATCH /api/theme`) | Five built-in themes (`dracula`, `aurora-light`, `obsidian-dark`, `matrix`, `specrails`), default `specrails`, persisted app-wide with an anti-FOUC inline script. |
266
+
267
+ Most client feature sections are gated by VITE flags, and they share one polarity: `VITE_FEATURE_TERMINAL_PANEL`, `VITE_FEATURE_AGENTS_SECTION`, `VITE_FEATURE_EXPLORE_PREMIUM_UX`, and `VITE_FEATURE_CODE_EXPLORER` are all **opt-out** — default ON, set the flag to `false` to hide that section. See [`configuration.md`](configuration.md) for the full flag and settings reference.
268
+
269
+ ---
270
+
271
+ ## Setup wizard flow
272
+
273
+ When a project is added without specrails-core, the setup wizard runs. The client renders a **3-step** indicator: **Configure → Install → Done**.
274
+
275
+ 1. **Configure** — confirm path and pick provider(s) and model presets. (Multi-provider projects get one Configure step per provider.)
276
+ 2. **Install** — the app writes `.specrails/install-config.yaml` and runs `npx --yes --prefer-online specrails-core@latest init --yes --from-config <tempPath>`, streaming the log. For multi-provider projects each provider's install runs sequentially.
277
+ 3. **Done** — per-provider completion summary.
278
+
279
+ `SetupManager` (server) owns wizard state; `DesktopProvider` (client) tracks which projects are in setup via `setupProjectIds`. The wizard does spawn a real AI CLI for the `/setup` chat, but that spawn is deliberately left uninstrumented (it writes no `ai_invocations` row).
280
+
281
+ ---
282
+
283
+ ## Desktop app layer
284
+
285
+ The **Tauri v2** desktop app wraps the Vite-built React client as a native macOS/Windows app.
286
+
287
+ - **Server sidecar** — `scripts/build-sidecar.mjs` compiles the Express server to a standalone binary. Tauri bundles it and manages its lifecycle.
288
+ - **Frameless window** — `tauri.conf.json` sets `decorations: false` on all platforms; the custom titlebar (drag region, window controls) is rendered in `TitleBar.tsx`. On macOS the native traffic-light controls are handled there.
289
+ - **GUI-launch PATH** — when launched from Finder/Dock the embedded server inherits a minimal launchd PATH, so `server/path-resolver.ts` resolves a usable PATH before any subprocess spawns (prepending well-known package-manager dirs, or the bundled runtime dirs in desktop mode).
290
+ - **Bundled runtimes** — in desktop mode the Tauri host sets `SPECRAILS_IS_DESKTOP=1` and `SPECRAILS_BUNDLED_RUNTIMES_PATH=<resource_dir>/runtimes` (only when a non-empty `runtimes/` dir is bundled), so the app can run without a system Node/Git. When no bundled runtimes are present it falls back to the system PATH.
291
+
292
+ ### Desktop commands
293
+
294
+ ```bash
295
+ npm run dev:desktop # tauri dev (development desktop app)
296
+ npm run build:desktop # build:server + client build + build:sidecar + tauri build
297
+ npm run generate-icons # tauri icon src-tauri/icons/icon.svg
298
+ ```
299
+
300
+ > There is no `npm run tauri` script — `npm run tauri dev` / `npm run tauri build` fail with "Missing script: tauri".
301
+
302
+ macOS desktop builds are signed + notarized. Windows builds (x64 and arm64) ship **unsigned** in v1 (SmartScreen "More info → Run anyway"). See [`../platforms/windows.md`](../platforms/windows.md) and [`../platforms/macos.md`](../platforms/macos.md).
303
+
304
+ ---
305
+
306
+ ## Ports
307
+
308
+ | Port | Service |
309
+ |------|---------|
310
+ | `4200` | Express server (API + WebSocket), bound to `127.0.0.1` (overridable via `--port`) |
311
+ | `4201` | Vite dev server (proxies `/api` and `/hooks` to 4200) |
312
+
313
+ ---
314
+
315
+ ## Security model
316
+
317
+ - **Loopback-only bind** — the server listens on `127.0.0.1` and is not exposed to a network.
318
+ - **Mandatory token auth** — every `/api/*` route and every WebSocket upgrade requires the app token (see [Authentication](#authentication)). The token lives in `~/.specrails/desktop.token` (mode `0600`).
319
+ - **Origin check** — a CORS middleware rejects cross-origin (non-localhost `Origin`) requests with `403`.
320
+ - **Parameterized SQL** — all SQLite operations use parameterized queries; user input is never string-interpolated into SQL.
321
+ - **Path validation** — project paths are validated as existing directories on registration.
322
+
323
+ ---
324
+
325
+ ## See also
326
+
327
+ - [API reference](api-reference.md) — REST routes and the full WebSocket event catalogue
328
+ - [Configuration](configuration.md) — env vars, feature flags, app/project settings
329
+ - [Agent profiles](profiles.md) — profile schema, resolution order, snapshot-per-job
330
+ - [Adding a provider](adding-a-provider.md) — the `ProviderAdapter` contract
331
+ - [OpenSpec workflow](openspec-workflow.md) — the spec-driven change lifecycle
332
+ - [Operations runbook](operations-runbook.md) — running, upgrading, and recovering the app
@@ -0,0 +1,172 @@
1
+ # Configuration
2
+
3
+ Reference for configuring specrails-desktop: app-wide settings, per-project settings, the authentication token, environment variables, CLI flags, and the `~/.specrails/` data directory.
4
+
5
+ Everything here is verified against the shipped code (v1.63.1). The app server binds to `127.0.0.1` only and rejects any non-localhost origin, so all of this is local-first by design.
6
+
7
+ ---
8
+
9
+ ## Authentication
10
+
11
+ The app is protected by a **mandatory** API token — there is no "off" switch and no UI to set it.
12
+
13
+ - On first run the server generates a token (two concatenated random UUIDs) and writes it to `~/.specrails/desktop.token` with mode `0600`. The same file is reused on every subsequent start.
14
+ - Every `/api/*` route requires the token via an `Authorization: Bearer <token>` or `X-Desktop-Token: <token>` header. The only exceptions are `GET /api/health` and `GET /api/token`.
15
+ - WebSocket upgrades carry the token as the `desktop-token.<token>` subprotocol.
16
+ - The browser client fetches the token same-origin from `GET /api/token`, so you never type it in.
17
+
18
+ Two more layers keep the app local-only:
19
+
20
+ - **Loopback bind** — the server listens on `127.0.0.1` exclusively (`server.listen(port, '127.0.0.1')`).
21
+ - **CORS allow-list** — only `localhost`, `127.0.0.1`, `tauri.localhost`, and `tauri://localhost` origins are accepted; anything else gets a `403`.
22
+
23
+ To rotate the token, stop the app, delete `~/.specrails/desktop.token`, and start again — a fresh token is generated.
24
+
25
+ ---
26
+
27
+ ## App settings
28
+
29
+ App settings apply across all projects. Open them from the **left sidebar → Settings**, or via the Command Palette (`Cmd/Ctrl+K`) → **Desktop Settings**. They are persisted in `~/.specrails/desktop.sqlite` under the `desktop_settings` key/value table.
30
+
31
+ The Global Settings page is organised into these sections:
32
+
33
+ | Section | What it controls | Stored key / default |
34
+ |---------|------------------|----------------------|
35
+ | **Appearance** | App-wide UI theme. Five built-ins: `specrails` (default), `dracula`, `aurora-light`, `obsidian-dark`, `matrix`. | `ui_theme` = `specrails` |
36
+ | **specrails-tech** | Base URL for the external specrails-tech agents service. | `specrails_tech_url` = `http://localhost:3000` (the `SPECRAILS_TECH_URL` env var is only a fallback when this setting is unset — the stored setting wins) |
37
+ | **Budget & Alerts** | App-wide daily spend cap (queues auto-pause when exceeded) and a per-job cost alert threshold. | `desktop_daily_budget_usd`, `cost_alert_threshold_usd` (both unset by default = no cap / no alert) |
38
+ | **OS Notifications** | Desktop notification preferences for long-running jobs and budget events. | — |
39
+ | **Outbound Webhooks** | HTTP webhooks fired on `job.completed`, `job.failed`, `job.canceled`, `daily_budget_exceeded`, and `desktop_daily_budget_exceeded`. | webhooks table (defaults to `["job.completed","job.failed"]` per hook) |
40
+ | **Code section** | Plain-language file-summary language (`en` / `es`) and the monthly summary budget cap. | `summary_language` = `en`, `summary_monthly_budget_usd` = `5.00` |
41
+ | **Terminal Panel** | App-wide defaults for the integrated terminal (font, render mode, copy-on-select, shell integration, image rendering, long-command threshold). | `terminal.*` keys |
42
+
43
+ > There is **no** "Claude model", "Max concurrent jobs", "Job timeout", or "Authentication token" app setting. Within a project, jobs run one at a time (see [Architecture](architecture.md)); the only automatic queue pause is budget-based. The default model is the provider adapter's default (the `sonnet` alias for Claude), resolved at spawn time — it is not a stored setting.
44
+
45
+ **Port is not a live setting.** `desktop_settings` does store a `port` value, but it is display-only. The port the server actually binds is taken from the `--port` argv (default `4200`); changing the stored value does not rebind a running server. Set the port with `--port <n>` on `specrails-desktop start`.
46
+
47
+ ---
48
+
49
+ ## Project settings
50
+
51
+ Project settings apply to a single project. Open them from the project's **Settings** entry in the right sidebar (route: `/settings`). The page is titled **Project Settings** and has these sections:
52
+
53
+ | Section | What it controls |
54
+ |---------|------------------|
55
+ | **Pipeline Telemetry** | Opt-in toggle that injects OpenTelemetry env vars into pipeline job spawns so they emit OTLP signals back to the app. Off by default. |
56
+ | **Rail Pre-prompt** | Text prepended to every rail launch for this project. |
57
+ | **Ultracode pre-prompt** | Text prepended to Ultracode-mode launches (the Claude-only autonomous rail mode). |
58
+ | **Budget** | Per-project daily spend cap (with queue auto-pause) and a per-job cost alert threshold. |
59
+ | **Terminal Settings** | Per-project overrides for the terminal panel defaults (project override → app default → built-in). |
60
+
61
+ > The project's **provider(s)** (Claude, Codex, or both) are chosen when you add the project and are **immutable after creation** — there is no provider switch in Project Settings. There is also **no** Name edit, Path row, or model-override field on this page.
62
+
63
+ ---
64
+
65
+ ## CLI
66
+
67
+ The `specrails-desktop` CLI is documented in full in [../cli.md](../cli.md). Quick reference:
68
+
69
+ ### Global flags
70
+
71
+ These can appear in any position and are stripped before the command runs.
72
+
73
+ | Flag | Description | Default |
74
+ |------|-------------|---------|
75
+ | `--port <n>` | Connect to (or start) the app on port `<n>` | `4200` |
76
+ | `--project <name\|path>` | Target a specific registered project (by name or path) | auto-detect from `cwd` |
77
+ | `--version`, `-v` | Print the CLI version and exit | — |
78
+ | `--help`, `-h` | Print usage and exit | — |
79
+ | `--status` | Print server status and exit | — |
80
+
81
+ > Project auto-detection is an **exact canonical-path match** (`realpathSync(cwd)` compared against registered project paths). It does **not** walk up parent directories — running from a subdirectory of a registered project will not match. Use `--project` to target a project from anywhere.
82
+
83
+ ### Server management
84
+
85
+ ```bash
86
+ specrails-desktop start # Start the app server (daemonized)
87
+ specrails-desktop stop # Stop the app server
88
+ specrails-desktop list # List all registered projects
89
+ specrails-desktop add <path> # Register a project by absolute path
90
+ specrails-desktop remove <project-id> # Unregister a project by ID
91
+ ```
92
+
93
+ ### Running work
94
+
95
+ ```bash
96
+ specrails-desktop implement "#42" # Queue /specrails:implement for spec #42
97
+ specrails-desktop batch-implement "#40" "#41" "#43" # Queue one batch job over several specs
98
+ specrails-desktop "any raw prompt" # Pass a raw prompt straight to the AI CLI
99
+ specrails-desktop /specrails:health-check # Pass any slash command directly
100
+ ```
101
+
102
+ > **Always quote issue refs.** An unquoted `#` starts a shell comment, so `batch-implement #40 #41` silently drops the refs. Quote each one: `"#40" "#41"`.
103
+
104
+ **Known verbs** (automatically prefixed with `/specrails:`): `implement`, `batch-implement`, `why`, `get-backlog-specs`, `auto-propose-backlog-specs`, `propose-spec`, `refactor-recommender`, `health-check`, `compat-check`, `enrich`. Any other first argument is passed as a raw prompt.
105
+
106
+ ### Port override example
107
+
108
+ ```bash
109
+ specrails-desktop --port 5000 start
110
+ specrails-desktop --port 5000 implement "#42"
111
+ ```
112
+
113
+ ---
114
+
115
+ ## Environment variables
116
+
117
+ A few env vars are read directly by the app. The two most useful operational ones:
118
+
119
+ | Variable | Description |
120
+ |----------|-------------|
121
+ | `SPECRAILS_TECH_URL` | Fallback specrails-tech base URL. Resolution order is the `specrails_tech_url` app setting **first**, then this env var, then `http://localhost:3000` — so a stored app setting takes precedence over this var. |
122
+ | `WM_ZOMBIE_TIMEOUT_MS` | Zombie-job detection timeout in milliseconds (default `1800000` = 30 min). This is a stuck-job watchdog, **not** a hard "kill after N minutes" cap. |
123
+
124
+ `ANTHROPIC_API_KEY` is **not** read by the app. The Claude CLI authenticates on its own — via a Claude subscription login or its own API-key configuration — so you do not set it for the app.
125
+
126
+ For the full catalogue of feature flags and kill switches (`SPECRAILS_*` server gates, `VITE_FEATURE_*` client flags, `SPECRAILS_CODEX_BETA`, `SPECRAILS_EXPLORE_*`), see [../customizing.md](../customizing.md#environment-variables).
127
+
128
+ ---
129
+
130
+ ## `~/.specrails/` directory structure
131
+
132
+ ```
133
+ ~/.specrails/
134
+ desktop.sqlite # App-level SQLite: project registry + desktop_settings
135
+ desktop.token # Auto-generated API token (mode 0600)
136
+ manager.pid # PID of the running specrails-desktop server process
137
+ desktop.log # Server stdout/stderr (appended on each start)
138
+ projects/
139
+ <project-slug>/
140
+ jobs.sqlite # Per-project job history, invocations, telemetry pointers
141
+ jobs/<jobId>/ # Per-job snapshots (profile.json, plugins.json) — chmod 400
142
+ telemetry/ # OTEL blobs (<jobId>.ndjson.gz) when telemetry is on
143
+ explore-cwd/ # App-managed cwd for Explore Spec turns
144
+ terminals/ # Per-session shell-integration shim dirs
145
+ codex-home/ # Per-project CODEX_HOME (Codex projects only)
146
+ browser-profile/ # Persistent browser-capture profile
147
+ attachments/ # Spec attachments, keyed by ticket
148
+ user-mcp.json # Materialised user-approved MCP config (chmod 600)
149
+ ```
150
+
151
+ **Slug generation.** The slug is derived from the project directory name: lowercased, every run of non-alphanumeric characters collapsed to a single hyphen, and leading/trailing hyphens stripped. Example: `My App v2!` → `my-app-v2`.
152
+
153
+ **Backup.** To back up all app data, copy `~/.specrails/`. Your project source code lives in your repos, not here.
154
+
155
+ **Reset.** To clear project registrations and job history:
156
+
157
+ ```bash
158
+ specrails-desktop stop
159
+ rm -rf ~/.specrails/desktop.sqlite ~/.specrails/projects/
160
+ ```
161
+
162
+ > This leaves `desktop.token`, `manager.pid`, and `desktop.log` in place. For a full wipe (including the API token), `rm -rf ~/.specrails`. Either way, your project source and specrails-core installations are untouched.
163
+
164
+ ---
165
+
166
+ ## Further reading
167
+
168
+ - [Getting started](../getting-started.md) — user-facing install guide
169
+ - [Architecture](architecture.md) — server modules, data flow, WebSocket protocol
170
+ - [CLI reference](../cli.md) — every command and flag in detail
171
+ - [Customising the app](../customizing.md) — feature flags, env vars, keybindings
172
+ - [Adding a provider](adding-a-provider.md) — wiring a third AI CLI adapter