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.
- package/README.md +13 -10
- package/dist/docs/en/configuration/config-files.md +63 -20
- package/dist/docs/en/configuration/data-locations.md +12 -4
- package/dist/docs/en/configuration/env-vars.md +4 -6
- package/dist/docs/en/configuration/overrides.md +13 -14
- package/dist/docs/en/configuration/providers.md +8 -6
- package/dist/docs/en/customization/agent-profiles.md +33 -38
- package/dist/docs/en/customization/agents.md +129 -107
- package/dist/docs/en/customization/hooks.md +41 -48
- package/dist/docs/en/customization/personas.md +19 -21
- package/dist/docs/en/customization/plugins.md +180 -156
- package/dist/docs/en/customization/prompt-fields.md +10 -6
- package/dist/docs/en/customization/skills.md +11 -13
- package/dist/docs/en/customization/skins.md +23 -27
- package/dist/docs/en/customization/themes.md +15 -15
- package/dist/docs/en/features/agents.md +85 -0
- package/dist/docs/en/features/daily.md +37 -7
- package/dist/docs/en/features/ecosystem.md +3 -1
- package/dist/docs/en/features/extend.md +7 -1
- package/dist/docs/en/features/freedom.md +4 -0
- package/dist/docs/en/features/index.md +6 -5
- package/dist/docs/en/features/long-work.md +23 -5
- package/dist/docs/en/features/look.md +1 -1
- package/dist/docs/en/features/people.md +10 -2
- package/dist/docs/en/features/spaces.md +16 -4
- package/dist/docs/en/features/workbench.md +11 -3
- package/dist/docs/en/getting-started/desktop-app.md +44 -29
- package/dist/docs/en/getting-started/first-launch.md +32 -21
- package/dist/docs/en/getting-started/installation.md +27 -12
- package/dist/docs/en/getting-started/use-cases.md +35 -35
- package/dist/docs/en/guides/goals.md +9 -7
- package/dist/docs/en/guides/interaction.md +26 -26
- package/dist/docs/en/guides/interface.md +18 -14
- package/dist/docs/en/guides/memory.md +43 -14
- package/dist/docs/en/guides/sessions.md +32 -26
- package/dist/docs/en/guides/settings.md +60 -29
- package/dist/docs/en/index.md +8 -2
- package/dist/docs/en/reference/command.md +8 -4
- package/dist/docs/en/reference/keyboard.md +18 -4
- package/dist/docs/en/reference/model-vocabulary.md +6 -8
- package/dist/docs/en/reference/slash-commands.md +4 -4
- package/dist/docs/en/reference/tools.md +92 -15
- package/dist/docs/en/release-notes/changelog.md +1 -9
- package/dist/docs/en/server/acp.md +1 -1
- package/dist/docs/en/server/ide.md +1 -1
- package/dist/docs/en/server/local-server.md +5 -5
- package/dist/docs/en/server/mcp.md +2 -2
- package/dist/docs/en/server/rest-api.md +79 -5
- package/dist/docs/en/server/sdk.md +2 -2
- package/dist/docs/zh/configuration/config-files.md +56 -15
- package/dist/docs/zh/configuration/data-locations.md +12 -4
- package/dist/docs/zh/configuration/env-vars.md +4 -6
- package/dist/docs/zh/configuration/overrides.md +13 -14
- package/dist/docs/zh/configuration/providers.md +7 -5
- package/dist/docs/zh/customization/agent-profiles.md +31 -36
- package/dist/docs/zh/customization/agents.md +120 -98
- package/dist/docs/zh/customization/hooks.md +35 -42
- package/dist/docs/zh/customization/personas.md +16 -18
- package/dist/docs/zh/customization/plugins.md +167 -142
- package/dist/docs/zh/customization/prompt-fields.md +9 -5
- package/dist/docs/zh/customization/skills.md +10 -12
- package/dist/docs/zh/customization/skins.md +19 -23
- package/dist/docs/zh/customization/themes.md +12 -12
- package/dist/docs/zh/features/agents.md +85 -0
- package/dist/docs/zh/features/daily.md +37 -7
- package/dist/docs/zh/features/ecosystem.md +3 -1
- package/dist/docs/zh/features/extend.md +7 -1
- package/dist/docs/zh/features/freedom.md +4 -0
- package/dist/docs/zh/features/index.md +6 -5
- package/dist/docs/zh/features/long-work.md +22 -4
- package/dist/docs/zh/features/look.md +1 -1
- package/dist/docs/zh/features/people.md +10 -2
- package/dist/docs/zh/features/spaces.md +15 -3
- package/dist/docs/zh/features/workbench.md +11 -3
- package/dist/docs/zh/getting-started/desktop-app.md +43 -28
- package/dist/docs/zh/getting-started/first-launch.md +32 -21
- package/dist/docs/zh/getting-started/installation.md +26 -11
- package/dist/docs/zh/getting-started/use-cases.md +35 -37
- package/dist/docs/zh/guides/goals.md +8 -8
- package/dist/docs/zh/guides/interaction.md +25 -25
- package/dist/docs/zh/guides/interface.md +18 -14
- package/dist/docs/zh/guides/memory.md +43 -14
- package/dist/docs/zh/guides/sessions.md +30 -24
- package/dist/docs/zh/guides/settings.md +54 -23
- package/dist/docs/zh/index.md +7 -1
- package/dist/docs/zh/reference/command.md +7 -3
- package/dist/docs/zh/reference/keyboard.md +18 -4
- package/dist/docs/zh/reference/model-vocabulary.md +6 -8
- package/dist/docs/zh/reference/slash-commands.md +3 -3
- package/dist/docs/zh/reference/tools.md +74 -9
- package/dist/docs/zh/release-notes/changelog.md +1 -9
- package/dist/docs/zh/server/acp.md +1 -1
- package/dist/docs/zh/server/ide.md +1 -1
- package/dist/docs/zh/server/local-server.md +5 -5
- package/dist/docs/zh/server/mcp.md +2 -2
- package/dist/docs/zh/server/rest-api.md +69 -1
- package/dist/docs/zh/server/sdk.md +2 -2
- package/dist/main.mjs +12545 -3456
- package/dist/web/assets/AppErrorBoundary-RFIAb-Uf.js +1 -0
- package/dist/web/assets/NavScopeBoundary-DY_ET7A-.js +1 -0
- package/dist/web/assets/{arc-y2SkSoyr.js → arc-CMgTB1m7.js} +1 -1
- package/dist/web/assets/{architectureDiagram-3BPJPVTR-uCwLz53m.js → architectureDiagram-3BPJPVTR-BU79ou2C.js} +1 -1
- package/dist/web/assets/{blockDiagram-GPEHLZMM-BZyWv36G.js → blockDiagram-GPEHLZMM-Bkuldod2.js} +1 -1
- package/dist/web/assets/{c4Diagram-AAUBKEIU-DKGx9i50.js → c4Diagram-AAUBKEIU-C3WMeqyu.js} +1 -1
- package/dist/web/assets/channel-DpDZUJRn.js +1 -0
- package/dist/web/assets/{chunk-2J33WTMH-CSkrhrsp.js → chunk-2J33WTMH-CesyWmwo.js} +1 -1
- package/dist/web/assets/{chunk-4BX2VUAB-CtxMoJ68.js → chunk-4BX2VUAB-C7rghYTf.js} +1 -1
- package/dist/web/assets/{chunk-55IACEB6-Dos3ftEy.js → chunk-55IACEB6-BqRHhwtz.js} +1 -1
- package/dist/web/assets/{chunk-727SXJPM-wbzEYK9z.js → chunk-727SXJPM-BhSqCRBc.js} +1 -1
- package/dist/web/assets/{chunk-AQP2D5EJ-B9GKvCD6.js → chunk-AQP2D5EJ-DdYE2ZVZ.js} +1 -1
- package/dist/web/assets/{chunk-FMBD7UC4-u5Y2P6IX.js → chunk-FMBD7UC4-BCRPUxDF.js} +1 -1
- package/dist/web/assets/{chunk-ND2GUHAM-B8rFKkTV.js → chunk-ND2GUHAM-CuvyDjTR.js} +1 -1
- package/dist/web/assets/{chunk-QZHKN3VN-EQsKtuD-.js → chunk-QZHKN3VN-BU5vAS78.js} +1 -1
- package/dist/web/assets/classDiagram-4FO5ZUOK-Bju1GfNu.js +1 -0
- package/dist/web/assets/classDiagram-v2-Q7XG4LA2-Bju1GfNu.js +1 -0
- package/dist/web/assets/client-C0oH7-8r.js +2 -0
- package/dist/web/assets/connection-BhO2nh7P.js +1 -0
- package/dist/web/assets/{cose-bilkent-S5V4N54A-D6dr5mIW.js → cose-bilkent-S5V4N54A-CXrvsA1a.js} +1 -1
- package/dist/web/assets/{dagre-BM42HDAG-Dnyhc4Hn.js → dagre-BM42HDAG-TaAea3Rt.js} +1 -1
- package/dist/web/assets/{diagram-2AECGRRQ-CYXkWdne.js → diagram-2AECGRRQ-CdEH4jGt.js} +1 -1
- package/dist/web/assets/{diagram-5GNKFQAL-DPwBf5Ag.js → diagram-5GNKFQAL-A0jZ_p-T.js} +1 -1
- package/dist/web/assets/{diagram-KO2AKTUF-DNeLYZ8X.js → diagram-KO2AKTUF-miHWORz3.js} +1 -1
- package/dist/web/assets/{diagram-LMA3HP47-zU8RsQTX.js → diagram-LMA3HP47-BlUIwEIg.js} +1 -1
- package/dist/web/assets/{diagram-OG6HWLK6-Cf9Mm94H.js → diagram-OG6HWLK6-DwDzMhEg.js} +1 -1
- package/dist/web/assets/{erDiagram-TEJ5UH35-Ch4CeiUI.js → erDiagram-TEJ5UH35-BJr5w62i.js} +1 -1
- package/dist/web/assets/export-BlxaZKEe.js +2 -0
- package/dist/web/assets/{flowDiagram-I6XJVG4X-Csn6WqEH.js → flowDiagram-I6XJVG4X-BP7KSFjx.js} +1 -1
- package/dist/web/assets/{ganttDiagram-6RSMTGT7-DsuBgEyu.js → ganttDiagram-6RSMTGT7-BstLBBof.js} +1 -1
- package/dist/web/assets/{gitGraphDiagram-PVQCEYII-CPA7jCxU.js → gitGraphDiagram-PVQCEYII-C57s7nZ-.js} +1 -1
- package/dist/web/assets/highlighted-body-OFNGDK62-BVb-7KsA.js +1 -0
- package/dist/web/assets/index-69qhvTvD.js +1 -0
- package/dist/web/assets/{index-BYUHmd8w.js → index-BDNM6yJI.js} +2 -2
- package/dist/web/assets/{index-BGgZxlEQ.js → index-BJF_gEDs.js} +2 -2
- package/dist/web/assets/index-BOwMP6BP.js +1 -0
- package/dist/web/assets/{index-C69a5Mcz.js → index-BZsyXCqm.js} +1 -1
- package/dist/web/assets/{index-C7EA7a_g.js → index-Bfl4JiNq.js} +2 -2
- package/dist/web/assets/index-BlD3AKX-.js +1 -0
- package/dist/web/assets/{index-CIymCfcP.js → index-BnvW0EvQ.js} +1 -1
- package/dist/web/assets/index-C4rmWyOm.js +1 -0
- package/dist/web/assets/index-CGLcb3HY.js +1 -0
- package/dist/web/assets/{index-kWBxPqIX.js → index-CPvOeQPX.js} +1 -1
- package/dist/web/assets/index-Cjbe0JKM.js +1 -0
- package/dist/web/assets/index-CmYoJWUm.js +1 -0
- package/dist/web/assets/index-CtUFrjKe.js +1 -0
- package/dist/web/assets/index-DDvDRMTK.js +1 -0
- package/dist/web/assets/index-DSpndwAR.css +1 -0
- package/dist/web/assets/index-D_JjTHxi.js +1 -0
- package/dist/web/assets/index-DbuwcnbT.js +1 -0
- package/dist/web/assets/index-DcXyS0nN.js +1 -0
- package/dist/web/assets/index-Dcl9ruKA.js +1 -0
- package/dist/web/assets/index-DgwALPNA.js +121 -0
- package/dist/web/assets/{index-DoN1FTEe.js → index-DkE8hRT1.js} +2 -2
- package/dist/web/assets/index-DsyRBZ4h.js +1 -0
- package/dist/web/assets/{index-29zav3JI.js → index-DuudNhLL.js} +4 -4
- package/dist/web/assets/index-Gc4F0b2f.js +1 -0
- package/dist/web/assets/index-HGqqwKoV.js +13 -0
- package/dist/web/assets/index-KchrJnno.js +3 -0
- package/dist/web/assets/{index-B0KNSyji.js → index-Tmi2BPYU.js} +1 -1
- package/dist/web/assets/index-Ya4GuDs0.js +1 -0
- package/dist/web/assets/index-_aDaKqLB.js +1 -0
- package/dist/web/assets/index-_qwOAotB.js +1 -0
- package/dist/web/assets/index-hnIkczza.js +7 -0
- package/dist/web/assets/{infoDiagram-5YYISTIA-D3Q__m62.js → infoDiagram-5YYISTIA-CifuVY6C.js} +1 -1
- package/dist/web/assets/{ishikawaDiagram-YF4QCWOH-CcvCBuZ5.js → ishikawaDiagram-YF4QCWOH-Cd60vQUi.js} +1 -1
- package/dist/web/assets/{journeyDiagram-JHISSGLW-COZU4LNt.js → journeyDiagram-JHISSGLW-Cb3Xl_wl.js} +1 -1
- package/dist/web/assets/{kanban-definition-UN3LZRKU-BrXjBoAU.js → kanban-definition-UN3LZRKU-Ei6ThuZt.js} +1 -1
- package/dist/web/assets/{linear-BgP1STFi.js → linear-CDZJx-o2.js} +1 -1
- package/dist/web/assets/mermaid-GHXKKRXX-DFxyxD7G.js +331 -0
- package/dist/web/assets/{mindmap-definition-RKZ34NQL-CgjSrE5r.js → mindmap-definition-RKZ34NQL-B0ygxzkx.js} +1 -1
- package/dist/web/assets/navViewState-Ck_HK-TK.js +1 -0
- package/dist/web/assets/{pieDiagram-4H26LBE5-DTfe1sKA.js → pieDiagram-4H26LBE5-B2FdrvDv.js} +1 -1
- package/dist/web/assets/{quadrantDiagram-W4KKPZXB-D95hfh0q.js → quadrantDiagram-W4KKPZXB-CwpOTy3d.js} +1 -1
- package/dist/web/assets/{requirementDiagram-4Y6WPE33-DtSLi7Mh.js → requirementDiagram-4Y6WPE33-ExdZNzLQ.js} +1 -1
- package/dist/web/assets/{sankeyDiagram-5OEKKPKP-gi_dJpcU.js → sankeyDiagram-5OEKKPKP-u0EZKD7D.js} +1 -1
- package/dist/web/assets/{sequenceDiagram-3UESZ5HK-DKQ9a72t.js → sequenceDiagram-3UESZ5HK-BXHMy5DY.js} +1 -1
- package/dist/web/assets/{spaces-B2Ccyh_T.js → spaces-C8n7xQPx.js} +1 -1
- package/dist/web/assets/{stateDiagram-AJRCARHV-Bz7tmSqa.js → stateDiagram-AJRCARHV-DMXx7ell.js} +1 -1
- package/dist/web/assets/stateDiagram-v2-BHNVJYJU-Bydq1_By.js +1 -0
- package/dist/web/assets/theme-BBnHttAf.js +1 -0
- package/dist/web/assets/{timeline-definition-PNZ67QCA-BfMXPwhV.js → timeline-definition-PNZ67QCA-DtqVG_4u.js} +1 -1
- package/dist/web/assets/{vennDiagram-CIIHVFJN-WLxW2KT5.js → vennDiagram-CIIHVFJN-Dom0ex8r.js} +1 -1
- package/dist/web/assets/{wardley-L42UT6IY-DiiqwIdq.js → wardley-L42UT6IY-C-RstmuQ.js} +1 -1
- package/dist/web/assets/{wardleyDiagram-YWT4CUSO-DmCukWuw.js → wardleyDiagram-YWT4CUSO-C8CzNfdf.js} +1 -1
- package/dist/web/assets/{xychartDiagram-2RQKCTM6-Cfq1W2tT.js → xychartDiagram-2RQKCTM6-1AxVTyB6.js} +1 -1
- package/dist/web/index.html +2 -2
- package/native/auth-native/prebuilds/linux-arm64/auth-native.node +0 -0
- package/native/auth-native/prebuilds/linux-x64/auth-native.node +0 -0
- package/native/auth-native/prebuilds/win32-arm64/auth-native.node +0 -0
- package/native/auth-native/prebuilds/win32-x64/auth-native.node +0 -0
- package/package.json +1 -1
- package/dist/web/assets/AppErrorBoundary-DWpgwxFV.js +0 -1
- package/dist/web/assets/NavScopeBoundary-D8Lf1G0U.js +0 -1
- package/dist/web/assets/channel-BGdXootG.js +0 -1
- package/dist/web/assets/classDiagram-4FO5ZUOK-CPcnLy_H.js +0 -1
- package/dist/web/assets/classDiagram-v2-Q7XG4LA2-CPcnLy_H.js +0 -1
- package/dist/web/assets/client-DSIbyfoz.js +0 -2
- package/dist/web/assets/connection-DYZn9oPZ.js +0 -1
- package/dist/web/assets/export-Bq8ZECqX.js +0 -2
- package/dist/web/assets/highlighted-body-OFNGDK62-CDPBxM_E.js +0 -1
- package/dist/web/assets/index-AksnytJj.js +0 -1
- package/dist/web/assets/index-B8xhhYDh.css +0 -1
- package/dist/web/assets/index-BUrlrKap.js +0 -1
- package/dist/web/assets/index-B_5-HLed.js +0 -62
- package/dist/web/assets/index-BfmoxdpP.js +0 -1
- package/dist/web/assets/index-Bo3e-ohM.js +0 -3
- package/dist/web/assets/index-BrYV9gV_.js +0 -1
- package/dist/web/assets/index-C8XUtAvK.js +0 -1
- package/dist/web/assets/index-C9uil5my.js +0 -13
- package/dist/web/assets/index-CKpWHSp9.js +0 -1
- package/dist/web/assets/index-CLKBgQxV.js +0 -1
- package/dist/web/assets/index-CTyyUNWj.js +0 -7
- package/dist/web/assets/index-D7cg9qYZ.js +0 -1
- package/dist/web/assets/index-D7dg8R_q.js +0 -1
- package/dist/web/assets/index-DCSpedV_.js +0 -1
- package/dist/web/assets/index-DLbD0Nx5.js +0 -1
- package/dist/web/assets/index-DaEzbvvu.js +0 -1
- package/dist/web/assets/index-DhbcjMZF.js +0 -1
- package/dist/web/assets/index-Dw2h88mF.js +0 -1
- package/dist/web/assets/index-FcMtfmKv.js +0 -1
- package/dist/web/assets/index-XFq9Kgg0.js +0 -1
- package/dist/web/assets/index-iI2mM43w.js +0 -1
- package/dist/web/assets/index-oXOF7lko.js +0 -1
- package/dist/web/assets/locale-CANfezJ4.js +0 -17
- package/dist/web/assets/mermaid-GHXKKRXX-_JLagMll.js +0 -321
- package/dist/web/assets/navViewState-DS5LnMYc.js +0 -1
- package/dist/web/assets/settings-CcwMWXbp.js +0 -42
- package/dist/web/assets/stateDiagram-v2-BHNVJYJU-D6-wdUbw.js +0 -1
- package/dist/web/assets/theme-DlDhDxeD.js +0 -1
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# Hooks
|
|
2
2
|
|
|
3
|
-
Hooks
|
|
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
|
-
- **
|
|
6
|
-
- **Desktop notifications**:
|
|
7
|
-
- **
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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"`)
|
|
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
|
-
|
|
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
|
|
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
|
-
##
|
|
65
|
+
## Legacy command hooks
|
|
66
66
|
|
|
67
|
-
|
|
67
|
+
Everything below describes the legacy contract: a rule names an event, targets to match, and a shell command to run.
|
|
68
68
|
|
|
69
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
##
|
|
77
|
+
## A minimal hook
|
|
85
78
|
|
|
86
|
-
|
|
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
|
-
##
|
|
91
|
+
## Legacy rule fields
|
|
99
92
|
|
|
100
|
-
|
|
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
|
|
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
|
|
108
|
+
### Event data format
|
|
116
109
|
|
|
117
|
-
Each time a hook triggers, the CLI passes
|
|
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
|
-
|
|
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
|
|
124
|
+
## Return values
|
|
132
125
|
|
|
133
|
-
After the script exits, the CLI
|
|
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
|
|
137
|
+
For exit code `0`, the CLI classifies stdout like this:
|
|
145
138
|
|
|
146
|
-
- **Valid JSON
|
|
147
|
-
- **Malformed object text
|
|
148
|
-
- **
|
|
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
|
|
162
|
-
Only
|
|
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
|
|
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:
|
|
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
|
|
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
|
|
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
|
-
- [
|
|
229
|
-
- [Agents and sub-agents](./agents.md) —
|
|
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**
|
|
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`
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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`
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|