difit 4.0.4 → 4.0.6

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 (172) hide show
  1. package/README.ja.md +3 -2
  2. package/README.ko.md +3 -2
  3. package/README.md +3 -2
  4. package/README.zh.md +3 -2
  5. package/dist/cli/comment.d.ts +2 -0
  6. package/dist/cli/comment.js +91 -0
  7. package/dist/cli/comment.test.d.ts +1 -0
  8. package/dist/cli/comment.test.js +164 -0
  9. package/dist/cli/index.js +104 -13
  10. package/dist/cli/index.test.js +5 -5
  11. package/dist/cli/utils.d.ts +1 -0
  12. package/dist/cli/utils.js +7 -0
  13. package/dist/client/assets/{_baseFor-DKyA49xd.js → _baseFor-Dq1lbcoh.js} +1 -1
  14. package/dist/client/assets/{arc-COOp7iVe.js → arc-1g1LrDb3.js} +1 -1
  15. package/dist/client/assets/architecture-YZFGNWBL-MZfdAdY6.js +1 -0
  16. package/dist/client/assets/architectureDiagram-Q4EWVU46-D87-Rmwy.js +36 -0
  17. package/dist/client/assets/{blockDiagram-DXYQGD6D-CtNJnEWN.js → blockDiagram-DXYQGD6D-Cep-MIFv.js} +1 -1
  18. package/dist/client/assets/{c4Diagram-AHTNJAMY-BqG-1m6C.js → c4Diagram-AHTNJAMY-BQuH9Txx.js} +1 -1
  19. package/dist/client/assets/channel-CJqLEVLU.js +1 -0
  20. package/dist/client/assets/{chunk-2KRD3SAO-DqP2NJNd.js → chunk-2KRD3SAO-CpQQpmvx.js} +1 -1
  21. package/dist/client/assets/chunk-336JU56O-Ddk9EzgO.js +2 -0
  22. package/dist/client/assets/chunk-426QAEUC-2xhUznDE.js +1 -0
  23. package/dist/client/assets/{chunk-4BX2VUAB-BT78EnQ6.js → chunk-4BX2VUAB-Ca-N0Wd9.js} +1 -1
  24. package/dist/client/assets/{chunk-4TB4RGXK-C4w_Bwzw.js → chunk-4TB4RGXK-ZTWP_Onw.js} +2 -2
  25. package/dist/client/assets/{chunk-55IACEB6-z3MQSTaj.js → chunk-55IACEB6-Dub40zHG.js} +1 -1
  26. package/dist/client/assets/{chunk-5FUZZQ4R-Chei69aj.js → chunk-5FUZZQ4R-Cgda0gtZ.js} +1 -1
  27. package/dist/client/assets/{chunk-5PVQY5BW-HgRiIs0X.js → chunk-5PVQY5BW-D8JPH_tm.js} +1 -1
  28. package/dist/client/assets/{chunk-67CJDMHE-B2q10-fp.js → chunk-67CJDMHE-U1KyLHzG.js} +1 -1
  29. package/dist/client/assets/{chunk-7N4EOEYR-DPgxysWq.js → chunk-7N4EOEYR-WzOy51nD.js} +1 -1
  30. package/dist/client/assets/{chunk-AA7GKIK3-BqmVmKLq.js → chunk-AA7GKIK3-DlWOj4lr.js} +1 -1
  31. package/dist/client/assets/{chunk-BSJP7CBP-CaIgleFn.js → chunk-BSJP7CBP-CcZ0op08.js} +1 -1
  32. package/dist/client/assets/{chunk-CIAEETIT-ByD-tlNF.js → chunk-CIAEETIT-qVSphnw5.js} +1 -1
  33. package/dist/client/assets/{chunk-EDXVE4YY-d3RUKKAj.js → chunk-EDXVE4YY-76SPH4sf.js} +1 -1
  34. package/dist/client/assets/{chunk-ENJZ2VHE-CNq5Qmg9.js → chunk-ENJZ2VHE-CKULNIzL.js} +1 -1
  35. package/dist/client/assets/{chunk-FMBD7UC4-DYfHJ6MV.js → chunk-FMBD7UC4-CvDPP3mb.js} +1 -1
  36. package/dist/client/assets/{chunk-FOC6F5B3-BRpSWlZj.js → chunk-FOC6F5B3-DceW0hWA.js} +1 -1
  37. package/dist/client/assets/{chunk-ICPOFSXX-B_MThwG6.js → chunk-ICPOFSXX-ChGBNZMk.js} +2 -2
  38. package/dist/client/assets/{chunk-K5T4RW27-DmamW1Ds.js → chunk-K5T4RW27-DBHdC4ln.js} +10 -10
  39. package/dist/client/assets/{chunk-KGLVRYIC-CRbg4c4z.js → chunk-KGLVRYIC-DRS7yiGQ.js} +1 -1
  40. package/dist/client/assets/{chunk-LIHQZDEY-CHQPSdB3.js → chunk-LIHQZDEY-KsE8dyJP.js} +1 -1
  41. package/dist/client/assets/{chunk-ORNJ4GCN-CIsQ4Zi4.js → chunk-ORNJ4GCN-Dnp4oHRD.js} +1 -1
  42. package/dist/client/assets/{chunk-OYMX7WX6-Cxi0kdGg.js → chunk-OYMX7WX6-CciaotDu.js} +1 -1
  43. package/dist/client/assets/chunk-QZHKN3VN-BiVE5u_E.js +1 -0
  44. package/dist/client/assets/{chunk-U2HBQHQK-V_hneCfR.js → chunk-U2HBQHQK-nbp7CjBP.js} +1 -1
  45. package/dist/client/assets/{chunk-X2U36JSP-De4pvO-I.js → chunk-X2U36JSP-Chs85loT.js} +1 -1
  46. package/dist/client/assets/{chunk-XPW4576I-B_osXKp6.js → chunk-XPW4576I-VtI9b561.js} +1 -1
  47. package/dist/client/assets/{chunk-YZCP3GAM-C_kqXssD.js → chunk-YZCP3GAM-sBsewSoO.js} +1 -1
  48. package/dist/client/assets/{chunk-ZZ45TVLE-B_xtlma5.js → chunk-ZZ45TVLE-TMgeW_px.js} +1 -1
  49. package/dist/client/assets/classDiagram-6PBFFD2Q-CfyHazmg.js +1 -0
  50. package/dist/client/assets/classDiagram-v2-HSJHXN6E-D7Rb-bnu.js +1 -0
  51. package/dist/client/assets/clone-8xC1huEg.js +1 -0
  52. package/dist/client/assets/cose-bilkent-S5V4N54A-5TzM3w9g.js +1 -0
  53. package/dist/client/assets/{cytoscape.esm-DRReFUEO.js → cytoscape.esm-DdcHPZAZ.js} +2 -2
  54. package/dist/client/assets/{dagre-KV5264BT-BWYGReXF.js → dagre-KV5264BT-xvyFOxd3.js} +1 -1
  55. package/dist/client/assets/{dagre-DU-XBdcU.js → dagre-sb6WtN4K.js} +1 -1
  56. package/dist/client/assets/{diagram-5BDNPKRD-DpUUhvWz.js → diagram-5BDNPKRD-ChRpAe5p.js} +1 -1
  57. package/dist/client/assets/{diagram-G4DWMVQ6-BJoTrUAx.js → diagram-G4DWMVQ6-C_8BED4A.js} +1 -1
  58. package/dist/client/assets/{diagram-MMDJMWI5-CAk1GW5g.js → diagram-MMDJMWI5-BMwXEou2.js} +1 -1
  59. package/dist/client/assets/{diagram-TYMM5635-Cct6g7FA.js → diagram-TYMM5635-CeAkx82D.js} +1 -1
  60. package/dist/client/assets/{dist-61sCfOmN.js → dist-CwC9dd2Z.js} +1 -1
  61. package/dist/client/assets/{erDiagram-SMLLAGMA-DHs2bXUj.js → erDiagram-SMLLAGMA-yGCTeXGt.js} +1 -1
  62. package/dist/client/assets/{flatten-mnWyE-RB.js → flatten-SRIRKgqP.js} +1 -1
  63. package/dist/client/assets/{flowDiagram-DWJPFMVM-DLu-6dfC.js → flowDiagram-DWJPFMVM-CugkvbmM.js} +1 -1
  64. package/dist/client/assets/ganttDiagram-T4ZO3ILL-BXnlBFgK.js +292 -0
  65. package/dist/client/assets/gitGraph-7Q5UKJZL-BeTWkPrd.js +1 -0
  66. package/dist/client/assets/{gitGraphDiagram-UUTBAWPF-Bc_rL3_k.js → gitGraphDiagram-UUTBAWPF-B61aCwwu.js} +1 -1
  67. package/dist/client/assets/{graphlib-BVMK0xYE.js → graphlib-BMWKz3zT.js} +1 -1
  68. package/dist/client/assets/index-D2Y8-unG.css +2 -0
  69. package/dist/client/assets/index-D9v_eYzS.js +79 -0
  70. package/dist/client/assets/info-OMHHGYJF-MUNR2tTt.js +1 -0
  71. package/dist/client/assets/{infoDiagram-42DDH7IO-Cf8u4jgP.js → infoDiagram-42DDH7IO-Bkh6nTL2.js} +1 -1
  72. package/dist/client/assets/{isEmpty-CiiIHfXR.js → isEmpty-CStpjy4G.js} +1 -1
  73. package/dist/client/assets/{ishikawaDiagram-UXIWVN3A-7n7DvfEb.js → ishikawaDiagram-UXIWVN3A-D_fdVT6_.js} +1 -1
  74. package/dist/client/assets/{journeyDiagram-VCZTEJTY-BMkeQqJb.js → journeyDiagram-VCZTEJTY-DkXVokNF.js} +1 -1
  75. package/dist/client/assets/{kanban-definition-6JOO6SKY-B8KkeZLS.js → kanban-definition-6JOO6SKY-y8qq7qvL.js} +1 -1
  76. package/dist/client/assets/{line-CVpcI6kj.js → line-B0LcTqNY.js} +1 -1
  77. package/dist/client/assets/{linear-DmhiOOKU.js → linear-CqIjr2qp.js} +1 -1
  78. package/dist/client/assets/mermaid-parser.core-Du6QzpZO.js +4 -0
  79. package/dist/client/assets/{mermaid.core-R7nXpPx-.js → mermaid.core-CZBu-oKJ.js} +3 -3
  80. package/dist/client/assets/{mindmap-definition-QFDTVHPH-CwcHocMZ.js → mindmap-definition-QFDTVHPH-BJrRxSkM.js} +1 -1
  81. package/dist/client/assets/{ordinal-k--hYEme.js → ordinal-DIg8h6NI.js} +1 -1
  82. package/dist/client/assets/packet-4T2RLAQJ-Ci-Uu57s.js +1 -0
  83. package/dist/client/assets/pie-ZZUOXDRM-pm57XGIg.js +1 -0
  84. package/dist/client/assets/{pieDiagram-DEJITSTG-BVAn8Lmr.js → pieDiagram-DEJITSTG-Debmhc0u.js} +1 -1
  85. package/dist/client/assets/prism-clojure-BpoF2XhX.js +1 -0
  86. package/dist/client/assets/{quadrantDiagram-34T5L4WZ-C2XZ_zxa.js → quadrantDiagram-34T5L4WZ-SE3g2BC9.js} +1 -1
  87. package/dist/client/assets/radar-PYXPWWZC-CH-AuSDw.js +1 -0
  88. package/dist/client/assets/{reduce-BTlHjXna.js → reduce-CG4cgj93.js} +1 -1
  89. package/dist/client/assets/{requirementDiagram-MS252O5E-CfO16pkI.js → requirementDiagram-MS252O5E-1mv41puC.js} +1 -1
  90. package/dist/client/assets/{sankeyDiagram-XADWPNL6-D_4_234M.js → sankeyDiagram-XADWPNL6-CLjPRtOP.js} +1 -1
  91. package/dist/client/assets/{sequenceDiagram-FGHM5R23-B-yHKMuK.js → sequenceDiagram-FGHM5R23-Cs-P3AtR.js} +1 -1
  92. package/dist/client/assets/src-5XpQHeIJ.js +1 -0
  93. package/dist/client/assets/{stateDiagram-FHFEXIEX-BeG2di4I.js → stateDiagram-FHFEXIEX-CmB1fohY.js} +1 -1
  94. package/dist/client/assets/stateDiagram-v2-QKLJ7IA2-D6jsrR-f.js +1 -0
  95. package/dist/client/assets/{timeline-definition-GMOUNBTQ-DhtnMGcE.js → timeline-definition-GMOUNBTQ-BMUafJOI.js} +1 -1
  96. package/dist/client/assets/treeView-SZITEDCU-BGsVMAdJ.js +1 -0
  97. package/dist/client/assets/treemap-W4RFUUIX-DXnhegXy.js +1 -0
  98. package/dist/client/assets/{vennDiagram-DHZGUBPP-CBn69TcQ.js → vennDiagram-DHZGUBPP-CpZ1Qhjz.js} +1 -1
  99. package/dist/client/assets/wardley-RL74JXVD-COd5nWj-.js +1 -0
  100. package/dist/client/assets/{wardleyDiagram-NUSXRM2D-CEoSJmN1.js → wardleyDiagram-NUSXRM2D-C-zH0lsd.js} +1 -1
  101. package/dist/client/assets/{xychartDiagram-5P7HB3ND-BZ_X9tkn.js → xychartDiagram-5P7HB3ND-SkLFuEHZ.js} +1 -1
  102. package/dist/client/index.html +2 -4
  103. package/dist/client/site-data/blobs/080c0e6/cHVibGljL3NpdGUtZGF0YS9vZy1pbWFnZS5wbmc.png +0 -0
  104. package/dist/client/site-data/blobs/55f23a1/bGFuZGluZy9wdWJsaWMvZGlmaXQvbG9nby5wbmc.png +0 -0
  105. package/dist/client/site-data/blobs/66ff7c6/cHVibGljL2xvZ28ucG5n.png +0 -0
  106. package/dist/client/site-data/blobs/e6977fe/cHVibGljL2xvZ28ucG5n.png +0 -0
  107. package/dist/client/site-data/og-image.png +0 -0
  108. package/dist/server/file-watcher.d.ts +2 -1
  109. package/dist/server/file-watcher.js +9 -3
  110. package/dist/server/git-diff.d.ts +5 -0
  111. package/dist/server/git-diff.js +65 -1
  112. package/dist/server/git-diff.test.js +50 -0
  113. package/dist/server/server.js +265 -68
  114. package/dist/server/server.test.js +228 -0
  115. package/dist/tui/App.js +0 -1
  116. package/dist/types/diff.d.ts +4 -4
  117. package/dist/types/watch.d.ts +30 -1
  118. package/dist/utils/commentImports.d.ts +2 -0
  119. package/dist/utils/commentImports.js +119 -1
  120. package/dist/utils/editorOptions.d.ts +58 -35
  121. package/dist/utils/editorOptions.js +150 -24
  122. package/dist/utils/editorOptions.test.js +201 -9
  123. package/package.json +9 -6
  124. package/dist/client/assets/architecture-YZFGNWBL-Cs2Q6RQP.js +0 -1
  125. package/dist/client/assets/architectureDiagram-Q4EWVU46-BO4dVPUA.js +0 -36
  126. package/dist/client/assets/channel-_xDT1u3-.js +0 -1
  127. package/dist/client/assets/chunk-336JU56O-D1qa7Qzb.js +0 -2
  128. package/dist/client/assets/chunk-426QAEUC-6J_A_wvD.js +0 -1
  129. package/dist/client/assets/chunk-CFjPhJqf.js +0 -1
  130. package/dist/client/assets/chunk-QZHKN3VN-C0QzfgZ8.js +0 -1
  131. package/dist/client/assets/classDiagram-6PBFFD2Q-5XrS-DAQ.js +0 -1
  132. package/dist/client/assets/classDiagram-v2-HSJHXN6E-Covl2vKy.js +0 -1
  133. package/dist/client/assets/clone-rhRH8pyW.js +0 -1
  134. package/dist/client/assets/cose-bilkent-S5V4N54A-BvXFc7Rr.js +0 -1
  135. package/dist/client/assets/ganttDiagram-T4ZO3ILL-CMIzlKAR.js +0 -292
  136. package/dist/client/assets/gitGraph-7Q5UKJZL-A_wWsXju.js +0 -1
  137. package/dist/client/assets/index-Cq_APK7Y.css +0 -2
  138. package/dist/client/assets/index-RcU838Ah.js +0 -79
  139. package/dist/client/assets/info-OMHHGYJF-Bv3kK2Bb.js +0 -1
  140. package/dist/client/assets/mermaid-parser.core-CnJ9Tv8l.js +0 -4
  141. package/dist/client/assets/packet-4T2RLAQJ-D2q3-9ae.js +0 -1
  142. package/dist/client/assets/pie-ZZUOXDRM-GivlQcUF.js +0 -1
  143. package/dist/client/assets/preload-helper-DSXbuxSR.js +0 -1
  144. package/dist/client/assets/radar-PYXPWWZC-C9pD6VNR.js +0 -1
  145. package/dist/client/assets/src-CjDs0_Ij.js +0 -1
  146. package/dist/client/assets/stateDiagram-v2-QKLJ7IA2-DvcSq7KE.js +0 -1
  147. package/dist/client/assets/treeView-SZITEDCU-BSNk8_yV.js +0 -1
  148. package/dist/client/assets/treemap-W4RFUUIX-ym4zQztE.js +0 -1
  149. package/dist/client/assets/wardley-RL74JXVD-B02H6ReJ.js +0 -1
  150. /package/dist/client/assets/{array-BNor45A1.js → array-DOVTz2Mq.js} +0 -0
  151. /package/dist/client/assets/{defaultLocale-DPzUsThw.js → defaultLocale-Ck2Xxk-C.js} +0 -0
  152. /package/dist/client/assets/{init-C0L3woqb.js → init-Bft5Ffpj.js} +0 -0
  153. /package/dist/client/assets/{katex-FOM3xZj7.js → katex-CeIlAR55.js} +0 -0
  154. /package/dist/client/assets/{path-sMK4d_s9.js → path-DfRbCp9y.js} +0 -0
  155. /package/dist/client/assets/{prism-bash-iQBez6et.js → prism-bash-CPkZUJMA.js} +0 -0
  156. /package/dist/client/assets/{prism-csharp-C1RDHXRk.js → prism-csharp-BEk8D1-3.js} +0 -0
  157. /package/dist/client/assets/{prism-dart-nIH9vDUM.js → prism-dart-ByLYrdQB.js} +0 -0
  158. /package/dist/client/assets/{prism-elixir-DUMUOd7H.js → prism-elixir-BZtyIEab.js} +0 -0
  159. /package/dist/client/assets/{prism-haskell-BP3SRvzt.js → prism-haskell-NAsbeo3V.js} +0 -0
  160. /package/dist/client/assets/{prism-hcl-C-ZHJGEE.js → prism-hcl-crnGqmVp.js} +0 -0
  161. /package/dist/client/assets/{prism-java-scuShSv5.js → prism-java-BovStacA.js} +0 -0
  162. /package/dist/client/assets/{prism-markup-templating-BFXREXfb.js → prism-markup-templating-Cl8NiLjy.js} +0 -0
  163. /package/dist/client/assets/{prism-nix-CO4UPu3E.js → prism-nix-BS_cm_1n.js} +0 -0
  164. /package/dist/client/assets/{prism-perl-BBDKnHRR.js → prism-perl-DGLVMq5H.js} +0 -0
  165. /package/dist/client/assets/{prism-php-DjIafOi_.js → prism-php-BskSwJN8.js} +0 -0
  166. /package/dist/client/assets/{prism-protobuf-BE1MoFmZ.js → prism-protobuf-DfbIYpO7.js} +0 -0
  167. /package/dist/client/assets/{prism-ruby-CZ-lrXfL.js → prism-ruby-FBVh1PRE.js} +0 -0
  168. /package/dist/client/assets/{prism-scala-DgnxHuDn.js → prism-scala--9AfMHPY.js} +0 -0
  169. /package/dist/client/assets/{prism-solidity-5fSUcW9Y.js → prism-solidity-BgJNkj1z.js} +0 -0
  170. /package/dist/client/assets/{prism-sql-CKkohPI_.js → prism-sql-C9Czmpov.js} +0 -0
  171. /package/dist/client/assets/{prism-vim-CkRmxTmK.js → prism-vim-CzUNf0WQ.js} +0 -0
  172. /package/dist/client/assets/{rough.esm-DeLgKbOI.js → rough.esm-Bbn_-PMU.js} +0 -0
package/README.ja.md CHANGED
@@ -151,6 +151,7 @@ git diff --cached | difit -
151
151
  | `--clean` | false | 起動時に既存コメントと閲覧済みファイルをすべてクリア |
152
152
  | `--include-untracked` | false | diffにuntrackedファイルを自動的に含める(`.`または`working`のみ有効) |
153
153
  | `--keep-alive` | false | ブラウザ切断後もサーバーを終了せず起動したままにする(Ctrl+Cで手動停止) |
154
+ | `--background` | false | サーバーをバックグラウンドで起動したままにし、接続情報をJSONで出力 |
154
155
  | `--context <lines>` | Gitの既定値 (3) | 変更ごとの前後コンテキスト行数を制限(`0` は変更行のみ表示。`--pr` と stdin では使用不可) |
155
156
 
156
157
  ## 💬 コメントシステム
@@ -197,10 +198,10 @@ npx skills add yoshiko-pg/difit
197
198
  - **JavaScript/TypeScript**:`.js`, `.jsx`, `.ts`, `.tsx`
198
199
  - **Web技術**:HTML, CSS, JSON, XML, Markdown
199
200
  - **シェルスクリプト**:`.sh`, `.bash`, `.zsh`, `.fish`
200
- - **バックエンド言語**:PHP, SQL, Ruby, Java, Scala, Perl, Elixir
201
+ - **バックエンド言語**:PHP, SQL, Ruby, Java, Scala, Perl, Elixir, Haskell, Clojure
201
202
  - **システム言語**:C, C++, C#, Rust, Go
202
203
  - **モバイル言語**:Swift, Kotlin, Dart
203
- - **IaC**:Terraform (HCL)
204
+ - **IaC**:Terraform (HCL), Nix
204
205
  - **その他**:Python, Protobuf, YAML, Solidity, Vim Script
205
206
 
206
207
  ## 🔍 自動折りたたみファイル
package/README.ko.md CHANGED
@@ -151,6 +151,7 @@ git diff --cached | difit -
151
151
  | `--clean` | false | 시작 시 모든 기존 코멘트와 열람된 파일 표시 초기화 |
152
152
  | `--include-untracked` | false | diff에 untracked 파일 자동 포함 (`.` 또는 `working`에서만 유효) |
153
153
  | `--keep-alive` | false | 브라우저 연결이 끊겨도 서버 유지 (Ctrl+C로 수동 종료) |
154
+ | `--background` | false | 서버를 백그라운드에서 계속 실행하고 JSON 연결 정보 출력 |
154
155
  | `--context <lines>` | Git 기본값 (3) | 변경 주변의 컨텍스트 줄 수를 제한 (`0`이면 변경된 줄만 표시, `--pr` 및 stdin에서는 사용 불가) |
155
156
 
156
157
  ## 💬 코멘트 시스템
@@ -197,10 +198,10 @@ npx skills add yoshiko-pg/difit
197
198
  - **JavaScript/TypeScript**: `.js`, `.jsx`, `.ts`, `.tsx`
198
199
  - **웹 기술**: HTML, CSS, JSON, XML, Markdown
199
200
  - **셸 스크립트**: `.sh`, `.bash`, `.zsh`, `.fish`
200
- - **백엔드 언어**: PHP, SQL, Ruby, Java, Scala, Perl, Elixir
201
+ - **백엔드 언어**: PHP, SQL, Ruby, Java, Scala, Perl, Elixir, Haskell, Clojure
201
202
  - **시스템 언어**: C, C++, C#, Rust, Go
202
203
  - **모바일 언어**: Swift, Kotlin, Dart
203
- - **인프라 코드**: Terraform (HCL)
204
+ - **인프라 코드**: Terraform (HCL), Nix
204
205
  - **기타**: Python, Protobuf, YAML, Solidity, Vim 스크립트
205
206
 
206
207
  ## 🔍 자동 접힘 파일
package/README.md CHANGED
@@ -151,6 +151,7 @@ Stdin mode is selected with intent-first rules:
151
151
  | `--clean` | false | Clear all existing comments and viewed files on startup |
152
152
  | `--include-untracked` | false | Automatically include untracked files in diff (only with `.` or `working`) |
153
153
  | `--keep-alive` | false | Keep server running after browser disconnects (stop manually with Ctrl+C) |
154
+ | `--background` | false | Keep the server running in the background and output JSON connection info |
154
155
  | `--context <lines>` | git default (3) | Limit surrounding context lines per change (`0` shows changes only; not available with `--pr` or stdin) |
155
156
 
156
157
  ## 💬 Comment System
@@ -197,10 +198,10 @@ After code edits or automated review, the agent can start the difit server with
197
198
  - **JavaScript/TypeScript**: `.js`, `.jsx`, `.ts`, `.tsx`
198
199
  - **Web Technologies**: HTML, CSS, JSON, XML, Markdown
199
200
  - **Shell Scripts**: `.sh`, `.bash`, `.zsh`, `.fish`
200
- - **Backend Languages**: PHP, SQL, Ruby, Java, Scala, Perl, Elixir
201
+ - **Backend Languages**: PHP, SQL, Ruby, Java, Scala, Perl, Elixir, Haskell, Clojure
201
202
  - **Systems Languages**: C, C++, C#, Rust, Go
202
203
  - **Mobile Languages**: Swift, Kotlin, Dart
203
- - **Infrastructure as Code**: Terraform (HCL)
204
+ - **Infrastructure as Code**: Terraform (HCL), Nix
204
205
  - **Others**: Python, Protobuf, YAML, Solidity, Vim script
205
206
 
206
207
  ## 🔍 Auto-collapsed Files
package/README.zh.md CHANGED
@@ -151,6 +151,7 @@ git diff --cached | difit -
151
151
  | `--clean` | false | 启动时清除所有现有评论和已查看的文件 |
152
152
  | `--include-untracked` | false | 自动将 untracked 文件包含在 diff 中(仅在 `.` 或 `working` 时有效) |
153
153
  | `--keep-alive` | false | 浏览器断开后保持服务器运行(使用 Ctrl+C 手动停止) |
154
+ | `--background` | false | 在后台保持服务器运行,并输出 JSON 连接信息 |
154
155
  | `--context <lines>` | Git 默认值 (3) | 限制每处变更周围的上下文行数(`0` 仅显示变更行;不可与 `--pr` 或 stdin 一起使用) |
155
156
 
156
157
  ## 💬 评论系统
@@ -197,10 +198,10 @@ npx skills add yoshiko-pg/difit
197
198
  - **JavaScript/TypeScript**:`.js`, `.jsx`, `.ts`, `.tsx`
198
199
  - **Web 技术**:HTML, CSS, JSON, XML, Markdown
199
200
  - **Shell 脚本**:`.sh`, `.bash`, `.zsh`, `.fish`
200
- - **后端语言**:PHP, SQL, Ruby, Java, Scala, Perl, Elixir
201
+ - **后端语言**:PHP, SQL, Ruby, Java, Scala, Perl, Elixir, Haskell, Clojure
201
202
  - **系统语言**:C, C++, C#, Rust, Go
202
203
  - **移动语言**:Swift, Kotlin, Dart
203
- - **基础设施即代码**:Terraform (HCL)
204
+ - **基础设施即代码**:Terraform (HCL), Nix
204
205
  - **其他**:Python, Protobuf, YAML, Solidity, Vim Script
205
206
 
206
207
  ## 🔍 自动折叠文件
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function createCommentCommand(): Command;
@@ -0,0 +1,91 @@
1
+ import { Command, Option } from 'commander';
2
+ import { parseCommentImportValue } from '../utils/commentImports.js';
3
+ import { detectStdinSource, readStdin } from './utils.js';
4
+ async function parseCommentAddInput(json) {
5
+ if (typeof json === 'string') {
6
+ return json;
7
+ }
8
+ if (detectStdinSource() === 'tty') {
9
+ throw new Error('Provide comment JSON as an argument or via stdin');
10
+ }
11
+ const stdin = await readStdin();
12
+ if (!stdin.trim()) {
13
+ throw new Error('No comment JSON received from stdin');
14
+ }
15
+ return stdin;
16
+ }
17
+ export function createCommentCommand() {
18
+ const comment = new Command('comment').description('Add or retrieve comments on a running difit server');
19
+ comment
20
+ .command('add')
21
+ .description('Add comments to a running difit server')
22
+ .argument('[json]', 'comment import JSON (object or array)')
23
+ .requiredOption('--port <port>', 'port of the running difit server', parseInt)
24
+ .action(async (json, opts) => {
25
+ try {
26
+ const input = await parseCommentAddInput(json);
27
+ const imports = parseCommentImportValue(input);
28
+ const response = await fetch(`http://localhost:${opts.port}/api/comment-imports`, {
29
+ method: 'POST',
30
+ headers: { 'Content-Type': 'application/json' },
31
+ body: JSON.stringify(imports),
32
+ });
33
+ if (!response.ok) {
34
+ const errorBody = (await response.json().catch(() => ({})));
35
+ console.error(`Error: ${errorBody.error ?? 'Failed to add comments'}`);
36
+ process.exit(1);
37
+ }
38
+ const result = (await response.json());
39
+ console.log(JSON.stringify({
40
+ success: result.success ?? true,
41
+ importId: result.importId,
42
+ count: result.count ?? imports.length,
43
+ warnings: result.warnings ?? [],
44
+ }));
45
+ }
46
+ catch (error) {
47
+ if (error instanceof TypeError && error.message.includes('fetch failed')) {
48
+ console.error(`Error: Cannot connect to difit server on port ${opts.port}. Is the server running?`);
49
+ }
50
+ else {
51
+ console.error(`Error: ${error instanceof Error ? error.message : 'Unknown error'}`);
52
+ }
53
+ process.exit(1);
54
+ }
55
+ });
56
+ comment
57
+ .command('get')
58
+ .description('Retrieve comments from a running difit server')
59
+ .requiredOption('--port <port>', 'port of the running difit server', parseInt)
60
+ .addOption(new Option('--format <format>', 'output format').choices(['text', 'json']).default('text'))
61
+ .action(async (opts) => {
62
+ try {
63
+ const endpoint = opts.format === 'json' ? '/api/comments-json' : '/api/comments-output';
64
+ const response = await fetch(`http://localhost:${opts.port}${endpoint}`);
65
+ if (!response.ok) {
66
+ console.error('Error: Failed to retrieve comments');
67
+ process.exit(1);
68
+ }
69
+ if (opts.format === 'json') {
70
+ const data = await response.json();
71
+ console.log(JSON.stringify(data));
72
+ }
73
+ else {
74
+ const text = await response.text();
75
+ if (text.trim()) {
76
+ console.log(text);
77
+ }
78
+ }
79
+ }
80
+ catch (error) {
81
+ if (error instanceof TypeError && error.message.includes('fetch failed')) {
82
+ console.error(`Error: Cannot connect to difit server on port ${opts.port}. Is the server running?`);
83
+ }
84
+ else {
85
+ console.error(`Error: ${error instanceof Error ? error.message : 'Unknown error'}`);
86
+ }
87
+ process.exit(1);
88
+ }
89
+ });
90
+ return comment;
91
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,164 @@
1
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
2
+ import { createCommentCommand } from './comment.js';
3
+ describe('createCommentCommand', () => {
4
+ const command = createCommentCommand();
5
+ it('creates a command named "comment"', () => {
6
+ expect(command.name()).toBe('comment');
7
+ });
8
+ it('has "add" and "get" subcommands', () => {
9
+ const subcommandNames = command.commands.map((c) => c.name());
10
+ expect(subcommandNames).toContain('add');
11
+ expect(subcommandNames).toContain('get');
12
+ });
13
+ describe('add subcommand', () => {
14
+ const addCommand = command.commands.find((c) => c.name() === 'add');
15
+ it('requires --port option', () => {
16
+ const portOption = addCommand.options.find((o) => o.long === '--port');
17
+ expect(portOption).toBeDefined();
18
+ expect(portOption?.mandatory).toBe(true);
19
+ });
20
+ it('accepts optional json argument', () => {
21
+ const args = addCommand.registeredArguments;
22
+ expect(args).toHaveLength(1);
23
+ expect(args[0].name()).toBe('json');
24
+ expect(args[0].required).toBe(false);
25
+ });
26
+ });
27
+ describe('get subcommand', () => {
28
+ const getCommand = command.commands.find((c) => c.name() === 'get');
29
+ it('requires --port option', () => {
30
+ const portOption = getCommand.options.find((o) => o.long === '--port');
31
+ expect(portOption).toBeDefined();
32
+ expect(portOption?.mandatory).toBe(true);
33
+ });
34
+ it('has --format option with choices', () => {
35
+ const formatOption = getCommand.options.find((o) => o.long === '--format');
36
+ expect(formatOption).toBeDefined();
37
+ expect(formatOption?.defaultValue).toBe('text');
38
+ expect(formatOption?.argChoices).toEqual(['text', 'json']);
39
+ });
40
+ });
41
+ });
42
+ function jsonResponse(body, status = 200) {
43
+ return new Response(JSON.stringify(body), {
44
+ status,
45
+ headers: { 'Content-Type': 'application/json' },
46
+ });
47
+ }
48
+ function textResponse(body, status = 200) {
49
+ return new Response(body, {
50
+ status,
51
+ headers: { 'Content-Type': 'text/plain' },
52
+ });
53
+ }
54
+ describe('comment subcommand integration', () => {
55
+ const originalFetch = globalThis.fetch;
56
+ let mockFetch;
57
+ let originalProcessExit;
58
+ let consoleOutput;
59
+ let consoleErrors;
60
+ beforeEach(() => {
61
+ mockFetch = vi.fn();
62
+ globalThis.fetch = mockFetch;
63
+ originalProcessExit = process.exit;
64
+ process.exit = vi.fn();
65
+ consoleOutput = [];
66
+ consoleErrors = [];
67
+ vi.spyOn(console, 'log').mockImplementation((...args) => {
68
+ consoleOutput.push(args.join(' '));
69
+ });
70
+ vi.spyOn(console, 'error').mockImplementation((...args) => {
71
+ consoleErrors.push(args.join(' '));
72
+ });
73
+ });
74
+ afterEach(() => {
75
+ globalThis.fetch = originalFetch;
76
+ process.exit = originalProcessExit;
77
+ vi.restoreAllMocks();
78
+ });
79
+ describe('add', () => {
80
+ it('sends comment imports to the server', async () => {
81
+ mockFetch.mockResolvedValue(jsonResponse({ success: true, importId: 'abc123', count: 1 }));
82
+ const command = createCommentCommand();
83
+ await command.parseAsync([
84
+ 'node',
85
+ 'difit',
86
+ 'add',
87
+ '--port',
88
+ '4966',
89
+ '{"type":"thread","filePath":"test.ts","position":{"side":"new","line":1},"body":"Test"}',
90
+ ]);
91
+ expect(mockFetch).toHaveBeenCalledWith('http://localhost:4966/api/comment-imports', expect.objectContaining({
92
+ method: 'POST',
93
+ headers: { 'Content-Type': 'application/json' },
94
+ }));
95
+ expect(consoleOutput[0]).toContain('"success":true');
96
+ });
97
+ it('validates JSON before sending', async () => {
98
+ const command = createCommentCommand();
99
+ await command.parseAsync(['node', 'difit', 'add', '--port', '4966', 'not-valid-json']);
100
+ expect(mockFetch).not.toHaveBeenCalled();
101
+ expect(consoleErrors[0]).toContain('Error:');
102
+ expect(process.exit).toHaveBeenCalledWith(1);
103
+ });
104
+ it('handles server error response', async () => {
105
+ mockFetch.mockResolvedValue(jsonResponse({ error: 'Bad request' }, 400));
106
+ const command = createCommentCommand();
107
+ await command.parseAsync([
108
+ 'node',
109
+ 'difit',
110
+ 'add',
111
+ '--port',
112
+ '4966',
113
+ '{"type":"thread","filePath":"test.ts","position":{"side":"new","line":1},"body":"Test"}',
114
+ ]);
115
+ expect(consoleErrors[0]).toContain('Bad request');
116
+ expect(process.exit).toHaveBeenCalledWith(1);
117
+ });
118
+ it('handles connection error', async () => {
119
+ const fetchError = new TypeError('fetch failed');
120
+ mockFetch.mockRejectedValue(fetchError);
121
+ const command = createCommentCommand();
122
+ await command.parseAsync([
123
+ 'node',
124
+ 'difit',
125
+ 'add',
126
+ '--port',
127
+ '9999',
128
+ '{"type":"thread","filePath":"test.ts","position":{"side":"new","line":1},"body":"Test"}',
129
+ ]);
130
+ expect(consoleErrors[0]).toContain('Cannot connect');
131
+ expect(consoleErrors[0]).toContain('9999');
132
+ expect(process.exit).toHaveBeenCalledWith(1);
133
+ });
134
+ });
135
+ describe('get', () => {
136
+ it('fetches comments in text format by default', async () => {
137
+ mockFetch.mockResolvedValue(textResponse('Comments output text'));
138
+ const command = createCommentCommand();
139
+ await command.parseAsync(['node', 'difit', 'get', '--port', '4966']);
140
+ expect(mockFetch).toHaveBeenCalledWith('http://localhost:4966/api/comments-output');
141
+ expect(consoleOutput[0]).toBe('Comments output text');
142
+ });
143
+ it('fetches comments in json format', async () => {
144
+ mockFetch.mockResolvedValue(jsonResponse({ threads: [{ id: '1' }] }));
145
+ const command = createCommentCommand();
146
+ await command.parseAsync(['node', 'difit', 'get', '--port', '4966', '--format', 'json']);
147
+ expect(mockFetch).toHaveBeenCalledWith('http://localhost:4966/api/comments-json');
148
+ expect(consoleOutput[0]).toContain('"threads"');
149
+ });
150
+ it('handles connection error', async () => {
151
+ mockFetch.mockRejectedValue(new TypeError('fetch failed'));
152
+ const command = createCommentCommand();
153
+ await command.parseAsync(['node', 'difit', 'get', '--port', '9999']);
154
+ expect(consoleErrors[0]).toContain('Cannot connect');
155
+ expect(process.exit).toHaveBeenCalledWith(1);
156
+ });
157
+ it('handles empty text output silently', async () => {
158
+ mockFetch.mockResolvedValue(textResponse(' '));
159
+ const command = createCommentCommand();
160
+ await command.parseAsync(['node', 'difit', 'get', '--port', '4966']);
161
+ expect(consoleOutput).toHaveLength(0);
162
+ });
163
+ });
164
+ });
package/dist/cli/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env node
2
+ import { spawn } from 'child_process';
2
3
  import { Command } from 'commander';
3
4
  import React from 'react';
4
5
  import { simpleGit } from 'simple-git';
@@ -7,7 +8,8 @@ import { startServer } from '../server/server.js';
7
8
  import { createDiffSelection } from '../utils/diffSelection.js';
8
9
  import { DiffMode } from '../types/watch.js';
9
10
  import { DEFAULT_DIFF_VIEW_MODE, normalizeDiffViewMode } from '../utils/diffMode.js';
10
- import { shouldReadStdin, findUntrackedFiles, markFilesIntentToAdd, promptUser, parseCommentOptions, validateDiffArguments, getGitRoot, } from './utils.js';
11
+ import { shouldReadStdin, findUntrackedFiles, markFilesIntentToAdd, promptUser, parseCommentOptions, validateDiffArguments, getGitRoot, readStdin, } from './utils.js';
12
+ import { createCommentCommand } from './comment.js';
11
13
  import { getPrPatch, getPrCommentImports } from './github.js';
12
14
  import { warnAboutTuiDeprecation } from './tuiDeprecation.js';
13
15
  function isSpecialArg(arg) {
@@ -48,27 +50,99 @@ function determineDiffMode(selection, compareWith) {
48
50
  // Default mode: HEAD^ vs HEAD or HEAD vs other commits (watch for HEAD changes)
49
51
  return DiffMode.DEFAULT;
50
52
  }
53
+ async function startBackgroundProcess() {
54
+ const scriptPath = process.argv[1];
55
+ if (!scriptPath) {
56
+ throw new Error('Unable to determine difit entrypoint for background process');
57
+ }
58
+ const childArgs = process.argv.slice(2).filter((arg) => arg !== '--background');
59
+ if (!childArgs.includes('--keep-alive')) {
60
+ childArgs.push('--keep-alive');
61
+ }
62
+ if (!childArgs.includes('--no-open')) {
63
+ childArgs.push('--no-open');
64
+ }
65
+ const child = spawn(process.execPath, [scriptPath, ...childArgs], {
66
+ detached: true,
67
+ stdio: ['ignore', 'pipe', 'pipe'],
68
+ env: {
69
+ ...process.env,
70
+ [BACKGROUND_CHILD_ENV]: '1',
71
+ },
72
+ });
73
+ child.stdout.setEncoding('utf8');
74
+ child.stderr.setEncoding('utf8');
75
+ await new Promise((resolve, reject) => {
76
+ const timeout = setTimeout(() => {
77
+ reject(new Error('Timed out while starting background difit server'));
78
+ }, 10_000);
79
+ let stderr = '';
80
+ let settled = false;
81
+ const finish = (callback) => {
82
+ if (settled) {
83
+ return;
84
+ }
85
+ settled = true;
86
+ clearTimeout(timeout);
87
+ callback();
88
+ };
89
+ child.stdout.on('data', (chunk) => {
90
+ const line = chunk
91
+ .split(/\r?\n/u)
92
+ .map((value) => value.trim())
93
+ .find((value) => value.length > 0);
94
+ if (!line) {
95
+ return;
96
+ }
97
+ finish(() => {
98
+ console.log(line);
99
+ child.unref();
100
+ resolve();
101
+ });
102
+ });
103
+ child.stderr.on('data', (chunk) => {
104
+ stderr += chunk;
105
+ });
106
+ child.once('error', (error) => {
107
+ finish(() => {
108
+ reject(error);
109
+ });
110
+ });
111
+ child.once('exit', (code) => {
112
+ finish(() => {
113
+ const trimmedStderr = stderr.trim();
114
+ reject(new Error(trimmedStderr || `Background difit server exited early (code ${code ?? 'unknown'})`));
115
+ });
116
+ });
117
+ });
118
+ }
119
+ const BACKGROUND_CHILD_ENV = 'DIFIT_BACKGROUND_CHILD';
51
120
  const program = new Command();
52
121
  program
53
122
  .name('difit')
54
123
  .description('A lightweight Git diff viewer with GitHub-like interface')
55
124
  .version(pkg.version, '-v, --version', 'output the version number')
125
+ .enablePositionalOptions()
126
+ .addCommand(createCommentCommand())
56
127
  .argument('[commit-ish]', 'Git commit, tag, branch, HEAD~n reference, or "working"/"staged"/"."', 'HEAD')
57
128
  .argument('[compare-with]', 'Optional: Compare with this commit/branch (shows diff between commit-ish and compare-with)')
58
129
  .option('--port <port>', 'preferred port (auto-assigned if occupied)', parseInt)
59
130
  .option('--host <host>', 'host address to bind', '')
60
131
  .option('--no-open', 'do not automatically open browser')
61
132
  .option('--mode <mode>', 'diff mode (split or unified)', normalizeDiffViewMode, DEFAULT_DIFF_VIEW_MODE)
62
- .option('--comment <json>', 'inject initial review comments (repeatable, accepts a JSON object or array)', (value, previous = []) => [...previous, value], [])
133
+ .option('--comment <json>', 'inject initial review comments (repeatable, accepts a JSON object or array)', (value, previous) => [...previous, value], [])
63
134
  .option('--tui', 'use terminal UI instead of web interface')
64
135
  .option('--pr <url>', 'GitHub PR URL to review (e.g., https://github.com/owner/repo/pull/123)')
65
136
  .option('--clean', 'start with a clean slate by clearing all existing comments')
66
137
  .option('--include-untracked', 'automatically include untracked files in diff')
67
138
  .option('--keep-alive', 'keep server running even after browser disconnects')
139
+ .option('--background', 'keep the server running in the background and output JSON info')
68
140
  .option('--context <lines>', 'number of context lines shown around each change', parseInt)
69
141
  .option('--merge-base', 'resolve the base revision with git merge-base before diffing (Git revision mode only)')
70
142
  .action(async (commitish, compareWith, options) => {
71
143
  try {
144
+ const isBackgroundChild = process.env[BACKGROUND_CHILD_ENV] === '1';
145
+ const backgroundMode = options.background || isBackgroundChild;
72
146
  let stdinDiff;
73
147
  let stdinReviewLabel = 'diff from stdin';
74
148
  let manualCommentImports = [];
@@ -78,6 +152,10 @@ program
78
152
  console.error('Error: --context must be a non-negative integer');
79
153
  process.exit(1);
80
154
  }
155
+ if (options.background && !isBackgroundChild) {
156
+ await startBackgroundProcess();
157
+ return;
158
+ }
81
159
  try {
82
160
  manualCommentImports = parseCommentOptions(options.comment);
83
161
  commentImports = manualCommentImports;
@@ -86,6 +164,10 @@ program
86
164
  console.error(`Error: ${error instanceof Error ? error.message : 'Invalid --comment value'}`);
87
165
  process.exit(1);
88
166
  }
167
+ if (backgroundMode) {
168
+ options.keepAlive = true;
169
+ options.open = false;
170
+ }
89
171
  if (options.pr) {
90
172
  if (commitish !== 'HEAD' || compareWith) {
91
173
  console.error('Error: --pr option cannot be used with positional arguments');
@@ -146,7 +228,7 @@ program
146
228
  }
147
229
  if (stdinDiff) {
148
230
  // Start server with stdin diff (including --pr patch)
149
- const { url } = await startServer({
231
+ const { url, port } = await startServer({
150
232
  stdinDiff,
151
233
  preferredPort: options.port,
152
234
  host: options.host,
@@ -156,6 +238,10 @@ program
156
238
  keepAlive: options.keepAlive,
157
239
  ...(commentImports.length > 0 ? { commentImports } : {}),
158
240
  });
241
+ if (backgroundMode) {
242
+ console.log(JSON.stringify({ port, url, pid: process.pid }));
243
+ return;
244
+ }
159
245
  console.log(`\n🚀 difit server started on ${url}`);
160
246
  console.log(`📋 Reviewing: ${stdinReviewLabel}`);
161
247
  if (options.keepAlive) {
@@ -180,9 +266,18 @@ program
180
266
  }
181
267
  if (selection.targetCommitish === 'working' || selection.targetCommitish === '.') {
182
268
  const git = simpleGit(repoPath);
183
- await handleUntrackedFiles(git, options.includeUntracked);
269
+ if (isBackgroundChild && !options.includeUntracked) {
270
+ // Skip interactive prompts in detached background mode.
271
+ }
272
+ else {
273
+ await handleUntrackedFiles(git, options.includeUntracked);
274
+ }
184
275
  }
185
276
  if (options.tui) {
277
+ if (backgroundMode) {
278
+ console.error('Error: --background option cannot be used with --tui');
279
+ process.exit(1);
280
+ }
186
281
  if (commentImports.length > 0) {
187
282
  console.error('Error: --comment option cannot be used with --tui');
188
283
  process.exit(1);
@@ -223,6 +318,10 @@ program
223
318
  repoPath,
224
319
  ...(commentImports.length > 0 ? { commentImports } : {}),
225
320
  });
321
+ if (backgroundMode) {
322
+ console.log(JSON.stringify({ port, url, pid: process.pid }));
323
+ return;
324
+ }
226
325
  console.log(`\n🚀 difit server started on ${url}`);
227
326
  console.log(`📋 Reviewing: ${selection.targetCommitish}`);
228
327
  if (options.keepAlive) {
@@ -264,15 +363,7 @@ program
264
363
  process.exit(1);
265
364
  }
266
365
  });
267
- program.parse();
268
- // Check for untracked files and prompt user to add them for diff visibility
269
- async function readStdin() {
270
- const chunks = [];
271
- for await (const chunk of process.stdin) {
272
- chunks.push(chunk);
273
- }
274
- return Buffer.concat(chunks).toString('utf8');
275
- }
366
+ void program.parseAsync();
276
367
  async function handleUntrackedFiles(git, addAutomatically) {
277
368
  const files = await findUntrackedFiles(git);
278
369
  if (files.length === 0) {
@@ -640,7 +640,7 @@ describe('CLI index.ts', () => {
640
640
  program
641
641
  .argument('[commit-ish]', 'commit-ish', 'HEAD')
642
642
  .argument('[compare-with]', 'compare-with')
643
- .option('--comment <json>', 'comment', (value, previous = []) => [...previous, value], [])
643
+ .option('--comment <json>', 'comment', (value, previous) => [...previous, value], [])
644
644
  .option('--port <port>', 'port', parseInt)
645
645
  .option('--host <host>', 'host', '')
646
646
  .option('--no-open', 'no-open')
@@ -706,7 +706,7 @@ describe('CLI index.ts', () => {
706
706
  program
707
707
  .argument('[commit-ish]', 'commit-ish', 'HEAD')
708
708
  .argument('[compare-with]', 'compare-with')
709
- .option('--comment <json>', 'comment', (value, previous = []) => [...previous, value], [])
709
+ .option('--comment <json>', 'comment', (value, previous) => [...previous, value], [])
710
710
  .option('--port <port>', 'port', parseInt)
711
711
  .option('--host <host>', 'host', '')
712
712
  .option('--no-open', 'no-open')
@@ -808,7 +808,7 @@ describe('CLI index.ts', () => {
808
808
  const program = new Command();
809
809
  program
810
810
  .argument('[commit-ish]', 'commit-ish', 'HEAD')
811
- .option('--comment <json>', 'comment', (value, previous = []) => [...previous, value], [])
811
+ .option('--comment <json>', 'comment', (value, previous) => [...previous, value], [])
812
812
  .option('--port <port>', 'port', parseInt)
813
813
  .option('--host <host>', 'host', '')
814
814
  .option('--no-open', 'no-open')
@@ -853,7 +853,7 @@ describe('CLI index.ts', () => {
853
853
  const program = new Command();
854
854
  program
855
855
  .argument('[commit-ish]', 'commit-ish', 'HEAD')
856
- .option('--comment <json>', 'comment', (value, previous = []) => [...previous, value], [])
856
+ .option('--comment <json>', 'comment', (value, previous) => [...previous, value], [])
857
857
  .option('--tui', 'tui')
858
858
  .action(async (_commitish, options) => {
859
859
  const commentImports = actualParseCommentOptions(options.comment);
@@ -874,7 +874,7 @@ describe('CLI index.ts', () => {
874
874
  const program = new Command();
875
875
  program
876
876
  .argument('[commit-ish]', 'commit-ish', 'HEAD')
877
- .option('--comment <json>', 'comment', (value, previous = []) => [...previous, value], [])
877
+ .option('--comment <json>', 'comment', (value, previous) => [...previous, value], [])
878
878
  .action(async (_commitish, options) => {
879
879
  try {
880
880
  actualParseCommentOptions(options.comment);
@@ -25,4 +25,5 @@ export declare function findUntrackedFiles(git: SimpleGit): Promise<string[]>;
25
25
  export declare function markFilesIntentToAdd(git: SimpleGit, files: string[]): Promise<void>;
26
26
  export declare function promptUser(message: string): Promise<boolean>;
27
27
  export declare function waitForEnter(message: string): Promise<void>;
28
+ export declare function readStdin(): Promise<string>;
28
29
  export {};
package/dist/cli/utils.js CHANGED
@@ -212,3 +212,10 @@ export async function waitForEnter(message) {
212
212
  rl.close();
213
213
  }
214
214
  }
215
+ export async function readStdin() {
216
+ const chunks = [];
217
+ for await (const chunk of process.stdin) {
218
+ chunks.push(chunk);
219
+ }
220
+ return Buffer.concat(chunks).toString('utf8');
221
+ }