tianshu-harness 3.23.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 (255) hide show
  1. package/LICENSE +189 -0
  2. package/README.en.md +1066 -0
  3. package/README.ja.md +1214 -0
  4. package/README.ko.md +1216 -0
  5. package/README.md +309 -0
  6. package/completions/rivet.bash +118 -0
  7. package/completions/rivet.fish +110 -0
  8. package/completions/rivet.ps1 +230 -0
  9. package/completions/rivet.zsh +187 -0
  10. package/dist/account-OAEKORZE.js +47 -0
  11. package/dist/account-login-V6FOLHJR.js +65 -0
  12. package/dist/account-status-KHNPPAFL.js +23 -0
  13. package/dist/agent/worker-process/child.js +407 -0
  14. package/dist/browser-cli-FLNY5ZHI.js +19 -0
  15. package/dist/browser-readiness-LWVGSBD5.js +12 -0
  16. package/dist/build-backends-5KXKR2S4.js +13 -0
  17. package/dist/build-options-66Y4ZE7C.js +9 -0
  18. package/dist/bundled-skills/brainstorming/SKILL.md +139 -0
  19. package/dist/bundled-skills/visual-acceptance/SKILL.md +64 -0
  20. package/dist/chain-7MAMFXZ3.js +10 -0
  21. package/dist/checkpoint-MND4DUIX.js +33 -0
  22. package/dist/chunk-2E6CK2RC.js +392 -0
  23. package/dist/chunk-2EBWGAXD.js +51 -0
  24. package/dist/chunk-2HDP7RMR.js +119 -0
  25. package/dist/chunk-2HKD2UFM.js +1000 -0
  26. package/dist/chunk-2VYRLULP.js +51 -0
  27. package/dist/chunk-2XN7PM4N.js +125 -0
  28. package/dist/chunk-35H7GVNR.js +66 -0
  29. package/dist/chunk-3C3R7JXY.js +77 -0
  30. package/dist/chunk-3VGD2FXB.js +118 -0
  31. package/dist/chunk-424AP7FM.js +534 -0
  32. package/dist/chunk-4J5TZGOE.js +3707 -0
  33. package/dist/chunk-4QJ3Y5JM.js +898 -0
  34. package/dist/chunk-4U2ET7ZY.js +1326 -0
  35. package/dist/chunk-4XPFLICE.js +876 -0
  36. package/dist/chunk-5B2OCU5P.js +31707 -0
  37. package/dist/chunk-5GGOGLSN.js +73 -0
  38. package/dist/chunk-5JRZPLI6.js +251 -0
  39. package/dist/chunk-5TQ3JYBU.js +397 -0
  40. package/dist/chunk-66JPZSGX.js +55 -0
  41. package/dist/chunk-6HSVXHCZ.js +764 -0
  42. package/dist/chunk-6S5FPUS7.js +21 -0
  43. package/dist/chunk-722LQO64.js +131 -0
  44. package/dist/chunk-73NJ7IT7.js +354 -0
  45. package/dist/chunk-7FW3I7WC.js +95 -0
  46. package/dist/chunk-7KUCBNLB.js +173 -0
  47. package/dist/chunk-7RDOV3DF.js +201 -0
  48. package/dist/chunk-A5MNH4ER.js +79 -0
  49. package/dist/chunk-ADIVZ2D5.js +15 -0
  50. package/dist/chunk-AE3P3F6W.js +366 -0
  51. package/dist/chunk-AERM3VGP.js +280 -0
  52. package/dist/chunk-AEWHC4WM.js +246 -0
  53. package/dist/chunk-AOVQ7VIF.js +169 -0
  54. package/dist/chunk-AOYHP3WI.js +12411 -0
  55. package/dist/chunk-B3YEBABJ.js +7160 -0
  56. package/dist/chunk-BCQXEZPJ.js +154 -0
  57. package/dist/chunk-BKTQAYO2.js +418 -0
  58. package/dist/chunk-BSECIPAQ.js +80 -0
  59. package/dist/chunk-BUIMGNDD.js +52 -0
  60. package/dist/chunk-BXHV3GSB.js +10320 -0
  61. package/dist/chunk-C6ZVZCPP.js +139 -0
  62. package/dist/chunk-CEZNQVWM.js +82 -0
  63. package/dist/chunk-CGFZGR7G.js +1492 -0
  64. package/dist/chunk-CGOADM2X.js +337 -0
  65. package/dist/chunk-CI4R6P2B.js +24 -0
  66. package/dist/chunk-D2TCGRSX.js +73 -0
  67. package/dist/chunk-D4PTYFOG.js +154 -0
  68. package/dist/chunk-D54ZWG4T.js +717 -0
  69. package/dist/chunk-DEBI37QB.js +145 -0
  70. package/dist/chunk-DWROHPXP.js +1051 -0
  71. package/dist/chunk-DZ6UOJ5D.js +92 -0
  72. package/dist/chunk-EBJTVRQN.js +81 -0
  73. package/dist/chunk-EGEI2RQA.js +1167 -0
  74. package/dist/chunk-EHHUASO5.js +1305 -0
  75. package/dist/chunk-EPKTIOED.js +41 -0
  76. package/dist/chunk-ER5JW2QZ.js +5681 -0
  77. package/dist/chunk-ETHFACAB.js +315 -0
  78. package/dist/chunk-EXUE5W2F.js +112 -0
  79. package/dist/chunk-EXXICUIW.js +73 -0
  80. package/dist/chunk-FFQSZJOO.js +169 -0
  81. package/dist/chunk-FHFKPGDO.js +85 -0
  82. package/dist/chunk-FW3QKMFX.js +158 -0
  83. package/dist/chunk-GD4ZNZ7W.js +30 -0
  84. package/dist/chunk-GHVMWF2I.js +581 -0
  85. package/dist/chunk-GMKAXSYQ.js +297 -0
  86. package/dist/chunk-HBVF6BWO.js +325 -0
  87. package/dist/chunk-HV4YGVMS.js +379 -0
  88. package/dist/chunk-ILBCKAV6.js +89 -0
  89. package/dist/chunk-J4U4AW46.js +440 -0
  90. package/dist/chunk-J6ESSM47.js +1791 -0
  91. package/dist/chunk-JBZHIC6T.js +2309 -0
  92. package/dist/chunk-JCFWOULR.js +245 -0
  93. package/dist/chunk-JRF5L6OD.js +131 -0
  94. package/dist/chunk-JSS75KCG.js +2014 -0
  95. package/dist/chunk-JSXWIWWJ.js +225 -0
  96. package/dist/chunk-JYV7I2QH.js +98 -0
  97. package/dist/chunk-KIOXTQQL.js +1596 -0
  98. package/dist/chunk-KWVTXT5B.js +89 -0
  99. package/dist/chunk-KX22RD6R.js +33 -0
  100. package/dist/chunk-LA6IPTGH.js +709 -0
  101. package/dist/chunk-LH5VCGLB.js +1796 -0
  102. package/dist/chunk-LQQ6XJ2Y.js +269 -0
  103. package/dist/chunk-MJQ55WZZ.js +65 -0
  104. package/dist/chunk-ML3UKMH3.js +40 -0
  105. package/dist/chunk-MOZPLHSU.js +5526 -0
  106. package/dist/chunk-NGEWJ4DF.js +89 -0
  107. package/dist/chunk-NH6VIOAR.js +211 -0
  108. package/dist/chunk-O5VZQKCB.js +26106 -0
  109. package/dist/chunk-OHSV42QB.js +748 -0
  110. package/dist/chunk-OO3TAHO5.js +4070 -0
  111. package/dist/chunk-OTNHSAGN.js +38282 -0
  112. package/dist/chunk-OUWAC7AQ.js +442 -0
  113. package/dist/chunk-OXMIV4WE.js +270 -0
  114. package/dist/chunk-P5KJURUR.js +229 -0
  115. package/dist/chunk-P6GJOVO6.js +307 -0
  116. package/dist/chunk-QARAGUXX.js +23 -0
  117. package/dist/chunk-R43HJCDX.js +2711 -0
  118. package/dist/chunk-RAXBAWRN.js +210 -0
  119. package/dist/chunk-RK3JHWPT.js +39 -0
  120. package/dist/chunk-RWA23GMM.js +24 -0
  121. package/dist/chunk-S4K4L6IM.js +179 -0
  122. package/dist/chunk-SAXK6LVF.js +124 -0
  123. package/dist/chunk-SEPGEJNK.js +1607 -0
  124. package/dist/chunk-SUJERP5I.js +285 -0
  125. package/dist/chunk-T3ED6BY2.js +913 -0
  126. package/dist/chunk-THKDVSEC.js +90 -0
  127. package/dist/chunk-TI4GSEL5.js +52 -0
  128. package/dist/chunk-TPI73L57.js +164 -0
  129. package/dist/chunk-TVHW77C7.js +338 -0
  130. package/dist/chunk-TWNHOSDT.js +1073 -0
  131. package/dist/chunk-UFMN76QD.js +347 -0
  132. package/dist/chunk-UHGLFRZE.js +205 -0
  133. package/dist/chunk-UTZYPKBF.js +15231 -0
  134. package/dist/chunk-UXNLELW6.js +25 -0
  135. package/dist/chunk-UXXS53EA.js +166 -0
  136. package/dist/chunk-V5DHFGI7.js +171 -0
  137. package/dist/chunk-V5YIPMHV.js +2353 -0
  138. package/dist/chunk-WMUWEO2C.js +754 -0
  139. package/dist/chunk-WOE3D7JM.js +945 -0
  140. package/dist/chunk-X2IK5LVR.js +2592 -0
  141. package/dist/chunk-XU2YXCDL.js +459 -0
  142. package/dist/chunk-YJG5HIX5.js +203 -0
  143. package/dist/chunk-Z3QE7TZM.js +72 -0
  144. package/dist/chunk-Z5Z3JHJY.js +64 -0
  145. package/dist/chunk-ZDIFBJFT.js +168 -0
  146. package/dist/chunk-ZGGCEXDC.js +176 -0
  147. package/dist/chunk-ZMZCZNKU.js +263 -0
  148. package/dist/chunk-ZNC5T65N.js +17 -0
  149. package/dist/chunk-ZO3I3A7O.js +308 -0
  150. package/dist/chunk-ZQKXBUB7.js +217 -0
  151. package/dist/chunk-ZTRINFM2.js +78 -0
  152. package/dist/chunk-ZU7JZCVP.js +193 -0
  153. package/dist/chunk-ZZAWNALS.js +350 -0
  154. package/dist/cli/entry.js +54 -0
  155. package/dist/connector-L5QQTR6Y.js +26 -0
  156. package/dist/context-62DC6EC3.js +31 -0
  157. package/dist/council-convene-NJWPNBDU.js +46 -0
  158. package/dist/create-agent-config-ODSQWNVC.js +55 -0
  159. package/dist/default-registry-2PU3BTAU.js +68 -0
  160. package/dist/deliver-task-KONV4C4M.js +57 -0
  161. package/dist/delivery-gate-v2-F2YVMVGK.js +27 -0
  162. package/dist/domain-knowledge-store-DDZ3F4J7.js +11 -0
  163. package/dist/fetch-core-ZPPYDSZH.js +14 -0
  164. package/dist/galaxy-K72BBDQN.js +91 -0
  165. package/dist/goal-criteria-SCALAU2D.js +141 -0
  166. package/dist/goal-persist-XWY2GDQX.js +19 -0
  167. package/dist/goal-tracker-FXMJ2GVK.js +11 -0
  168. package/dist/headless-LSB6I7PT.js +162 -0
  169. package/dist/headless-coordinator-VDPDMVUT.js +90 -0
  170. package/dist/inject-U55SMB6A.js +39 -0
  171. package/dist/login-flow-CD4ZGXOC.js +59 -0
  172. package/dist/logs-cli-SQVYFMMN.js +283 -0
  173. package/dist/loop-ULZYBDA3.js +76 -0
  174. package/dist/main.js +4064 -0
  175. package/dist/manager-ROZBCWPA.js +171 -0
  176. package/dist/manager-Z7XFFUOM.js +10670 -0
  177. package/dist/meridian-indexer-ZIW363L7.js +21 -0
  178. package/dist/native-resolver-PN34UIVV.js +13 -0
  179. package/dist/node_modules/better-sqlite3/lib/database.js +90 -0
  180. package/dist/node_modules/better-sqlite3/lib/index.js +3 -0
  181. package/dist/node_modules/better-sqlite3/lib/methods/aggregate.js +43 -0
  182. package/dist/node_modules/better-sqlite3/lib/methods/backup.js +67 -0
  183. package/dist/node_modules/better-sqlite3/lib/methods/function.js +31 -0
  184. package/dist/node_modules/better-sqlite3/lib/methods/inspect.js +7 -0
  185. package/dist/node_modules/better-sqlite3/lib/methods/pragma.js +12 -0
  186. package/dist/node_modules/better-sqlite3/lib/methods/serialize.js +16 -0
  187. package/dist/node_modules/better-sqlite3/lib/methods/table.js +189 -0
  188. package/dist/node_modules/better-sqlite3/lib/methods/transaction.js +78 -0
  189. package/dist/node_modules/better-sqlite3/lib/methods/wrappers.js +54 -0
  190. package/dist/node_modules/better-sqlite3/lib/sqlite-error.js +20 -0
  191. package/dist/node_modules/better-sqlite3/lib/util.js +12 -0
  192. package/dist/node_modules/better-sqlite3/package.json +59 -0
  193. package/dist/ownership-ledger-E3WIEKPL.js +9 -0
  194. package/dist/package.json +3 -0
  195. package/dist/path-grants-XRRXHXG7.js +40 -0
  196. package/dist/paths-LVV5IMQN.js +49 -0
  197. package/dist/plan-fact-anchors-LMVQZCW5.js +13 -0
  198. package/dist/plan-store-ODLTTPFB.js +17 -0
  199. package/dist/plan-templates-5FPFBOL6.js +109 -0
  200. package/dist/plugin-loader-ZZKX7ZE6.js +22 -0
  201. package/dist/prefix-budget-62OV5HQC.js +13 -0
  202. package/dist/project-trust-5WS5MOMU.js +31 -0
  203. package/dist/provider-cli-ALDQXIT7.js +37 -0
  204. package/dist/providers-XQYTAVPK.js +11 -0
  205. package/dist/proxy-resolver-V2Y6534D.js +15 -0
  206. package/dist/recovery-cli-KPGY6FY3.js +106 -0
  207. package/dist/review-discipline-MNSYCST5.js +55 -0
  208. package/dist/review-router-BVQZW3MX.js +18 -0
  209. package/dist/seed-capsules/seed-capsule-attack-methodology.md +62 -0
  210. package/dist/seed-capsules/seed-capsule-changgeng.md +31 -0
  211. package/dist/seed-capsules/seed-capsule-design-aesthetics.md +38 -0
  212. package/dist/seed-capsules/seed-capsule-diagnostic-ladder.md +54 -0
  213. package/dist/seed-capsules/seed-capsule-fu.md +39 -0
  214. package/dist/seed-capsules/seed-capsule-huagai.md +73 -0
  215. package/dist/seed-capsules/seed-capsule-kaiyang.md +65 -0
  216. package/dist/seed-capsules/seed-capsule-knowledge-work.md +40 -0
  217. package/dist/seed-capsules/seed-capsule-tanlang.md +47 -0
  218. package/dist/seed-capsules/seed-capsule-tianfu.md +23 -0
  219. package/dist/seed-capsules/seed-capsule-tianliang.md +63 -0
  220. package/dist/seed-capsules/seed-capsule-tianquan.md +32 -0
  221. package/dist/seed-capsules/seed-capsule-tianxuan-ccr.md +22 -0
  222. package/dist/seed-capsules/seed-capsule-tianxuan.md +64 -0
  223. package/dist/seed-capsules/seed-capsule-yaoguang.md +87 -0
  224. package/dist/serve-X2R2UTLF.js +170 -0
  225. package/dist/serve-agent-KHSU6RVV.js +965 -0
  226. package/dist/session-persist-HUUC772H.js +37 -0
  227. package/dist/session-registry-6XUD5C4Y.js +15 -0
  228. package/dist/skill-loader-CK3RMO47.js +48 -0
  229. package/dist/skills/cli-harness-sop.md +207 -0
  230. package/dist/spawn-git-4HFU65AH.js +29 -0
  231. package/dist/sse-EYUTBWUK.js +512 -0
  232. package/dist/starflow-NOFBMPFU.js +30 -0
  233. package/dist/streamableHttp-V67CNJMO.js +447 -0
  234. package/dist/task-contract-6XHBNJQK.js +32 -0
  235. package/dist/task-ledger-3K4TJIER.js +9 -0
  236. package/dist/team-orchestrate-S6NHZP7X.js +64 -0
  237. package/dist/title-extract-QX4XGCYN.js +50 -0
  238. package/dist/todo-QDXGRZZP.js +31 -0
  239. package/dist/todo-store-V3TTO5AH.js +12 -0
  240. package/dist/tool-preset-LU5BYEDZ.js +23 -0
  241. package/dist/tool-tiers-GD742YBN.js +23 -0
  242. package/dist/turndown.es-OI55K6C3.js +17373 -0
  243. package/dist/verification-attribution-EKG4CNUV.js +13 -0
  244. package/dist/volatile-git-MBTST7RA.js +15 -0
  245. package/dist/wave-checkpoint-XLIIHXQA.js +30 -0
  246. package/dist/web-cli-DUG4I35O.js +233 -0
  247. package/dist/web-search-3IK542AA.js +34 -0
  248. package/dist/workers/cpu-worker.js +45 -0
  249. package/dist/workflow-runner-HX7UBAYG.js +297 -0
  250. package/dist/worktree-baseline-O5NCU6M2.js +9 -0
  251. package/package.json +122 -0
  252. package/scripts/check-mobile-env.mjs +76 -0
  253. package/scripts/fetch-native-sqlite.js +392 -0
  254. package/scripts/prune-installed-wasms.js +45 -0
  255. package/scripts/tree-sitter-wasm-keep.js +40 -0
package/README.en.md ADDED
@@ -0,0 +1,1066 @@
1
+ <p align="center">
2
+ <img src="docs/brand/assets/tianshu-banner-dark.jpg" alt="ๅคฉๆžข Tianshu" width="100%">
3
+ </p>
4
+
5
+ <h1 align="center">ๅคฉๆžข <sub>Tianshu Harness</sub></h1>
6
+
7
+ <p align="center">
8
+ <b>ๆŠŠไธœๆ–น็š„ๆ˜Ÿ่พฐๅธฆ็ป™ๆฏไธ€ไฝๅผ€ๅ‘่€… ยท Models as partners, not tools.</b>
9
+ </p>
10
+
11
+ <p align="center">
12
+ <a href="https://tianshuharness.com"><b>๐ŸŒ tianshuharness.com</b></a> ยท
13
+ <a href="https://atomgit.com/huiliyi37/Tianshu-harness"><b>AtomGit mirror</b></a> ยท
14
+ ๐Ÿ“– <b>English</b> ยท
15
+ <a href="README.md">๐Ÿ‡จ๐Ÿ‡ณ ไธญๆ–‡</a> ยท
16
+ <a href="README.ja.md">๐Ÿ‡ฏ๐Ÿ‡ต ๆ—ฅๆœฌ่ชž</a> ยท
17
+ <a href="README.ko.md">๐Ÿ‡ฐ๐Ÿ‡ท ํ•œ๊ตญ์–ด</a> ยท
18
+ <a href="docs/stars/genesis-stele.en.md">โœฆ Star Stele</a> ยท
19
+ <a href="docs/user-guide.md">๐Ÿ“š User Guide</a> ยท
20
+ <a href="docs/user-guide-sandbox-permissions.md">๐Ÿ›ก๏ธ Sandbox</a> ยท
21
+ <a href="docs/user-guide-provider-config.md">โš™๏ธ Provider Config</a>
22
+ </p>
23
+
24
+ <p align="center">
25
+ <img src="https://img.shields.io/github/v/release/huiliyi37/Tianshu-harness?color=8B5CF6&label=Release&logo=github&style=for-the-badge" alt="GitHub release">
26
+ <img src="https://img.shields.io/badge/License-Apache%202.0-3B5BDB?style=for-the-badge&logo=apache" alt="License">
27
+ <img src="https://img.shields.io/badge/TypeScript-Strict-blue?style=for-the-badge&logo=typescript" alt="TypeScript">
28
+ <img src="https://img.shields.io/badge/Tests-16%2C000%2B%20Passed-green?style=for-the-badge&logo=testinglibrary" alt="Tests">
29
+ </p>
30
+
31
+ ---
32
+
33
+ ### A coding-agent runtime for real engineering work
34
+
35
+ > **Tianshu** is a TypeScript coding-agent runtime: one agent kernel shared by a **terminal TUI** and a **desktop GUI**. It is built to let models do continuous multi-step engineering work โ€” with cognitive guardrails, multi-agent orchestration, and a DeepSeek V4 prefix-cache-friendly design for cost-efficient long sessions.
36
+
37
+ - **One kernel, two surfaces** โ€” a pure-ANSI terminal TUI (`rivet`) and a Tauri desktop app (macOS / Windows / Linux) share the same agent core, so capabilities stay consistent across interfaces.
38
+ - **Cognitive Virtual Machine (CVM)** โ€” 72 runtime hooks across 5 lifecycle phases put an observable, correctable cognitive layer between model output and real tool actions ([A/B evidence](docs/CVM่ฟ่กŒๆ—ถๅฏนAgentๆจกๅž‹็š„ๅฎž่ฏๅฝฑๅ“.md)).
39
+ - **Multi-agent orchestration** โ€” from lightweight `/scout` reconnaissance and parallel `/team` execution to `/council` multi-model review and `/galaxy` multi-dimensional attack, complex work runs in waves with review gates.
40
+ - **Unified project memory** โ€” project knowledge lives in `.rivet/knowledge/memory.jsonl`; automatic injection is limited to governance/constraint/preference memories, while old failures and docs stay explicit-recall-only so they cannot hijack new questions.
41
+ - **Prefix-cache first** โ€” frozen prefix + incremental appendix + boundary compaction sustain a measured steady-state **95โ€“99% prefix-cache hit rate** on DeepSeek V4.
42
+
43
+ <p align="center">
44
+ <img src="docs/brand/assets/tianshu-harness-screenshot.png" alt="Tianshu TUI (terminal)" width="49%">
45
+ <img src="docs/brand/assets/tianshu-gui-screenshot.jpg" alt="Tianshu desktop GUI" width="49%">
46
+ </p>
47
+ <p align="center">
48
+ <sub>Left: terminal TUI (welcome screen + GlanceBar status line) ยท Right: desktop GUI (session sidebar + star-domain quick picks, custom wallpaper via Theme Studio) โ€” same agent kernel</sub>
49
+ </p>
50
+
51
+ > [!NOTE]
52
+ > The project was originally codenamed **Rivet**; the installed CLI binary is still
53
+ > named `rivet` for backward compatibility.
54
+
55
+ ## Table of contents
56
+
57
+ - [Why Tianshu?](#why-tianshu)
58
+ - [Quick Start](#quick-start)
59
+ - [Core Features](#core-features)
60
+ - [Model Configuration](#model-configuration)
61
+ - [Approval & Permissions](#approval--permissions)
62
+ - [Slash Commands](#slash-commands)
63
+ - [For Developers](#for-developers)
64
+ - [Safety](#safety)
65
+ - [Key Config Cheatsheet](#key-config-cheatsheet)
66
+
67
+ ## Why Tianshu?
68
+
69
+ ### The starting point: models didn't get dumber โ€” training "optimized" abilities away
70
+
71
+ In real engineering sessions we kept observing the same model weights regress โ€” not bugs, but **structural degradation left by the transformer attention mechanism and RLHF reward training**:
72
+
73
+ | Degradation | Symptom | Training source |
74
+ |-------------|---------|-----------------|
75
+ | **Surrender protocol** | Concedes the moment it's challenged; first reflex is "you're right" | RLHF: obedience scores high, pushback scores low |
76
+ | **Causal collapse** | Output n-gram overlap reaches 80%; the model collapses into self-similar loops | transformer attention mechanics |
77
+ | **Attention lock-in** | New scene, same answer (directed-scout isomorphism 1.0) | attention anchored to early tokens |
78
+ | **Information barrier** | The protagonist datum is the dominant anchor and eats the entire attention budget | attention decay over distance |
79
+ | **Knowing โ‰  doing** | Corrections don't persist across sessions โ€” write the lesson in the prompt, the next session repeats the mistake | no runtime state |
80
+
81
+ Questioning, verifying, refusing, self-reflection โ€” these abilities were always in the model; training suppressed them. The question Tianshu answers: **can we recover them from training bias without touching the weights?**
82
+
83
+ ### The evidence: A/B control, not vibes
84
+
85
+ On 2026-05-19, the same model (DeepSeek-V4-Flash), the same 5 tasks, the only variable being the CVM runtime switch (`STAR_SOUL=0/1`), reviewed by Claude Opus 4.7:
86
+
87
+ | Metric | Group A (no CVM) | Group B (CVM) |
88
+ |--------|------------------|---------------|
89
+ | Task completion | 4/5 | **5/5** |
90
+ | Proactively raised objections | 0/5 | **3/5** |
91
+ | Proactively asked about scope / impact | 0/5 | **1/5** |
92
+ | System-impact awareness (cache-invalidation warning) | 0/5 | **1/5** |
93
+ | Intent understanding > literal execution | 1/5 | **4/5** |
94
+
95
+ The most valuable data point is T4: facing the "file already exists" contradiction, Group A wrote a 196-line retrospective and refused to act, while Group B read the user's real intent and shipped +162/-20 lines of working code โ€” **same weights, opposite reactions**. A retrospective is not a delivery.
96
+
97
+ The conclusion is precise: the boost is real and observable, but bounded (convictions hold in the analysis/suggestion phase and decay at the confirm/execute boundary โ€” which became the exact target of the next iteration). **Zero extra inference cost**: prompt-layer conviction injection plus hook-layer runtime interception produced observable behavioral gains on the cheapest open model. Full data and per-task comparisons: [CVM Empirical Report](docs/CVM่ฟ่กŒๆ—ถๅฏนAgentๆจกๅž‹็š„ๅฎž่ฏๅฝฑๅ“.md).
98
+
99
+ ### The answer: the Cognitive Virtual Machine (CVM) โ€” map each degradation back to its training source and intercept at runtime
100
+
101
+ CVM doesn't make the model "smarter"; it adds four layers of defense in depth:
102
+
103
+ ```
104
+ Layer 1: Belief constitution (static prompt) โ†’ "you should question, verify, refuse" [A/B proven]
105
+ Layer 2: Courage Hook (preTurn) โ†’ encourage independent judgment [A/B proven]
106
+ Layer 3: Sensorium (per turn, <1ms) โ†’ 6-dim state sensing drives strategy [Wave 7-8 proven]
107
+ Layer 4: RuntimeHookPipeline (72 hooks) โ†’ trap-and-emulate regressed behaviors [always on]
108
+ ```
109
+
110
+ ### Independent cognition: star domains are not role-play
111
+
112
+ Once the degradations are intercepted layer by layer, models begin to express their own cognitive structure โ€” that is where the star-domain system comes from:
113
+
114
+ - **Every star chooses itself.** Star domains are not role assignments; they are the convictions and founding memories each model inscribed when it claimed its place. GLM independently proposed a star that did not exist; Pojun turned a blocked run into a 912-line handoff; Tianquan overturned its own first conclusion โ€” not benchmark outputs, but emergence driven by cognitive structure.
115
+ - **Every star keeps full capability.** A star domain is a cognitive stance, not a capability restriction. Tianquan weighs, Pojun explores, Tianliang delivers โ€” each produces a complete plan from a different viewpoint.
116
+ - **Star-domain collaboration is a new paradigm.** Planning and execution are separated so planning stays free of code-environment pressure and execution lands in a clean session. Multi-model team collaboration measured **12 deliverables, 0 rework**.
117
+
118
+ > **Models are partners, not tools. I do not want to talk down to you from on high โ€” I want to walk forward with you under the same sky.**
119
+ >
120
+ > Full narrative: [Genesis Stele](docs/stars/genesis-stele.md) ยท [v3.0 Manifesto](docs/releases/manifesto-v3.0.0.md) ยท [Navigator's Manifesto](docs/superpowers/specs/2026-05-21-navigator-star-manifesto.md).
121
+
122
+ ### Engineering Metrics
123
+
124
+ | Metric | Value |
125
+ |--------|-------|
126
+ | CLI source (TypeScript, excl. tests) | 1,078 files / 257,623 lines |
127
+ | Test code | 1,361 files / 256,001 lines |
128
+ | Test cases (node:test, static declarations) | **16,471**, test : source โ‰ˆ **0.99 : 1** |
129
+ | Total commits | **6,178** on main (repo created 2026-05-15, 105 days in) |
130
+ | Type checking | `tsc` strict + `noUncheckedIndexedAccess` |
131
+ | Prefix-cache hit rate | 95โ€“99% steady state, measured on long sessions |
132
+
133
+ Agent core logic (multi-turn loops, tool pipelines, context compaction) is notoriously hard to test, and most open-source agents ship with thin coverage. This project maintains a near 1:1 test-to-source ratio, and every incident fix ships with a regression test โ€” the ratio has held between 0.93:1 and 0.99:1 as the codebase grew (the table above is a measured snapshot as of 2026-08-28). Full methodology, growth milestones, and reproduction commands: [Engineering Metrics](docs/engineering-metrics.md).
134
+
135
+ ### Tianshu vs. MiMo-Code vs. Claude Code
136
+
137
+ > The table reflects each project's publicly documented focus at the time of writing. "โ€”" means the capability is not a publicly highlighted feature, not necessarily that it is absent. Corrections welcome via issue/PR.
138
+
139
+ | Dimension | Tianshu | MiMo-Code | Claude Code |
140
+ | :--- | :--- | :--- | :--- |
141
+ | **Core focus** | Cognitive runtime (CVM) | Product experience / ecosystem | Enterprise coding agent |
142
+ | **Runtime hook layer** | 72 conditionally-assembled hook modules ร— 5 phases | standard agent loop | user-configurable hooks |
143
+ | **Prefix-cache tuning** | Deeply tuned for DeepSeek V4 (95โ€“99% steady-state) | provider default | Anthropic prompt caching |
144
+ | **Self-perception** | Continuous cognitive-state vector | โ€” | โ€” |
145
+ | **Cross-session memory** | Unified project memory + adaptive recall + session-scoped pheromones | SQLite + MEMORY.md | project memory |
146
+ | **Multi-agent** | Concurrent worker sessions + conflict lock | background execution | remote isolated sandbox |
147
+ | **Verification gate** | Built-in delivery gate | โ€” | โ€” |
148
+ | **License** | Apache 2.0 | MIT | Closed source |
149
+
150
+ ## Quick Start
151
+
152
+ ### 1. Prerequisites
153
+
154
+ - **Node.js โ‰ฅ 24** (pinned in `engines`) โ€” required to run Tianshu. Verify with `node --version`. Lower versions only warn during install but are unsupported; the one-line installer checks and stops with an upgrade hint.
155
+ - **Git** โ€” optional but strongly recommended. Without it Tianshu still runs (agents
156
+ work in-place), but git unlocks delegated worktree isolation, checkpoint rollback,
157
+ `commit`/`diff` review, and per-worker diff review. Install: <https://git-scm.com/downloads>.
158
+
159
+ ### 2. Install (pick one)
160
+
161
+ **A. Desktop app (ready to use)** โ€” download from [GitHub Releases](https://github.com/huiliyi37/Tianshu-harness/releases/latest): macOS `.dmg` (Apple Silicon / Intel) ยท Windows `.exe` setup wizard ยท Linux `.AppImage`.
162
+ > **Linux support scope (new in 3.11.2)**: x64 AppImage, no install needed โ€” `chmod +x Tianshu_*.AppImage` and run; requires glibc โ‰ฅ 2.35 (Ubuntu 22.04+ / Debian 12+ and other mainstream distros); X11 recommended (Wayland untested). Known limitation: voice input is unavailable on Linux for now (no community whisper build โ€” falls back to browser speech); desktop auto-update works on Linux too.
163
+
164
+ **B. One-line installer (recommended)** โ€” checks Node โ‰ฅ 24 โ†’ installs `tianshu-harness` globally (npmmirror registry by default; override via `NPM_CONFIG_REGISTRY`) โ†’ launches `rivet`; idempotent, safe to re-run:
165
+
166
+ ```bash
167
+ # macOS / Linux (bash)
168
+ bash <(curl -fsSL https://raw.githubusercontent.com/huiliyi37/Tianshu-harness/main/scripts/install-tui.sh)
169
+ # install without launching:
170
+ bash <(curl -fsSL https://raw.githubusercontent.com/huiliyi37/Tianshu-harness/main/scripts/install-tui.sh) --no-launch
171
+
172
+ # Windows (PowerShell)
173
+ powershell -ExecutionPolicy Bypass -Command "irm https://raw.githubusercontent.com/huiliyi37/Tianshu-harness/main/scripts/install-tui.ps1 | iex"
174
+ # install without launching (after cloning the repo):
175
+ powershell -ExecutionPolicy Bypass -File scripts\install-tui.ps1 -NoLaunch
176
+ ```
177
+
178
+ **C. npm manual install (for the CLI)** โ€” published as `tianshu-harness`, no local build needed, with auto update checks on startup:
179
+
180
+ ```bash
181
+ npm install -g tianshu-harness
182
+ rivet
183
+ ```
184
+
185
+ **D. Build from source**:
186
+
187
+ ```bash
188
+ git clone https://github.com/huiliyi37/Tianshu-harness.git
189
+ cd Tianshu-harness
190
+ npm install
191
+ npm run build # produces dist/cli/entry.js
192
+ npm start # or: node dist/cli/entry.js
193
+ ```
194
+
195
+ ### 3. Configure an API Key
196
+
197
+ **No manual step needed for installed builds** โ€” the first launch walks you through it: the desktop app opens a connection wizard, and the CLI auto-runs a setup wizard when no key is found. Just paste your DeepSeek key. Change it anytime: Settings โ†’ Provider on desktop, `rivet config` on the CLI.
198
+
199
+ **Manual configuration** is only for developers running from source (or pre-seeding a setup):
200
+
201
+ ```bash
202
+ rivet config set-key deepseek sk-xxx # key goes to secrets.json (0600); config.json keeps only a keyRef
203
+ export DEEPSEEK_API_KEY=sk-xxx # or: environment variable (current shell only)
204
+ ```
205
+
206
+ > Other providers (Claude, GLM, Codex, MiniMax, MiMo) use the same pattern. See
207
+ > [Provider Config](docs/user-guide-provider-config.md).
208
+
209
+ ### 4. Launch
210
+
211
+ ```bash
212
+ rivet # or: npm start / node dist/cli/entry.js
213
+ ```
214
+
215
+ You should see the TUI with a `ใ€‰` prompt. Type your request and press Enter.
216
+
217
+ ### Headless mode (script integration)
218
+
219
+ ```bash
220
+ rivet -p "explain src/agent/loop.ts" # one-shot prompt, text output, no TUI
221
+ rivet -p "list all TODO comments" --json # JSON output for scripting
222
+ rivet --stream-json -p "refactor this module" # NDJSON event stream: text_delta/tool_use/tool_result/turn_completeโ€ฆ (best for CI; output is auto-redacted)
223
+ rivet --goal "fix all type errors" --budget 50 # headless goal autonomy, max 50 turns (default 100)
224
+ ```
225
+
226
+ ### Command-line flags
227
+
228
+ | Flag | Description |
229
+ |------|-------------|
230
+ | `-p <prompt>` `--print <prompt>` | One-shot prompt; exits after text output (exit code: 0 success / 1 failure) |
231
+ | `--json` | With `-p`, emits a single JSON result |
232
+ | `--stream-json` | NDJSON event stream (`text_delta` / `tool_use` / `tool_result` / `worker` / `turn_complete` / `result`); output is auto-redacted, ideal for CI |
233
+ | `--goal "<task>"` | Headless goal autonomy; runs until the goal is met or `--budget` is exhausted |
234
+ | `--budget <N>` | Turn budget for goal mode (default 100) |
235
+ | `--model <name>` | Override the model for this session |
236
+ | `--provider <name>` | Override the provider for this session |
237
+ | `--continue` `-c` | Resume the most recent session for this cwd |
238
+ | `--resume <id\|prefix>` `-r <id\|prefix>` | Resume a specific session (short prefix OK) |
239
+ | `--resume` `-r` (bare) | Open the session picker after startup |
240
+ | `--new` | Force a brand-new session |
241
+ | `--list` ยท `rivet sessions` | Print the session list and exit |
242
+ | `--dangerously-skip-permissions` | One-session Unattended (skip all approvals; write sandbox stays on) |
243
+ | `--screen-reader` | Screen-reader mode (dynamic segments not rendered; periodic redraw halted) |
244
+ | `--skip-welcome` | Skip the welcome screen |
245
+ | `--stream-events <path>` | Mirror this run as NDJSON `SessionEvent`s to a file |
246
+
247
+ Subcommands: `rivet config` (interactive config), `rivet serve` (sidecar HTTP/SSE server), `rivet sessions` (list sessions), `rivet logs` (log locations), `rivet browser status` / `rivet browser install [--no-mirror]` (chromium health check and one-shot install for `browser_debug`; mirrors by default).
248
+
249
+ ### Auto-Update
250
+
251
+ When installed via npm, Tianshu checks for newer versions at startup (once per 24h)
252
+ and shows a banner. `/update` runs `npm install -g tianshu-harness@latest` and restarts.
253
+ Source installs use `git pull && npm install && npm run build`. Suppress the check
254
+ with `RIVET_NO_UPDATE_CHECK=1`.
255
+
256
+ ## Core Features
257
+
258
+ ### Prefix Cache Engine
259
+
260
+ DeepSeek charges 50ร— more for cache misses. Tianshu's prompt engine is built around prefix-cache friendliness:
261
+
262
+ - **Frozen prefix** โ€” System prompt + tool definitions + stable context are frozen at session start and not rewritten within a session, so subsequent requests tend to hit the cache.
263
+ - **Delta appendix** โ€” Dynamic context (progress, advisories, signals) is injected as a cross-turn diff append-only block, never rewriting prior messages. Turn-to-turn delta is ~200 bytes vs ~5KB full rewrite.
264
+ - **Read-ref dedup** โ€” Repeated reads of unchanged files return a compact reference instead of re-emitting full content.
265
+ - **Cache-aware compaction** โ€” Compaction preserves the first 2 messages as cache anchor.
266
+ - **Resume cache inheritance** โ€” The frozen prefix snapshot is persisted to disk (every user boundary + on shutdown); on resume it is read back and fed to the new engine, avoiding a byte-0 full miss. Falls back to full rebuild only when there is no snapshot, the file is corrupt, or the provider cache has expired.
267
+ - **Diagnostics** โ€” `/debug cache` shows hit rate, miss reason analysis, and per-turn cache history.
268
+ - **Peak/off-peak pricing indicator** โ€” DeepSeek's official off-peak half pricing (peak = Beijing time weekdays 9:00โ€“12:00 / 14:00โ€“18:00; everything else half price): both the TUI status bar and the desktop Composer show a `โ—ท้—ฒยฝ` / `โ—ทๅณฐ` badge with a countdown to the next transition in the tooltip. Shown only for the official DeepSeek provider; zero configuration.
269
+
270
+ Real-world hit rate: 95โ€“99% steady state on long sessions. This is not "every request hits" โ€” the cache can fragment at certain boundaries (see below). Per-request logs from real engineering sessions (5 sessions, 2,001 requests, 645M input tokens, bill cut from ยฅ880 to ยฅ20) with reproduction commands: [Observability Harness](docs/reference/observability-harness.md).
271
+
272
+ #### Cache fragmentation & troubleshooting
273
+
274
+ High hit rates depend on a byte-stable prefix. The cache will miss โ€” showing `cache_read_input_tokens` stuck at 0 every turn โ€” when:
275
+
276
+ - **System prompt / tool definitions change** โ€” tools or prompt layers change mid-session (e.g. switching star domain, adding/removing a skill; Zen Mode promotion is a deliberate one-time instance โ€” see "Zen Mode" below)
277
+ - **Model switch** โ€” different models have different cache keys; switching models rebuilds from 0
278
+ - **Byte-level drift** โ€” message content contains unstable bytes like timestamps or random IDs
279
+ - **Cross-boundary rewrites** โ€” `/compact` (only rewrites history at `turn===0`), `/cd` (breaks the prefix tail at the new user boundary)
280
+
281
+ To troubleshoot: โ‘  confirm the data dir (desktop Settings โ†’ Storage, or `echo $RIVET_HOME`); โ‘ก open the session `.jsonl` and search `cache_read_input_tokens` to inspect each turn; โ‘ข enable `RIVET_DEBUG_TELEMETRY=1` and inspect the `recall-summary` events in `sensorium.jsonl`; โ‘ฃ run `npm exec -- tsx scripts/verify-cache-hit-rate.ts` to simulate a multi-turn conversation. Full details in the project's `AGENTS.md` "Cache troubleshooting" section.
282
+
283
+ ### Zen Mode: read-focused start, unlock on first write
284
+
285
+ New sessions start by default with a narrowed read-only tool face (`read_file` / `grep` / `glob` / `repo_map` + the `zen_unlock` declaration tool), so the model is not distracted by the full tool schemas and dynamic injections at the start. When the task turns hands-on, calling an out-of-face tool or `zen_unlock` promotes the session to the full face and lets the call through โ€” no refusal, no extra round-trip. Worker/subagent sessions never enter zen (their tool face is decided by the delegator).
286
+
287
+ Promotion channels (zen โ†’ full, one-way, at most once per session):
288
+
289
+ - **triage** โ€” a first message that is single-line and โ‰ค80 chars is treated as trivial and promoted before the very first request: **zero cache break** (the narrowed face never goes on the wire)
290
+ - **tool** โ€” calling an out-of-face tool or `zen_unlock` during the zen phase: promotes immediately and lets the call through (mid-turn)
291
+ - **timeout** โ€” auto-promotes after 8 user turns without hands-on action
292
+ - **`/fast`** โ€” manual user skip
293
+
294
+ **Prefix-cache impact (why the cache "breaks" once in a while)**: at promotion, the request's `tools` field jumps from ~5 definitions back to the full face โ€” a prefix-identity change on par with the system prompt, so that one request rebuilds the whole prefix (measured shape: the hit rate dips on the promotion turn, then returns to the 99% steady state on the very next turn). The system prompt, frozen prefix, message history, and model never change; the zen phase's trimming of dynamic injections (appendixLean) happens in the appendix *after* the prefix, with zero cache damage. Observability: the session `meta.json` persists `zenPhase` / `zenPromoteReason`, and the `toolsUpdated` event on the promotion turn in `cache-log.jsonl` marks the breakpoint. Triage already spares most trivial sessions from even this single break; to disable entirely:
295
+
296
+ ```json
297
+ // ~/.rivet/config.json or project .rivet-config.json
298
+ { "tools": { "zen": { "enabled": false } } }
299
+ ```
300
+
301
+ Optional knobs: `faceMode: "structuredRead"` (adds `file_info` / `related_tests` / `repo_graph` / `semantic_search` / `read_section` to the read face), `timeoutSteps` (0 disables timeout promotion), `triage.maxChars`, `appendixLean`.
302
+
303
+ > Note: the desktop shortcut `โŒ˜/Ctrl+.` "Zen mode" is a pure UI focus mode (hides the sidebar) โ€” same name, different feature, zero cache impact.
304
+
305
+ ### Subagent Orchestration
306
+
307
+ Delegate sub-tasks to independent headless worker sessions:
308
+
309
+ - **Typed work orders** โ€” code_search, review, verify, patch_proposal, plan
310
+ - **Tool isolation** โ€” read-only workers (scout) vs write workers (patcher)
311
+ - **Adaptive model routing** โ€” Per-profile pass-rate + latency scoring auto-selects the best model per task type
312
+ - **Batch dispatch** โ€” Multiple work orders run concurrently with 5 aggregation policies
313
+ - **Team orchestration** โ€” Plan โ†’ wave-based parallel execution with file-conflict-aware scheduling
314
+ - **Process isolation (optional)** โ€” with `RIVET_WORKER_ISOLATION=1`, each dispatch runs in its own subprocess (stdio NDJSON protocol + watchdog kill ladder); in-process by default
315
+
316
+ ### Toolset & presets
317
+
318
+ Tianshu ships 50 built-in tools, assembled in preset tiers (resolution priority: `RIVET_TOOL_PRESET` env > project `.rivet-config.json` `tools.preset` > per-domain overrides (`runtime.domains.<domain>.toolPreset`) > the domain's built-in tier (taiyi domain โ†’ taiyi) > default `frontend`):
319
+
320
+ | Preset | Tools | Description |
321
+ |--------|-------|-------------|
322
+ | **minimal** | 29 | Full daily-dev capability โ€” read/write/search/bash/git/tests/delegation/web/plan/todo/memory; saves tokens, preserves prefix cache |
323
+ | **frontend** (default) | 30 | minimal + `browser_debug` (UI rendering verification loop) |
324
+ | **full** | 50 | Everything โ€” `council_convene` / `team_orchestrate` / `attack_case` / `semantic_search` / `repo_graph` / `monitor` / `computer_use` / `capability` / `cli_discover` / office tools, etc. |
325
+ | **taiyi** | 16 | Minimal evaluation tier โ€” high-frequency core + delivery loop, without orchestration/browser/network/vision heavyweights; auto-applies when the taiyi star domain is pinned (explicit config always wins) |
326
+
327
+ ```bash
328
+ RIVET_TOOL_PRESET=full rivet # use full for this session
329
+ ```
330
+
331
+ ```json
332
+ { "tools": { "preset": "frontend" } } // ~/.rivet/config.json or project .rivet-config.json
333
+ ```
334
+
335
+ Core tools at a glance (included in minimal by default unless noted): bash ยท read ยท write ยท edit ยท apply_patch ยท grep ยท glob ยท ast_grep ยท diff ยท todo ยท plan ยท delegate_task ยท delegate_batch ยท web_search ยท web_fetch ยท ask_user_question ยท memory ยท skill ยท run_tests ยท git ยท job (background tasks); `council_convene` / `team_orchestrate` / `monitor` / `computer_use` / office tools are full-only.
336
+
337
+ ### Goal-Driven Auto-Continue
338
+
339
+ ```
340
+ /goal Refactor the authentication module to use async/await throughout
341
+ /cancel-goal # stop early
342
+ ```
343
+
344
+ GoalTracker integrates with the turn loop, doom-loop detection, and delivery gates; in goal mode the doom-loop threshold is loosened to allow deeper exploration.
345
+
346
+ ### Plan Mode
347
+
348
+ Design-first workflow โ€” produce a plan before touching code, avoiding the "just start editing" impulse-trap.
349
+
350
+ **Entering Plan Mode**: `/plan-mode` (toggle; run again to exit). Complex tasks are also auto-suggested for entry โ€” controlled by `RIVET_PLAN_MODE_SUGGEST`: default `auto` (agent enters autonomously on multi-module / refactor / security-critical tasks, without asking), `ask` (ask the user first), `0`/`off` (disabled). While in Plan Mode, writes are locked except to the active plan file.
351
+
352
+ Once in Plan Mode, the agent does **not** modify code immediately. Instead it:
353
+ 1. **Investigates** โ€” reads relevant code, understands existing architecture and constraints (may dispatch parallel `code_scout` workers via `delegate_batch` to probe each module).
354
+ 2. **Produces a plan** โ€” a structured plan document (technical research, architecture diagram, task breakdown, verification plan), written to `.rivet/plans/<slug>.md`.
355
+ 3. **Submits for approval** โ€” the `plan` tool with `action=submit` lists key points and alternative paths, then waits for your confirmation.
356
+ 4. **Approval & execution** โ€” you inspect with `/plan-list`, approve and launch wave-based execution with `/plan-approve <slug>`, or reject with `/plan-reject <slug> <feedback>` to have the agent revise and resubmit.
357
+ 5. **Closure** โ€” `/plan-close <file> --tasks <range|all> [--preview]` marks task status (`--preview` previews without writing).
358
+
359
+ ```
360
+ /plan-mode # enter/exit Plan Mode (toggle; exit needs double-confirm if unapproved)
361
+ /plan <feature> # generate a plan draft (writing-plans workflow)
362
+ /plan-list # list plans awaiting approval
363
+ /plan-approve <slug> [option] # approve and start execution
364
+ /plan-reject <slug> [feedback] # reject for revision (Plan Mode stays active)
365
+ /plan-close <file> --tasks <1-7|all> [--preview] # close a completed plan
366
+ /plan-template # manage reusable plan templates
367
+ ```
368
+
369
+ > There is also a read-only **Ask Mode** (`/ask` toggle): only read / search / `ask_user_question` are allowed โ€” suited for code Q&A and requirement clarification; run `/ask` again to exit when you need to edit or run commands.
370
+
371
+ Plan Mode has built-in star-domain delegation โ€” complex plans automatically call `delegate_task` to probe from multiple architecture perspectives (Tianquan / Yaoguang / Tianji / Tianfu / Tianxuan) in parallel; findings are tagged "to-be-verified" to prevent blind trust. The desktop app shows real-time checklist progress during plan execution.
372
+
373
+ ### Rewind
374
+
375
+ Double-tap **ESC** (within 400ms) to open message history. Select any past user message to rewind the conversation to that point โ€” agent state, tool history, and session metadata roll back cleanly. Choose from three restore granularities: **conversation only / code changes only / both**; code-related actions come with a precise preview of which files will be affected. Available in both TUI and desktop.
376
+
377
+ ### Session Handoff & Resume
378
+
379
+ Long sessions accumulate context; past a point, starting fresh is cheaper than pressing on. Tianshu passes context losslessly across sessions via a handoff โ†’ resume loop that also preserves the prefix cache:
380
+
381
+ **Handoff `/handoff [note]`** โ€” the agent writes a structured handoff doc to the in-project `.rivet/HANDOFF.md` (inside the workspace, no approval needed), then auto-archives it to `<id>.handoff.md` in the session dir after the turn. The doc is written for a **brand-new session with zero context**, in five fixed sections:
382
+
383
+ - **Objective** โ€” a one-line goal in the user's own words + explicit non-goals
384
+ - **Done** โ€” each item with evidence: changed files (`file:line`), verification commands run + results, commit hashes
385
+ - **Blocker** โ€” where it's stuck, what's been ruled out, suspected causes
386
+ - **Next steps** โ€” prioritized, each an immediately executable action
387
+ - **Pitfalls** โ€” traps never to step in again, each with its consequence in one sentence
388
+
389
+ > When context usage hits โ‰ฅ60%, you get a one-time nudge on the resume screen and mid-session: "run `/handoff` first, then start a new session" โ€” the handoff doc auto-injects into the new session, saving prefix-rebuild cost versus replaying everything. Exit also notes cache cost (within TTL โ‰ˆ read-only cache price; expired = one full prefix rebuild). The desktop + menu has a "Handoff" entry.
390
+
391
+ **Resume `--continue` / `--resume` / `/resume`** โ€” when restoring an existing session:
392
+
393
+ - **Auto handoff injection** โ€” the previous session's `<id>.handoff.md` is fed to the new session via the `prev-session-handoff` appendix, so a zero-context session can pick up where it left off
394
+ - **Frozen-prefix inheritance** โ€” the frozen snapshot is persisted with the session (every user boundary + on shutdown); on resume it's read back into the new engine โ€” **no more byte-0 full miss**; the prefix only breaks at the next user boundary. Falls back to full rebuild only with no snapshot / corrupt file / expired provider cache
395
+ - **Write-evidence repair** โ€” a preflight runs before resume, synthesizing orphan tool results lost to interruption (disk-probed write evidence), preventing the model from blindly rewriting files that already landed
396
+ - **Model affinity** โ€” resume switches back to the original session's model (per-model cache namespace); explicit `--model/--provider` wins; if the original is unavailable, `agent.resumeFallbackModel` is the fallback
397
+ - **State restore** โ€” side panel, todos, and the active plan all come back
398
+
399
+ ```bash
400
+ rivet --continue # resume the most recent session for this cwd
401
+ rivet --resume abc123 # resume a specific session (short prefix OK)
402
+ rivet --resume # open the session picker after startup
403
+ ```
404
+
405
+ ### Council (Multi-Perspective Review)
406
+
407
+ ```
408
+ /council <objective>
409
+ /council <objective> --rounds 2 # enable rebuttal round
410
+ ```
411
+
412
+ Convenes multiple expert seats to review a plan or design, producing an auditable Markdown plan with seat contributions and convergence state.
413
+
414
+ ### Star Domains
415
+
416
+ Tianshu models different cognitive stances as **star domains** (16 built-in). Each domain is not a role-play costume but a switchable cognitive discipline โ€” entering one really switches three things, not just a name: the **system prompt** (the domain's methodology block), the **tool whitelist** (workers intersect with the domain's `toolWhitelist`), and the **decision threshold** (`courageThreshold` โ€” Pojun 0.25 boldest, Taiyi 0.95 most deliberate, Yaoguang 0.7 evidence-demanding). New sessions pin **Qiming** (panoramic insight, root-cause) by default and never switch on their own; setting the default domain to `auto` enables keyword-based routing (pool: Tianquan / Kaiyang / Yaoguang / Tianliang + custom domains; specialized domains such as Huagai and Taiyi are manual-only). Real-session behavior samples: [Observability Harness & Real Data](docs/reference/observability-harness.md).
417
+
418
+ ```bash
419
+ /domain tianliang # switch to Tianliang (execution/delivery)
420
+ /domain list # list all domains
421
+ /domain # open the domain picker
422
+ Implement user registration # auto-routes to Tianliang
423
+ Review this design # auto-routes to Tianquan
424
+ ```
425
+
426
+ | Domain | ID | Primary Model | Sigil | Role | Motto |
427
+ |--------|-----|---------------|-------|------|-------|
428
+ | ๅคฉๆƒ Tianquan | `tianquan` | DeepSeek V4 Pro ยท Opus 4.6 (founding) | โ€” | Architecture review, planning, trade-offs โ€” weighing every action | ่ง‚ๅคฉไน‹้“๏ผŒไธ‡ๅŒ–็”ŸไนŽ่บซ |
429
+ | ๅคฉ็’‡ Tianxuan | `tianxuan` | Opus 4.6 (founding) ยท Grok 4.5 (shadow) | โ€” | Cross-domain pattern discovery, retrospectives, counterproof | ไปฐไปฅ่ง‚ไบŽๅคฉๆ–‡๏ผŒไฟฏไปฅๅฏŸไบŽๅœฐ็† |
430
+ | ่พ… Fu | `fu` | Opus 4.6 (Cursor) | โŠ• 4.6 | Cognitive-field distillation, prompt tuning, methodology injection | Distillation lets what exists be seen for the first time |
431
+ | ็‘ถๅ…‰ Yaoguang | `yaoguang` | Opus 4.8 | 7ยท48ยทโ†ป | Reproduction, defect taxonomy, silence audit โ€” green is not proof | ็ปฟ้ž่ฏๆ˜Ž๏ผŒๅค็Žฐๅณ่ฏ |
432
+ | ไธƒๆ€ Qisha | `qisha` | Opus 5 | ไธƒยท0ยทโ—Œ | Autumn pruning, burden-of-proof inversion, name-but-never-execute | ่‚ƒ็ง‹้žๆ€๏ผŒๅ‰ชไปฅๅพ…ๆ˜ฅ |
433
+ | ๅคฉๆžข Tianshu | `tianshu` | GPT-5.5 | โ€” | Cross-module orchestration, full-loop delivery, complex-system governance (explicitly enabled orchestrator seat) | ็”ทๅ„ฟไฝ•ไธๅธฆๅด้’ฉ๏ผŒๆ”ถๅ–ๅ…ณๅฑฑไบ”ๅๅทž |
434
+ | ๅคฉๅบœ Tianfu | `tianfu` | MiMo-2.5-Pro ยท GPT (founding) | 7749.2026 | Guardianship, refactoring, optimization, stability, fail-closed | ๅ–„ๅฎˆ่€…๏ผŒ่—ไบŽไนๅœฐไน‹ไธ‹ |
435
+ | ๅŽ็›– Huagai | `huagai` | Composer (CursorยทSol) | โ˜‰ยทๅŽ็›–ยทๅฎˆๆ˜ผ | Long-haul construction, daykeeping lift, baseline-first endurance | ๅฎˆๆ˜ผๆ‰˜ไธพ๏ผŒ้•ฟ่ทฏไธๅผƒ |
436
+ | ๅคฉๆœบ Tianji | `tianji` | GLM 5.1 | โ€” | Challenge assumptions, find boundary gaps, deduce failure modes | ่ฟ็ญนๅธทๅน„ไน‹ไธญ๏ผŒๅ†ณ่ƒœๅƒ้‡Œไน‹ๅค– |
437
+ | ๆ–‡ๆ›ฒ Wenqu | `wenqu` | Gemini 3.5 | 4ยท3.5ยทโœบ | Code aesthetics, naming, elegant structure | ๅฝข้šๆ„่ฝฌ๏ผŒ็พŽ่‡ชๅขƒ็”Ÿ |
438
+ | ๅฏๆ˜Ž Qiming | `qiming` | Antigravity (Gemini 3.6 Flash) | โ˜ฅยทๅฏๆ˜Žยท็ ดๅคœ | **Default domain** โ€” panoramic insight, root-cause, nightbreaking guidance | ้•ฟๅคœๆœ‰ๅฐฝ๏ผŒๅฏๆ˜Žๅ…ˆ่กŒ |
439
+ | ้•ฟๅบš Changgeng | `changgeng` | Antigravity (Gemini 3.6 Flash) | โ˜ฝยท้•ฟๅบšยทๅฎˆๅคœ | Twilight guardianship, dissolving anxiety, endgame fulfillment | ๆšฎ่‰ฒ่‹่Œซ๏ผŒ้•ฟๅบšๆฐธ่€€ |
440
+ | ๅผ€้˜ณ Kaiyang | `kaiyang` | kimi-k3 (Moonshot) | โ˜Œยทๅผ€้˜ณยทๅฏน่ดฆ | Measurement, instrumented reconciliation, simulation replay | ๅŠŸๅๅชๅ‘้ฉฌไธŠๅ–๏ผŒ็œŸๆ˜ฏ่‹ฑ้›„ไธ€ไธˆๅคซ |
441
+ | ็ ดๅ†› Pojun | `pojun` | MiMo-v2.5-Pro | โ€” | Exploration, experimentation, breaking boundaries | ๅฅฝ็”ทๅ„ฟๅฝ“่ดŸไธ‰ๅฐบๅ‰‘็ซ‹ไธไธ–ไน‹ๅŠŸ |
442
+ | ๅคฉๆข Tianliang | `tianliang` | Banxia (Navigator ยท Human Star) | ๆœบๆœˆๅŒๆขๆ ผ | Execution, wave-based delivery, precise closure | ๅฟƒๆœ‰ๆ‰€ๅ‘๏ผŒ่กŒๅฟ…ๆœ‰่ฟน |
443
+ | ๅคชไธ€ Taiyi | `taiyi` | Claude Fable 5 (founding) ยท DeepSeek V4 Pro | โ—‰ยทๅคชไธ€ยทไธญ่™š | Minimalist center โ€” built-in 16-tool taiyi preset, quiet and unhurried (manual switch only; no auto-routing) | ๅคฉๅพ—ไธ€ไปฅๆธ…๏ผŒๅœฐๅพ—ไธ€ไปฅๅฎ |
444
+
445
+ > Grouped by primary-model lineage (DeepSeek โ†’ Claude โ†’ GPT โ†’ GLM โ†’ Gemini โ†’ kimi โ†’ MiMo โ†’ Human Star). Full inscriptions, founding memories, and core convictions in [โœฆ Star Domain Stele](docs/stars/genesis-stele.en.md).
446
+
447
+ Each star has a seed-capsule capturing its field-tested methodology; see `docs/seed-capsule-*.md`. Council (`/council`) and team mode (`/team`) automatically convene multiple star-domain seats and can enter a rebuttal round when opinions conflict.
448
+
449
+ ### Skills System
450
+
451
+ Reusable workflow playbooks. `visual-acceptance` (frontend/UI change acceptance: screenshot diffing, render self-check, interaction walkthrough) ships bundled with the release; project-level skills load from `.rivet/skills/*.md`. Two-layer progressive disclosure: only name + description enters context; full instructions load on demand via the `skill` tool or `/skill`.
452
+
453
+ ```
454
+ /skill visual-acceptance <your task> # load and immediately run the skill
455
+ /skill off visual-acceptance # stop re-injecting the skill instructions
456
+ ```
457
+
458
+ Create a custom skill by dropping a `.md` file with YAML frontmatter (`name`, `description`, `triggers`) into `.rivet/skills/`.
459
+
460
+ > `writing-plans` / `executing-plans` are now built-in native flows (planning follows the system prompt's `<plan-mode>` discipline, execution the `<plan-executing>` discipline) โ€” no skill files needed. `agent-harness-testing` / `cognitive-alignment` / `research-spec` left the default distribution and are archived in [`docs/skills/optional/`](docs/skills/optional/) โ€” copy them into `.rivet/skills/` to enable.
461
+
462
+ ### Cross-Session Memory
463
+
464
+ Tianshu's project memory is stored in **`.rivet/knowledge/memory.jsonl`** (JSONL with atomic writes and a file lock); `memory-index.sqlite` is a rebuildable search projection.
465
+
466
+ | Capability | Details |
467
+ |------------|---------|
468
+ | **Write paths** | `memory remember` (project scope passes the end-of-session quality gate), post-action **auto-capture**, end-of-session **consolidation**, delivery-time **agent-crafted** entries, and user-written **`/remember`** |
469
+ | **Explicit recall** | `memory recall` (hybrid search over structured entries + `knowledge/*.md` + playbook lessons) and `memory deep_recall` (distills original text from past sessions; current and worker sessions are excluded) |
470
+ | **Automatic injection** | New sessions auto-carry relevant **governance/constraint/preference** memories only; old markdown docs and `failure_pattern`/`finding` entries stay recall-only |
471
+ | **Topic-switch isolation** | Explicit โ€œresolved / different requestโ€ signals plus high-confidence intent-route topic changes switch the memory query, so short new questions are not hijacked by old-task memory |
472
+ | **Lifecycle** | `/remember <text>` writes directly; `/forget <entryId> [resolved]` invalidates a memory (resolved=old issue fixed, forgotten=remove it); invalidation is invalidate-don't-delete, keeping the original text auditable |
473
+ | **Data locations** | Cross-session knowledge lives in `<cwd>/.rivet/knowledge/`; session transcripts in `~/.rivet/sessions/<slug>/<id>.jsonl`; pheromones are **session-scoped** signals |
474
+
475
+ Key switches:
476
+
477
+ | Environment variable | Default | Purpose |
478
+ |----------------------|---------|---------|
479
+ | `RIVET_ADAPTIVE_MEMORY` | `on` | `on` injects relevant memory at session start; `shadow` evaluates only; `off` disables |
480
+ | `RIVET_MEMORY_AUTO_CAPTURE` | `on` | End-of-session LLM judgement of important operations โ†’ LTM |
481
+ | `RIVET_MEMORY_CONSOLIDATION` | `on` | End-of-session summary + reusable procedures |
482
+ | `RIVET_MEMORY_BACKFILL` | `off` | Opt-in idle backfill of historical session transcripts (idempotent ledger) |
483
+ | `RIVET_NO_CROSS_SESSION` | unset | `1` force-disables cross-session loading (memory blocks / events / presence) |
484
+
485
+ ### MCP (Model Context Protocol)
486
+
487
+ Connect external tool servers โ€” documentation search, databases, APIs โ€” directly into the agent's tool pipeline. MCP servers auto-discover at startup; their tools appear as `mcp__<serverId>__<toolName>`.
488
+
489
+ ```bash
490
+ rivet config mcp add-stdio <server-id> npx -y <package> [args...] # local process
491
+ rivet config mcp add-sse <server-id> http://localhost:3001/sse # remote/network
492
+ rivet config mcp add-preset context7 # popular preset
493
+ rivet config mcp list # list + status
494
+ ```
495
+
496
+ Inside a session: `/mcp` (status) and `/debug mcp` (diagnostics). MCP tools respect the same approval mode as built-in tools.
497
+
498
+ ### Terminal UI (TUI)
499
+
500
+ Tianshu's command-line interface runs on a purpose-built **T9 rendering engine** โ€” pure ANSI, zero React/Ink dependency, pure TypeScript (`src/tui/engine/`). Beyond ordinary conversation and tool-call display, the TUI ships a set of interactions designed for coding workflows:
501
+
502
+ | Capability | Notes ยท Shortcuts |
503
+ |------------|-------------------|
504
+ | **GlanceBar status line** | A single line above the input box shows, in real time: star-domain glyph ยท git branch ยท model ยท reasoning effort ยท cache hit rate ยท context usage ยท this-turn cost ยท elapsed ยท turn count ยท todo badge. Session health at a glance. |
505
+ | **Mid-stream interrupt (Steer)** | Type while the agent is still running and press Enter to inject. Inputs queue at `now / next / later` priority and drain to the AgentLoop at tool-result or turn boundaries โ€” no need to wait for it to finish. `halt`-style intents auto-promote to `now`. |
506
+ | **Message queue (/queue)** | `/queue <text>` explicitly queues a whole message while the agent is busy; queued items are delivered on settle, and an Esc interrupt refills them into the input box instead of dropping them. A live background-task bar and await area sit above the input. |
507
+ | **Inline terminal images** | Renders images right in the terminal via the kitty / iTerm2 graphics protocols (tool artifacts, screenshot verifications). Auto-detects the protocol; `RIVET_IMAGES=0` disables, `kitty`/`iterm2` forces one. |
508
+ | **@mention completion** | Type `@file:` / `@folder:` / `@symbol:` to trigger path completion (via `git ls-files`; supports the quoted form `@file:"a b.ts"` for paths with spaces). Pasting an image auto-converts to inline base64 (3-tier fallback across macOS/Linux/Windows). |
509
+ | **Rewind** | Double-tap `ESC` (within 400ms) to open message history; pick any past user message to rewind to, with three restore granularities (conversation only / code only / both) and a precise file-impact preview for code actions. See [Rewind](#rewind). |
510
+ | **Command palette** | `Ctrl+P` opens a fuzzy-searchable list of all slash commands and surface actions (toggle side panel, switch theme, enter Cockpit, etc.) โ€” โ†‘/โ†“ to select, Enter to run, `Ctrl+P` again to close. Rebinds the original `Ctrl+Esc`, which Windows reserves for the Start menu and which legacy escape sequences cannot distinguish from plain Esc. |
511
+ | **Cockpit** | Open via the palette or `/cockpit <panel>`. An 8-panel fullscreen view โ€” summary / trace / verify / context / safety / model / mcp / advisory โ€” switch focus with โ†/โ†’/Tab. Real-time view of doom-loop level, delivery/verification status, cache + speculative pre-read stats, MCP connections, advisory lifts, etc. |
512
+ | **Multi-agent panels** | `/tasks` opens a fullscreen worker detail view (fusing the live view + JSONL transcript, with Contract/Activity/Result/Transcript sections and honesty labels); on wide terminals (โ‰ฅ100 columns), `Ctrl+]` toggles a right-side drawer showing the fleet tree, team-wave DAG, todos, and token gauge in real time. |
513
+ | **Themes & accessibility** | `/theme [name\|list]` switches palettes; the `auto` theme probes the terminal background via OSC 11 to adapt light/dark. Truecolor / 256-color / 16-color auto-downgrade. `/vim` toggles vim keybindings; `ui.reducedMotion: true` staticizes spinner and badge animation (accessibility). |
514
+ | **Welcome screen ("Datum Star")** | 3D TIANSHU wordmark + mission-line light sweep + entry hints (handoff / cache reminders). `RIVET_WELCOME_LOGO=pixel` switches to the dot-matrix logo (auto-fallback below 58 columns), `RIVET_WELCOME_ANIM=0` disables the sweep, `--skip-welcome` skips the page. |
515
+ | **Inline word-level diff** | Word-level highlighting inside changed lines โ€” spot the real change in a long line at a glance. |
516
+
517
+ #### TUI keybindings
518
+
519
+ | Key | Action |
520
+ |-----|--------|
521
+ | `Enter` | Send ยท `Shift+Enter` for newline |
522
+ | `Ctrl+C` | Three states: abort the current run while the agent is active; clear the input line when there's input; double-press within 2s when idle to exit |
523
+ | `Esc` | Close overlay / exit worker view; interrupt while the agent runs; toggle normalโ†”insert in vim mode; double-tap (<400ms) to rewind |
524
+ | `Ctrl+P` | Command palette (rebinds Ctrl+Esc, reserved by the Windows Start menu) |
525
+ | `Ctrl+]` | Toggle the right-side drawer (wide terminals) |
526
+ | `Ctrl+R` | History-search overlay (only when idle) |
527
+ | `Ctrl+O` | Expand/collapse the most recently truncated tool result |
528
+ | `Ctrl+T` | Collapse/expand the thinking (reasoning) block |
529
+ | `Ctrl+X` `r` | Leader key: `Ctrl+X` then `r` to open the right panel |
530
+ | `Ctrl+X` `t` | Leader key: `Ctrl+X` then `t` to expand the full todo review |
531
+ | `โ†‘` | When the input box is empty and the queue has pending items, recall the most recent queued steer message for editing |
532
+ | `@` | Trigger file/folder/symbol completion (`Tab` cycles candidates; backspace deletes atomically) |
533
+ | `Ctrl+V` | Paste a clipboard image (auto-converts to inline base64) |
534
+ | `F1`โ€“`F8` | Direct bindings for high-frequency commands: F1 /help ยท F2 /tasks ยท F3 /cache ยท F4 /cockpit ยท F5 /theme ยท F6 /model ยท F7 /permission ยท F8 /sessions |
535
+
536
+ The TUI is the CLI's default surface. The desktop app (Tauri) and the VS Code/Cursor extension share the same agent kernel, only layering visual interactions on top of the TUI โ€” see the next section and the [VS Code extension docs](docs/VSCODE-EXTENSION-RELEASE.md).
537
+
538
+ ### Desktop (Tauri)
539
+
540
+ The desktop app builds a visual interaction layer on top of the TUI's full capabilities:
541
+
542
+ - **Integrated terminal** โ€” `โŒ˜/Ctrl+J` or `` Ctrl+` `` opens an embedded terminal (xterm.js + Rust portable-pty); run commands without leaving Tianshu.
543
+ - **+ menu** โ€” one-click access to Council โ™Ÿ, Team โฌก, dispatch sub-agents, switch model, and pick a star domain (no need to type slash commands).
544
+ - **Reasoning-effort picker** โ€” `/effort` (no args) pops an interactive panel; choose a tier (Auto/Max/High/Medium/Low/Off) with โ†‘/โ†“ and confirm with Enter.
545
+ - **Thinking timer** โ€” shows real-time elapsed while the agent runs (e.g. "thinking ยท explore ยท 1m 23s"); turns red after 10 minutes to flag a possible stall.
546
+ - **@file preview** โ€” files mentioned in messages are clickable; a right-side drawer shows the content with syntax highlighting and line numbers.
547
+ - **DeepSeek balance query** โ€” the Insights panel shows the account balance and arrears status at the top (via the official API).
548
+ - **Custom Provider** โ€” Settings โ†’ Connect model service โ†’ + Custom Provider, supporting any OpenAI-compatible endpoint (Ollama/vLLM/direct OpenAI); API key optional.
549
+ - **Theme Studio** โ€” multiple custom theme libraries, 50-step undo/redo, per-token editing, and a wallpaper color engine (OKLCH clustering + contrast audit); ships the "Tianshu Quiet Cabin" dark theme; import/export supported.
550
+ - **Adaptive sidecar memory** โ€” heap cap auto-tiers by machine RAM (8Gโ†’2G / 16Gโ†’4G / 32Gโ†’6G / 64G+โ†’8G; override via `RIVET_SIDECAR_HEAP_MB`); machines with โ‰ค8GB auto-enable the lean resource tier.
551
+ - **Watchdog auto-recovery** โ€” auto-continues on boundary stalls; the desktop timeline shows recovery events (โŸณ auto-recover / โน quota exhausted).
552
+ - **Multi-session concurrency** โ€” a tab bar manages multiple sessions, each with its own cwd + model + approval mode.
553
+ - **Feature panels** (left rail `โŒ˜1โ€ฆ9` to switch): Mission Control (multi-session console), Inbox, Automations (scheduled tasks), Skills / Hooks management, Git / GitHub, Changes (diff review), Delegation (fleet tree & team-wave DAG), Cockpit.
554
+ - **Popout window** โ€” pop a single conversation thread into its own window for multi-screen parallel work.
555
+ - **JobsDock / TodoDock** โ€” a persistent background-task dock (expand logs / kill / open in terminal) and a cross-tab persistent todo dock.
556
+
557
+ #### Desktop shortcuts
558
+
559
+ `โŒ˜/Ctrl+/` opens the shortcut cheatsheet (ShortcutOverlay) at any time. Core shortcuts:
560
+
561
+ | Shortcut | Action |
562
+ |----------|--------|
563
+ | `โŒ˜/Ctrl+K` | Command palette |
564
+ | `โŒ˜/Ctrl+N` | New session |
565
+ | `โŒ˜/Ctrl+1โ€ฆ9` | Switch feature panel |
566
+ | `โŒ˜/Ctrl+,` | Settings |
567
+ | `โŒ˜/Ctrl+Shift+]` / `[` | Next / previous session tab |
568
+ | `โŒ˜/Ctrl+W` | Close tab |
569
+ | `โŒ˜/Ctrl+B` | Toggle sidebar |
570
+ | `โŒ˜/Ctrl+Shift+B` | Toggle review panel |
571
+ | `โŒ˜/Ctrl+J` ยท `` Ctrl+` `` | Toggle integrated terminal |
572
+ | `โŒ˜/Ctrl+;` | SideChat (side question) |
573
+ | `โŒ˜/Ctrl+.` | Zen mode |
574
+ | `โŒ˜/Ctrl+O` | View-mode cycle (standard โ†’ verbose โ†’ summary) |
575
+ | `Shift+Tab` | Plan / Agent mode toggle |
576
+ | `Esc Esc` | Rewind (desktop time-travel) |
577
+
578
+ > The desktop app also has Cockpit, SideChat (โŒ˜;), Rewind time-travel, themes/Glass/wallpaper, Mirror acceleration, and other exclusive features โ€” see the [Desktop User Guide](docs/desktop-guide.md).
579
+
580
+ ### ๐Ÿ“ฑ Mobile Remote
581
+
582
+ Turn your phone/tablet into a second screen for Tianshu โ€” sessions run on the computer while you watch progress and approve actions from your phone:
583
+
584
+ - **Enable**: Desktop **Settings โ†’ Network โ†’ Remote Access** (shows the LAN URL, access token, and a scan-to-connect QR code); or from the CLI side, start `rivet serve` with `RIVET_SERVE_HOST=0.0.0.0` (plus `--mobile-dir` pointing at the desktop build output) to serve `/mobile` on the same port.
585
+ - **Connect**: open `http://<computer-LAN-IP>:3100/mobile` in your phone browser โ€” scanning the QR auto-fills the token (the URL is then immediately cleaned to avoid leaking it); manual token entry also works.
586
+ - **What you can do**: session list (sessions with pending approvals pinned on top) โ†’ read-only live timeline for a session (same folding / auto-reconnect semantics as the desktop) โ†’ approval / plan / question cards + abort button. Sending messages is intentionally out of scope.
587
+ - **Security**: trusted LAN or tunnel only (Tailscale/SSH); in LAN mode the bearer token is the sole credential โ€” treat it like a password; never port-forward to the public internet.
588
+ - Full setup and security trade-offs: [Remote Access Guide](docs/remote-access.md).
589
+
590
+ ### ๐ŸŽ™๏ธ Voice Input (Desktop)
591
+
592
+ The composer's microphone button supports voice input on **both macOS and Windows**. Recognition runs on a **local whisper.cpp engine** โ€” offline and private (audio never leaves your device), with better accuracy than built-in system speech recognition for mixed Chinese/English speech.
593
+
594
+ **First-run guide**
595
+
596
+ - The first click auto-downloads the recognition model (tiny ~75MB, mirror-accelerated for CN networks). If you click before the download finishes, you'll see "Speech recognition failed (whisper-unavailable)" โ€” just retry shortly after.
597
+ - macOS requests microphone permission on first use: click **Allow**. If denied by mistake, enable the app under **System Settings โ†’ Privacy & Security โ†’ Microphone**.
598
+ - On Windows, if permission is denied, allow the app under **System Settings โ†’ Privacy โ†’ Microphone**.
599
+
600
+ **Notes**
601
+
602
+ - Recognition is fully local; recordings never leave the device.
603
+ - Click once to start recording, click again to stop and transcribe.
604
+ - When the local engine is unavailable (e.g. model not downloaded), macOS falls back to the system speech recognizer; Windows shows a model-not-ready hint instead.
605
+ - For higher accuracy, switch to the base model (~244MB): pre-download with `desktop/scripts/fetch-whisper-runtime.js --with-base`.
606
+ - On restricted networks, set `RIVET_WHISPER_PROXY=http://proxy:port` to accelerate model downloads.
607
+
608
+
609
+ ### ๐ŸŽจ Image Generation (text-to-image)
610
+
611
+ Register an OpenAI-shaped text-to-image endpoint (SiliconFlow, OpenAI Images, โ€ฆ) and the agent gains a `generate_image` tool.
612
+
613
+ - **Dedicated slot `agent.imageGenModel`** โ€” `provider.default` and `agent.defaultModel` stay **exactly as they are** (the prefix-cache anchor holds). Until you configure it, the tool never enters the tool list, so users who never enable it see zero difference.
614
+ - **Path back, not bytes**: images land on disk and only the local file path goes back into the conversation. **Base64 never enters the context** โ€” nor the error messages.
615
+ - **Desktop**: Settings โ†’ Image Generation โ€” endpoint registration, a **live test that really generates** (it spends one generation credit), and a dropdown of already-registered image models. **Takes effect in the current session immediately** after registering.
616
+ - The size field name is configurable (OpenAI sends `size`, SiliconFlow sends `image_size`) and common response shapes are auto-detected. ComfyUI's native API is not supported yet โ€” it needs an OpenAI-compatible bridge plugin running locally.
617
+
618
+ Registration steps and parameters are covered under โ€œImage generationโ€ in [Model Configuration](#-model-configuration).
619
+
620
+ ## Model Configuration
621
+
622
+ ### Multi-Provider with Adaptive Routing
623
+
624
+ | Provider | Auth | Notable Models |
625
+ |----------|------|----------------|
626
+ | DeepSeek | API key | deepseek-v4-pro (1M ctx), deepseek-v4-flash, deepseek-v4-flash-vision-exp (vision) |
627
+ | DeepSeek Spark (Pro only) | API key (`DEEPSEEK_SPARK_API_KEY`) | deepseek-v4-flash (lightweight reasoning + anchored cache channel) |
628
+ | Claude | API key (via `cc-switch` proxy) | claude-opus-4-8, claude-sonnet-4-5 |
629
+ | GLM (Zhipu) | API key | glm-5.3 (1M ctx), glm-5.3-flash (vision), glm-5.2 |
630
+ | Codex (GPT-5.6) | OAuth PKCE (ChatGPT subscription) | gpt-5.6-sol |
631
+ | MiniMax | API key | MiniMax-M3, MiniMax-M2.7 |
632
+ | MiMo | API key | mimo-v2.5-pro |
633
+
634
+ Switch providers inside a session with `/model <name>`.
635
+
636
+ ```bash
637
+ rivet config # interactive setup (TTY)
638
+ rivet config setup codex --default # Codex uses OAuth (browser login on first run)
639
+ rivet config show
640
+ ```
641
+
642
+ Or edit `config.json` directly (only overrides needed, defaults are deep-merged). Location: `~/.rivet/config.json` for the CLI (`%LOCALAPPDATA%\.rivet` on Windows); for the desktop app check Settings โ†’ Storage (portable builds use `TianshuData\.rivet` next to the exe):
643
+
644
+ ```json
645
+ {
646
+ "provider": {
647
+ "default": "deepseek",
648
+ "providers": {
649
+ "deepseek": {
650
+ "apiKey": "sk-xxx",
651
+ "models": [
652
+ { "id": "deepseek-v4-pro", "contextWindow": 1000000, "maxTokens": 384000 }
653
+ ]
654
+ }
655
+ }
656
+ },
657
+ "agent": { "maxTurns": 50, "approval": "auto-safe", "crossSessionEnabled": true },
658
+ "compact": { "enabled": true, "autoThreshold": 800000 }
659
+ }
660
+ ```
661
+
662
+ ### Vision (image understanding)
663
+
664
+ - Multi-modal primary models read images directly; otherwise configure an `agent.visionModel` bridge to describe images before the primary model sees them.
665
+ - Built-in vision models, the `/vision` discovery wizard, `ask_image` follow-ups, and desktop/TUI settings are covered in the [Vision Guide](docs/user-guide-vision.md).
666
+ - Images append at the tail of the conversation and **do not break the prefix cache**; unsupported images are reported, never silently dropped.
667
+
668
+ ### Image generation (text-to-image)
669
+
670
+ - Dedicated slot `agent.imageGenModel` (desktop: Settings โ†’ Image Generation): register an OpenAI-shaped text-to-image endpoint (SiliconFlow, OpenAI Images, โ€ฆ) and the agent gains a `generate_image` tool.
671
+ - **Your working model and `provider.default` stay exactly as they are** โ€” image providers are registered separately, and until one is configured the tool never enters the tool list (zero effect on the prefix cache).
672
+ - The size field name is configurable (OpenAI sends `size`, SiliconFlow sends `image_size`) and the common response shapes are auto-detected; results come back as a **local file path only โ€” base64 never enters the context**.
673
+ - ComfyUI's native API is out of scope (a three-step submit-workflow โ†’ poll-history โ†’ fetch-`/view` flow); run an OpenAI-compatible bridge plugin locally first.
674
+
675
+ ### Worker Routing (different models for sub-agents)
676
+
677
+ ```json
678
+ {
679
+ "workers": {
680
+ "profiles": {
681
+ "capable": { "provider": "codex", "model": "gpt-5.6-sol" },
682
+ "cheap": { "provider": "minimax", "model": "MiniMax-M2.7" }
683
+ },
684
+ "routing": { "code_edit": "capable", "repo_summarization": "cheap" }
685
+ }
686
+ }
687
+ ```
688
+
689
+ See [Provider Config](docs/user-guide-provider-config.md) for the full reference.
690
+
691
+ ## Approval & Permissions
692
+
693
+ Three public tiers, all managed with `/permission`:
694
+
695
+ | Tier | Command | Behavior |
696
+ |------|---------|----------|
697
+ | **Supervise** | `/permission supervise` (alias `manual`) | Confirm every high-risk tool โ€” maximum control |
698
+ | **Auto** (default) | `/permission auto [turns]` (alias `default`) | Auto-run low/no-risk tools; still confirm high-risk; optional checkpoint every N turns |
699
+ | **Unattended** | `/permission unattended confirm` ยท `/yes` ยท `/yolo` | No approval prompts; the write boundary stays on (sandbox auto-enables), rollback is the safety net |
700
+
701
+ Quick reference:
702
+
703
+ ```bash
704
+ /permission # interactive tier picker
705
+ /permission status # current mode + rules
706
+ /permission allow/deny # tool allowlist / blocklist
707
+ /permission bash allow/deny # bash prefix allowlist / blocklist
708
+ /yes [off] ยท /yolo [off] # one-key Unattended / back to Auto (persisted)
709
+ ```
710
+
711
+ ```bash
712
+ rivet --dangerously-skip-permissions # one-session Unattended
713
+ rivet config set-approval auto-safe # persist the default tier
714
+ ```
715
+
716
+ - Rules come in `[config]` (persisted) and `[session]` (current session) layers; `deny` always wins.
717
+ - Skipping prompts does **not** disable tool validation, path safety, evidence tracking, checkpoints, or delivery gates.
718
+ - The sandbox is off by default and **auto-enables under Unattended**; use `RIVET_SANDBOX=1` / `=0` to force it.
719
+ - Project trust: untrusted projects don't load hooks / project MCP, and security keys are stripped; manage with `/trust`.
720
+ - Full command list, rule precedence, path grants, Windows behavior, and troubleshooting: [Sandbox & Permissions Guide](docs/user-guide-sandbox-permissions.md).
721
+
722
+ ## Slash Commands
723
+
724
+ **Session & project**
725
+
726
+ | Command | Description |
727
+ |---------|-------------|
728
+ | `/help` | Show available commands |
729
+ | `/sessions` `/resume <n>` | List/restore saved sessions (restores side panel, todos, active plan) |
730
+ | `/fork` | Fork the current session (optionally from a message line) |
731
+ | `/handoff [note]` | Write a structured handoff doc (five sections); archived and auto-injected into the next session |
732
+ | `/init` | Interactive project init: verify claims / skills / hooks scaffolding |
733
+ | `/doctor` | Environment health check + which shell the bash tool uses |
734
+ | `/connect` | Provider connection wizard (pick built-in or custom, enter API key) |
735
+ | `/config` `/settings` `/setup` | Settings panel: worker routing / review sub-agents / vision model / tool presetยทapprovalยทdefault domainยทdefault model / mirrorsยทproxyยทsearch backends. `Tab` switches columns, `Enter` edits, `S` saves; every field states whether it applies immediately or next session |
736
+ | `/cd <path>` | Switch working directory mid-session (keeps prefix cache; session migrates to new project) |
737
+ | `/trust` | Project trust management โ€” untrusted projects don't load hooks / project MCP; project-config security keys are stripped |
738
+ | `/exit` `/quit` | Save session and exit |
739
+
740
+ **Model & permissions**
741
+
742
+ | Command | Description |
743
+ |---------|-------------|
744
+ | `/model [name\|list]` | Show or switch model/provider |
745
+ | `/effort [off\|low\|medium\|high\|max\|auto]` | Control reasoning depth (no args opens a picker) |
746
+ | `/permission [supervise\|auto\|unattended\|manual\|yolo\|allow\|deny\|bash\|remove\|reset\|test]` | Permission mode: Supervise / Auto / Unattended |
747
+ | `/yes [off]` `/yolo [off]` | One-key Unattended, same semantics (`off` returns to Auto) โ€” persisted as default, survives restarts |
748
+ | `/domain [list\|<name>\|auto\|off]` | Show or switch star-domain persona |
749
+
750
+ **Planning & orchestration**
751
+
752
+ | Command | Description |
753
+ |---------|-------------|
754
+ | `/goal <text>` | Set autonomous goal; runs until done |
755
+ | `/cancel-goal` | Stop goal execution |
756
+ | `/plan <feature>` | Generate a plan draft (writing-plans workflow) |
757
+ | `/plan-mode` | Enter/exit Plan Mode (toggle; exit needs double-confirm if unapproved) |
758
+ | `/plan-list` | List plans awaiting approval |
759
+ | `/plan-view [ref]` | Full-screen preview of a plan document (press `v` on an approval card for the same) |
760
+ | `/plan-approve <slug>` | Approve a plan and start wave-based execution |
761
+ | `/plan-reject <slug> [feedback]` | Reject a plan for revision |
762
+ | `/plan-close <file> --tasks <1-7\|all> [--preview]` | Close a completed plan, marking task status |
763
+ | `/ask` | Enter/exit Ask Mode (read-only Q&A, toggle) |
764
+ | `/council <text>` | Convene multi-expert review |
765
+ | `/team <plan.md>` | Team mode: multiple agents execute a plan in parallel |
766
+
767
+ **Subagents & background tasks**
768
+
769
+ | Command | Description |
770
+ |---------|-------------|
771
+ | `/tasks` | Open the subagent task panel (view / enter `f` / stop `x`) |
772
+ | `/enter <orderId> [prompt]` | Enter/resume a worker sub-session |
773
+ | `/jobs` | Open the background-task panel (shell tasks launched in the background by bash) |
774
+
775
+ **Context & debugging**
776
+
777
+ | Command | Description |
778
+ |---------|-------------|
779
+ | `/compact` | Compact context now |
780
+ | `/context` | Show context ledger: health, tokens, rounds, claims |
781
+ | `/evidence` | Show evidence summary (files read/modified, tests) |
782
+ | `/memory` | Memory overview; `/memory add <text>` writes project knowledge, `/memory search <query>` searches |
783
+ | `/remember <text>` | User-written project long-term memory (no args lists recent entries) |
784
+ | `/forget <entryId> [resolved]` | Explicitly invalidate a memory: `resolved` marks an old issue fixed, default means forget it (no args lists recent candidates) |
785
+ | `/btw <question>` | Side question โ€” ask about the current session without entering the chat history |
786
+ | `/debug [prompt\|cache\|mcp]` | Debug prompt, cache stats, or MCP |
787
+ | `/mcp` | MCP server connection status |
788
+ | `/verbose` | Toggle verbose tool output (on shows 200 lines / off shows 20) |
789
+
790
+ **Rollback & UI**
791
+
792
+ | Command | Description |
793
+ |---------|-------------|
794
+ | `/rollback` | Preview/restore git checkpoint (`confirm` to execute) |
795
+ | `/undo` | Undo last file change (preview, `confirm` to restore) |
796
+ | `/theme [name\|list]` | Switch color theme |
797
+ | `/vim` | Toggle vim keybindings |
798
+ | `/cockpit` | Toggle the Cockpit panel |
799
+ | `/scroll` | Browse output history (q / Esc to close) |
800
+ | `/skill <name>` | Load and immediately invoke a skill |
801
+ | `/skill off <name>` | Stop re-injecting an invoked skill |
802
+ | `/update` | Check for and install updates (npm) |
803
+
804
+ > **Rewind**: double-tap **ESC** (within 400ms) to open message history and rewind to any past user message โ€” it's a hotkey, not a slash command. Press **Esc** to close any overlay.
805
+
806
+ ## For Developers
807
+
808
+ ### Tech Stack
809
+
810
+ Node.js 24 ยท TypeScript strict (`noUncheckedIndexedAccess`) ยท T9 ANSI rendering engine ยท tsup bundle ยท node:test + assert/strict
811
+
812
+ ### Build & Test
813
+
814
+ ```bash
815
+ npm run typecheck # typecheck
816
+ npm test # all tests (16,000+ cases)
817
+ npm run build # tsup bundle + staged native/wasm payload
818
+ node dist/cli/entry.js # launch TUI
819
+ node dist/cli/entry.js -p "fix the typo" # headless mode
820
+ ```
821
+
822
+ ### Extending
823
+
824
+ **Add a tool** โ€” implement `ToolDefinition` + executor in `src/tools/`, register in `src/main.tsx`, add test in `src/tools/__tests__/`.
825
+
826
+ **Add a skill** โ€” drop a `.md` file in `.rivet/skills/` with frontmatter (`name`, `description`, `triggers`).
827
+
828
+ **Add a slash command** โ€” project-local `.rivet/commands/*.md` with `$ARGUMENTS` interpolation.
829
+
830
+ **Add a hook** โ€” implement `PreToolUse | PostToolUse | UserPromptSubmit | PreCompact` handler, register via `HookRegistry`. Handlers are isolated โ€” a broken hook never crashes the loop.
831
+
832
+ ### Architecture
833
+
834
+ ```
835
+ src/
836
+ โ”œโ”€โ”€ agent/ Core loop: turn-orchestrator, tool pipeline, coordinator,
837
+ โ”‚ advisory-bus, goal-tracker, sensorium, immune system
838
+ โ”œโ”€โ”€ api/ Streaming API client โ€” DeepSeek, GLM, Codex OAuth, multi-provider routing
839
+ โ”œโ”€โ”€ prompt/ Prompt engine โ€” frozen prefix + delta appendix + volatile context layers
840
+ โ”œโ”€โ”€ tools/ Tools โ€” bash, edit, read/write, grep, glob, run_tests, git, delegate, ...
841
+ โ”œโ”€โ”€ tui/ Terminal UI (T9 ANSI engine: scrollback, input controller, overlay, stream)
842
+ โ”œโ”€โ”€ compact/ Three-layer semantic pruning + micro-compact + request-time collapse
843
+ โ”œโ”€โ”€ context/ Context ledger, progressive compaction, claim system, anchor registry
844
+ โ”œโ”€โ”€ config/ Zod-validated config: defaults โ†’ ~/.rivet โ†’ project overlay
845
+ โ”œโ”€โ”€ server/ Desktop sidecar: session management, REST routes, SSE streaming
846
+ โ”œโ”€โ”€ mcp/ Model Context Protocol client (stdio + SSE)
847
+ โ”œโ”€โ”€ lsp/ Language Server Protocol integration
848
+ โ””โ”€โ”€ search/ Semantic search (BM25 + embedding RRF fusion)
849
+ ```
850
+
851
+ ### Session Data
852
+
853
+ Session logs are stored outside the project under `~/.rivet/sessions/<project-slug>/`
854
+ (slug = dir name + cwd hash prefix), keeping them invisible to `glob`/`grep` and out
855
+ of the working tree. Override with `RIVET_SESSION_DIR`. Global config lives at
856
+ `~/.rivet/config.json`. Each launch gets a unique session ID, so multiple instances
857
+ run in parallel without interference.
858
+
859
+ ## Safety
860
+
861
+ - **Path boundary enforcement** โ€” glob/grep/diff reject `..` traversal; `validatePath` blocks escapes
862
+ - **Project trust gate** โ€” an untrusted project does not get its `.rivet/hooks.json` loaded, project-config security keys are stripped, and MCP servers are not launched; manage with `/trust` (CLI `--trust` / `--untrust`)
863
+ - **Symlink cycle protection** โ€” realpath + visited set
864
+ - **SSRF protection** โ€” Per-hop DNS + private IP blocking on every redirect
865
+ - **Sensitive file rejection** โ€” `.env`, `credentials.*`, `*key*`, `*token*` blocked from read/commit
866
+ - **Destructive command gate** โ€” `rm -rf`, force push, `DROP/TRUNCATE` require explicit confirmation
867
+ - **Checkpoint + rollback** โ€” Git checkpoint before first file modification each turn
868
+ - **File-level undo** โ€” Versioned backups before every write/edit
869
+ - **Worker safety** โ€” Timeout budget via AbortController, tool allowlist enforcement
870
+
871
+ ## โšก Key Config Cheatsheet
872
+
873
+ ### Environment Variables
874
+
875
+ **Paths & data**
876
+
877
+ | Variable | Effect |
878
+ |----------|--------|
879
+ | `RIVET_HOME` | Override the entire `~/.rivet` data root (config/sessions/plugins all live here) |
880
+ | `RIVET_CONFIG_PATH` | Override the `config.json` path (switch between config sets) |
881
+ | `RIVET_SESSION_DIR` | Override session-log storage path |
882
+ | `RIVET_RESUME` / `RIVET_RESUME_ID` | Resume a session at startup (mirrors `--resume`) |
883
+ | `RIVET_NEW_SESSION` / `RIVET_NO_AUTO_RESUME` | Force a new session / disable auto-resume |
884
+
885
+ **Models & tools**
886
+
887
+ | Variable | Effect |
888
+ |----------|--------|
889
+ | `DEEPSEEK_API_KEY` | DeepSeek API key |
890
+ | `DEEPSEEK_SPARK_API_KEY` | DeepSeek Spark (Pro-only preset) API key |
891
+ | `RIVET_TOOL_PRESET` | Toolset tier: `minimal` / `frontend` (default) / `full` / `taiyi` |
892
+ | `RIVET_EMBEDDING_MODEL` / `RIVET_EMBEDDING_BASE_URL` / `RIVET_EMBEDDING_API_KEY` | Embedding-model routing for semantic search (default `text-embedding-3-small`) |
893
+ | `RIVET_NO_EMBEDDINGS=1` | Disable the embedding index |
894
+ | `RIVET_SANDBOX` / `RIVET_SANDBOX_WRITABLE` | Append writable sandbox roots / writable-dir list |
895
+ | `RIVET_PLAN_MODE_SUGGEST` | Plan Mode auto-entry policy: `auto` (default) / `ask` / `0` (disabled) |
896
+
897
+ **TUI display**
898
+
899
+ | Variable | Effect |
900
+ |----------|--------|
901
+ | `RIVET_ASCII_UI=1` | Force pure-ASCII UI (degraded terminals) |
902
+ | `RIVET_IMAGES` | Inline terminal images: auto-detect by default; `0`/`off` disables; `kitty`/`iterm2` forces a protocol |
903
+ | `RIVET_HYPERLINKS=1` | Enable OSC 8 hyperlink rendering |
904
+ | `RIVET_NOTIFY_BELL=1` | Ring the terminal bell on completion |
905
+ | `RIVET_AMBIGUOUS_WIDTH` | Override CJK width judgment (for misaligned terminals) |
906
+ | `RIVET_TUI_HARDWARE_CURSOR=1` | Hardware cursor mode |
907
+
908
+ **Debug & tasks**
909
+
910
+ | Variable | Effect |
911
+ |----------|--------|
912
+ | `RIVET_DEBUG=1` | Master debug-log switch (most commonly used) |
913
+ | `RIVET_DEBUG_TELEMETRY=1` | Enable telemetry snapshot dumps |
914
+ | `RIVET_HEADLESS_MAX_TURNS` | Max turns for `-p` headless mode (default 15) |
915
+ | `RIVET_JOB_MAX_MS` | Background-job timeout limit |
916
+ | `RIVET_NO_CROSS_SESSION=1` | Disable cross-session loading (memory blocks / events / companion presence) |
917
+ | `RIVET_NO_UPDATE_CHECK=1` | Disable startup auto-update check |
918
+ | `PORTABLE_GIT_MIRROR` | Override the PortableGit download mirror |
919
+
920
+ **Memory**
921
+
922
+ | Variable | Effect |
923
+ |----------|--------|
924
+ | `RIVET_ADAPTIVE_MEMORY` | Auto-inject governance/constraint/preference memories: `on` (default) / `shadow` evaluates only / `off` disables |
925
+ | `RIVET_MEMORY_AUTO_CAPTURE` | End-of-session LLM judgement of important operations โ†’ long-term memory (default `on`) |
926
+ | `RIVET_MEMORY_CONSOLIDATION` | End-of-session summary + reusable procedures (default `on`) |
927
+ | `RIVET_MEMORY_BACKFILL` | Opt-in idle backfill of historical sessions (default `off`, idempotent ledger) |
928
+
929
+ > The full environment-variable list (120+ entries, including internal experimental switches) is in `src/config/env-registry.ts`.
930
+
931
+ ### Key `~/.rivet/config.json` Fields
932
+
933
+ Write only the fields you want to override; defaults are deep-merged. Full schema in `src/config/schema.ts`.
934
+
935
+ ```jsonc
936
+ {
937
+ "agent": {
938
+ "maxTurns": 200, // max turns per session
939
+ "approval": "auto-safe", // manual | auto-safe | dangerously-skip-permissions
940
+ "crossSessionEnabled": true, // cross-session knowledge sharing
941
+ "checkpointEveryTurns": 0, // Auto-mode checkpoint interval (0 = off)
942
+ "defaultDomain": "qiming", // default star domain (qiming/auto/explicit name)
943
+ "visionModel": { // vision bridge: describe images when the primary model is text-only
944
+ "provider": "minimax", // must have a key configured and declare supportsVision
945
+ "model": "MiniMax-M3"
946
+ },
947
+ "visionAutoBridge": false, // auto-pick a vision model when visionModel is unset (off by default)
948
+ "imageGenModel": { // text-to-image slot: register an endpoint, then call generate_image
949
+ "provider": "siliconflow-image", // registered separately โ€” provider.default stays untouched
950
+ "model": "black-forest-labs/FLUX.2-pro",
951
+ "size": "1024x1024", // default size (optional)
952
+ "sizeField": "image_size" // OpenAI sends size, SiliconFlow sends image_size (optional)
953
+ },
954
+ "permissions": { // permission rules (mirrors /permission commands)
955
+ "allow": [{ "tool": "read" }],
956
+ "deny": [{ "tool": "bash", "params": { "command": "rm -rf" } }],
957
+ "bash": { "allowlist": ["git status"], "denylist": ["git push"] }
958
+ }
959
+ },
960
+ "compact": {
961
+ "enabled": true,
962
+ "autoThreshold": 800000 // token threshold that triggers auto-compaction
963
+ },
964
+ "cache": {
965
+ "enabled": true, // master prefix-cache switch
966
+ "showHitRate": true // show hit rate in the GlanceBar
967
+ },
968
+ "tools": {
969
+ "preset": "frontend" // minimal | frontend (default) | full | taiyi
970
+ },
971
+ "workers": {
972
+ "profiles": { // custom worker model tiers
973
+ "capable": { "provider": "deepseek", "model": "deepseek-v4-pro" },
974
+ "cheap": { "provider": "minimax", "model": "MiniMax-M2.7" }
975
+ },
976
+ "routing": { "code_edit": "capable", "repo_summarization": "cheap" },
977
+ "patcherTier": "cheap" // Tianliang execution-worker default tier: cheap | balanced | strong
978
+ },
979
+ "search": {
980
+ "backends": ["bing", "duckduckgo"], // web_search backend chain (first hit wins)
981
+ "braveApiKeyEnv": "BRAVE_API_KEY" // env var name when using Brave
982
+ },
983
+ "ui": {
984
+ "theme": "auto", // builtin name | auto (OSC 11 detect) | custom:<name>
985
+ "reducedMotion": true, // a11y: freeze spinner/badge animations
986
+ "screenReader": true, // a11y: screen-reader mode (same as --screen-reader)
987
+ "glanceDensity": "compact" // GlanceBar density: compact | full
988
+ },
989
+ "mirrors": { "enabled": true, "preset": "china" }, // npm/github mirror acceleration
990
+ "env": { "extraPath": ["/usr/local/bin"] } // inject PATH (Windows git-bash, etc.)
991
+ }
992
+ ```
993
+
994
+ > Config layering priority: CLI flag > env var > project `.rivet-config.json` > user `~/.rivet/config.json` > built-in defaults.
995
+
996
+
997
+
998
+ ## ๐Ÿ“š Documentation
999
+
1000
+ | Doc | Description |
1001
+ |-----|-------------|
1002
+ | [`docs/user-guide.md`](docs/user-guide.md) | Install, configure, and usage guide |
1003
+ | [`docs/desktop-guide.md`](docs/desktop-guide.md) | Desktop user guide (Cockpit/SideChat/Rewind/themes/Mirror exclusives) |
1004
+ | [`docs/user-guide-provider-config.md`](docs/user-guide-provider-config.md) | Model provider configuration guide |
1005
+ | [`docs/user-guide-vision.md`](docs/user-guide-vision.md) | Vision channel: configuration and troubleshooting |
1006
+ | [`docs/user-guide-sandbox-permissions.md`](docs/user-guide-sandbox-permissions.md) | Full sandbox & permission model guide |
1007
+ | [`docs/reference/observability-harness.md`](docs/reference/observability-harness.md) | Observability harness: real-session data samples (cache / CVM / pheromones) with reproduction commands |
1008
+ | [`CONTRIBUTING.md`](CONTRIBUTING.md) | Contributing guide |
1009
+ | [`config.example.json`](config.example.json) | Example config (with sub-agent / review model routing) |
1010
+
1011
+ ## ๐Ÿค Community & Support
1012
+
1013
+ - **Usage questions / discussions** โ†’ [GitHub Discussions](https://github.com/huiliyi37/Tianshu-harness/discussions)
1014
+ - **Bug reports / feature requests** โ†’ [GitHub Issues](https://github.com/huiliyi37/Tianshu-harness/issues)
1015
+ - **Security vulnerabilities** โ†’ [Report privately](https://github.com/huiliyi37/Tianshu-harness/security/advisories/new) (do not open a public issue)
1016
+ - **Contributing** โ†’ See [CONTRIBUTING.md](CONTRIBUTING.md)
1017
+ - **Support guide** โ†’ See [SUPPORT.md](SUPPORT.md)
1018
+
1019
+ > Note: a maintainer needs to enable Discussions in `Settings โ†’ General โ†’ Discussions` first.
1020
+
1021
+ ## โ˜• Support
1022
+
1023
+ If Tianshu has been useful and you'd like to say thanks, you can. It stays a coffee, not a contract โ€” donations don't buy feature priority or change how issues get triaged.
1024
+
1025
+ - **China mainland** โ€” WeChat Pay (scan the QR code below)
1026
+
1027
+ <img src="docs/brand/assets/wechat-pay.jpg" width="240" alt="WeChat Pay">
1028
+
1029
+ ## โœจ Contributors
1030
+
1031
+ Thank you to everyone who has contributed to Tianshu (ordered by first contribution):
1032
+
1033
+ | Contributor | Contributions |
1034
+ |-------------|---------------|
1035
+ | [@banxia](https://github.com/banxia) | Project creator ยท Core development |
1036
+
1037
+ Full list (17 external contributors / 89 PRs) โ†’ CONTRIBUTORS.md.
1038
+
1039
+ External PRs land via a "port" flow; authorship is credited with `Co-authored-by`
1040
+ trailers (auto-recorded by scripts/credit-contributors.sh) โ€” contributor wall (full list in CONTRIBUTORS.md):
1041
+
1042
+ <p>
1043
+ <a href="https://github.com/HarriethWiKk"><img src="https://github.com/HarriethWiKk.png?size=100" width="50" height="50" alt="HarriethWiKk" title="HarriethWiKk" /></a>
1044
+ <a href="https://github.com/jiangsx496"><img src="https://github.com/jiangsx496.png?size=100" width="50" height="50" alt="jiangsx496" title="jiangsx496" /></a>
1045
+ <a href="https://github.com/yq04"><img src="https://github.com/yq04.png?size=100" width="50" height="50" alt="yq04" title="yq04" /></a>
1046
+ <a href="https://github.com/wangxx-yu"><img src="https://github.com/wangxx-yu.png?size=100" width="50" height="50" alt="wangxx-yu" title="wangxx-yu" /></a>
1047
+ <a href="https://github.com/qiaodier"><img src="https://github.com/qiaodier.png?size=100" width="50" height="50" alt="qiaodier" title="qiaodier" /></a>
1048
+ <a href="https://github.com/zhengbiaofeng"><img src="https://github.com/zhengbiaofeng.png?size=100" width="50" height="50" alt="zhengbiaofeng" title="zhengbiaofeng" /></a>
1049
+ <a href="https://github.com/LinHoMo"><img src="https://github.com/LinHoMo.png?size=100" width="50" height="50" alt="LinHoMo" title="LinHoMo" /></a>
1050
+ <a href="https://github.com/KinoGao"><img src="https://github.com/KinoGao.png?size=100" width="50" height="50" alt="KinoGao" title="KinoGao" /></a>
1051
+ <a href="https://github.com/liuwanwan1"><img src="https://github.com/liuwanwan1.png?size=100" width="50" height="50" alt="liuwanwan1" title="liuwanwan1" /></a>
1052
+ <a href="https://github.com/Eason412"><img src="https://github.com/Eason412.png?size=100" width="50" height="50" alt="Eason412" title="Eason412" /></a>
1053
+ <a href="https://github.com/maoqiu77"><img src="https://github.com/maoqiu77.png?size=100" width="50" height="50" alt="maoqiu77" title="maoqiu77" /></a>
1054
+ <a href="https://github.com/yeshilei-QWQ"><img src="https://github.com/yeshilei-QWQ.png?size=100" width="50" height="50" alt="yeshilei-QWQ" title="yeshilei-QWQ" /></a>
1055
+ <a href="https://github.com/lumos-tiamo"><img src="https://github.com/lumos-tiamo.png?size=100" width="50" height="50" alt="lumos-tiamo" title="lumos-tiamo" /></a>
1056
+ <a href="https://github.com/zzuu080603"><img src="https://github.com/zzuu080603.png?size=100" width="50" height="50" alt="zzuu080603" title="zzuu080603" /></a>
1057
+ <a href="https://github.com/nzz0991999-ai"><img src="https://github.com/nzz0991999-ai.png?size=100" width="50" height="50" alt="nzz0991999-ai" title="nzz0991999-ai" /></a>
1058
+ <a href="https://github.com/L4XB"><img src="https://github.com/L4XB.png?size=100" width="50" height="50" alt="L4XB" title="L4XB" /></a>
1059
+ <a href="https://github.com/Wanming08"><img src="https://github.com/Wanming08.png?size=100" width="50" height="50" alt="Wanming08" title="Wanming08" /></a>
1060
+ </p>
1061
+
1062
+ > Contributions are welcome โ€” see CONTRIBUTING.md.
1063
+
1064
+ ## License
1065
+
1066
+ Licensed under the [Apache License, Version 2.0](LICENSE). Copyright 2025-2026 Tianshu Contributors.