@cursor/bdk 0.2.4 → 0.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (348) hide show
  1. package/README.md +76 -1154
  2. package/dist/bin/agent-serve.js +17 -11
  3. package/dist/channels/github/github-channel.d.ts +4 -4
  4. package/dist/channels/github/github-channel.js +5 -5
  5. package/dist/channels/slack/eval-directive.js +1 -1
  6. package/dist/docs/404.html +2 -2
  7. package/dist/docs/assets/{app.4kQ8Db_q.js → app.CJLKDVza.js} +4 -4
  8. package/dist/docs/assets/{building-with-agents.md.-fcjCmJU.js → building-with-agents.md.BPjPFxFg.js} +2 -2
  9. package/dist/docs/assets/{building-with-agents.md.-fcjCmJU.lean.js → building-with-agents.md.BPjPFxFg.lean.js} +1 -1
  10. package/dist/docs/assets/chunks/@localSearchIndexroot.Bq-pxRXm.js +1 -0
  11. package/dist/docs/assets/chunks/{VPLocalSearchBox.DY1RwB8Q.js → VPLocalSearchBox.BW9mrQmq.js} +1 -1
  12. package/dist/docs/assets/chunks/{arc.CxE_fSPK.js → arc.D8ZOvM1m.js} +1 -1
  13. package/dist/docs/assets/chunks/{architectureDiagram-Q4EWVU46.CPX426ui.js → architectureDiagram-Q4EWVU46.CXEKhLW-.js} +1 -1
  14. package/dist/docs/assets/chunks/{baseUniq.CB52JrKG.js → baseUniq.BJkVKblr.js} +1 -1
  15. package/dist/docs/assets/chunks/{blockDiagram-DXYQGD6D.J0cNaQCL.js → blockDiagram-DXYQGD6D.DQDbHxor.js} +1 -1
  16. package/dist/docs/assets/chunks/{c4Diagram-AHTNJAMY.DJn3vEGT.js → c4Diagram-AHTNJAMY.ByMD6LYM.js} +1 -1
  17. package/dist/docs/assets/chunks/channel.DCU8W1RP.js +1 -0
  18. package/dist/docs/assets/chunks/{chunk-4BX2VUAB.Dao618F6.js → chunk-4BX2VUAB.Dtq1aVI9.js} +1 -1
  19. package/dist/docs/assets/chunks/{chunk-4TB4RGXK.QW8Rhjai.js → chunk-4TB4RGXK.BL_XrkoQ.js} +1 -1
  20. package/dist/docs/assets/chunks/{chunk-55IACEB6.DfRLLKF_.js → chunk-55IACEB6.BDPXu94_.js} +1 -1
  21. package/dist/docs/assets/chunks/{chunk-EDXVE4YY.CIV2ApKQ.js → chunk-EDXVE4YY.DhGOQj4k.js} +1 -1
  22. package/dist/docs/assets/chunks/{chunk-FMBD7UC4.BEheSuxp.js → chunk-FMBD7UC4.DSF5nr8v.js} +1 -1
  23. package/dist/docs/assets/chunks/{chunk-OYMX7WX6.CUN88ENB.js → chunk-OYMX7WX6.Day7wayw.js} +1 -1
  24. package/dist/docs/assets/chunks/{chunk-QZHKN3VN.CgqCs8b_.js → chunk-QZHKN3VN.CpBEC0zA.js} +1 -1
  25. package/dist/docs/assets/chunks/{chunk-YZCP3GAM.iCH0nnTJ.js → chunk-YZCP3GAM.X_7rY1rx.js} +1 -1
  26. package/dist/docs/assets/chunks/classDiagram-6PBFFD2Q.DwpXsM06.js +1 -0
  27. package/dist/docs/assets/chunks/classDiagram-v2-HSJHXN6E.DwpXsM06.js +1 -0
  28. package/dist/docs/assets/chunks/clone.DH6Mx2zB.js +1 -0
  29. package/dist/docs/assets/chunks/{cose-bilkent-S5V4N54A.BLcUxhWE.js → cose-bilkent-S5V4N54A.BVRmi2ko.js} +1 -1
  30. package/dist/docs/assets/chunks/{dagre-KV5264BT.Ep7LofOm.js → dagre-KV5264BT.Dei9oslB.js} +1 -1
  31. package/dist/docs/assets/chunks/{diagram-5BDNPKRD.Bzf4GSQ4.js → diagram-5BDNPKRD._M-efGt7.js} +1 -1
  32. package/dist/docs/assets/chunks/{diagram-G4DWMVQ6.DD6Jh-eM.js → diagram-G4DWMVQ6.D1Vmhfsj.js} +1 -1
  33. package/dist/docs/assets/chunks/{diagram-MMDJMWI5.oOIl8bWd.js → diagram-MMDJMWI5.cE1bmvAC.js} +1 -1
  34. package/dist/docs/assets/chunks/{diagram-TYMM5635.DHs85Ade.js → diagram-TYMM5635.DkXAfznP.js} +1 -1
  35. package/dist/docs/assets/chunks/{erDiagram-SMLLAGMA.BIb5ghCk.js → erDiagram-SMLLAGMA.DH_pSwPg.js} +1 -1
  36. package/dist/docs/assets/chunks/{flowDiagram-DWJPFMVM.DV4paY9k.js → flowDiagram-DWJPFMVM.kAWVN9j1.js} +1 -1
  37. package/dist/docs/assets/chunks/{ganttDiagram-T4ZO3ILL.AyEKA6_v.js → ganttDiagram-T4ZO3ILL.8r0w49-p.js} +1 -1
  38. package/dist/docs/assets/chunks/{gitGraphDiagram-UUTBAWPF.BltiCDFo.js → gitGraphDiagram-UUTBAWPF.BDa7Bi1i.js} +1 -1
  39. package/dist/docs/assets/chunks/{graph.DzuEYGdC.js → graph.BMPXHz_B.js} +1 -1
  40. package/dist/docs/assets/chunks/{infoDiagram-42DDH7IO.BV2l981J.js → infoDiagram-42DDH7IO.BmlcqewS.js} +1 -1
  41. package/dist/docs/assets/chunks/{ishikawaDiagram-UXIWVN3A.BA4Izf-m.js → ishikawaDiagram-UXIWVN3A.CVSEQSul.js} +1 -1
  42. package/dist/docs/assets/chunks/{journeyDiagram-VCZTEJTY.DjaFbFS3.js → journeyDiagram-VCZTEJTY.BpeWJ5n-.js} +1 -1
  43. package/dist/docs/assets/chunks/{kanban-definition-6JOO6SKY.CfTFieDs.js → kanban-definition-6JOO6SKY.DHbDXuxB.js} +1 -1
  44. package/dist/docs/assets/chunks/{layout.DzfWqTBV.js → layout.CzrCDgkP.js} +1 -1
  45. package/dist/docs/assets/chunks/{linear.BO6mpulV.js → linear.HwBsflwN.js} +1 -1
  46. package/dist/docs/assets/chunks/{min.BGgTadgT.js → min.DqGHolT3.js} +1 -1
  47. package/dist/docs/assets/chunks/{mindmap-definition-QFDTVHPH.DPuIXVWY.js → mindmap-definition-QFDTVHPH.ZYGlOawh.js} +1 -1
  48. package/dist/docs/assets/chunks/{pieDiagram-DEJITSTG.BOnl3bBg.js → pieDiagram-DEJITSTG.C2KRXlNR.js} +1 -1
  49. package/dist/docs/assets/chunks/{quadrantDiagram-34T5L4WZ.DNB6Ckdc.js → quadrantDiagram-34T5L4WZ.CHj3Qefp.js} +1 -1
  50. package/dist/docs/assets/chunks/{requirementDiagram-MS252O5E.D5-Qo7vb.js → requirementDiagram-MS252O5E.B1L4Tf7k.js} +1 -1
  51. package/dist/docs/assets/chunks/{sankeyDiagram-XADWPNL6.8t65cesf.js → sankeyDiagram-XADWPNL6.dNR2yi1B.js} +1 -1
  52. package/dist/docs/assets/chunks/{sequenceDiagram-FGHM5R23.CaG07BdS.js → sequenceDiagram-FGHM5R23.BrvQ3C6m.js} +1 -1
  53. package/dist/docs/assets/chunks/{stateDiagram-FHFEXIEX.TKOweTB6.js → stateDiagram-FHFEXIEX.BtehEykA.js} +1 -1
  54. package/dist/docs/assets/chunks/stateDiagram-v2-QKLJ7IA2.kzD0-U89.js +1 -0
  55. package/dist/docs/assets/chunks/{theme.Dx-JhpTB.js → theme.BDHBZUkP.js} +2 -2
  56. package/dist/docs/assets/chunks/{timeline-definition-GMOUNBTQ.fE53zQ2s.js → timeline-definition-GMOUNBTQ.Bn7nhqEN.js} +1 -1
  57. package/dist/docs/assets/chunks/{vennDiagram-DHZGUBPP.DJsZZaJg.js → vennDiagram-DHZGUBPP.DKhc38sz.js} +1 -1
  58. package/dist/docs/assets/chunks/wardley-RL74JXVD.DOXQ0w8J.js +162 -0
  59. package/dist/docs/assets/chunks/{wardleyDiagram-NUSXRM2D.CMZ-Ru_t.js → wardleyDiagram-NUSXRM2D.Bbq5B2Ic.js} +1 -1
  60. package/dist/docs/assets/chunks/{xychartDiagram-5P7HB3ND.XXrhBc7a.js → xychartDiagram-5P7HB3ND.B77HE1K8.js} +1 -1
  61. package/dist/docs/assets/{deployment.md.UhnJIMr-.js → deployment.md.BdqTiGdc.js} +4 -4
  62. package/dist/docs/assets/{deployment.md.UhnJIMr-.lean.js → deployment.md.BdqTiGdc.lean.js} +1 -1
  63. package/dist/docs/assets/{evals.md.CCAtNcuL.js → evals.md.C851kViu.js} +3 -3
  64. package/dist/docs/assets/{evals.md.CCAtNcuL.lean.js → evals.md.C851kViu.lean.js} +1 -1
  65. package/dist/docs/assets/{guides_agent-to-agent.md.CGkicXeB.js → guides_agent-to-agent.md.Cps5NiCV.js} +2 -2
  66. package/dist/docs/assets/{guides_agent-to-agent.md.CGkicXeB.lean.js → guides_agent-to-agent.md.Cps5NiCV.lean.js} +1 -1
  67. package/dist/docs/assets/{guides_bitbucket.md.Cb3LPKt3.js → guides_bitbucket.md.BB6fqD-M.js} +2 -2
  68. package/dist/docs/assets/{guides_bitbucket.md.Cb3LPKt3.lean.js → guides_bitbucket.md.BB6fqD-M.lean.js} +1 -1
  69. package/dist/docs/assets/{guides_cloud-agents.md.BuEkDCwo.js → guides_cloud-agents.md.CWJjS9No.js} +2 -2
  70. package/dist/docs/assets/{guides_cloud-agents.md.BuEkDCwo.lean.js → guides_cloud-agents.md.CWJjS9No.lean.js} +1 -1
  71. package/dist/docs/assets/{guides_convert-automation.md.Ci-Y2iD5.js → guides_convert-automation.md.DMEX9nF-.js} +3 -3
  72. package/dist/docs/assets/{guides_convert-automation.md.Ci-Y2iD5.lean.js → guides_convert-automation.md.DMEX9nF-.lean.js} +1 -1
  73. package/dist/docs/assets/{guides_github.md.Bq9kQU9B.js → guides_github.md.Cr1Xlf-m.js} +3 -3
  74. package/dist/docs/assets/{guides_github.md.Bq9kQU9B.lean.js → guides_github.md.Cr1Xlf-m.lean.js} +1 -1
  75. package/dist/docs/assets/{guides_gitlab.md.BM27P43u.js → guides_gitlab.md.CMpmFi4M.js} +2 -2
  76. package/dist/docs/assets/{guides_gitlab.md.BM27P43u.lean.js → guides_gitlab.md.CMpmFi4M.lean.js} +1 -1
  77. package/dist/docs/assets/{guides_grokbot-agents.md.yxVbSlKA.js → guides_grokbot-agents.md.tD1smFhU.js} +2 -2
  78. package/dist/docs/assets/{guides_grokbot-agents.md.yxVbSlKA.lean.js → guides_grokbot-agents.md.tD1smFhU.lean.js} +1 -1
  79. package/dist/docs/assets/{guides_hooks.md.BWoiNaMq.js → guides_hooks.md.5Ce3NXxZ.js} +2 -2
  80. package/dist/docs/assets/{guides_hooks.md.BWoiNaMq.lean.js → guides_hooks.md.5Ce3NXxZ.lean.js} +1 -1
  81. package/dist/docs/assets/{guides_improve.md.COtL-6ft.js → guides_improve.md.CRrYq22s.js} +2 -2
  82. package/dist/docs/assets/{guides_improve.md.COtL-6ft.lean.js → guides_improve.md.CRrYq22s.lean.js} +1 -1
  83. package/dist/docs/assets/{guides_jev.md.CRcgmjDb.js → guides_jev.md.D7XH4JH3.js} +2 -2
  84. package/dist/docs/assets/{guides_jev.md.CRcgmjDb.lean.js → guides_jev.md.D7XH4JH3.lean.js} +1 -1
  85. package/dist/docs/assets/{guides_mcp-oauth.md.Cu6mhZ_3.js → guides_mcp-oauth.md.DR3zhC9r.js} +2 -2
  86. package/dist/docs/assets/{guides_mcp-oauth.md.Cu6mhZ_3.lean.js → guides_mcp-oauth.md.DR3zhC9r.lean.js} +1 -1
  87. package/dist/docs/assets/{guides_opentelemetry.md.DLlIB5rv.js → guides_opentelemetry.md.jcPNrQbH.js} +8 -6
  88. package/dist/docs/assets/{guides_opentelemetry.md.DLlIB5rv.lean.js → guides_opentelemetry.md.jcPNrQbH.lean.js} +1 -1
  89. package/dist/docs/assets/{guides_slack.md.diqqXTTm.js → guides_slack.md.Bn-WupSE.js} +8 -8
  90. package/dist/docs/assets/{guides_slack.md.diqqXTTm.lean.js → guides_slack.md.Bn-WupSE.lean.js} +1 -1
  91. package/dist/docs/assets/{guides_webhooks.md.D0furjw0.js → guides_webhooks.md.BBvAm_VF.js} +2 -2
  92. package/dist/docs/assets/{guides_webhooks.md.D0furjw0.lean.js → guides_webhooks.md.BBvAm_VF.lean.js} +1 -1
  93. package/dist/docs/assets/{hillclimbing.md.Biy0m-Qb.js → hillclimbing.md.Dxvd-0gT.js} +2 -2
  94. package/dist/docs/assets/{hillclimbing.md.Biy0m-Qb.lean.js → hillclimbing.md.Dxvd-0gT.lean.js} +1 -1
  95. package/dist/docs/assets/index.md.Dxxr7pFa.js +27 -0
  96. package/dist/docs/assets/{index.md.CVc_oOA3.lean.js → index.md.Dxxr7pFa.lean.js} +1 -1
  97. package/dist/docs/assets/{quickstart.md.CHpHPBUN.js → quickstart.md.BK5gjHM2.js} +2 -2
  98. package/dist/docs/assets/{quickstart.md.CHpHPBUN.lean.js → quickstart.md.BK5gjHM2.lean.js} +1 -1
  99. package/dist/docs/assets/{reference_agent-config.md.Cj5uBKp4.js → reference_agent-config.md.DrtLxWgR.js} +4 -4
  100. package/dist/docs/assets/{reference_agent-config.md.Cj5uBKp4.lean.js → reference_agent-config.md.DrtLxWgR.lean.js} +1 -1
  101. package/dist/docs/assets/{reference_artifacts.md.CQfKq8F2.js → reference_artifacts.md.DLV9MZES.js} +2 -2
  102. package/dist/docs/assets/{reference_artifacts.md.CQfKq8F2.lean.js → reference_artifacts.md.DLV9MZES.lean.js} +1 -1
  103. package/dist/docs/assets/{reference_channels.md.mbNtKCiR.js → reference_channels.md.LbNIJBwd.js} +2 -2
  104. package/dist/docs/assets/{reference_channels.md.mbNtKCiR.lean.js → reference_channels.md.LbNIJBwd.lean.js} +1 -1
  105. package/dist/docs/assets/{reference_cli.md.DgeLTO18.js → reference_cli.md.BsgDqYPh.js} +4 -4
  106. package/dist/docs/assets/{reference_cli.md.DgeLTO18.lean.js → reference_cli.md.BsgDqYPh.lean.js} +1 -1
  107. package/dist/docs/assets/{reference_connections.md.COq--gAm.js → reference_connections.md.Bljpve-y.js} +4 -4
  108. package/dist/docs/assets/{reference_connections.md.COq--gAm.lean.js → reference_connections.md.Bljpve-y.lean.js} +1 -1
  109. package/dist/docs/assets/{reference_evals.md.CJm3uCUm.js → reference_evals.md.D5i8PuXJ.js} +2 -2
  110. package/dist/docs/assets/{reference_evals.md.CJm3uCUm.lean.js → reference_evals.md.D5i8PuXJ.lean.js} +1 -1
  111. package/dist/docs/assets/{reference_extensions.md.pa2tN-e4.js → reference_extensions.md.OUacPetl.js} +3 -3
  112. package/dist/docs/assets/{reference_extensions.md.pa2tN-e4.lean.js → reference_extensions.md.OUacPetl.lean.js} +1 -1
  113. package/dist/docs/assets/{reference_hooks.md.DbthhtIR.js → reference_hooks.md.C5LCJ1R3.js} +2 -2
  114. package/dist/docs/assets/{reference_hooks.md.DbthhtIR.lean.js → reference_hooks.md.C5LCJ1R3.lean.js} +1 -1
  115. package/dist/docs/assets/{reference_http-api.md.BZOvhCqY.js → reference_http-api.md.DbFNOubV.js} +1 -1
  116. package/dist/docs/assets/{reference_instructions.md.Bdwscs4G.js → reference_instructions.md.DrcHZXig.js} +2 -2
  117. package/dist/docs/assets/{reference_instructions.md.Bdwscs4G.lean.js → reference_instructions.md.DrcHZXig.lean.js} +1 -1
  118. package/dist/docs/assets/reference_playground.md.1hx0gcIu.js +1 -0
  119. package/dist/docs/assets/{reference_playground.md.BdQzRJc2.lean.js → reference_playground.md.1hx0gcIu.lean.js} +1 -1
  120. package/dist/docs/assets/{reference_project-layout.md.CpLQ9j4K.js → reference_project-layout.md.C2JMRh7p.js} +2 -2
  121. package/dist/docs/assets/{reference_prompt.md.BQZB4eaV.js → reference_prompt.md.DqPh71XN.js} +3 -3
  122. package/dist/docs/assets/{reference_prompt.md.BQZB4eaV.lean.js → reference_prompt.md.DqPh71XN.lean.js} +1 -1
  123. package/dist/docs/assets/{reference_schedules.md.BVU5EFbz.js → reference_schedules.md.BuJ8fgMa.js} +2 -2
  124. package/dist/docs/assets/{reference_schedules.md.BVU5EFbz.lean.js → reference_schedules.md.BuJ8fgMa.lean.js} +1 -1
  125. package/dist/docs/assets/reference_sessions.md.CM5zo3w4.js +1 -0
  126. package/dist/docs/assets/{reference_sessions.md.DeRUItHD.lean.js → reference_sessions.md.CM5zo3w4.lean.js} +1 -1
  127. package/dist/docs/assets/{reference_skills.md.Cy00QMKS.js → reference_skills.md.ClkMoQsV.js} +2 -2
  128. package/dist/docs/assets/{reference_skills.md.Cy00QMKS.lean.js → reference_skills.md.ClkMoQsV.lean.js} +1 -1
  129. package/dist/docs/assets/{reference_subagents.md.B8oyeXOI.js → reference_subagents.md.gmPt5J-M.js} +2 -2
  130. package/dist/docs/assets/{reference_subagents.md.B8oyeXOI.lean.js → reference_subagents.md.gmPt5J-M.lean.js} +1 -1
  131. package/dist/docs/assets/{reference_tools.md.hg2Wi5Bq.js → reference_tools.md.v3SXVSs_.js} +2 -2
  132. package/dist/docs/assets/{reference_tools.md.hg2Wi5Bq.lean.js → reference_tools.md.v3SXVSs_.lean.js} +1 -1
  133. package/dist/docs/assets/{templates_agentic-owners.md.BykUiZ8j.js → templates_agentic-owners.md.CvmABtia.js} +2 -2
  134. package/dist/docs/assets/templates_grokbot-agents.md.2sydjFiO.js +5 -0
  135. package/dist/docs/assets/templates_grokbot-agents.md.2sydjFiO.lean.js +1 -0
  136. package/dist/docs/assets/{templates_security-reviewer.md.DXMmKl_o.js → templates_security-reviewer.md.Gh6EF9Us.js} +3 -2
  137. package/dist/docs/assets/{templates_security-reviewer.md.DXMmKl_o.lean.js → templates_security-reviewer.md.Gh6EF9Us.lean.js} +1 -1
  138. package/dist/docs/assets/{templates_thermo-quality-review.md.Dg1p1MsG.js → templates_thermo-quality-review.md.B77UyTrX.js} +2 -2
  139. package/dist/docs/assets/{templates_thermo-quality-review.md.Dg1p1MsG.lean.js → templates_thermo-quality-review.md.B77UyTrX.lean.js} +1 -1
  140. package/dist/docs/assets/{templates_thermo-review.md.Dlylkowj.js → templates_thermo-review.md.DRJ7mC5U.js} +2 -2
  141. package/dist/docs/assets/{templates_thermo-review.md.Dlylkowj.lean.js → templates_thermo-review.md.DRJ7mC5U.lean.js} +1 -1
  142. package/dist/docs/assets/templates_triage.md.CNN6b0JZ.js +9 -0
  143. package/dist/docs/assets/{templates_triage.md.CvJyx81N.lean.js → templates_triage.md.CNN6b0JZ.lean.js} +1 -1
  144. package/dist/docs/assets/troubleshooting.md.Bscj6ODe.js +1 -0
  145. package/dist/docs/assets/{troubleshooting.md.Cw5PKa3t.lean.js → troubleshooting.md.Bscj6ODe.lean.js} +1 -1
  146. package/dist/docs/building-with-agents.html +36 -36
  147. package/dist/docs/building-with-agents.md +0 -3
  148. package/dist/docs/deployment.html +38 -38
  149. package/dist/docs/deployment.md +2 -9
  150. package/dist/docs/evals.html +37 -37
  151. package/dist/docs/evals.md +2 -5
  152. package/dist/docs/guides/agent-to-agent.html +36 -36
  153. package/dist/docs/guides/agent-to-agent.md +0 -3
  154. package/dist/docs/guides/bitbucket.html +36 -36
  155. package/dist/docs/guides/bitbucket.md +0 -3
  156. package/dist/docs/guides/cloud-agents.html +36 -36
  157. package/dist/docs/guides/cloud-agents.md +0 -4
  158. package/dist/docs/guides/convert-automation.html +37 -37
  159. package/dist/docs/guides/convert-automation.md +2 -5
  160. package/dist/docs/guides/github.html +37 -37
  161. package/dist/docs/guides/github.md +1 -4
  162. package/dist/docs/guides/gitlab.html +36 -36
  163. package/dist/docs/guides/gitlab.md +0 -3
  164. package/dist/docs/guides/grokbot-agents.html +37 -37
  165. package/dist/docs/guides/grokbot-agents.md +1 -4
  166. package/dist/docs/guides/hooks.html +36 -36
  167. package/dist/docs/guides/hooks.md +0 -3
  168. package/dist/docs/guides/improve.html +36 -36
  169. package/dist/docs/guides/improve.md +0 -3
  170. package/dist/docs/guides/jev.html +36 -36
  171. package/dist/docs/guides/jev.md +0 -3
  172. package/dist/docs/guides/mcp-oauth.html +37 -37
  173. package/dist/docs/guides/mcp-oauth.md +1 -4
  174. package/dist/docs/guides/opentelemetry.html +42 -40
  175. package/dist/docs/guides/opentelemetry.md +4 -5
  176. package/dist/docs/guides/slack.html +43 -43
  177. package/dist/docs/guides/slack.md +14 -24
  178. package/dist/docs/guides/webhooks.html +36 -36
  179. package/dist/docs/guides/webhooks.md +0 -3
  180. package/dist/docs/hashmap.json +1 -1
  181. package/dist/docs/hillclimbing.html +36 -36
  182. package/dist/docs/hillclimbing.md +0 -3
  183. package/dist/docs/index.html +38 -38
  184. package/dist/docs/index.md +9 -16
  185. package/dist/docs/llms-full.txt +153 -234
  186. package/dist/docs/llms.txt +1 -0
  187. package/dist/docs/quickstart.html +36 -36
  188. package/dist/docs/quickstart.md +2 -7
  189. package/dist/docs/reference/agent-config.html +38 -38
  190. package/dist/docs/reference/agent-config.md +4 -7
  191. package/dist/docs/reference/artifacts.html +36 -36
  192. package/dist/docs/reference/artifacts.md +0 -3
  193. package/dist/docs/reference/channels.html +37 -37
  194. package/dist/docs/reference/channels.md +1 -6
  195. package/dist/docs/reference/cli.html +38 -38
  196. package/dist/docs/reference/cli.md +7 -14
  197. package/dist/docs/reference/connections.html +38 -38
  198. package/dist/docs/reference/connections.md +7 -10
  199. package/dist/docs/reference/evals.html +36 -36
  200. package/dist/docs/reference/evals.md +0 -3
  201. package/dist/docs/reference/extensions.html +37 -37
  202. package/dist/docs/reference/extensions.md +2 -5
  203. package/dist/docs/reference/hooks.html +36 -36
  204. package/dist/docs/reference/hooks.md +0 -3
  205. package/dist/docs/reference/http-api.html +37 -37
  206. package/dist/docs/reference/http-api.md +1 -1
  207. package/dist/docs/reference/instructions.html +36 -36
  208. package/dist/docs/reference/instructions.md +0 -3
  209. package/dist/docs/reference/playground.html +36 -36
  210. package/dist/docs/reference/playground.md +0 -3
  211. package/dist/docs/reference/project-layout.html +37 -37
  212. package/dist/docs/reference/project-layout.md +2 -2
  213. package/dist/docs/reference/prompt.html +37 -37
  214. package/dist/docs/reference/prompt.md +0 -3
  215. package/dist/docs/reference/schedules.html +36 -36
  216. package/dist/docs/reference/schedules.md +0 -3
  217. package/dist/docs/reference/sessions.html +36 -36
  218. package/dist/docs/reference/sessions.md +0 -3
  219. package/dist/docs/reference/skills.html +36 -36
  220. package/dist/docs/reference/skills.md +0 -3
  221. package/dist/docs/reference/subagents.html +36 -36
  222. package/dist/docs/reference/subagents.md +0 -3
  223. package/dist/docs/reference/tools.html +36 -36
  224. package/dist/docs/reference/tools.md +1 -5
  225. package/dist/docs/templates/agentic-owners.html +37 -37
  226. package/dist/docs/templates/agentic-owners.md +2 -3
  227. package/dist/docs/templates/grokbot-agents.html +64 -0
  228. package/dist/docs/templates/grokbot-agents.md +55 -0
  229. package/dist/docs/templates/security-reviewer.html +38 -37
  230. package/dist/docs/templates/security-reviewer.md +7 -11
  231. package/dist/docs/templates/thermo-quality-review.html +37 -37
  232. package/dist/docs/templates/thermo-quality-review.md +5 -8
  233. package/dist/docs/templates/thermo-review.html +37 -37
  234. package/dist/docs/templates/thermo-review.md +5 -7
  235. package/dist/docs/templates/triage.html +39 -39
  236. package/dist/docs/templates/triage.md +8 -4
  237. package/dist/docs/troubleshooting.html +36 -36
  238. package/dist/docs/troubleshooting.md +3 -7
  239. package/dist/evals.d.ts +2 -2
  240. package/dist/internal/cli-ax.d.ts.map +1 -1
  241. package/dist/internal/cli-ax.js +14 -7
  242. package/dist/internal/eval-runner.js +7 -4
  243. package/dist/internal/init-interview.d.ts +0 -1
  244. package/dist/internal/init-interview.d.ts.map +1 -1
  245. package/dist/internal/init-interview.js +15 -24
  246. package/dist/internal/legacy-command-guard.d.ts +4 -1
  247. package/dist/internal/legacy-command-guard.d.ts.map +1 -1
  248. package/dist/internal/legacy-command-guard.js +11 -2
  249. package/dist/internal/platform-timers.d.ts +8 -1
  250. package/dist/internal/platform-timers.d.ts.map +1 -1
  251. package/dist/internal/platform-timers.js +10 -2
  252. package/dist/internal/reminder-control-plane-protocol.d.ts +8 -1
  253. package/dist/internal/reminder-control-plane-protocol.d.ts.map +1 -1
  254. package/dist/internal/reminder-runner.d.ts +5 -0
  255. package/dist/internal/reminder-runner.d.ts.map +1 -1
  256. package/dist/internal/reminder-runner.js +27 -1
  257. package/dist/internal/resolve-prod-target.d.ts +3 -0
  258. package/dist/internal/resolve-prod-target.d.ts.map +1 -1
  259. package/dist/internal/resolve-prod-target.js +2 -1
  260. package/dist/internal/run-client.d.ts +10 -1
  261. package/dist/internal/run-client.d.ts.map +1 -1
  262. package/dist/internal/run-client.js +152 -51
  263. package/dist/internal/server.d.ts +6 -0
  264. package/dist/internal/server.d.ts.map +1 -1
  265. package/dist/internal/server.js +20 -8
  266. package/dist/internal/session-links.d.ts.map +1 -1
  267. package/dist/internal/session-links.js +8 -7
  268. package/dist/internal/sessions-client.d.ts +1 -0
  269. package/dist/internal/sessions-client.d.ts.map +1 -1
  270. package/dist/internal/sessions-client.js +2 -0
  271. package/docs/README.md +9 -16
  272. package/docs/building-with-agents.md +0 -3
  273. package/docs/deployment.md +2 -9
  274. package/docs/evals.md +2 -5
  275. package/docs/guides/agent-to-agent.md +0 -3
  276. package/docs/guides/bitbucket.md +0 -3
  277. package/docs/guides/cloud-agents.md +0 -4
  278. package/docs/guides/convert-automation.md +2 -5
  279. package/docs/guides/github.md +1 -4
  280. package/docs/guides/gitlab.md +0 -3
  281. package/docs/guides/grokbot-agents.md +1 -4
  282. package/docs/guides/hooks.md +0 -3
  283. package/docs/guides/improve.md +0 -3
  284. package/docs/guides/jev.md +0 -3
  285. package/docs/guides/mcp-oauth.md +1 -4
  286. package/docs/guides/opentelemetry.md +4 -5
  287. package/docs/guides/slack.md +14 -24
  288. package/docs/guides/webhooks.md +0 -3
  289. package/docs/hillclimbing.md +0 -3
  290. package/docs/quickstart.md +2 -7
  291. package/docs/reference/agent-config.md +4 -7
  292. package/docs/reference/artifacts.md +0 -3
  293. package/docs/reference/channels.md +1 -6
  294. package/docs/reference/cli.md +7 -14
  295. package/docs/reference/connections.md +7 -10
  296. package/docs/reference/evals.md +0 -3
  297. package/docs/reference/extensions.md +2 -5
  298. package/docs/reference/hooks.md +0 -3
  299. package/docs/reference/http-api.md +1 -1
  300. package/docs/reference/instructions.md +0 -3
  301. package/docs/reference/playground.md +0 -3
  302. package/docs/reference/project-layout.md +2 -2
  303. package/docs/reference/prompt.md +0 -3
  304. package/docs/reference/schedules.md +0 -3
  305. package/docs/reference/sessions.md +0 -3
  306. package/docs/reference/skills.md +0 -3
  307. package/docs/reference/subagents.md +0 -3
  308. package/docs/reference/tools.md +1 -5
  309. package/docs/templates/agentic-owners.md +2 -3
  310. package/docs/templates/grokbot-agents.md +60 -0
  311. package/docs/templates/security-reviewer.md +7 -11
  312. package/docs/templates/thermo-quality-review.md +5 -8
  313. package/docs/templates/thermo-review.md +5 -7
  314. package/docs/templates/triage.md +8 -4
  315. package/docs/troubleshooting.md +3 -7
  316. package/package.json +2 -2
  317. package/templates/agentic-owners/README.md +0 -3
  318. package/templates/agents-md/README.md +4 -3
  319. package/templates/agents-md/evals/agents.eval.ts +1 -0
  320. package/templates/code-wiki/README.md +0 -3
  321. package/templates/code-wiki/bot/instructions.md +4 -4
  322. package/templates/demo/README.md +0 -3
  323. package/templates/grokbot-agents/README.md +4 -6
  324. package/templates/security-help/README.md +12 -6
  325. package/templates/security-reviewer/README.md +5 -6
  326. package/templates/security-reviewer/bot/tools/post_findings.ts +8 -8
  327. package/templates/thermo-quality-review/README.md +0 -3
  328. package/templates/thermo-quality-review/bot/tools/post_findings.ts +8 -8
  329. package/templates/thermo-review/README.md +0 -3
  330. package/templates/thermo-review/bot/tools/post_findings.ts +8 -8
  331. package/templates/triage/README.md +0 -3
  332. package/templates/triage/overlays/jira/README.md +0 -3
  333. package/templates/triage/overlays/linear/README.md +0 -3
  334. package/dist/docs/assets/chunks/@localSearchIndexroot.CvuAJ0My.js +0 -1
  335. package/dist/docs/assets/chunks/channel.BoNycAoN.js +0 -1
  336. package/dist/docs/assets/chunks/classDiagram-6PBFFD2Q.C4x07Gkj.js +0 -1
  337. package/dist/docs/assets/chunks/classDiagram-v2-HSJHXN6E.C4x07Gkj.js +0 -1
  338. package/dist/docs/assets/chunks/clone.Db22cH_-.js +0 -1
  339. package/dist/docs/assets/chunks/stateDiagram-v2-QKLJ7IA2.CuqmyQc4.js +0 -1
  340. package/dist/docs/assets/chunks/wardley-RL74JXVD.844kyrjl.js +0 -162
  341. package/dist/docs/assets/index.md.CVc_oOA3.js +0 -27
  342. package/dist/docs/assets/reference_playground.md.BdQzRJc2.js +0 -1
  343. package/dist/docs/assets/reference_sessions.md.DeRUItHD.js +0 -1
  344. package/dist/docs/assets/templates_triage.md.CvJyx81N.js +0 -9
  345. package/dist/docs/assets/troubleshooting.md.Cw5PKa3t.js +0 -1
  346. /package/dist/docs/assets/{reference_http-api.md.BZOvhCqY.lean.js → reference_http-api.md.DbFNOubV.lean.js} +0 -0
  347. /package/dist/docs/assets/{reference_project-layout.md.CpLQ9j4K.lean.js → reference_project-layout.md.C2JMRh7p.lean.js} +0 -0
  348. /package/dist/docs/assets/{templates_agentic-owners.md.BykUiZ8j.lean.js → templates_agentic-owners.md.CvmABtia.lean.js} +0 -0
package/README.md CHANGED
@@ -1,1185 +1,107 @@
1
1
  # Grok Bot Development Kit (BDK)
2
2
 
3
- Grok Bot Development Kit (BDK) uses the `@cursor/bdk` package and `bdk`
4
- binary.
3
+ The Grok Bot Development Kit (BDK) is how Cursor builds bots and
4
+ agents. It is the open-source version of the engine behind Bugbot,
5
+ Security Review, and Approval Bot.
5
6
 
6
- Install the package to obtain the binary, then create and run a bot:
7
+ A BDK project is a folder of Markdown and TypeScript. Combine model
8
+ judgment with deterministic code, then make the result available in
9
+ source control, Slack, issue trackers, and Cursor.
7
10
 
8
- ```text
9
- npm install --global @cursor/bdk
10
- bdk init ./my-bot
11
- cd my-bot
12
- bdk dev
13
- ```
14
-
15
- BDK is a filesystem-first framework for building and serving Cursor bots and
16
- agents. Define a project as ordinary files: Markdown for prose and TypeScript
17
- for typed behavior. The framework discovers those files, compiles them into a
18
- manifest, and serves the project over channels with the Cursor SDK
19
- (`@cursor/sdk`) and harness as the execution engine.
20
-
21
- **User-facing documentation lives in [`docs/`](./docs/README.md)**.
22
- After the package publishes, open it with `bdk docs`, or at `/docs` on every
23
- running `bdk serve` host. It covers getting started, concepts, guides (Slack,
24
- GitHub webhooks, approvals, and agent-to-agent), evals, hillclimbing,
25
- deployment, troubleshooting, and reference pages for each folder. This README
26
- is the compact package reference.
27
-
28
- Instead of one large configuration object, each part of the agent gets a
29
- clear home. Instructions go in one file, tools in one folder, channels in
30
- another; a file's location says what it does, and its path gives it its
31
- name. There is no registry to keep in sync: add the file and it is
32
- discovered, move or rename it and its identity moves with it.
33
-
34
- ```text
35
- my-agent/
36
- ├── package.json
37
- └── bot/
38
- ├── agent.ts # runtime config: the Cursor model
39
- ├── instructions.md # the always-on system prompt
40
- ├── tools/
41
- │ └── get_weather.ts # one typed tool per file
42
- ├── skills/
43
- │ └── forecast.md # on-demand procedures (SKILL.md convention)
44
- ├── mcp-connections/
45
- │ └── linear.ts # tools from external MCP servers
46
- ├── subagents/
47
- │ └── researcher/ # specialist child agents
48
- ├── channels/
49
- │ └── webhook.ts # HTTP surfaces beyond the built-in session API
50
- ├── hooks/
51
- │ └── audit.ts # observe the runtime event stream
52
- ├── storage.ts # optional durable storage
53
- ├── artifacts.ts # optional artifact kinds and retention
54
- ├── result.ts # optional host commit on the final assistant text
55
- ├── otel.ts # optional OpenTelemetry export
56
- ├── playground/ # optional custom playground tool chips
57
- ├── schedules/
58
- │ └── heartbeat.md # cron-driven runs
59
- ├── sandbox/workspace/ # files seeded into each session's workspace
60
- └── lib/ # shared code (import-only, never discovered)
61
- ```
62
-
63
- Scaffold a starter project with `bdk init ./my-agent`. It writes
64
- `AGENTS.md`, `.gitignore`, `package.json`, `tsconfig.json`, `bot/agent.ts`,
65
- `bot/instructions.md`, `bot/tools/echo.ts`, and `bot/hooks/memory.ts`.
66
- The project serves immediately and type-checks with `npm run check`. From
67
- there, grow it folder by folder. The
68
- [docs](./docs/README.md) walk a weather agent from a single
69
- `get_weather` tool through skills, channels, evals, and deployment.
70
-
71
- Serve one project with `bdk serve --dir ./my-agent --dev`, or point
72
- `serve` at a folder of agent projects to mount every child under its
73
- directory name.
74
-
75
- ## Node only: do not run under Bun
76
-
77
- When published, `@cursor/bdk` requires **Node 22.13+** and supplies the
78
- `bdk` binary. Do not run it under Bun: Bun's HTTP/2 client
79
- corrupts the Cursor SDK's local harness tool-result streams
80
- (`NGHTTP2_FRAME_SIZE_ERROR`), so every built-in read/grep the model
81
- makes fails and turns degrade into failed-read retry loops.
82
-
83
- ## Serving many agents at once
84
-
85
- Point `serve` at a **folder of agent projects** and it hosts all of them on
86
- one port, each under its own slug (its directory name):
87
-
88
- ```text
89
- bdk serve --dir ./agents --dev
90
- # 2 agents listening
91
- # playground <printed URL>
92
- ```
93
-
94
- `serve` always uses multi-agent layout by default: agents are mounted under
95
- `/<slug>/v1/*` with an index at `/`. A directory that is itself an agent
96
- project is mounted under its directory name. Opt into the unslugged
97
- `/v1/*` surface with `serve(dir, { mode: "single" })`.
98
-
99
- In multi-agent mode:
100
-
101
- - `GET /` is a web index listing every agent, linking to its playground;
102
- `GET /v1/agents` is the JSON equivalent.
103
- - `GET /v1/health` is host-level liveness (for ALB/ECS); each agent also has
104
- `/<slug>/v1/health`.
105
- - each agent is fully namespaced: `/<slug>/v1/session`,
106
- `/<slug>/v1/session/:id/stream`, `/<slug>/playground`, `/<slug>/v1/info`,
107
- custom channels at `/<slug>/v1/channels/<id>`, etc.
108
- - sessions are isolated per agent (`<stateRoot>/<slug>/`), and the playground
109
- gains a "← all agents" link back to the index.
110
- - point the terminal client at a slug:
111
- `bdk chat --url http://127.0.0.1:3000/weather-agent`.
112
-
113
- Slugs come from directory names and must match `[A-Za-z0-9][A-Za-z0-9_-]*`
114
- and not collide with the reserved `v1` / `playground` / `docs` path
115
- segments.
116
-
117
- ## Agent-to-agent: every agent is an MCP server
118
-
119
- Every mounted agent also serves the **Model Context Protocol** over
120
- streamable HTTP at `/<slug>/v1/mcp` (or `/v1/mcp` in single mode), so other
121
- agents, and any MCP client, can delegate work to it. The surface is
122
- stateless (session identity travels in tool arguments) and runs the same
123
- route auth chain as the session API. Tools:
124
-
125
- | Tool | Behavior |
126
- | ---- | -------- |
127
- | `ask` | Send a message; runs a model turn in **this agent's own session, tools, and context** and returns `{ status, sessionId, reply }`. Omit `sessionId` for a fresh session; pass it to follow up. |
128
- | `check` | Wait for / poll a running session (`waitSeconds: 0` for a non-blocking poll). |
129
- | `call_tool` | Call one of the agent's deterministic server tools directly (no model turn). Registered only when the agent has server tools. |
130
-
131
- Waits are bounded (~50s, below MCP client request timeouts): a long turn
132
- returns `status: "running"` and the caller keeps waiting with `check`.
133
- Sessions created this way live on the `mcp` channel, bind to the calling
134
- principal, and show up in the playground and `GET /v1/sessions` like any
135
- other session.
136
-
137
- **Peer MCP connections** make delegation first-class between agents on the
138
- same host. Author an MCP connection whose transport is a peer slug:
139
-
140
- ```ts
141
- // agents/concierge/bot/mcp-connections/weather.ts
142
- import { defineConnection } from "@cursor/bdk/connections";
11
+ ## Why use it
143
12
 
144
- export default defineConnection({
145
- agent: "weather-agent",
146
- description: "Delegate weather questions to the weather agent.",
147
- });
148
- ```
149
-
150
- The parent model then sees the peer's `ask` / `check` (/ `call_tool`) tools
151
- under the `weather` server name: subagent-style delegation where the peer
152
- keeps its **own** instructions, tools, MCP connections, and sessions. Peer URLs
153
- resolve when the server starts, so `run` and `eval` ephemeral ports work.
154
- Local-runtime turns, host-side `ctx.host.mcp`, and channel handlers use
155
- loopback under the default `localDevStrict()` auth. Turns that do not run on
156
- the serve host require `--public-url`; without it, BDK omits peers from those
157
- turns and prints a warning.
158
-
159
- Unknown peer slugs and self-references fail at serve startup. Peers require
160
- the multi-agent layout (each agent mounted under its slug). There is no
161
- cross-host loop protection yet: if agent A's instructions delegate to B and
162
- B's delegate back to A, they can recurse. Scope each agent's delegation
163
- instructions narrowly (the concierge above delegates *weather questions* to
164
- `weather-agent`, not everything).
165
-
166
- ```text
167
- bdk serve --dir ./agents --dev
168
- bdk chat --url http://127.0.0.1:3000/concierge \
169
- --message "What's the weather in Paris right now?"
170
- # concierge → weather.ask → weather-agent's own session/tools → reply
171
- ```
172
-
173
- ## Quick start
174
-
175
- A minimal agent is two files.
13
+ - **Bots and agents live in your repo.** Review, version, and ship
14
+ instructions, tools, and evals with the rest of your code.
176
15
 
177
- `bot/instructions.md`:
16
+ - **Cursor runs the loop.** Your project gets Cursor's models, tool
17
+ calling, skills, MCP, and subagents.
178
18
 
179
- ```md
180
- You are a concise assistant. Use tools when they are available.
181
- ```
182
-
183
- `bot/agent.ts`:
184
-
185
- ```ts
186
- import { defineAgent } from "@cursor/bdk";
187
-
188
- export default defineAgent({
189
- // optional: defaults to grok-4.5 with effort=high and fast=true
190
- });
191
- ```
19
+ - **Use it where you work.** Trigger a project from source-control
20
+ events, Slack threads, custom webhooks, or schedules.
192
21
 
193
- Serve it (turns run on the Cursor harness, so the host needs a Cursor
194
- credential: sign in once, or export an API key):
22
+ - **Test normal TypeScript.** Add evals and unit tests without a
23
+ separate configuration language.
195
24
 
196
- ```text
197
- bdk login # browser sign-in; mints + stores a revocable API key
198
- # or: export CURSOR_API_KEY=key_...
199
- bdk serve --dir . --port 3000
200
- # e.g. playground at http://127.0.0.1:3000/<dirname>/playground
201
- ```
25
+ - **Choose where it runs.** Deploy to Cursor-managed hosting or run
26
+ the process on your infrastructure.
202
27
 
203
- Start a session, then follow the NDJSON event stream (replace `<slug>` with
204
- the agent directory name):
28
+ ## When to use BDK
205
29
 
206
- ```bash
207
- curl -X POST http://127.0.0.1:3000/<slug>/v1/session \
208
- -H 'content-type: application/json' \
209
- -d '{"message":"What can you do?"}'
210
- # {"ok":true,"sessionId":"ses_...","continuationToken":"http:..."}
30
+ | | Cursor Automations | Grok Bot | BDK |
31
+ | --- | --- | --- | --- |
32
+ | **Use for** | Repeatable jobs driven by a prompt and trigger | Interactive agents you work with in Cursor | Agents that need custom code, integrations, tests, or deployment choices |
33
+ | **You define** | A prompt, model, and trigger in the dashboard | Instructions, skills, and connected tools in the app | A versioned Markdown and TypeScript project |
34
+ | **Where it runs** | Cursor-managed | Cursor-managed | Cursor-managed hosting or your infrastructure |
35
+ | **Choose it when** | The job fits a schedule or event trigger | You want an agent without creating a software project | You want deterministic code around model judgment and a project your team can review and test |
211
36
 
212
- curl -N http://127.0.0.1:3000/<slug>/v1/session/ses_.../stream
213
- # {"type":"session.started",...}
214
- # {"type":"message.appended","data":{"delta":"I can","text":"I can"},...}
215
- # {"type":"message.completed",...}
216
- # {"type":"turn.completed",...}
217
- # {"type":"session.waiting",...}
218
- ```
37
+ ## Get started
219
38
 
220
- Send a follow-up to the same durable session with the continuation token
221
- from the previous response (each accepted follow-up rotates it):
39
+ BDK requires Node 22.13 or newer. Install `@cursor/bdk`, create a
40
+ project, and start the development server:
222
41
 
223
42
  ```bash
224
- curl -X POST http://127.0.0.1:3000/<slug>/v1/session/ses_... \
225
- -H 'content-type: application/json' \
226
- -d '{"continuationToken":"http:...","message":"Shorter, please."}'
227
- ```
228
-
229
- Inspect the discovered surface at any time:
230
-
231
- ```text
232
- bdk info --dir . # or GET /<slug>/v1/info on a running server
233
- bdk validate --dir . # exit non-zero on error diagnostics
234
- ```
235
-
236
- ## Terminal client
237
-
238
- `bdk chat` talks to a running server over the same public API and
239
- renders the reply live: streamed text, tool calls, and a per-turn usage
240
- footer. Pass `--json` for a compact trajectory (same shape as `run`).
241
-
242
- ```text
243
- # interactive REPL against a local server
244
- bdk chat --url http://127.0.0.1:3000
245
-
246
- # one-shot (good for piping / scripts)
247
- bdk chat --url http://127.0.0.1:3000 --message "Weather in Paris?"
248
-
249
- # JSON trajectory (for coding agents / scripts)
250
- bdk chat --url http://127.0.0.1:3000 --message "hello" --json
251
-
252
- # against an authed server
253
- bdk chat --url https://my-agent.example.com --bearer-token "$TOKEN"
254
- ```
255
-
256
- ## Agent loop
257
-
258
- Coding agents should prefer the JSON-first commands: edit files → inspect
259
- → run a turn → assert with filesystem evals.
260
-
261
- ```text
262
- bdk validate --dir .
263
- bdk info --dir . --json
264
-
265
- # Ephemeral server + one (or more) turns; JSON trajectory on stdout
266
- bdk run --dir . --message "What's the temperature in NYC?"
267
-
268
- # Optional event log for later summarization
269
- bdk run --dir . --message "..." --events /tmp/run.ndjson
270
- bdk trajectory --events /tmp/run.ndjson
271
-
272
- # Scaffold (or print the setup guide with no directory)
273
- bdk init ./my-agent
274
- bdk init
275
- ```
276
-
277
- `run` / `eval` boot a temporary server on port `0` with a temp `stateRoot`
278
- outside the project so session workspaces do not inherit ambient monorepo
279
- `AGENTS.md` / `.cursor` rules. Pass `--url` to target an already-running
280
- agent instead.
281
-
282
- ### Evals
283
-
284
- Author cases under `evals/**/*.eval.ts` with `defineEval`. Drive the
285
- agent and assert inline:
286
-
287
- ```ts
288
- import { defineEval, includes } from "@cursor/bdk/evals";
289
-
290
- export default defineEval({
291
- description: "Uses get_weather for temperature questions.",
292
- tags: ["smoke"],
293
- async test(t) {
294
- await t.send("What's the temperature in NYC?");
295
- t.succeeded();
296
- t.calledTool("get_weather");
297
- t.check(t.reply, includes(/°|[FC]/));
298
- },
299
- });
300
- ```
301
-
302
- Case id is the path under `evals/` for a single-`test` file, or
303
- `<fileId>/<case.id>` when using `cases` in one file.
304
-
305
- Use `t.judge` when wording needs an LLM grader. The built-in JUnit and
306
- Artifacts reporters write CI results and per-case evidence.
307
-
308
- Every project with evals needs `evals/evals.config.ts` with a required
309
- `maxConcurrency` (hard-capped at 200 due to model provider request limits).
310
- Playground batches are in-memory by default; declare an `evals` table in
311
- `bot/storage.ts` (`defineStorage`) to keep them across serve restarts.
312
- Optional `maxPlaygroundRuns` caps how many batches the playground /
313
- `/v1/dev/evals*` history keeps (default 20):
314
-
315
- ```ts
316
- import { defineEvalConfig } from "@cursor/bdk/evals";
317
-
318
- export default defineEvalConfig({
319
- maxConcurrency: 20,
320
- // Optional: playground /v1/dev/evals history window (default 20):
321
- // maxPlaygroundRuns: 50,
322
- });
323
- ```
324
-
325
- ```text
326
- bdk eval --dir . --list
327
- bdk eval --dir . --json
328
- bdk eval --dir . weather/nyc # one datapoint
329
- bdk eval --dir . weather # whole file
330
- bdk eval --dir . weather forecast # multiple files
331
- bdk eval --dir . --tag smoke
332
- ```
333
-
334
- See [`docs/`](./docs/README.md) for the full documentation set,
335
- [`AGENTS.md`](./AGENTS.md) for the coding-agent guide, and
336
- [`skills/`](./skills/) for task-shaped guides (create an agent, author
337
- evals, hillclimb, GitHub webhooks, Slack setup, debugging).
338
-
339
- ## Web playground
340
-
341
- Every served agent ships with a built-in playground. The default multi-agent
342
- mode serves it at `http://127.0.0.1:3000/<slug>/playground`.
343
- `--mode single` uses `http://127.0.0.1:3000/playground`. The playground
344
- uses the same public HTTP API for manual testing and demo recordings:
345
-
346
- - chat with the agent and watch text/reasoning stream live, rendered as
347
- markdown (headings, lists, tables, blockquotes, links) with syntax
348
- highlighting for fenced code blocks (C-like languages, Python, shell,
349
- and diffs),
350
- - invoke custom channels as **slash commands** in the composer (e.g. a
351
- `/drive https://github.com/org/repo/pull/1` channel route). Routes from `GET /v1/info`,
352
- with `/help` and autocomplete; same HTTP as the Agent surface **Try**
353
- buttons,
354
- - see tool calls inline (args, output, error state) as `actions.requested`
355
- / `action.result` events arrive,
356
- - browse the sessions you own (chat, custom-channel, and schedule
357
- task sessions) and replay their event streams. In `--dev` on loopback,
358
- or with `--allow-anonymous`, the list includes every principal,
359
- - dispatch schedules by hand in dev mode,
360
- - inspect the discovered agent surface (tools, skills, subagents, MCP
361
- connections, channels, hooks),
362
- - flip on the raw NDJSON pane to see the exact wire events.
363
-
364
- `bdk serve` serves the playground bundle. Disable it with
365
- `--no-playground` (CLI) or `serve(dir, { playground: false })`. When
366
- serving many agents, each has its own playground at `/<slug>/playground`
367
- and `/` is an index of them all (see "Serving many agents at once").
368
- `serve --dev` prints a playground URL; open that URL if the UI looks stale.
369
-
370
- To share the server beyond localhost (a tunnel, a LAN address, a phone),
371
- pass `--bearer-token <secret>` (or `serve(dir, { authToken })`). That
372
- replaces the loopback-only default with `bearerAuth(secret)` on every
373
- channel that doesn't author its own auth. The default
374
- `localDevStrict()` only admits direct loopback callers, rejects
375
- proxy-forwarding headers (`X-Forwarded-For`, `X-Real-IP`, `Forwarded`,
376
- `X-Forwarded-Host`), and requires a loopback `Host` header, so
377
- same-host reverse proxies / tunnels do not accidentally re-expose the
378
- default routes. Open the playground on the remote device and paste the
379
- token into the top-right field.
380
-
381
- Session follow-up, stream, and list routes also bind to the principal that
382
- created the session (`403` when a different admitted principal addresses
383
- someone else's handle).
384
-
385
- ## How it runs on the Cursor harness
386
-
387
- Each session is one Cursor SDK agent. Turns run on this host.
388
-
389
- Authored files reach the model as instructions, tools, skills, and
390
- workspace seed files. Sessions and their event
391
- streams survive server restarts. Reconnect with `?startIndex=` to
392
- replay.
393
-
394
- ## Folder structure
395
-
396
- ### `agent.ts`
397
-
398
- ```ts
399
- import { defineAgent } from "@cursor/bdk";
400
-
401
- export default defineAgent({
402
- model: {
403
- id: "grok-4.5",
404
- params: [
405
- { id: "effort", value: "high" },
406
- { id: "fast", value: "true" },
407
- ],
408
- }, // optional; this is the default
409
- });
410
- ```
411
-
412
- `model` accepts a Cursor model id string or `{ id, params }`. When omitted
413
- on the root agent, BDK defaults to `grok-4.5` with `effort=high`
414
- and `fast=true`.
415
-
416
- Turns use the Cursor SDK local harness on this machine. Authored tools,
417
- skills, and sandbox seeds apply.
418
-
419
- ### Instructions
420
-
421
- `bot/instructions.md` is the always-on system prompt (required on the
422
- root agent). When the prompt needs to be generated, use
423
- `bot/instructions.ts` with `defineInstructions({ markdown })` or a plain
424
- string default export, or split prose across a `bot/instructions/`
425
- directory (composed in filename order).
426
-
427
- ### Tools (`bot/tools/*.ts`)
428
-
429
- One file per tool; the filename is the tool name the model sees.
430
-
431
- `execution` chooses where the tool body runs:
432
-
433
- | Value | Behavior |
434
- | ----- | -------- |
435
- | `"server"` (default) | Runs on the serve host. Requires `execute`. |
436
- | `"agent"` | Materialized into the agent environment as a shell script. Requires `script` (JSON on stdin, result on stdout). |
437
-
438
- Server tool (default):
439
-
440
- ```ts
441
- import { defineTool } from "@cursor/bdk/tools";
442
- import { z } from "zod";
443
-
444
- export default defineTool({
445
- description: "Get the current weather for a city.",
446
- // execution: "server", // default
447
- inputSchema: z.object({ city: z.string() }),
448
- async execute({ city }, ctx) {
449
- return { city, condition: "Sunny", temperatureF: 72 };
450
- },
451
- });
452
- ```
453
-
454
- A server tool can call `decide` from
455
- [`@cursor/bdk/extensions/jev`](./docs/guides/jev.md) for a risk tier or
456
- a finding gate. Jev is not the turn model on `defineAgent`.
457
-
458
- Human-in-the-loop: set `needsApproval: true` (or an
459
- `(input) => boolean` predicate on validated args) so the host parks the in-flight
460
- tool call until a human approves or denies. The turn stays running; the
461
- stream emits `action.approval_requested` / `action.approval_resolved`.
462
-
463
- **Resolve surfaces** (park is always on when `needsApproval` is set):
464
-
465
- - Playground Approve / Deny buttons
466
- - HTTP: `POST /v1/session/:sessionId/approvals/:callId` with
467
- `{"decision":"approve"|"deny"}`
468
- - **Slack** (opt-in channel surface): set `toolApprovals: true` on
469
- `slackChannel`, and enable `interactivity` in the Slack app
470
- manifest:
471
-
472
- ```ts
473
- import { slackChannel } from "@cursor/bdk/channels/slack";
474
-
475
- export default slackChannel({
476
- credentials: { /* … */ },
477
- toolApprovals: true, // posts Block Kit Approve/Deny + routes clicks
478
- });
479
- ```
480
-
481
- Or compose the builders yourself:
482
-
483
- ```typescript
484
- import {
485
- buildDefaultEvents,
486
- buildToolApprovalEvents,
487
- slackChannel,
488
- } from "@cursor/bdk/channels/slack";
489
-
490
- export default slackChannel({
491
- deliverDefaults: false,
492
- // Required so Socket Mode routes Approve/Deny clicks when composing
493
- // buildToolApprovalEvents by hand (toolApprovals: true also enables this).
494
- interactivity: true,
495
- events: {
496
- ...buildDefaultEvents({ credentials }),
497
- ...buildToolApprovalEvents({ credentials }),
498
- },
499
- });
500
- ```
501
-
502
- In `--dev`, the playground can list and stream Slack sessions, and Approve/Deny
503
- parked tools on those sessions (audit `by` records the HTTP caller). That bridge
504
- does **not** open cross-owner approval for HTTP sessions. Production and
505
- bearer-auth hosts stay strict: Slack resolve must come from Slack interactivity
506
- (or a matching principal).
507
-
508
- `--allow-anonymous` is for trusted-network demos only. Every HTTP caller shares
509
- the same `anonymous` principal. Prefer `--bearer-token` when the host is shared.
510
-
511
- Slack cards show **redacted / truncated** args for Block Kit limits; execution
512
- still uses the full validated tool input. Review sensitive tools in the
513
- playground or a private surface when args may exceed the card.
514
-
515
- Example tool:
516
-
517
- ```ts
518
- export default defineTool({
519
- description: "Post a weather alert to ops.",
520
- needsApproval: true,
521
- inputSchema: z.object({
522
- city: z.string(),
523
- message: z.string(),
524
- }),
525
- async execute({ city, message }) {
526
- return { posted: true, city, message };
527
- },
528
- });
529
- ```
530
-
531
- Approvals are only supported for `execution: "server"` tools on the
532
- `local` runtime. Exact resume of a parked SDK tool call does **not**
533
- survive host process restart. Pending approvals left after a crash are
534
- treated as interrupted.
535
- Agent tool (runs in the Cursor agent workspace):
536
-
537
- ```ts
538
- import { defineTool } from "@cursor/bdk/tools";
539
- import { z } from "zod";
540
-
541
- export default defineTool({
542
- description: "Echo a message from the agent workspace.",
543
- execution: "agent",
544
- inputSchema: z.object({ message: z.string() }),
545
- script: `#!/usr/bin/env bash
546
- set -euo pipefail
547
- message=$(python3 -c 'import json,sys; print(json.load(sys.stdin)["message"])')
548
- printf '%s\\n' "$message"
549
- `,
550
- });
43
+ npm install --global @cursor/bdk
44
+ bdk init ./my-bot
45
+ cd my-bot
46
+ bdk dev
551
47
  ```
552
48
 
553
- `inputSchema` is a Zod schema (validated and typed for server tools) or a
554
- plain JSON Schema object (forwarded as-is). `outputSchema` advertises a
555
- structured result schema. The host doesn't validate results against it.
556
- Plain objects fill `structuredContent` automatically. Envelope results set
557
- it explicitly next to `content` and `isError`. For server tools, `ctx` carries
558
- `{ toolCallId, session, workspaceDir }`.
559
-
560
- #### Deterministic tool calls
561
-
562
- Server tools can also be called **deterministically**. You pick the tool
563
- and the input, no model turn decides anything. The input is validated
564
- against the tool's schema and `execute` runs in-process; the result comes
565
- back exactly as the model would receive it. No Cursor API key is needed.
566
-
567
- Over HTTP (`POST /v1/tools/:toolName`, same auth chain as the session API):
49
+ For a one-off scaffold without a global install:
568
50
 
569
51
  ```bash
570
- curl -X POST http://127.0.0.1:3000/<slug>/v1/tools/get_weather \
571
- -H 'content-type: application/json' \
572
- -d '{"input":{"city":"NYC"}}'
573
- # {"ok":true,"toolName":"get_weather","callId":"tool_get_weather_...",
574
- # "isError":false,"result":{...},"durationMs":12}
52
+ npx @cursor/bdk init ./my-bot
575
53
  ```
576
54
 
577
- From the CLI (boots an ephemeral server unless `--url` targets a running
578
- one):
55
+ Open the project in Cursor. BDK uses `bot/` for the agent and keeps
56
+ `evals/` at the project root:
579
57
 
580
58
  ```text
581
- bdk call get_weather --dir . --input '{"city":"NYC"}'
582
- bdk call get_weather --url http://127.0.0.1:3000/<slug> --input '{"city":"NYC"}'
583
- ```
584
-
585
- Programmatically, `callTool(toolName, input, options?)` is available on the
586
- serve handle, on channel route handlers and `onStart` args, and on schedule
587
- `run` handlers, so a channel can mix deterministic tool calls with model
588
- turns (e.g. fetch PR metadata deterministically, then `send()` the review
589
- prompt):
590
-
591
- ```ts
592
- const outcome = await handle.callTool("get_weather", { city: "NYC" });
593
- // { toolName, callId, isError, result, durationMs }
594
- ```
595
-
596
- By default the tool runs against an ephemeral scratch workspace,
597
- materialized like a session workspace (AGENTS.md, skills, seed files)
598
- and removed once the call returns. Pass `sessionId` (body field over
599
- HTTP, `--session` on the CLI, `options.sessionId` programmatically) to
600
- run it inside an existing session instead: the tool sees that session's
601
- info and materialized workspace, and the call is recorded on the
602
- session's event stream as `actions.requested` / `action.result` under a
603
- per-call `turnId`. That call is visible in the playground, NDJSON
604
- trace, and trajectories like any model-initiated call. Session-bound
605
- writes are serialized with model turns: while a turn is running a
606
- write-effect call is rejected with `409 session_busy`, while a
607
- read-effect call runs alongside the turn.
608
-
609
- Unknown tools are rejected with the available tool names, `execution:
610
- "agent"` tools cannot be called on the host (400), schema-invalid input is a
611
- 400 before the tool body runs (zod schemas validate; plain JSON Schema
612
- inputs pass through unvalidated, matching the model path), and a tool body
613
- that throws is reported as `isError: true` with the same
614
- `{ content, isError }` envelope the model would see.
615
-
616
- ### Skills (`bot/skills/*`)
617
-
618
- Skills follow the `SKILL.md` convention: model-loadable procedures the
619
- harness advertises by description and loads on demand. Author them as flat
620
- markdown (`skills/forecast.md`, optional `description` frontmatter. The
621
- first body line is the fallback), packaged directories
622
- (`skills/research/SKILL.md` plus `references/…`, which require `description`
623
- frontmatter), or TypeScript (`defineSkill` from
624
- `@cursor/bdk/skills`) when content must be generated.
625
-
626
- ### MCP connections (`bot/mcp-connections/*.ts`)
627
-
628
- ```ts
629
- import { defineConnection } from "@cursor/bdk/connections";
630
-
631
- export default defineConnection({
632
- url: "https://mcp.linear.app/mcp",
633
- headers: { authorization: `Bearer ${process.env.LINEAR_TOKEN}` },
634
- });
635
- ```
636
-
637
- The filename becomes the MCP server name. `{ command, args, env, cwd }`
638
- declares a local stdio server instead. `{ tools }` authors TypeScript
639
- handlers that BDK packages as stdio MCP for the agent
640
- environment, including a repo-less cloud VM. `{ agent: "<slug>" }` declares a
641
- **peer MCP connection** to another agent mounted on the same serve host (see
642
- "Agent-to-agent: every agent is an MCP server").
643
-
644
- `{ cursorAccount: true }` declares a **Cursor account MCP connection**: the
645
- agent gets the MCP connectors the signed-in Cursor account already
646
- authorized (dashboard → MCP) with zero token plumbing. Every tool executes
647
- on the Cursor backend with the account's stored OAuth credentials; raw
648
- tokens never reach the serve host, session workspaces, or traces. Omit
649
- `servers`, or pass `servers: "*"`, to forward every connected HTTP/SSE
650
- connector. Pass `servers: ["Linear", ...]` to expose only named connectors.
651
-
652
- ```ts
653
- // bot/mcp-connections/account.ts: every connected connector
654
- export default defineConnection({
655
- cursorAccount: true,
656
- advertiseTools: true,
657
- });
658
- // same, spelled out:
659
- export default defineConnection({
660
- cursorAccount: true,
661
- servers: "*",
662
- advertiseTools: true,
663
- });
664
- // only Linear:
665
- export default defineConnection({
666
- cursorAccount: true,
667
- servers: ["Linear"],
668
- advertiseTools: true,
669
- });
670
- ```
671
-
672
- Name the file `account.ts`. `cursor.ts` collides with the IDE `cursor` MCP
673
- namespace. `advertiseTools: true` puts connector tools on local turns by
674
- name.
675
-
676
- Requirements and behavior:
677
-
678
- - The host must be signed in (`bdk login`, `CURSOR_API_KEY`, or `CURSOR_SERVICE_ACCOUNT_KEY`);
679
- `serve` fails fast at startup otherwise, and logs each connector's live
680
- status (`connected` / `needsAuth` / `error`) as it starts.
681
- - Local turns and host-side calls go through a loopback bridge route guarded
682
- by a per-boot secret.
683
- - Backend execution covers the account's HTTP/SSE servers; stdio servers
684
- cannot run server-side (author a `{ command }` MCP connection for those).
685
- - **Exposure**: whoever can talk to the agent can drive these connectors
686
- (they are ordinary agent tools). `serve` refuses to start when
687
- `--allow-anonymous` is combined with Cursor account MCP connections; use
688
- `--bearer-token` on shared hosts.
689
-
690
- Every MCP connection is available in three places:
691
-
692
- 1. the Cursor agent, via SDK `mcpServers`
693
- 2. the serve host, for in-process tools via `ctx.host.mcp`
694
- 3. channel / schedule handlers, via `args.host.mcp` (deterministic; no agent loop)
695
-
696
- ```ts
697
- export default defineTool({
698
- description: "Search Linear issues.",
699
- inputSchema: z.object({ query: z.string() }),
700
- async execute({ query }, ctx) {
701
- return ctx.host.mcp.callTool("linear", "list_issues", { query });
702
- },
703
- });
704
- ```
705
-
706
- ```ts
707
- // bot/channels/webhook.ts: call MCP directly from a webhook
708
- POST("/sync", {
709
- bodySchema: z.object({}),
710
- handler: async (_req, { host }) => {
711
- const result = await host.mcp.callTool("linear", "list_issues", {});
712
- return Response.json(result);
713
- },
714
- });
715
- ```
716
-
717
- `host.mcp.names()` lists MCP connection names; `listTools(name)` and
718
- `callTool(name, tool, args)` open the client lazily on first use.
719
-
720
- ### Subagents (`bot/subagents/<id>/`)
721
-
722
- A subagent is its own directory with the same `agent.ts` +
723
- `instructions.md` shape. `description` is required. The parent model reads
724
- it to decide when to delegate, and `model` is optional (`inherit` by
725
- default). On the Cursor harness, subagents run as SDK custom subagents:
726
- they inherit the parent's execution surface, so per-subagent `tools/`,
727
- `skills/`, and `mcp-connections/` are reported as warnings and ignored for now.
728
-
729
- ### Extensions (`bot/extensions/<ns>.ts`)
730
-
731
- An extension is a package of agent contributions mounted with one file;
732
- the filename is the namespace and every contribution appears as
733
- `<ns>__<name>`. A Cursor plugin mounts the same way with `cursorPlugin`.
734
-
735
- ```ts
736
- // bot/extensions/ci.ts
737
- import ci from "@acme/ci-triage";
738
- export default ci({ org: "acme", token: process.env.BUILDKITE_TOKEN! });
739
-
740
- // bot/extensions/notion.ts
741
- import { cursorPlugin } from "@cursor/bdk/extensions";
742
- export default cursorPlugin({
743
- path: "plugins/notion-workspace",
744
- variables: { NOTION_TOKEN: process.env.NOTION_TOKEN! },
745
- });
746
- ```
747
-
748
- Mount as a directory (`bot/extensions/<ns>/extension.ts`) to overlay
749
- any slot; `disableTool()`, `disableConnection()`, and `disable()` remove
750
- a contribution. Mounting a plugin trusts it like authored code. Details
751
- in [Extensions](./docs/reference/extensions.md).
752
-
753
- ### Channels (`bot/channels/*.ts`)
754
-
755
- The **built-in HTTP channel** is always mounted (under `/<slug>` in the
756
- default multi-agent layout; at the server root with `mode: "single"`):
757
-
758
- - `POST /v1/session`: start a session (`{"message": "..."}`; returns
759
- `sessionId` + `continuationToken`)
760
- - `POST /v1/session/:sessionId`: follow-up (`{"message", "continuationToken"}`;
761
- rotates the token; works for any chat session including custom channels like
762
- `drive`; `409` on stale tokens or task sessions;
763
- `403` if the caller is not the session owner)
764
- - `GET /v1/session/:sessionId/stream?startIndex=N`: replay + live NDJSON
765
- (same owner check)
766
- - `GET /v1/session/:sessionId/approvals`: pending human-in-the-loop
767
- tool approvals for the session
768
- - `POST /v1/session/:sessionId/approvals/:callId`: approve or deny
769
- (`{"decision":"approve"|"deny"}`)
770
- - `GET /v1/sessions`: sessions owned by the calling principal
771
- - `POST /v1/tools/:toolName`: call a server tool deterministically
772
- (`{"input": {...}, "sessionId"?}`; see "Deterministic tool calls")
773
- - `GET /v1/health`, `GET /v1/info`: liveness and the manifest snapshot
774
-
775
- **Custom channels** declare their own routes (mounted under
776
- `/v1/channels/<id>`), observe stream events for the sessions they own, and
777
- control their continuation-token format (e.g. a thread id):
778
-
779
- ```ts
780
- import { defineChannel, POST } from "@cursor/bdk/channels";
781
- import { z } from "zod";
782
-
783
- export default defineChannel({
784
- routes: [
785
- POST("/message", {
786
- description: "Enqueue a chat turn on this channel",
787
- bodySchema: z.object({
788
- message: z.string(),
789
- thread: z.string().optional(),
790
- }),
791
- handler: async (_req, { send, body }) => {
792
- const { message, thread } = body;
793
- // `auth` defaults to the request principal resolved by the auth chain.
794
- const session = await send(message, {
795
- continuationToken: thread, // stable key: same thread, same session
796
- });
797
- return Response.json({ sessionId: session.id });
798
- },
799
- }),
800
- ],
801
- events: {
802
- "message.completed"(event, channel, ctx) {
803
- // deliver the reply back to the surface that owns this channel
804
- },
805
- },
806
- });
807
- ```
808
-
809
- `GET` requires a Zod `querySchema` and `POST` / `PUT` / `PATCH` require a
810
- Zod `bodySchema` at compile time. Plain JSON Schema objects will not
811
- type-check. Use `z.object({})` or `z.unknown()` when the surface is
812
- intentionally open. Schemas are validated by the host before the handler
813
- runs (handlers get typed `args.body` / `args.query`) and projected on
814
- `GET /v1/info` so the playground Agent surface can **Try** the route, and
815
- so the composer can offer matching **slash commands** (e.g. `/drive`).
816
-
817
- Route handlers receive a Fetch `Request` and helpers: `send`, `getSession`,
818
- `receive` (cross-channel hand-off), `params`, `requestIp`, `auth`, `host`
819
- (shared host services: MCP / GitHub / Slack; same as tool `ctx.host`), and
820
- `waitUntil`. Channel `state` declares initial per-session adapter state,
821
- persisted across events; handlers receive it on `channel.state`.
822
-
823
- **Auth**: channel routes and the session API run an auth-policy chain
824
- (`auth` on the channel). The host index, docs, and health routes run no
825
- auth. The default policy is `[localDevStrict()]`: direct loopback
826
- callers only, with proxy-forwarding headers and non-loopback `Host`
827
- rejected, so nothing is exposed publicly until you add real auth
828
- (`bearerAuth(...)`, a custom policy, or the explicit `allowAll()`).
829
-
830
- **Slack** (`@cursor/bdk/channels/slack`): a platform channel pack
831
- that defaults to **Socket Mode**. Author `bot/channels/slack.ts` with
832
- `slackChannel()`:
833
-
834
- ```ts
835
- import { slackChannel } from "@cursor/bdk/channels/slack";
836
-
837
- // Single agent: SLACK_BOT_TOKEN + SLACK_APP_TOKEN
838
- export default slackChannel();
839
-
840
- // Multi-agent serve: one Slack app (and token pair) per agent
841
- export default slackChannel({ envPrefix: "WEATHER_AGENT" });
842
- // → WEATHER_AGENT_SLACK_BOT_TOKEN + WEATHER_AGENT_SLACK_APP_TOKEN
843
- ```
844
-
845
- Transport uses `@slack/socket-mode` + `@slack/web-api`. Socket Mode starts
846
- on channel mount when both tokens are present; otherwise the channel stays
847
- **idle** (`channel idle … missing credentials`) so multi-agent serve can
848
- mount agents that do not have Slack tokens configured yet.
849
-
850
- The pack dispatches via `waitUntil`, streams assistant text (`chat.startStream` /
851
- `appendStream` / `stopStream`) with postMessage fallback, shows rotating status
852
- + tool thinking steps, and sets thread titles / suggested prompts. Handlers may
853
- return a prepared `message` or `workspaceFiles` to host-prepare PR
854
- reviews from an `@mention`.
855
-
856
- **Engagement:** by default the agent is summoned, never proactive. It
857
- dispatches only on `app_mention` and DMs. Channel watch is an explicit opt-in:
858
-
859
- ```ts
860
- export default slackChannel({
861
- envPrefix: "TRIAGE",
862
- engagement: {
863
- // mentions / directMessages default to true
864
- channelPosts: {
865
- allow: ["#triage-alerts"], // explicit allowlist only; no wildcard
866
- posts: "top-level", // default: never dispatch on thread replies
867
- debounceMs: 15_000, // optional: let rapid edits settle
868
- },
869
- },
870
- onChannelPost: async (ctx, message) => {
871
- // Same contract as onAppMention: return null to skip.
872
- return message.markdown.length > 20 ? {} : null;
873
- },
874
- });
875
- ```
876
-
877
- Watched posts dispatch with the same thread-scoped principal as mentions
878
- (so a later `@mention` continues the session) plus an
879
- `engagement: "channel_post"` auth attribute. Posts that mention the bot are
880
- left to the `app_mention` path; bot-authored posts never dispatch; deleting
881
- a post inside the debounce window cancels its dispatch. The Slack app must
882
- subscribe to `message.channels` / `message.groups`
883
- (`bdk slack create --channel-posts`) and be a member of each watched channel. Watched channels surface in
884
- `info` via `meta.slackChannelPosts`.
885
-
886
- **HITL compose:** park/resume is independent (`needsApproval` on tools). Opt in
887
- to Slack delivery with `toolApprovals: true` (or spread
888
- `buildToolApprovalEvents` into `events` and set `interactivity: true` on
889
- `slackChannel` so Approve/Deny buttons resolve). That posts Block Kit
890
- Approve/Deny cards and routes Socket Mode `interactive` clicks to
891
- `resolveApproval`. Enable `interactivity: true` on
892
- `buildSlackManifest` when you use that surface. Threads bind with
893
- `continuationToken = channelId:threadTs`. Dev and prod are
894
- **separate Slack apps**. Requires `SLACK_BOT_TOKEN` + `SLACK_APP_TOKEN`
895
- (App-Level Token with `connections:write`).
896
-
897
- `bdk slack create` mints one dedicated bot and writes
898
- `<DIR>_SLACK_*` plus `envPrefix` from the directory name. Keep the
899
- channel file as `slack-app.ts` when the same app should carry tool
900
- approvals or channel watch.
901
-
902
- For Socket Mode apps (channel watch / approvals), run
903
- `bdk slack create`. It opens the dashboard wizard, creates and
904
- installs the app, and writes the token pair to `.env.local`. To own the
905
- Slack app yourself, run `bdk slack init --manual` and paste the
906
- manifests at api.slack.com.
907
-
908
- CLI (`bdk slack …`; guided setup in `skills/setup-slack/SKILL.md`):
909
-
910
- ```text
911
- bdk slack create --dir ./my-agent # dashboard wizard (dev app)
912
- bdk slack create --dir ./my-agent --prod # prod app
913
- bdk slack init --manual --dir ./my-agent # manifests for api.slack.com
914
- bdk slack setup
915
- bdk slack doctor --prefix MY_AGENT
916
- ```
917
-
918
- **GitHub** (`@cursor/bdk/channels/github`): a webhook channel pack
919
- (Eve-compatible dispatch). Author `bot/channels/github.ts` with
920
- `githubChannel()` and declare inbound hooks:
921
-
922
- ```ts
923
- import { defaultGitHubAuth, githubChannel } from "@cursor/bdk/channels/github";
924
-
925
- export default githubChannel({
926
- botName: "my-agent", // or GITHUB_APP_SLUG
927
- cursorAccount: {
928
- repos: ["owner/repo"],
929
- // permissions?: "read" | "pr-write" | "contents-write" (default pr-write)
930
- },
931
- onPullRequest: (ctx, pr) =>
932
- pr.action === "opened" ? { auth: defaultGitHubAuth(ctx) } : null,
933
- onCheckSuite: (ctx, suite) =>
934
- suite.conclusion === "failure" ? { task: () => triage(ctx) } : null,
935
- });
936
- ```
937
-
938
- Mounts at `POST /<slug>/v1/channels/github`. When a webhook secret is set the
939
- channel verifies `X-Hub-Signature-256` before parsing (the HMAC becomes the
940
- request auth); without one it stays loopback-only (`localDevStrict()`), except
941
- under `serve --dev`, which admits unsigned loopback deliveries so
942
- `gh webhook forward` and fixtures work with zero config. Hooks return
943
- `{ auth }` to start a model turn as the actor, `{ task }` for host-side work
944
- (202 ACK, runs past GitHub's ~10s timeout), or `null` to skip.
945
-
946
- **Testing GitHub agents locally.** `cursorAccount` uses the host Cursor
947
- credential (`bdk login`, `CURSOR_API_KEY`, or
948
- `CURSOR_SERVICE_ACCOUNT_KEY`) for both Cursor SCM events and a refreshing
949
- repo-scoped GitHub credential used
950
- by `ctx.github`, `ctx.host.github`, and child `gh` commands. Default
951
- `permissions: "pr-write"` covers comments without `contents:write`; opt up to
952
- `"contents-write"` when the agent must push or post merge-box checks.
953
- Enabling `progress.commitStatus` opts hosted `cursorAccount` up to that
954
- tier so github-proxy mints `checks:write`. Without `cursorAccount`, API
955
- auth prefers GitHub App installation tokens when `GITHUB_APP_ID` /
956
- `GITHUB_APP_PRIVATE_KEY` (and an installation id) are set, then falls back to
957
- `GITHUB_TOKEN` / `GH_TOKEN` or `gh auth login`. The channel publishes the
958
- webhook events it dispatches on (derived from the declared hooks, or pinned
959
- via `webhookEvents`), so `bdk github …` can forward live
960
- deliveries with zero hand-listing. It wraps [`gh webhook
961
- forward`](https://docs.github.com/en/webhooks/testing-and-troubleshooting-webhooks/using-the-github-cli-to-forward-webhooks-for-testing):
962
-
963
- ```text
964
- # One-time: gh + the cli/gh-webhook extension
965
- bdk github doctor --install
966
-
967
- # Terminal A: serve the agent (dev accepts unsigned loopback deliveries)
968
- bdk serve --dir ./my-agent --dev
969
-
970
- # Terminal B: forward this repo's deliveries to the discovered github channel
971
- # (URL + events auto-derived; repo inferred from the git remote). No secret
972
- # needed against a --dev server; set GITHUB_WEBHOOK_SECRET to verify signatures.
973
- bdk github forward --dir ./my-agent
974
-
975
- # Inspect what would be forwarded (URL + events per agent)
976
- bdk github events --dir ./agents --json
977
-
978
- # Forward to EVERY discovered github channel at once
979
- bdk github forward --dir ./agents
980
- ```
981
-
982
- When several channels match (e.g. a folder of agent projects with more than
983
- one github channel), one forwarder fans out to all of them: `gh webhook
984
- forward` runs against a local proxy that re-posts each raw (still-signed)
985
- delivery to the channels whose event set matches. This is required. GitHub
986
- allows only one forwarder per repo, and `gh webhook forward` targets a single
987
- URL, so N processes would collide with `Hook already exists`.
988
-
989
- `gh webhook forward` needs **admin** on the repo (or org owner for `--org`).
990
- It registers a real webhook, and authenticates its relay with the GitHub CLI's
991
- own login. If `GITHUB_TOKEN` / `GH_TOKEN` is set in your env, deliveries fail
992
- with **HTTP 401** (the relay rejects env tokens); blank it for the command
993
- (`GITHUB_TOKEN= GH_TOKEN= bdk github forward …`) or `unset` it.
994
- `bdk github doctor` / `forward` warn when they detect this.
995
-
996
- Pass `--repo owner/repo` / `--org ORG` to override the inferred target,
997
- `--events a,b,c` to narrow the set, `--url` for a custom endpoint (e.g. a
998
- tunnel), and `--slug` / `--channel` to forward to just one of several agents.
999
- Against a `--dev` server no secret is needed; set `GITHUB_WEBHOOK_SECRET` (or
1000
- `--secret`) to exercise signature verification (required for a non-dev target).
1001
- Only one forwarder per repo/org at a time (a GitHub limitation). Fixture replay
1002
- still works too: `POST` a saved payload with an `x-github-event` header (no
1003
- signature needed in `--dev`).
1004
-
1005
- **No admin? Hillclimbing? Use `github replay`.** `gh webhook forward` needs repo
1006
- admin and a live event. `bdk github replay <pr_url>` instead **reads**
1007
- the PR (pull access is enough: no admin, no relay, and `GITHUB_TOKEN` is fine)
1008
- and synthesizes GitHub-shaped payloads it POSTs straight at the channel:
1009
-
1010
- ```text
1011
- # Replay a pull_request delivery for a PR to the discovered channel
1012
- bdk github replay https://github.com/owner/repo/pull/123 --dir ./my-agent
1013
-
1014
- # Replay everything the channel listens for (its declared events), CI failing
1015
- bdk github replay owner/repo#123 --dir ./my-agent --events '*' --conclusion failure
1016
-
1017
- # Inspect payloads without POSTing (and snapshot them as reusable fixtures)
1018
- bdk github replay owner/repo#123 --dir ./my-agent --events '*' --dry-run --out fixtures/github
1019
- ```
1020
-
1021
- `--events` defaults to `pull_request` (`*` = the channel's declared events);
1022
- `--action` / `--conclusion` / `--comment` / `--context` tune each synthesized
1023
- event; `--secret` (or `GITHUB_WEBHOOK_SECRET`) signs them so a secret-configured
1024
- channel verifies. Because replay sends a clean, signed loopback request, it
1025
- passes both the `localDevStrict()` and `allowAll()`+signature auth modes, and
1026
- it's fully deterministic, which is what hillclimbing wants.
1027
-
1028
- **Production alternative: pull from Cursor (`--cursor-events`).** If the
1029
- Cursor GitHub App is on the repo, `serve --cursor-events --repo owner/repo`
1030
- long-polls `/v0/scm-events` with the host's Cursor account (no public URL /
1031
- repo admin). Offset + consumer id live under `<state-root>/cursor-events/`.
1032
- The stream is read as your Cursor user, so the flag **requires a signed-in
1033
- host** (`bdk login`, `CURSOR_API_KEY`, `CURSOR_SERVICE_ACCOUNT_KEY`, or `serve({ apiKey })`).
1034
- Serve fails fast rather than starting with a relay that can never receive
1035
- events.
1036
-
1037
- ### Hooks (`bot/hooks/*.ts`)
1038
- Observe-only subscribers that run after each event is recorded: audit
1039
- logs, metrics, mirroring transcripts into your own store. Keys are event
1040
- types (or `*`); handler errors are logged, never fatal.
1041
-
1042
- ### Schedules (`bot/schedules/*`)
1043
-
1044
- Markdown form (fire-and-forget task session):
1045
-
1046
- ```md
1047
- ---
1048
- cron: "0 9 * * 1-5"
1049
- ---
1050
-
1051
- Pull open incidents and post a summary to the metrics endpoint.
1052
- ```
1053
-
1054
- Handler form (full control, hand off to a channel):
1055
-
1056
- ```ts
1057
- import { defineSchedule } from "@cursor/bdk/schedules";
1058
- import webhook from "../channels/webhook.js";
1059
-
1060
- export default defineSchedule({
1061
- cron: "*/30 * * * *",
1062
- async run({ receive, waitUntil, appAuth, mcp }) {
1063
- // optional: await mcp.callTool("units", "celsius_to_fahrenheit", { value: 0 });
1064
- waitUntil(
1065
- receive(webhook, {
1066
- message: "Check for new critical alerts. Report only when there are any.",
1067
- auth: appAuth,
1068
- })
1069
- );
1070
- },
1071
- });
1072
- ```
1073
-
1074
- Cron expressions are standard 5-field, evaluated in UTC with minute
1075
- granularity. In production mode (`bdk serve`) schedules fire on
1076
- cadence; in dev mode (`--dev`) they never fire automatically. Dispatch one
1077
- by hand, exactly once, through the same path production uses:
59
+ my-bot/
60
+ ├── package.json
61
+ ├── bot/
62
+ │ ├── agent.ts
63
+ │ ├── instructions.md
64
+ │ ├── tools/
65
+ │ ├── skills/
66
+ │ ├── mcp-connections/
67
+ │ ├── subagents/
68
+ │ ├── channels/
69
+ │ ├── hooks/
70
+ │ └── schedules/
71
+ └── evals/
72
+ ```
73
+
74
+ Describe the bot or agent in Cursor, or edit the files yourself.
75
+
76
+ ## Start from a template
77
+
78
+ Pass a template to `bdk init` when one matches your goal:
79
+
80
+ | Template | Capability |
81
+ | --- | --- |
82
+ | `grokbot-agents` | Consult named Grok Bot agents |
83
+ | `security-reviewer` | Review pull requests for exploitable bugs |
84
+ | `thermo-quality-review` | Review structural code quality |
85
+ | `thermo-review` | Review bugs and breakage |
86
+ | `agentic-owners` | Apply owners policies to pull requests |
87
+ | `triage-linear` or `triage-jira` | Triage tracker issues |
1078
88
 
1079
89
  ```bash
1080
- curl -X POST http://127.0.0.1:3000/<slug>/v1/dev/schedules/heartbeat
1081
- # {"scheduleId":"heartbeat","sessionIds":["ses_..."]}
90
+ bdk init ./security-reviewer --template security-reviewer
91
+ bdk init ./grokbot --template grokbot-agents
1082
92
  ```
1083
93
 
1084
- ## Sessions, events, and streaming
1085
-
1086
- Two handles do two jobs: the **continuation token** resumes a conversation
1087
- (owned by the channel; one active continuation per session, stale tokens
1088
- rejected), and the **session id** streams and inspects it (owned by the
1089
- runtime).
1090
-
1091
- ### Reminders
1092
-
1093
- Per-session durable wakes (distinct from deploy-time `bot/schedules/`):
1094
-
1095
- ```ts
1096
- await handle.createReminder({
1097
- purpose: "ci_recheck",
1098
- channelId: "drive",
1099
- continuationToken: "pr-owner-repo-1",
1100
- delay: "2h",
1101
- prompt: "Re-check CI. Only act if still failing.",
1102
- until: "Cancel once CI is green or the PR is merged.",
1103
- });
1104
- ```
1105
-
1106
- Host/policy packs may pass `run` (return `stop` / `skip` / `delivered`)
1107
- instead of prompts. `--dev` does not auto-fire reminders. Dispatch one
1108
- with `POST /v1/dev/reminders/:id` or `handle.dispatchReminder`. Run
1109
- handlers are in-memory. After a restart those reminders are disarmed
1110
- (`handler_lost_on_restart`); re-arm from enroll/policy.
1111
-
1112
- The NDJSON stream vocabulary: one JSON object per line, each carrying
1113
- `{ type, index, sessionId, turnId?, at, data }`:
1114
-
1115
- | Event | Meaning |
1116
- | --------------------- | -------------------------------------------------------------- |
1117
- | `session.started` | A durable session was created. |
1118
- | `message.received` | An inbound user message was accepted. |
1119
- | `turn.started` | A turn began. |
1120
- | `step.started` / `step.completed` | Model step boundaries (with duration). |
1121
- | `reasoning.appended` / `reasoning.completed` | Reasoning deltas and the block end. |
1122
- | `message.appended` | Assistant text delta (with cumulative text so far). |
1123
- | `message.completed` | A finalized assistant text block (`finishReason`: `stop` or `tool_call`). |
1124
- | `actions.requested` | The model requested a tool call (streams before execution). |
1125
- | `action.approval_requested` | A `needsApproval` tool is parked awaiting a human. |
1126
- | `action.approval_resolved` | Human approved or denied the parked tool call. |
1127
- | `action.result` | A tool call returned (`output`, `isError`). |
1128
- | `subagent.called` / `subagent.completed` | Delegation to a subagent. |
1129
- | `turn.completed` | The turn finished (`result`, `usage`). |
1130
- | `turn.failed` | The turn failed (`message`). |
1131
- | `session.waiting` | The session parked, ready for the next message. |
1132
- | `session.completed` / `session.failed` | Terminal states for task-mode (schedule) sessions. |
1133
-
1134
- The stream is durable: reconnect with `?startIndex=<n>` to replay from any
1135
- point, or from 0 to rewind the whole session.
1136
-
1137
- ## Serving programmatically
1138
-
1139
- ```ts
1140
- import { serve } from "@cursor/bdk";
1141
-
1142
- const handle = await serve("./my-agent", {
1143
- port: 3000,
1144
- apiKey: process.env.CURSOR_API_KEY, // optional: see credential order below
1145
- });
1146
- console.log(`listening on ${handle.url}`);
1147
- // handle.dispatchSchedule("heartbeat"), handle.project, await handle.close()
1148
- ```
1149
-
1150
- The Cursor credential resolves in one order everywhere (SDK turns and
1151
- Cursor account MCP connections): explicit `apiKey` option / `--api-key`
1152
- → `CURSOR_API_KEY` → `CURSOR_API_KEY_FILE` (hosted default
1153
- `/run/cursor/secrets/CURSOR_API_KEY` when unset) → `CURSOR_SERVICE_ACCOUNT_KEY`
1154
- → the key stored by `bdk login`. A bind file wins over
1155
- `CURSOR_SERVICE_ACCOUNT_KEY`. `whoami` shows
1156
- which one is active; `logout` removes the stored key (revoke it in the
1157
- Cursor dashboard to kill it outright).
1158
-
1159
- Local-dev note: login/account RPCs honor `CURSOR_API_BASE_URL` while the
1160
- Cursor SDK harness honors `CURSOR_BACKEND_URL`. When pointing at a
1161
- non-production backend, set **both** to the same URL. A key minted on one
1162
- backend is rejected by the other.
1163
-
1164
- `serve` refuses to start when discovery produced error diagnostics; run
1165
- `bdk validate` (or read `project.diagnostics`) to see why.
1166
-
1167
- State lives under the project state directory (override with
1168
- `--state-root`). Forget a conversation by removing that session from
1169
- state.
94
+ `--template triage` selects `triage-linear`.
1170
95
 
1171
- Session workspaces are real Cursor project directories, so the harness
1172
- also loads ambient project config from ancestor directories. Nested git
1173
- checkouts default `local.cwd` to a per-project cache directory under
1174
- `~/.cache`. Point `cwd` at a checkout only when the agent should inherit
1175
- that tree.
96
+ ## Next steps
1176
97
 
1177
- ## Not supported (yet)
98
+ Run `bdk docs` to open the full documentation. By default,
99
+ `bdk serve` also serves the same documentation at `/docs`.
1178
100
 
1179
- BDK does not load per-subagent tools, skills, or MCP connections.
1180
- It also rejects nested subagents, WebSocket channel routes, and custom
1181
- sandbox backends. Discord and Teams do not have channel packs. Use an
1182
- authored `defineChannel` integration for those platforms.
101
+ The docs include:
1183
102
 
1184
- Parked approval calls do not resume after a host restart. Context compaction
1185
- is owned by the Cursor harness.
103
+ - A complete PR reviewer quickstart
104
+ - GitHub, Slack, webhook, and MCP guides
105
+ - Evals and hillclimbing
106
+ - Deployment and troubleshooting
107
+ - Project layout, CLI, and API reference