kiki-agent-lite 0.3.1 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (228) hide show
  1. package/README.md +13 -10
  2. package/dist/docs/en/configuration/config-files.md +63 -20
  3. package/dist/docs/en/configuration/data-locations.md +12 -4
  4. package/dist/docs/en/configuration/env-vars.md +4 -6
  5. package/dist/docs/en/configuration/overrides.md +13 -14
  6. package/dist/docs/en/configuration/providers.md +8 -6
  7. package/dist/docs/en/customization/agent-profiles.md +33 -38
  8. package/dist/docs/en/customization/agents.md +129 -107
  9. package/dist/docs/en/customization/hooks.md +41 -48
  10. package/dist/docs/en/customization/personas.md +19 -21
  11. package/dist/docs/en/customization/plugins.md +180 -156
  12. package/dist/docs/en/customization/prompt-fields.md +10 -6
  13. package/dist/docs/en/customization/skills.md +11 -13
  14. package/dist/docs/en/customization/skins.md +23 -27
  15. package/dist/docs/en/customization/themes.md +15 -15
  16. package/dist/docs/en/features/agents.md +85 -0
  17. package/dist/docs/en/features/daily.md +37 -7
  18. package/dist/docs/en/features/ecosystem.md +3 -1
  19. package/dist/docs/en/features/extend.md +7 -1
  20. package/dist/docs/en/features/freedom.md +4 -0
  21. package/dist/docs/en/features/index.md +6 -5
  22. package/dist/docs/en/features/long-work.md +23 -5
  23. package/dist/docs/en/features/look.md +1 -1
  24. package/dist/docs/en/features/people.md +10 -2
  25. package/dist/docs/en/features/spaces.md +16 -4
  26. package/dist/docs/en/features/workbench.md +11 -3
  27. package/dist/docs/en/getting-started/desktop-app.md +44 -29
  28. package/dist/docs/en/getting-started/first-launch.md +32 -21
  29. package/dist/docs/en/getting-started/installation.md +27 -12
  30. package/dist/docs/en/getting-started/use-cases.md +35 -35
  31. package/dist/docs/en/guides/goals.md +9 -7
  32. package/dist/docs/en/guides/interaction.md +26 -26
  33. package/dist/docs/en/guides/interface.md +18 -14
  34. package/dist/docs/en/guides/memory.md +43 -14
  35. package/dist/docs/en/guides/sessions.md +32 -26
  36. package/dist/docs/en/guides/settings.md +60 -29
  37. package/dist/docs/en/index.md +8 -2
  38. package/dist/docs/en/reference/command.md +8 -4
  39. package/dist/docs/en/reference/keyboard.md +18 -4
  40. package/dist/docs/en/reference/model-vocabulary.md +6 -8
  41. package/dist/docs/en/reference/slash-commands.md +4 -4
  42. package/dist/docs/en/reference/tools.md +92 -15
  43. package/dist/docs/en/release-notes/changelog.md +1 -9
  44. package/dist/docs/en/server/acp.md +1 -1
  45. package/dist/docs/en/server/ide.md +1 -1
  46. package/dist/docs/en/server/local-server.md +5 -5
  47. package/dist/docs/en/server/mcp.md +2 -2
  48. package/dist/docs/en/server/rest-api.md +79 -5
  49. package/dist/docs/en/server/sdk.md +2 -2
  50. package/dist/docs/zh/configuration/config-files.md +56 -15
  51. package/dist/docs/zh/configuration/data-locations.md +12 -4
  52. package/dist/docs/zh/configuration/env-vars.md +4 -6
  53. package/dist/docs/zh/configuration/overrides.md +13 -14
  54. package/dist/docs/zh/configuration/providers.md +7 -5
  55. package/dist/docs/zh/customization/agent-profiles.md +31 -36
  56. package/dist/docs/zh/customization/agents.md +120 -98
  57. package/dist/docs/zh/customization/hooks.md +35 -42
  58. package/dist/docs/zh/customization/personas.md +16 -18
  59. package/dist/docs/zh/customization/plugins.md +167 -142
  60. package/dist/docs/zh/customization/prompt-fields.md +9 -5
  61. package/dist/docs/zh/customization/skills.md +10 -12
  62. package/dist/docs/zh/customization/skins.md +19 -23
  63. package/dist/docs/zh/customization/themes.md +12 -12
  64. package/dist/docs/zh/features/agents.md +85 -0
  65. package/dist/docs/zh/features/daily.md +37 -7
  66. package/dist/docs/zh/features/ecosystem.md +3 -1
  67. package/dist/docs/zh/features/extend.md +7 -1
  68. package/dist/docs/zh/features/freedom.md +4 -0
  69. package/dist/docs/zh/features/index.md +6 -5
  70. package/dist/docs/zh/features/long-work.md +22 -4
  71. package/dist/docs/zh/features/look.md +1 -1
  72. package/dist/docs/zh/features/people.md +10 -2
  73. package/dist/docs/zh/features/spaces.md +15 -3
  74. package/dist/docs/zh/features/workbench.md +11 -3
  75. package/dist/docs/zh/getting-started/desktop-app.md +43 -28
  76. package/dist/docs/zh/getting-started/first-launch.md +32 -21
  77. package/dist/docs/zh/getting-started/installation.md +26 -11
  78. package/dist/docs/zh/getting-started/use-cases.md +35 -37
  79. package/dist/docs/zh/guides/goals.md +8 -8
  80. package/dist/docs/zh/guides/interaction.md +25 -25
  81. package/dist/docs/zh/guides/interface.md +18 -14
  82. package/dist/docs/zh/guides/memory.md +43 -14
  83. package/dist/docs/zh/guides/sessions.md +30 -24
  84. package/dist/docs/zh/guides/settings.md +54 -23
  85. package/dist/docs/zh/index.md +7 -1
  86. package/dist/docs/zh/reference/command.md +7 -3
  87. package/dist/docs/zh/reference/keyboard.md +18 -4
  88. package/dist/docs/zh/reference/model-vocabulary.md +6 -8
  89. package/dist/docs/zh/reference/slash-commands.md +3 -3
  90. package/dist/docs/zh/reference/tools.md +74 -9
  91. package/dist/docs/zh/release-notes/changelog.md +1 -9
  92. package/dist/docs/zh/server/acp.md +1 -1
  93. package/dist/docs/zh/server/ide.md +1 -1
  94. package/dist/docs/zh/server/local-server.md +5 -5
  95. package/dist/docs/zh/server/mcp.md +2 -2
  96. package/dist/docs/zh/server/rest-api.md +69 -1
  97. package/dist/docs/zh/server/sdk.md +2 -2
  98. package/dist/main.mjs +12545 -3456
  99. package/dist/web/assets/AppErrorBoundary-RFIAb-Uf.js +1 -0
  100. package/dist/web/assets/NavScopeBoundary-DY_ET7A-.js +1 -0
  101. package/dist/web/assets/{arc-y2SkSoyr.js → arc-CMgTB1m7.js} +1 -1
  102. package/dist/web/assets/{architectureDiagram-3BPJPVTR-uCwLz53m.js → architectureDiagram-3BPJPVTR-BU79ou2C.js} +1 -1
  103. package/dist/web/assets/{blockDiagram-GPEHLZMM-BZyWv36G.js → blockDiagram-GPEHLZMM-Bkuldod2.js} +1 -1
  104. package/dist/web/assets/{c4Diagram-AAUBKEIU-DKGx9i50.js → c4Diagram-AAUBKEIU-C3WMeqyu.js} +1 -1
  105. package/dist/web/assets/channel-DpDZUJRn.js +1 -0
  106. package/dist/web/assets/{chunk-2J33WTMH-CSkrhrsp.js → chunk-2J33WTMH-CesyWmwo.js} +1 -1
  107. package/dist/web/assets/{chunk-4BX2VUAB-CtxMoJ68.js → chunk-4BX2VUAB-C7rghYTf.js} +1 -1
  108. package/dist/web/assets/{chunk-55IACEB6-Dos3ftEy.js → chunk-55IACEB6-BqRHhwtz.js} +1 -1
  109. package/dist/web/assets/{chunk-727SXJPM-wbzEYK9z.js → chunk-727SXJPM-BhSqCRBc.js} +1 -1
  110. package/dist/web/assets/{chunk-AQP2D5EJ-B9GKvCD6.js → chunk-AQP2D5EJ-DdYE2ZVZ.js} +1 -1
  111. package/dist/web/assets/{chunk-FMBD7UC4-u5Y2P6IX.js → chunk-FMBD7UC4-BCRPUxDF.js} +1 -1
  112. package/dist/web/assets/{chunk-ND2GUHAM-B8rFKkTV.js → chunk-ND2GUHAM-CuvyDjTR.js} +1 -1
  113. package/dist/web/assets/{chunk-QZHKN3VN-EQsKtuD-.js → chunk-QZHKN3VN-BU5vAS78.js} +1 -1
  114. package/dist/web/assets/classDiagram-4FO5ZUOK-Bju1GfNu.js +1 -0
  115. package/dist/web/assets/classDiagram-v2-Q7XG4LA2-Bju1GfNu.js +1 -0
  116. package/dist/web/assets/client-C0oH7-8r.js +2 -0
  117. package/dist/web/assets/connection-BhO2nh7P.js +1 -0
  118. package/dist/web/assets/{cose-bilkent-S5V4N54A-D6dr5mIW.js → cose-bilkent-S5V4N54A-CXrvsA1a.js} +1 -1
  119. package/dist/web/assets/{dagre-BM42HDAG-Dnyhc4Hn.js → dagre-BM42HDAG-TaAea3Rt.js} +1 -1
  120. package/dist/web/assets/{diagram-2AECGRRQ-CYXkWdne.js → diagram-2AECGRRQ-CdEH4jGt.js} +1 -1
  121. package/dist/web/assets/{diagram-5GNKFQAL-DPwBf5Ag.js → diagram-5GNKFQAL-A0jZ_p-T.js} +1 -1
  122. package/dist/web/assets/{diagram-KO2AKTUF-DNeLYZ8X.js → diagram-KO2AKTUF-miHWORz3.js} +1 -1
  123. package/dist/web/assets/{diagram-LMA3HP47-zU8RsQTX.js → diagram-LMA3HP47-BlUIwEIg.js} +1 -1
  124. package/dist/web/assets/{diagram-OG6HWLK6-Cf9Mm94H.js → diagram-OG6HWLK6-DwDzMhEg.js} +1 -1
  125. package/dist/web/assets/{erDiagram-TEJ5UH35-Ch4CeiUI.js → erDiagram-TEJ5UH35-BJr5w62i.js} +1 -1
  126. package/dist/web/assets/export-BlxaZKEe.js +2 -0
  127. package/dist/web/assets/{flowDiagram-I6XJVG4X-Csn6WqEH.js → flowDiagram-I6XJVG4X-BP7KSFjx.js} +1 -1
  128. package/dist/web/assets/{ganttDiagram-6RSMTGT7-DsuBgEyu.js → ganttDiagram-6RSMTGT7-BstLBBof.js} +1 -1
  129. package/dist/web/assets/{gitGraphDiagram-PVQCEYII-CPA7jCxU.js → gitGraphDiagram-PVQCEYII-C57s7nZ-.js} +1 -1
  130. package/dist/web/assets/highlighted-body-OFNGDK62-BVb-7KsA.js +1 -0
  131. package/dist/web/assets/index-69qhvTvD.js +1 -0
  132. package/dist/web/assets/{index-BYUHmd8w.js → index-BDNM6yJI.js} +2 -2
  133. package/dist/web/assets/{index-BGgZxlEQ.js → index-BJF_gEDs.js} +2 -2
  134. package/dist/web/assets/index-BOwMP6BP.js +1 -0
  135. package/dist/web/assets/{index-C69a5Mcz.js → index-BZsyXCqm.js} +1 -1
  136. package/dist/web/assets/{index-C7EA7a_g.js → index-Bfl4JiNq.js} +2 -2
  137. package/dist/web/assets/index-BlD3AKX-.js +1 -0
  138. package/dist/web/assets/{index-CIymCfcP.js → index-BnvW0EvQ.js} +1 -1
  139. package/dist/web/assets/index-C4rmWyOm.js +1 -0
  140. package/dist/web/assets/index-CGLcb3HY.js +1 -0
  141. package/dist/web/assets/{index-kWBxPqIX.js → index-CPvOeQPX.js} +1 -1
  142. package/dist/web/assets/index-Cjbe0JKM.js +1 -0
  143. package/dist/web/assets/index-CmYoJWUm.js +1 -0
  144. package/dist/web/assets/index-CtUFrjKe.js +1 -0
  145. package/dist/web/assets/index-DDvDRMTK.js +1 -0
  146. package/dist/web/assets/index-DSpndwAR.css +1 -0
  147. package/dist/web/assets/index-D_JjTHxi.js +1 -0
  148. package/dist/web/assets/index-DbuwcnbT.js +1 -0
  149. package/dist/web/assets/index-DcXyS0nN.js +1 -0
  150. package/dist/web/assets/index-Dcl9ruKA.js +1 -0
  151. package/dist/web/assets/index-DgwALPNA.js +121 -0
  152. package/dist/web/assets/{index-DoN1FTEe.js → index-DkE8hRT1.js} +2 -2
  153. package/dist/web/assets/index-DsyRBZ4h.js +1 -0
  154. package/dist/web/assets/{index-29zav3JI.js → index-DuudNhLL.js} +4 -4
  155. package/dist/web/assets/index-Gc4F0b2f.js +1 -0
  156. package/dist/web/assets/index-HGqqwKoV.js +13 -0
  157. package/dist/web/assets/index-KchrJnno.js +3 -0
  158. package/dist/web/assets/{index-B0KNSyji.js → index-Tmi2BPYU.js} +1 -1
  159. package/dist/web/assets/index-Ya4GuDs0.js +1 -0
  160. package/dist/web/assets/index-_aDaKqLB.js +1 -0
  161. package/dist/web/assets/index-_qwOAotB.js +1 -0
  162. package/dist/web/assets/index-hnIkczza.js +7 -0
  163. package/dist/web/assets/{infoDiagram-5YYISTIA-D3Q__m62.js → infoDiagram-5YYISTIA-CifuVY6C.js} +1 -1
  164. package/dist/web/assets/{ishikawaDiagram-YF4QCWOH-CcvCBuZ5.js → ishikawaDiagram-YF4QCWOH-Cd60vQUi.js} +1 -1
  165. package/dist/web/assets/{journeyDiagram-JHISSGLW-COZU4LNt.js → journeyDiagram-JHISSGLW-Cb3Xl_wl.js} +1 -1
  166. package/dist/web/assets/{kanban-definition-UN3LZRKU-BrXjBoAU.js → kanban-definition-UN3LZRKU-Ei6ThuZt.js} +1 -1
  167. package/dist/web/assets/{linear-BgP1STFi.js → linear-CDZJx-o2.js} +1 -1
  168. package/dist/web/assets/mermaid-GHXKKRXX-DFxyxD7G.js +331 -0
  169. package/dist/web/assets/{mindmap-definition-RKZ34NQL-CgjSrE5r.js → mindmap-definition-RKZ34NQL-B0ygxzkx.js} +1 -1
  170. package/dist/web/assets/navViewState-Ck_HK-TK.js +1 -0
  171. package/dist/web/assets/{pieDiagram-4H26LBE5-DTfe1sKA.js → pieDiagram-4H26LBE5-B2FdrvDv.js} +1 -1
  172. package/dist/web/assets/{quadrantDiagram-W4KKPZXB-D95hfh0q.js → quadrantDiagram-W4KKPZXB-CwpOTy3d.js} +1 -1
  173. package/dist/web/assets/{requirementDiagram-4Y6WPE33-DtSLi7Mh.js → requirementDiagram-4Y6WPE33-ExdZNzLQ.js} +1 -1
  174. package/dist/web/assets/{sankeyDiagram-5OEKKPKP-gi_dJpcU.js → sankeyDiagram-5OEKKPKP-u0EZKD7D.js} +1 -1
  175. package/dist/web/assets/{sequenceDiagram-3UESZ5HK-DKQ9a72t.js → sequenceDiagram-3UESZ5HK-BXHMy5DY.js} +1 -1
  176. package/dist/web/assets/{spaces-B2Ccyh_T.js → spaces-C8n7xQPx.js} +1 -1
  177. package/dist/web/assets/{stateDiagram-AJRCARHV-Bz7tmSqa.js → stateDiagram-AJRCARHV-DMXx7ell.js} +1 -1
  178. package/dist/web/assets/stateDiagram-v2-BHNVJYJU-Bydq1_By.js +1 -0
  179. package/dist/web/assets/theme-BBnHttAf.js +1 -0
  180. package/dist/web/assets/{timeline-definition-PNZ67QCA-BfMXPwhV.js → timeline-definition-PNZ67QCA-DtqVG_4u.js} +1 -1
  181. package/dist/web/assets/{vennDiagram-CIIHVFJN-WLxW2KT5.js → vennDiagram-CIIHVFJN-Dom0ex8r.js} +1 -1
  182. package/dist/web/assets/{wardley-L42UT6IY-DiiqwIdq.js → wardley-L42UT6IY-C-RstmuQ.js} +1 -1
  183. package/dist/web/assets/{wardleyDiagram-YWT4CUSO-DmCukWuw.js → wardleyDiagram-YWT4CUSO-C8CzNfdf.js} +1 -1
  184. package/dist/web/assets/{xychartDiagram-2RQKCTM6-Cfq1W2tT.js → xychartDiagram-2RQKCTM6-1AxVTyB6.js} +1 -1
  185. package/dist/web/index.html +2 -2
  186. package/native/auth-native/prebuilds/linux-arm64/auth-native.node +0 -0
  187. package/native/auth-native/prebuilds/linux-x64/auth-native.node +0 -0
  188. package/native/auth-native/prebuilds/win32-arm64/auth-native.node +0 -0
  189. package/native/auth-native/prebuilds/win32-x64/auth-native.node +0 -0
  190. package/package.json +1 -1
  191. package/dist/web/assets/AppErrorBoundary-DWpgwxFV.js +0 -1
  192. package/dist/web/assets/NavScopeBoundary-D8Lf1G0U.js +0 -1
  193. package/dist/web/assets/channel-BGdXootG.js +0 -1
  194. package/dist/web/assets/classDiagram-4FO5ZUOK-CPcnLy_H.js +0 -1
  195. package/dist/web/assets/classDiagram-v2-Q7XG4LA2-CPcnLy_H.js +0 -1
  196. package/dist/web/assets/client-DSIbyfoz.js +0 -2
  197. package/dist/web/assets/connection-DYZn9oPZ.js +0 -1
  198. package/dist/web/assets/export-Bq8ZECqX.js +0 -2
  199. package/dist/web/assets/highlighted-body-OFNGDK62-CDPBxM_E.js +0 -1
  200. package/dist/web/assets/index-AksnytJj.js +0 -1
  201. package/dist/web/assets/index-B8xhhYDh.css +0 -1
  202. package/dist/web/assets/index-BUrlrKap.js +0 -1
  203. package/dist/web/assets/index-B_5-HLed.js +0 -62
  204. package/dist/web/assets/index-BfmoxdpP.js +0 -1
  205. package/dist/web/assets/index-Bo3e-ohM.js +0 -3
  206. package/dist/web/assets/index-BrYV9gV_.js +0 -1
  207. package/dist/web/assets/index-C8XUtAvK.js +0 -1
  208. package/dist/web/assets/index-C9uil5my.js +0 -13
  209. package/dist/web/assets/index-CKpWHSp9.js +0 -1
  210. package/dist/web/assets/index-CLKBgQxV.js +0 -1
  211. package/dist/web/assets/index-CTyyUNWj.js +0 -7
  212. package/dist/web/assets/index-D7cg9qYZ.js +0 -1
  213. package/dist/web/assets/index-D7dg8R_q.js +0 -1
  214. package/dist/web/assets/index-DCSpedV_.js +0 -1
  215. package/dist/web/assets/index-DLbD0Nx5.js +0 -1
  216. package/dist/web/assets/index-DaEzbvvu.js +0 -1
  217. package/dist/web/assets/index-DhbcjMZF.js +0 -1
  218. package/dist/web/assets/index-Dw2h88mF.js +0 -1
  219. package/dist/web/assets/index-FcMtfmKv.js +0 -1
  220. package/dist/web/assets/index-XFq9Kgg0.js +0 -1
  221. package/dist/web/assets/index-iI2mM43w.js +0 -1
  222. package/dist/web/assets/index-oXOF7lko.js +0 -1
  223. package/dist/web/assets/locale-CANfezJ4.js +0 -17
  224. package/dist/web/assets/mermaid-GHXKKRXX-_JLagMll.js +0 -321
  225. package/dist/web/assets/navViewState-DS5LnMYc.js +0 -1
  226. package/dist/web/assets/settings-CcwMWXbp.js +0 -42
  227. package/dist/web/assets/stateDiagram-v2-BHNVJYJU-D6-wdUbw.js +0 -1
  228. package/dist/web/assets/theme-DlDhDxeD.js +0 -1
@@ -1,10 +1,10 @@
1
1
  # Hooks
2
2
 
3
- Hooks subscribe to engine events. Declarative v2 rules add guidance or observe events without running a process; legacy hooks run local shell commands. Typical use cases:
3
+ Hooks react to engine events. A declarative (v2) rule adds guidance or watches an event without running anything; a legacy hook runs a local shell command. Common uses:
4
4
 
5
- - **Security interception**: Before the Agent executes a shell command, check whether it contains dangerous operations (such as `rm -rf`) and block execution if so
6
- - **Desktop notifications**: When a background task completes, pop up a system notification to bring you back to review the results
7
- - **Automatic checks**: Each time the user submits a message, automatically append some background information to the context (such as the current Git branch)
5
+ - **Blocking something risky**: check a shell command for `rm -rf` before it runs and block it
6
+ - **Desktop notifications**: pop up a system notification when a background task finishes
7
+ - **Adding context**: append something the model should always see, such as the current Git branch, to every submitted message
8
8
 
9
9
  ## Declarative rules (v2)
10
10
 
@@ -34,56 +34,49 @@ type = "inject"
34
34
  text = "Check the goal, existing evidence, and next action before continuing."
35
35
  ```
36
36
 
37
- A step is one committed model response with all its tool results settled, not one tool call or retry attempt. After five such steps, the reminder appears before the next model request. If the fifth step ends the turn, no extra turn is created: delivery waits for the next request on that model. Counts belong to each agent and canonical model configuration identity, so switching A → B → A preserves A's count. `counter_scope = "turn"` instead clears the count at the next turn. Recovery, compaction, and undo do not rewind counts or replay delivered reminders. Changing the matcher or cadence starts a new semantic revision at zero; changing only the text uses the new text at the next milestone.
37
+ A step is one committed model response with all its tool results settled, not one tool call. After five such steps the reminder is injected before the next model request; if the fifth step ended the turn, it waits for the next request on that model rather than starting one. Counts belong to each agent and canonical model identity, so switching A → B → A keeps A's count, and `counter_scope = "turn"` clears it at the next turn instead. Recovery, compaction and undo neither rewind counts nor replay a reminder; changing the matcher or cadence starts a new count at zero, while changing only the text uses the new text at the next milestone.
38
38
 
39
- The current v2 implementation accepts only `inject` and `observe`. `inject` is available on `step.before` and `prompt.submit`; `observe` is available on those events plus `step.after`, `tool.before`, `tool.after`, `turn.stopping`, `turn.after`, and `session.start`. Cadence is limited to step events. An observer records metadata without changing the operation. V2 `command`, `block`, `gate`, and `continue` actions are rejected during loading; script automation remains on the legacy contract below.
39
+ Only `inject` and `observe` exist today. `inject` works on `step.before` and `prompt.submit`; `observe` works on those plus `step.after`, `tool.before`, `tool.after`, `turn.stopping`, `turn.after` and `session.start`, and only records metadata. Cadence applies to step events. Writing `command`, `block`, `gate` or `continue` is rejected at load time — those are the legacy contract below.
40
40
 
41
41
  ### Sources and matching
42
42
 
43
- Rules combine across user configuration, a trusted project's `.kiki/hooks.toml`, and enabled plugin manifests. They receive distinct IDs such as `user/evidence-check`, `workspace/check`, and `plugin/example/check`. Lower `priority` runs first, with the qualified ID breaking ties. There is no model-over-profile override chain. Duplicate IDs within one namespace are errors; the same short ID in different namespaces is allowed. Untrusted project rules remain visible but inactive, including text-only rules.
43
+ Rules combine from your user configuration, a trusted project's `.kiki/hooks.toml`, and enabled plugin manifests, and each gets a qualified id such as `user/evidence-check` or `workspace/check`. Lower `priority` runs first, with the qualified id breaking ties. A duplicate id inside one namespace is an error; the same short id in different namespaces is fine. Rules from an untrusted project stay visible but inactive, text-only ones included.
44
44
 
45
- `match.models`, `profiles`, `routes`, `executors`, and `agent_roles` use exact values. Different fields must all match; values within one field are alternatives; omitted fields are unrestricted. Model aliases resolve at loading, so a misspelled alias is diagnosed before the first request. Tool names use `match.tools`; tool outcomes use `match.statuses` (`success`, `error`, `cancelled`, `denied`). `prompt.submit` defaults to `source = user`; select other sources explicitly with `match.sources`. External executors without native step/tool interception are reported as unsupported by inspection rather than simulated from tool counts.
45
+ `match.models`, `profiles`, `routes`, `executors` and `agent_roles` take exact values: every field you write must match, several values in one field are alternatives, and an omitted field is unrestricted. Model aliases resolve at load time, so a typo shows up before the first request. Tool names go in `match.tools` and outcomes in `match.statuses` (`success`, `error`, `cancelled`, `denied`). `prompt.submit` defaults to `source = user`; name other sources in `match.sources`. An external executor without native step or tool interception is reported as unsupported rather than approximated from tool counts.
46
46
 
47
- Long guidance can use `text_file = "reminders/check.md"` instead of `text`; the two are mutually exclusive. `[hooks] files = ["hooks.toml"]` includes other v2 documents. Paths are relative to the declaring file and must remain inside its source scope after realpath resolution. Includes cannot be URLs, cyclic, or repeated. Missing files, empty text, unsupported actions, invalid cadence, and injections exceeding the 8 KiB UTF-8 budget are load-time diagnostics. Guidance is source-labelled conversation context, not a replacement system prompt, and cannot override higher-priority instructions.
47
+ Long guidance can point at a file with `text_file = "reminders/check.md"` instead of `text` — the two are mutually exclusive — and `[hooks] files = ["hooks.toml"]` pulls in other v2 documents. Paths are relative to the declaring file and must stay inside its source scope once resolved. Includes cannot be URLs, repeat, or form a cycle. A missing file, empty text, unsupported action, invalid cadence or an injection over 8 KiB is a load-time diagnostic. Injected guidance is labelled conversation context: it does not replace the system prompt and cannot override higher-priority instructions.
48
48
 
49
- Set a rule's `enabled = false` to disable it. The user section can disable qualified IDs from any source with `disabled = ["workspace/check"]`, or disable all v2 rules with `enabled = false`. Project and plugin declarations can disable only their own rules. Changes take effect at the next safe event boundary; the current event keeps its snapshot.
49
+ Set `enabled = false` on a rule to disable it. The user section can disable qualified ids from any source with `disabled = ["workspace/check"]`, or turn off all v2 rules with `enabled = false`; project and plugin declarations can only disable their own. Changes take effect at the next safe event boundary.
50
50
 
51
51
  ### Inspecting effective rules
52
52
 
53
- The engine's contributed command `hooks-inspect` reports source, activation or failure reason, execution order, binding, semantic revision, completed counts, and the next due count. Invoke it through the existing client command API:
53
+ The `hooks-inspect` command reports each rule's source, why it is active or not, execution order, binding, count so far, and the count due next:
54
54
 
55
55
  ```ts
56
56
  await klient.session(sessionId).agent("main").runCommand({ name: "hooks-inspect" });
57
57
  ```
58
58
 
59
- The result is a `hook.result` diagnostic event (`hookEvent = "hooks.inspect"`); it is not appended to the model's conversation. In the GUI, open **Hooks** in the session's agent panel to see effective rules, source paths, inactive reasons, and cadence counts. This view uses `GET /api/sessions/{session_id}/agents/{agent_id}/hooks`; saving a setting does not prove that its rules are active in that session.
59
+ The result is a `hook.result` diagnostic event (`hookEvent = "hooks.inspect"`) and is not added to the model's conversation. In the GUI, **Automatic rules** in the session's agent panel shows the same information, reading `GET /api/sessions/{session_id}/agents/{agent_id}/hooks` — a rule that saved successfully can still be inactive in a given session, and this is where you see why. With no rules configured and no source to repair, the panel shows no block at all.
60
60
 
61
- To edit the user configuration, open **Settings → Capabilities → Hooks** (`/settings/hooks`). Select a declarative or command rule to edit it, or use **Advanced: edit JSON** for the complete legacy array or v2 object. Adding the first declarative rule explicitly switches a legacy array to v2 and preserves commands in `legacy`; opening or saving the page never runs those commands. **Save actions** validates the whole hooks value and displays the server's saved values. A failed save keeps your draft. The v2 enable switch and disabled IDs affect declarative rules only, not command rules.
61
+ **Settings → Capabilities → Hooks** (`/settings/hooks`) edits the user configuration. Pick a rule to edit it, or use **Advanced: edit JSON** for the whole legacy array or v2 object. Adding the first declarative rule switches a legacy array to v2 and keeps the commands under `legacy`; opening or saving that page never runs them. **Save actions** validates the entire hooks value and shows what the server stored, and a failed save keeps your draft. The v2 enable switch and disabled ids affect declarative rules only.
62
62
 
63
- TOML cannot declare both `[[hooks]]` and `[hooks]` under the same key. Existing arrays continue unchanged. To keep legacy commands in a v2 document, move those entries explicitly to `[[hooks.legacy]]`, preserving their `event`, `matcher`, `command`, and seconds-based `timeout`. They still use the legacy runner and output protocol; no automatic migration or script-protocol conversion occurs.
63
+ TOML cannot declare both `[[hooks]]` and `[hooks]` under the same key, and an existing array keeps working as it is. To keep legacy commands inside a v2 document, move them explicitly to `[[hooks.legacy]]`, keeping their `event`, `matcher`, `command` and seconds-based `timeout`; they still run under the legacy runner and output protocol.
64
64
 
65
- ## How Hooks Work
65
+ ## Legacy command hooks
66
66
 
67
- The remaining sections describe the legacy command contract, not v2 declarative rules.
67
+ Everything below describes the legacy contract: a rule names an event, targets to match, and a shell command to run.
68
68
 
69
- Configuring a hook rule requires specifying three things: **which event to trigger on**, **which targets to match**, and **which script to run**.
69
+ On a match, the CLI passes the event details as JSON on **standard input** (stdin) — the trigger reason, tool name, command text and so on — and your script decides what to do. Its **exit code** carries the decision (`0` allows) and **standard output** (stdout) can carry explanation.
70
70
 
71
- When triggered, the CLI packages the event's details (trigger reason, tool name, command content, etc.) into JSON and passes it to your script via **standard input** (stdin). The script reads this information and decides how to respond.
72
-
73
- The script's response is determined by two things:
74
-
75
- - **Exit code**: `0` means allow; non-zero values block a blocking event, while observation-only events continue.
76
- - **Standard output** (stdout): can include explanatory text.
77
-
78
- Blocking events fail closed when a script fails or times out: the pending operation stops with a reason. Observation-only events do not interrupt the main flow. The [return-value table](#return-values) explains both cases.
71
+ A blocking event fails closed when the script fails or times out: the pending operation stops with a reason. An observation-only event never interrupts the main flow. The [return-value table](#return-values) covers both.
79
72
 
80
73
  ::: warning Note
81
- Hooks supplement permissions; they are not an operating-system sandbox and cannot approve a tool on the user's behalf. Keep permission checks and manual confirmation for high-risk operations.
74
+ A hook supplements permission rules; it is not an operating-system sandbox and cannot approve a tool for you. Keep permission checks and manual confirmation in place for anything high-risk.
82
75
  :::
83
76
 
84
- ## Quick Start: A Minimal Hook
77
+ ## A minimal hook
85
78
 
86
- The following hook flashes a notification in the terminal title bar each time a background task completes (macOS requires `terminal-notifier` to be installed):
79
+ This flashes a notification in the terminal title bar when a background task completes (macOS needs `terminal-notifier` installed):
87
80
 
88
81
  ```toml
89
82
  # Written in ~/.kiki/config.toml
@@ -95,13 +88,13 @@ command = "terminal-notifier -title Kimi -message 'Task done'"
95
88
 
96
89
  Save the config, start a new session, and a notification will appear the next time a background task completes.
97
90
 
98
- ## Configuration
91
+ ## Legacy rule fields
99
92
 
100
- All hook rules are written in the `[[hooks]]` array in `~/.kiki/config.toml`, where each entry is one rule:
93
+ Each legacy rule is one entry in the `[[hooks]]` array in `~/.kiki/config.toml`:
101
94
 
102
95
  | Field | Type | Required | Description |
103
96
  | --- | --- | --- | --- |
104
- | `event` | `string` | Yes | Trigger event name; must be one of the entries in the "Event Reference" table below |
97
+ | `event` | `string` | Yes | Trigger event name; must be one of the entries in the event reference below |
105
98
  | `matcher` | `string` | No | A regular expression to filter event targets; if omitted, matches all |
106
99
  | `command` | `string` | Yes | The shell command to run when triggered |
107
100
  | `timeout` | `integer` | No | Timeout in seconds, range 1–600; defaults to 30 seconds |
@@ -112,9 +105,9 @@ All hook rules are written in the `[[hooks]]` array in `~/.kiki/config.toml`, wh
112
105
 
113
106
  The working directory for hook commands is the current session's project directory. On non-Windows platforms, hook processes are placed in a separate process group; on timeout, a signal is sent first to give the process a chance to clean up, then it is forcibly terminated.
114
107
 
115
- ### Event Data Format
108
+ ### Event data format
116
109
 
117
- Each time a hook triggers, the CLI passes the following base information to the script via stdin:
110
+ Each time a hook triggers, the CLI passes this base information to the script on stdin:
118
111
 
119
112
  ```json
120
113
  {
@@ -126,11 +119,11 @@ Each time a hook triggers, the CLI passes the following base information to the
126
119
  }
127
120
  ```
128
121
 
129
- Specific events will also include additional fields (such as tool name and command content); see the event reference below. All field names use snake_case.
122
+ Individual events add their own fields (tool name, command text, and so on); see the event reference below. All field names are snake_case.
130
123
 
131
- ## Return Values
124
+ ## Return values
132
125
 
133
- After the script exits, the CLI determines the hook's intent based on the exit code:
126
+ After the script exits, the CLI reads its intent from the exit code:
134
127
 
135
128
  | Exit code | Meaning | CLI behavior |
136
129
  | --- | --- | --- |
@@ -141,11 +134,11 @@ After the script exits, the CLI determines the hook's intent based on the exit c
141
134
 
142
135
  ### JSON protocol detection
143
136
 
144
- For exit code `0`, the CLI classifies stdout using these rules:
137
+ For exit code `0`, the CLI classifies stdout like this:
145
138
 
146
- - **Valid JSON**: The CLI recursively checks objects and arrays. If an object at any depth contains its own `message` or `hookSpecificOutput` key, the output is a protocol attempt and the top-level value must match the strict hook response object. A different top-level shape or invalid protocol field blocks a blocking event. JSON with neither key remains unstructured output and is allowed.
147
- - **Malformed object text**: Object-shaped text is a protocol attempt only when it contains a recognizable exact `message` or `hookSpecificOutput` key. Text starting with `[` is considered array-shaped only when its first non-whitespace character is a JSON value starter, so `[INFO]` and `[DEBUG]` logs stay unstructured. The key check recognizes common errors such as single-quoted keys, missing separators, and a missing colon before a value without treating prefixes such as `messageCount` as protocol keys. A recognized malformed attempt blocks a blocking event.
148
- - **Residual ambiguous text**: Malformed text without a recognizable exact protocol key cannot be reliably distinguished from ordinary logs, so it remains unstructured output and is allowed. This includes logs such as `[INFO] response contains "message": metadata`.
139
+ - **Valid JSON** is walked recursively. If any object at any depth has its own `message` or `hookSpecificOutput` key, the output counts as a protocol attempt and the top-level value must match the strict hook response object — a different top-level shape or an invalid protocol field blocks a blocking event. JSON with neither key stays unstructured and is allowed.
140
+ - **Malformed object text** counts as a protocol attempt only when it contains a recognizable exact `message` or `hookSpecificOutput` key. Text starting with `[` is treated as array-shaped only when its first non-whitespace character could start a JSON value, so `[INFO]` and `[DEBUG]` logs stay unstructured. Single-quoted keys, missing separators and a missing colon are recognized as mistakes, while a prefix such as `messageCount` is not treated as a protocol key. A recognized malformed attempt blocks a blocking event.
141
+ - **Everything else** — malformed text with no recognizable protocol key, such as a log line quoting the word "message" — stays unstructured and is allowed, because it cannot be told apart from an ordinary log.
149
142
 
150
143
  You can also return a JSON object via stdout to block:
151
144
 
@@ -158,11 +151,11 @@ You can also return a JSON object via stdout to block:
158
151
  }
159
152
  ```
160
153
 
161
- ::: info Which events support blocking?
162
- Only **blockable events** (`PreToolUse`, `Stop`, `UserPromptSubmit`) have return values that affect the main flow. All other events are **observation-only events** — they fire and forget; the main flow is unaffected regardless of what the script returns.
154
+ ::: info Which events can block?
155
+ Only `PreToolUse`, `Stop` and `UserPromptSubmit` have return values that affect the main flow. Every other event is observation-only — it fires and the main flow continues whatever the script returns.
163
156
  :::
164
157
 
165
- ## Event Reference
158
+ ## Event reference
166
159
 
167
160
  | Event | Matcher matches | Supports blocking? | Description |
168
161
  | --- | --- | --- | --- |
@@ -187,7 +180,7 @@ Only **blockable events** (`PreToolUse`, `Stop`, `UserPromptSubmit`) have return
187
180
  | `PostCompact` | `manual` or `auto` | — | Triggered after context compaction completes (observation only) |
188
181
  | `Notification` | Notification type (e.g. `task.completed`) | — | Triggered when a background task status changes (observation only) |
189
182
 
190
- ## Example: Blocking Dangerous Shell Commands
183
+ ## Example: blocking a dangerous shell command
191
184
 
192
185
  The following hook checks the command content before the Agent calls the `Bash` tool and blocks it if `rm -rf` is detected:
193
186
 
@@ -217,13 +210,13 @@ process.stdin.on('end', () => {
217
210
  });
218
211
  ```
219
212
 
220
- After blocking, Kiki writes the blocking reason back into the context, and the model can use this to choose a safer alternative.
213
+ After blocking, Kiki writes the reason back into the context, so the model can pick a safer alternative.
221
214
 
222
215
  ::: warning Note
223
- This example only demonstrates the blocking mechanism — it is not a production-grade security parser. Real scenarios are better served by whitelists, or a dedicated shell parser to handle quoting, variable expansion, and multi-command sequences.
216
+ This example shows how blocking works; matching on a substring is not a security parser. For real protection, allowlist the commands you permit or use a shell parser that understands quoting, variable expansion and command chaining.
224
217
  :::
225
218
 
226
219
  ## Next steps
227
220
 
228
- - [Configuration](#configuration) — Full field reference for `[[hooks]]` in `config.toml`
229
- - [Agents and sub-agents](./agents.md) — Use the `SubagentStop` event to trigger notifications after a sub-agent completes
221
+ - [Legacy rule fields](#legacy-rule-fields) — the full `[[hooks]]` field reference
222
+ - [Agents and sub-agents](./agents.md) — use the `SubagentStop` event to notify when a sub-agent finishes
@@ -1,8 +1,6 @@
1
1
  # Personas, Bots, and rooms
2
2
 
3
- A **persona** keeps an identity and its memories across conversations, and gives it a stable address you can come back to. A [profile](./agent-profiles.md) still controls tools, permissions, model, and execution. A **Bot** is the persistent conversation behind a persona — the address a scheduled prompt, another persona, or a room reaches — while a **room** lets several personas discuss a topic in separate member sessions.
4
-
5
- A persona is a long-term identity; a profile is execution configuration. They answer different questions — who this is and what it remembers, versus which tools it may call, what model and effort it runs on, and the prompt it starts from. A persona card names the profile it rides on and you can rebind that profile without losing the identity, but the two are not two names for the same thing.
3
+ A **persona** is an identity that keeps its memory across conversations and has a stable address you can come back to. Its [profile](./agent-profiles.md) controls tools, permissions, model and execution — the persona answers "who this is and what it remembers", the profile answers "what it can call and how it runs", and rebinding the profile leaves the identity intact. A **bot** is the persistent conversation behind a persona, reachable by a scheduled prompt, another persona or a room; a **room** lets several personas discuss a topic in separate member sessions.
6
4
 
7
5
  ## Start with a persona
8
6
 
@@ -22,7 +20,7 @@ You coordinate release preparation. Ask for missing evidence and distinguish
22
20
  confirmed facts from open questions.
23
21
  ```
24
22
 
25
- The directory name is the stable ID: lowercase letters, digits, and single hyphens between words. The Markdown body supplies the identity. Optional `model_alias` and `thinking_effort` select a configured model and effort; they do not grant permissions. Fields such as `tools` are rejected because permissions belong to the profile.
23
+ The directory name is the stable ID: lowercase letters, digits, and single hyphens between words. The Markdown body supplies the identity. Optional `model_alias` and `thinking_effort` pick a configured model and effort; they grant no permissions, and fields such as `tools` are rejected because permissions belong to the profile.
26
24
 
27
25
  Choose the persona when creating a GUI session, or start it from the terminal:
28
26
 
@@ -30,25 +28,25 @@ Choose the persona when creating a GUI session, or start it from the terminal:
30
28
  kiki --persona release-guide
31
29
  ```
32
30
 
33
- Every persona also has a fixed daily conversation: the same entry the sidebar row, the switcher, the session header, and the persona page all point at. Clicking a persona's name lands you in that one conversation, so "ask this persona" means the same thing every time. A persona can hold several conversations at once and you switch between them from its conversation list, so one identity can work across projects. The terminal equivalent is `/persona switch release-guide`, which opens a **new** session and leaves the previous conversation intact.
31
+ Every persona has one **daily conversation** — the same entry the sidebar row, the switcher, the session header and the persona page all open — so "ask this persona" always means the same conversation. A persona can hold several at once; switch between them from its conversation list. In the terminal, `/persona switch release-guide` opens a **new** session and leaves the previous conversation alone. `/persona list` shows the catalog.
34
32
 
35
- In the TUI, `/persona list` lists the catalog. Explicit model selection overrides the persona's model; otherwise Kiki uses the persona's model before the profile or default model. An explicitly selected profile overrides the persona's profile without discarding the identity.
33
+ An explicit model selection beats the persona's model; otherwise Kiki uses the persona's model before the profile's or the default. An explicitly selected profile replaces the persona's profile without discarding the identity.
36
34
 
37
- Each session freezes its persona snapshot. Editing a card does not silently change an ongoing conversation's system prompt; start a new session or rebuild its context to apply the edit. The opening greeting is local presentation until you explicitly reply to it; merely opening a conversation does not add the greeting to model history.
35
+ Each session freezes its persona snapshot, so editing a card does not change an ongoing conversation — start a new session or rebuild its context. The opening greeting is local until you reply to it; opening a conversation does not put it in the model's history.
38
36
 
39
37
  ## Memory and character cards
40
38
 
41
- Persona memory follows the persona across profiles and models. Persona-specific entries are isolated from other personas; by default the persona can also read shared global and workspace memory. Set `memory.shared: []` to exclude those shared memories. The memory page provides persona and persona-workspace scopes, including the namespaces the home conversation uses; see [Memory](../guides/memory.md) for the full memory management model, the review inbox, and the undoable change history. Deleting a persona also removes its persona namespaces. If memory cleanup fails, deletion reports the error and retains the card for retry.
39
+ Persona memory follows the persona across profiles and models. Persona-specific entries are isolated from other personas, and by default the persona can also read shared global and workspace memory — set `memory.shared: []` to exclude those. The memory page offers persona and persona-workspace scopes; [Memory](../guides/memory.md) covers the model, the review inbox and the undoable history. Deleting a persona removes its namespaces, and if that cleanup fails the deletion reports the error and keeps the card so you can retry.
42
40
 
43
- The Personas page supports Character Card V3 JSON, PNG, and CHARX import/export. Preview an import before saving it: card lorebook entries can become persona memory, which influences later model requests. Unknown card extensions are preserved on export; keep the original card if it contains binary assets other than its avatar, because those assets are not fully retained. The avatar picker accepts PNG, JPEG, and WebP originals up to 20 MB, then uploads a 256-pixel crop. Choose a circle or square frame; the saved shape survives reloads. **Remove avatar** restores the initials without deleting the persona or its memories. Direct API uploads remain limited to 2 MiB. Duplicate creates a new identity without copying conversation state or private memory; archive hides a persona from ordinary selection without erasing it.
41
+ The Personas page imports and exports Character Card V3 in JSON, PNG and CHARX. Preview an import before saving: lorebook entries can become persona memory and therefore influence later model requests. Unknown card extensions survive an export, but binary assets other than the avatar are not fully retained, so keep the original if it has them. The avatar picker accepts PNG, JPEG and WebP up to 20 MB and uploads a 256-pixel crop in a circle or square frame that survives reloads. **Remove avatar** restores the initials without deleting the persona or its memories. Direct API uploads are still limited to 2 MiB. **Duplicate** creates a new identity without copying conversation state or private memory, and **archive** hides a persona from ordinary selection without erasing it.
44
42
 
45
- Saved persona files are limited to 1 MiB for `persona.md` and 256 KiB each for examples and extensions, measured as UTF-8 bytes. Saving or importing oversized content fails before changing the card or its memory; shorten the content and try again. An older invalid or oversized card can still be replaced through `PUT /api/personas/{id}` or deleted through `DELETE /api/personas/{id}`; deletion still removes its persona memory first.
43
+ Saved persona files are capped at 1 MiB for `persona.md` and 256 KiB each for examples and extensions, measured in UTF-8 bytes. Oversized content fails before the card or its memory changes, so shorten it and try again. An older invalid or oversized card can still be replaced with `PUT /api/personas/{id}` or removed with `DELETE /api/personas/{id}`, which removes its memory first.
46
44
 
47
45
  ## The persistent conversation
48
46
 
49
- A persona is reachable at a stable address whether or not you have typed to it. Its **daily conversation** is that address: the sidebar row, the switcher, the session header, and the persona page all open the same one, and the persona page lists the persona's other conversations so you can move the daily entry to another of them. Opening it for the first time creates it.
47
+ A persona is reachable whether or not you have typed to it. Its **daily conversation** is that address: the sidebar row, the switcher, the session header and the persona page all open the same one, and the persona page lists the others so you can move the daily entry to a different conversation. Opening it for the first time creates it.
50
48
 
51
- The same conversation is what a scheduled prompt, a message from another persona, and a room seat address — there is no second copy of the persona to set up. The persona works in its own directory for it, `$KIKI_HOME/bots/<id>` by default, or the one named by `home_workspace`. Related limits are configured in `config.toml`:
49
+ That same conversation is what a scheduled prompt, a message from another persona and a room seat address reach — there is no second persona to set up. It works in its own directory, `$KIKI_HOME/bots/<id>` by default, or the one named by `home_workspace`. Related limits live in `config.toml`:
52
50
 
53
51
  ```toml
54
52
  [bot]
@@ -57,27 +55,27 @@ max_handoffs_per_hour = 30
57
55
  room_budget = 12
58
56
  ```
59
57
 
60
- A session's `delivery` is either `reply` or `message`. In message mode, only successful `SendMessage` calls become delivered messages; ordinary model text remains in the process view. If a user-triggered turn ends with ordinary text but no successful send, Kiki asks the model to reconsider **once**, which can incur one extra model request. The shipped `agent` profile exposes `SendMessage` in message mode, while reply-mode turns omit it. A custom profile with an explicit `tools` allowlist must include `SendMessage`; delivery mode does not bypass profile permissions. The tool table is frozen for a turn, so changing delivery takes effect on the next turn.
58
+ A session's `delivery` is either `reply` or `message`. In message mode only successful `SendMessage` calls become delivered messages, and ordinary model text stays in the process view; if a user-triggered turn ends with text and no send, Kiki asks the model to reconsider **once**, which can cost one extra request. The shipped `agent` profile exposes `SendMessage` in message mode and omits it in reply mode, and a custom profile with an explicit `tools` allowlist must list it — delivery mode does not bypass profile permissions. The tool table is frozen for a turn, so a delivery change applies to the next one.
61
59
 
62
- `SendMessage` can address the user or another persona with `to: "@Name"`. Use the persona ID when names collide. A handoff can wake a closed persistent conversation and counts toward the hourly limit; retrying the same delivery key does not consume another slot. Attachments are immutable copies from the session workspace, its additional directories, or the persona's own area—not arbitrary filesystem paths.
60
+ `SendMessage` addresses the user or another persona with `to: "@Name"`; use the persona ID when names collide. A handoff can wake a closed conversation and counts toward the hourly limit, though retrying the same delivery key does not consume another slot. Attachments are immutable copies from the session workspace, its additional directories or the persona's own area, not arbitrary filesystem paths.
63
61
 
64
62
  ## Discuss in a room
65
63
 
66
- Create a room with two to six members, a classification workspace, and a host. Persona members get dedicated message-mode sessions. The API also accepts existing threads (`kind: "thread"`); these reuse their own sessions, workspaces, and permissions, require `[thread_communication] enabled = true`, and cannot be subagents. In the GUI, Ctrl/⌘-click threads in the sidebar and choose **Pull into a new room**, use **Add to room…** on a thread, add threads from the **Threads** tab under **Add member**, or choose **Open a room with these threads** on a thread link. Scheduling has three rules:
64
+ Create a room with two to six members, a classification workspace and a host. Persona members get their own message-mode sessions. The API also accepts existing threads (`kind: "thread"`), which reuse their own sessions, workspaces and permissions, need `[thread_communication] enabled = true`, and cannot be subagents. In the GUI, Ctrl/⌘-click threads in the sidebar and choose **Pull into a new room**, use **Add to room…** on a thread, add them from the **Threads** tab under **Add member**, or pick **Open a room with these threads** on a thread link. Three rules decide who wakes:
67
65
 
68
66
  1. A user mention wakes the named members; `@everyone` selects all members.
69
67
  2. A user message without mentions goes to the host, whether the host is a persona or a thread.
70
- 3. A persona message wakes only the members it mentions. A message with no mentions does not continue the discussion.
68
+ 3. A persona or thread room message wakes only the members it mentions. A message with no mentions is logged but wakes no one.
71
69
 
72
- Members run sequentially, so later speakers receive earlier speakers' results. Muted members are skipped by persona mentions and host fallback, but an explicit user mention still wakes them. Each member sees the messages since its last wake, excluding its own already-recorded output.
70
+ Persona turns run one after another; existing threads each have their own queue. A muted member is skipped by agent mentions and host fallback, but an explicit user mention still wakes it. Each member sees messages since its last successfully completed catch-up, minus its own already-recorded output. Notifications already covered by that successful batch do not start separate turns; a failed or cancelled turn does not confirm the batch.
73
71
 
74
- The budget limits member messages after each user message (12 by default). When exhausted, discussion pauses; **Continue** resets the budget and resumes retained work. **Pause** cancels queued wakes but allows the active turn to finish. **Stop all** also interrupts an active persona turn, never an original thread task; completed actions are not undone. Persona-only rooms retain user interruption steering, while mixed rooms retain queued work. At most one room question is shown at a time; later questions queue.
72
+ The budget limits member messages after each user message (12 by default). When it runs out the discussion pauses; **Continue** resets the budget and resumes the retained work. **Pause** cancels queued wakes but lets the active turn finish, and **Stop all** also interrupts an active persona turn — never an original thread task — without undoing completed actions. Persona-only rooms keep user interruption steering, mixed rooms keep queued work. One room question is shown at a time; later ones queue.
75
73
 
76
- Thread members default to `queueWhenBusy: true`: room input waits for their current turn to finish instead of steering it. Cold threads resume in their own workspaces. For every member other than the host, unmentioned messages are included in their next since catch-up without a separate model call. To speak, a thread must use `ThreadSend({room, content, mentions?})`; its ordinary assistant text never enters the room.
74
+ Thread members default to `queueWhenBusy: true`, so room input waits for their current turn instead of steering it, and cold threads resume in their own workspaces. Messages that do not select a member are included in that member's next catch-up without a separate model call. To speak, a thread must use `ThreadSend({room, content, mentions?})`; its ordinary assistant text never enters the room. Use exact member IDs (`sessionId` for a thread, `personaId` for a persona) in `mentions`, not display names. A send without mentions does not wake the host; that fallback applies only to user messages.
77
75
 
78
- Renaming, changing the host, muting, and workspace classification never rewrite member system prompts or permissions. Removing a thread leaves a system record in its session and preserves the room log; it does not archive the original thread. Creation requires two to six members, but leaving can reduce a room below two.
76
+ Renaming, changing the host, muting and workspace classification never rewrite a member's system prompt or permissions. Removing a thread leaves a system record in its session and preserves the room log without archiving the original thread. Creating a room needs two to six members, though members can leave and take it below two.
79
77
 
80
- If a member cannot wake, the room shows the failure and a recovery action instead of promising an automatic retry. For a model login failure, sign in under **Settings → Models & providers → Connections**, or open the member's conversation and select an available model. Existing member sessions retain their bound model; editing the persona card does not change it. After fixing the problem, send another room message and mention the failed member if it is not the host. **Continue** resumes a paused room; it does not retry an unpaused failed wake.
78
+ If a member cannot wake, the room shows the failure and what to do about it. For a model login failure, sign in under **Settings → Models & providers → Connections**, or open that member's conversation and pick an available model — existing member sessions keep their bound model, and editing the persona card does not change it. Then send another room message mentioning the failed member if it is not the host. **Continue** resumes a paused room; it does not retry a failed wake on an unpaused one.
81
79
 
82
80
  ## API entry points
83
81