cade-cli 0.13.3__tar.gz → 0.14.0__tar.gz

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 (175) hide show
  1. {cade_cli-0.13.3 → cade_cli-0.14.0}/PKG-INFO +52 -36
  2. {cade_cli-0.13.3 → cade_cli-0.14.0}/README.md +51 -35
  3. {cade_cli-0.13.3 → cade_cli-0.14.0}/pyproject.toml +1 -1
  4. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cade_mcp_local/server.py +13 -0
  5. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cade_mcp_local/tools/__init__.py +5 -0
  6. cade_cli-0.14.0/src/cade_mcp_local/tools/agents.py +151 -0
  7. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cade_mcp_local/tools/notifications.py +2 -2
  8. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/ai/prompts.py +33 -19
  9. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/cli/app.py +156 -115
  10. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/cli/commands/account.py +3 -1
  11. cade_cli-0.14.0/src/cadecoder/cli/commands/agents.py +440 -0
  12. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/cli/commands/auth.py +0 -19
  13. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/cli/commands/chat.py +4 -23
  14. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/cli/commands/hooks.py +60 -59
  15. cade_cli-0.14.0/src/cadecoder/cli/commands/mem.py +221 -0
  16. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/cli/commands/serve.py +64 -3
  17. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/cli/commands/tasks.py +19 -7
  18. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/cli/commands/thread.py +1 -1
  19. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/cli/commands/tools.py +48 -31
  20. cade_cli-0.14.0/src/cadecoder/core/agent.py +501 -0
  21. cade_cli-0.14.0/src/cadecoder/core/comms.py +177 -0
  22. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/core/config.py +25 -203
  23. cade_cli-0.14.0/src/cadecoder/core/inbox.py +138 -0
  24. cade_cli-0.14.0/src/cadecoder/core/memory.py +76 -0
  25. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/core/paths.py +57 -19
  26. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/core/runtime.py +27 -10
  27. {cade_cli-0.13.3/src/cadecoder/serve → cade_cli-0.14.0/src/cadecoder/core}/secrets.py +15 -5
  28. cade_cli-0.14.0/src/cadecoder/core/spawn.py +215 -0
  29. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/execution/orchestrator.py +2 -2
  30. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/hooks/__init__.py +9 -3
  31. cade_cli-0.14.0/src/cadecoder/hooks/config.py +193 -0
  32. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/providers/__init__.py +8 -3
  33. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/providers/anthropic.py +3 -3
  34. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/providers/openai.py +4 -2
  35. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/serve/__init__.py +1 -1
  36. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/serve/allowlist.py +2 -2
  37. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/serve/config.py +52 -53
  38. cade_cli-0.14.0/src/cadecoder/serve/cron.py +37 -0
  39. cade_cli-0.14.0/src/cadecoder/serve/daemon.py +661 -0
  40. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/serve/install.py +50 -27
  41. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/serve/observability.py +3 -1
  42. cade_cli-0.14.0/src/cadecoder/serve/owner.py +44 -0
  43. cade_cli-0.14.0/src/cadecoder/serve/secrets.py +24 -0
  44. cade_cli-0.14.0/src/cadecoder/serve/services.py +309 -0
  45. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/serve/worker.py +65 -0
  46. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/tasks/__init__.py +1 -8
  47. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/tasks/store.py +4 -4
  48. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/tasks/types.py +0 -9
  49. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/templates/serve/launchd.plist.tmpl +1 -1
  50. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/templates/serve/systemd.service.tmpl +2 -2
  51. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/tools/manager/composite.py +279 -132
  52. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/tools/manager/config.py +25 -20
  53. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/tools/manager/mcp.py +230 -94
  54. cade_cli-0.14.0/src/cadecoder/ui/completion.py +74 -0
  55. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/ui/display.py +13 -7
  56. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/ui/input.py +49 -13
  57. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/ui/session.py +219 -116
  58. cade_cli-0.14.0/src/cadecoder/ui/slash.py +84 -0
  59. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/voice/session.py +22 -2
  60. cade_cli-0.13.3/src/cadecoder/cli/commands/channels.py +0 -79
  61. cade_cli-0.13.3/src/cadecoder/cli/commands/context.py +0 -205
  62. cade_cli-0.13.3/src/cadecoder/cli/commands/mem.py +0 -176
  63. cade_cli-0.13.3/src/cadecoder/cli/commands/model.py +0 -255
  64. cade_cli-0.13.3/src/cadecoder/cli/commands/persona.py +0 -572
  65. cade_cli-0.13.3/src/cadecoder/hooks/config.py +0 -151
  66. cade_cli-0.13.3/src/cadecoder/serve/daemon.py +0 -383
  67. cade_cli-0.13.3/src/cadecoder/storage/personas.py +0 -243
  68. cade_cli-0.13.3/src/cadecoder/tasks/channels.py +0 -89
  69. cade_cli-0.13.3/src/cadecoder/tasks/notifications.py +0 -100
  70. cade_cli-0.13.3/src/cadecoder/ui/slash.py +0 -47
  71. {cade_cli-0.13.3 → cade_cli-0.14.0}/.gitignore +0 -0
  72. {cade_cli-0.13.3 → cade_cli-0.14.0}/LICENSE +0 -0
  73. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cade_mcp_local/__init__.py +0 -0
  74. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cade_mcp_local/__main__.py +0 -0
  75. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cade_mcp_local/_metadata.py +0 -0
  76. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cade_mcp_local/config.py +0 -0
  77. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cade_mcp_local/errors.py +0 -0
  78. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cade_mcp_local/resources.py +0 -0
  79. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cade_mcp_local/tools/_read_cache.py +0 -0
  80. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cade_mcp_local/tools/context.py +0 -0
  81. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cade_mcp_local/tools/filesystem.py +0 -0
  82. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cade_mcp_local/tools/git.py +0 -0
  83. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cade_mcp_local/tools/questions.py +0 -0
  84. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cade_mcp_local/tools/results.py +0 -0
  85. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cade_mcp_local/tools/schemas.py +0 -0
  86. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cade_mcp_local/tools/search.py +0 -0
  87. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cade_mcp_local/tools/shell.py +0 -0
  88. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cade_mcp_local/tools/snippets.py +0 -0
  89. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cade_mcp_local/tools/tasks.py +0 -0
  90. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cade_mcp_local/tools/web_fetch.py +0 -0
  91. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cade_mcp_local/tools/web_search.py +0 -0
  92. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cade_mcp_local/utils.py +0 -0
  93. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cade_mcp_local/web/__init__.py +0 -0
  94. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cade_mcp_local/web/arcade_client.py +0 -0
  95. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cade_mcp_local/web/cache.py +0 -0
  96. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cade_mcp_local/web/extract.py +0 -0
  97. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cade_mcp_local/web/markdown.py +0 -0
  98. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cade_mcp_local/web/preapproved.py +0 -0
  99. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cade_mcp_local/web/prompts.py +0 -0
  100. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cade_mcp_local/web/scrape.py +0 -0
  101. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cade_mcp_local/web/search/__init__.py +0 -0
  102. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cade_mcp_local/web/search/arcade.py +0 -0
  103. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cade_mcp_local/web/search/base.py +0 -0
  104. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cade_mcp_local/web/search/http.py +0 -0
  105. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/__init__.py +0 -0
  106. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/ai/__init__.py +0 -0
  107. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/cli/__init__.py +0 -0
  108. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/cli/auth.py +0 -0
  109. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/cli/commands/__init__.py +0 -0
  110. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/cli/commands/cron.py +0 -0
  111. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/cli/commands/mcp.py +0 -0
  112. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/core/__init__.py +0 -0
  113. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/core/constants.py +0 -0
  114. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/core/errors.py +0 -0
  115. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/core/frozen.py +0 -0
  116. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/core/git.py +0 -0
  117. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/core/logging.py +0 -0
  118. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/core/model_specs.py +0 -0
  119. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/core/names.py +0 -0
  120. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/core/types.py +0 -0
  121. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/execution/__init__.py +0 -0
  122. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/execution/context_window.py +0 -0
  123. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/execution/mcp_schema_index.py +0 -0
  124. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/execution/parallel.py +0 -0
  125. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/execution/tool_result_store.py +0 -0
  126. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/execution/tool_schema_cache.py +0 -0
  127. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/hooks/engine.py +0 -0
  128. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/hooks/executors/__init__.py +0 -0
  129. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/hooks/executors/callback.py +0 -0
  130. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/hooks/executors/command.py +0 -0
  131. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/hooks/executors/http.py +0 -0
  132. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/hooks/executors/prompt.py +0 -0
  133. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/hooks/executors/ssrf_guard.py +0 -0
  134. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/hooks/matchers.py +0 -0
  135. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/hooks/registry.py +0 -0
  136. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/hooks/types.py +0 -0
  137. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/providers/base.py +0 -0
  138. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/providers/ollama.py +0 -0
  139. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/serve/adapters/__init__.py +0 -0
  140. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/serve/adapters/base.py +0 -0
  141. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/serve/adapters/desktop.py +0 -0
  142. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/serve/adapters/registry.py +0 -0
  143. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/serve/adapters/stub.py +0 -0
  144. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/serve/adapters/telegram.py +0 -0
  145. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/serve/chunker.py +0 -0
  146. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/serve/commands.py +0 -0
  147. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/serve/elicitation.py +0 -0
  148. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/serve/format.py +0 -0
  149. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/serve/lock.py +0 -0
  150. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/serve/progress_sink.py +0 -0
  151. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/serve/router.py +0 -0
  152. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/serve/sinks.py +0 -0
  153. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/storage/__init__.py +0 -0
  154. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/storage/threads.py +0 -0
  155. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/tasks/lock.py +0 -0
  156. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/tasks/scheduler.py +0 -0
  157. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/templates/login_failed.html +0 -0
  158. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/templates/login_success.html +0 -0
  159. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/templates/serve/serve.toml.example +0 -0
  160. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/templates/styles.css +0 -0
  161. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/tools/__init__.py +0 -0
  162. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/tools/manager/__init__.py +0 -0
  163. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/tools/manager/_request_ctx.py +0 -0
  164. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/tools/manager/base.py +0 -0
  165. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/tools/search/__init__.py +0 -0
  166. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/tools/search/discovered.py +0 -0
  167. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/tools/search/scoring.py +0 -0
  168. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/tools/search/service.py +0 -0
  169. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/ui/__init__.py +0 -0
  170. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/ui/elicitation.py +0 -0
  171. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/voice/__init__.py +0 -0
  172. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/voice/audio.py +0 -0
  173. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/voice/cleanup.py +0 -0
  174. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/voice/stt.py +0 -0
  175. {cade_cli-0.13.3 → cade_cli-0.14.0}/src/cadecoder/voice/tts.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cade-cli
3
- Version: 0.13.3
3
+ Version: 0.14.0
4
4
  Summary: Cade - The CLI Agent from Arcade.dev
5
5
  Project-URL: Homepage, https://arcade.dev
6
6
  Project-URL: Documentation, https://docs.arcade.dev
@@ -91,7 +91,7 @@ Description-Content-Type: text/markdown
91
91
  The CLI agent from [Arcade.dev](https://arcade.dev). Coding, research, and everyday automation — driven from a terminal, a single shell pipe, or a long-lived daemon that replies over Telegram.
92
92
 
93
93
  ```bash
94
- brew install ArcadeAI/tap/cade # or: uv tool install cade-cli | pip install cade-cli
94
+ curl -fsSL https://arcadeagent.dev/install | sh # or: uv tool install cade-cli | pip install cade-cli
95
95
  cade login
96
96
  cade
97
97
  ```
@@ -101,10 +101,10 @@ cade
101
101
  ## Highlights
102
102
 
103
103
  - **Three deployment modes from the same binary.** Interactive chat (`cade`), one-shot or pipe (`cade -m "…"`), or a headless daemon that replies over messaging (`cade serve`).
104
- - **Tools from anywhere.** Built-in local tools (filesystem / shell / git / search / tasks / channels / memory), [Arcade Cloud](https://arcade.dev) tools (Slack, GitHub, Gmail, calendars, …), and any [MCP](https://modelcontextprotocol.io/) server you register — all unified under one tool surface.
104
+ - **Tools from anywhere.** Built-in local tools (filesystem / shell / git / search / tasks / memory), [Arcade Cloud](https://arcade.dev) tools (Slack, GitHub, Gmail, calendars, …), and any [MCP](https://modelcontextprotocol.io/) server you register — all unified under one tool surface.
105
105
  - **Bidirectional MCP.** Tools can call `context.ui.elicit(…)` for structured input, `context.log.*` for live operator logs, and `context.progress.report(…)` for editable progress UI — routed end-to-end through whichever adapter is active (Telegram inline keyboard, terminal prompt).
106
- - **Personas + per-persona memory.** Multiple agent profiles with their own system prompt and an indexed memory store backed by [agent-library](https://pypi.org/project/agent-library/).
107
- - **Extensibility surface.** Hooks (lifecycle events), tasks (file-backed durable work), cron (scheduled prompts), channels (cross-session pub/sub) — all available to the agent as `Local_*` tools and to you as `cade <subcommand>`.
106
+ - **Agents + per-agent memory.** Multiple agents, each with their own model, system prompt, tools, and an indexed memory store backed by [agent-library](https://pypi.org/project/agent-library/).
107
+ - **Extensibility surface.** Hooks (lifecycle events), tasks (durable work), cron (scheduled prompts) — all available to the agent as `Local_*` tools and to you as `cade <subcommand>`.
108
108
  - **Bring your own LLM.** OpenAI, Anthropic, or any OpenAI-compatible endpoint (Ollama, vLLM, Together, Groq, Fireworks, …). `--local-only` skips Arcade Cloud entirely.
109
109
 
110
110
  ---
@@ -113,12 +113,21 @@ cade
113
113
 
114
114
  | Source | Command |
115
115
  |---|---|
116
- | Homebrew | `brew install ArcadeAI/tap/cade` |
116
+ | **Install script** (recommended) | `curl -fsSL https://arcadeagent.dev/install \| sh` |
117
117
  | uv | `uv tool install cade-cli` |
118
118
  | pip | `pip install cade-cli` |
119
119
  | From source | `git clone https://github.com/arcadeai-labs/cade.git && cd cade && uv sync` |
120
120
 
121
- Homebrew installs from a private release feed. Export `HOMEBREW_GITHUB_API_TOKEN` (a token with read access to `arcadeai-labs/cade`) before running `brew install`.
121
+ The install script detects your OS/arch, downloads the matching prebuilt binary
122
+ (macOS arm64, Linux x64), verifies its checksum, and drops `cade` in
123
+ `~/.local/bin` — no GitHub token required. Pin a version or install location:
124
+
125
+ ```bash
126
+ CADE_VERSION=0.14.0 CADE_INSTALL_DIR=/usr/local/bin \
127
+ sh -c "$(curl -fsSL https://arcadeagent.dev/install)"
128
+ ```
129
+
130
+ (Windows: grab the `.zip` from the releases page, or `pip install cade-cli`.)
122
131
 
123
132
  **Prerequisites:** Python 3.11+, an Arcade account ([arcade.dev](https://arcade.dev)) for cloud tools, and an LLM provider key (`OPENAI_API_KEY` or `ANTHROPIC_API_KEY`). Skip the Arcade account with `--local-only` or `CADE_LOCAL_ONLY=1`.
124
133
 
@@ -138,9 +147,9 @@ Full install and first-run docs: [`docs/install.md`](./docs/install.md) and
138
147
  cade # interactive chat
139
148
  cade -m "What changed in HEAD?" # single message, then exit
140
149
  cade -m "What went wrong?" < error.log # prompt + file/stdin
141
- cade -r # resume the most recent thread
150
+ cade resume # resume the most recent thread
142
151
  cade resume "auth-rewrite" # resume a thread by name
143
- cade --persona reviewer # use a saved persona's system prompt
152
+ cade use reviewer # switch the current agent
144
153
  cade --voice # speak / hear (requires cade-cli[voice])
145
154
  ```
146
155
 
@@ -148,10 +157,8 @@ cade --voice # speak / hear (requires cade-cli[voi
148
157
 
149
158
  | Flag | Description |
150
159
  |---|---|
151
- | `-r`, `--resume` | Resume most recent thread |
152
160
  | `-m`, `--message` | Single-message mode; piped stdin is appended to the prompt |
153
- | `-P`, `--persona` | Use a saved persona |
154
- | `-V`, `--voice` | Voice mode; install `cade-cli[voice]` first |
161
+ | `--voice` | Voice mode; install `cade-cli[voice]` first |
155
162
  | `-v`, `--verbose` | Debug logging |
156
163
  | `--version` | Print version |
157
164
 
@@ -165,7 +172,7 @@ cade --voice # speak / hear (requires cade-cli[voi
165
172
  | `/logs` | Recent log entries |
166
173
  | `/thread`, `/history` | Current thread info |
167
174
  | `/pin`, `/unpin` | Pin reference material into the session |
168
- | `/tasks`, `/cron`, `/hooks`, `/channels`, `/notify` | Coordination surfaces (mirrored as `cade tasks` / `cade cron` / `cade hooks` / `cade channels`) |
175
+ | `/tasks`, `/cron`, `/hooks`, `/notify` | Coordination surfaces (mirrored as `cade tasks` / `cade cron` / `cade hooks`) |
169
176
  | `/usage` | Context-window status and token usage |
170
177
  | `/cd`, `/pwd`, `/!` | Shell shortcuts |
171
178
  | `Ctrl+C` | Exit |
@@ -177,7 +184,7 @@ cade --voice # speak / hear (requires cade-cli[voi
177
184
  Tools come from three sources and are addressed uniformly by their registered name:
178
185
 
179
186
  - **`Local_*`** — built-in: filesystem (`ReadFile`, `WriteFile`, `Edit`, `ListFiles`), shell (`Bash`), `Search`, `Git`, `Task*`, `AskUserQuestion`, `RetrieveToolResult`, `ToolSchema`, `PinContext`, `PushNotification`, `WebFetch`, and `WebSearch`.
180
- - **`Memory_*`** — agent-library backed, per-persona indexed knowledge store.
187
+ - **`Memory_*`** — agent-library backed, per-agent indexed knowledge store.
181
188
  - **Arcade Cloud + user MCP servers** — anything you register.
182
189
 
183
190
  ```bash
@@ -198,37 +205,46 @@ cade mcp authorize my-server # OAuth flow (browser)
198
205
  cade mcp list / status / test / enable / disable / rm
199
206
  ```
200
207
 
201
- User MCP servers register at `~/.cade/config/contexts/<context>.toml [[mcp]]`. Servers with large catalogs are auto-deferred (parameter schemas stripped to keep tool-list bytes down) and fetched on demand via `Local_ToolSchema`.
208
+ User MCP servers register on the agent's `~/.cade/config/agents/<name>.toml [[mcp]]` list (with `cade.toml [agent_defaults].mcp` as the shared default). Servers with large catalogs are auto-deferred (parameter schemas stripped to keep tool-list bytes down) and fetched on demand via `Local_ToolSchema`.
202
209
 
203
210
  ---
204
211
 
205
- ## Personas + memory
212
+ ## Agents + memory
213
+
214
+ Each **agent** bundles a model, system prompt, tools, and memory. The current
215
+ agent is ambient — most commands act on it.
206
216
 
207
217
  ```bash
208
- cade persona list / create / get / edit / delete / default # manage system prompts
209
- cade --persona reviewer # use one for a session
218
+ cade new reviewer --prompt "You are a meticulous code reviewer." # create + switch
219
+ cade list # all agents
220
+ cade use reviewer # switch the current agent
221
+ cade info / cade edit reviewer # inspect / change config
210
222
 
211
- cade mem list # sources indexed for the active persona
223
+ cade mem # the current agent's memory (status)
212
224
  cade mem add ~/notes # index a directory
213
225
  cade mem search "auth design" # semantic search
214
226
  ```
215
227
 
216
- Memory is persona-scoped — each persona has its own `~/.cade/data/contexts/<context>/memory/<persona>/.librarian/` index, so a `reviewer` persona's notes never leak into `default`.
228
+ Memory is per-agent — each agent has its own
229
+ `~/.cade/data/agents/<id>/memory/.librarian/` index, so a `reviewer` agent's
230
+ notes never leak into another.
217
231
 
218
232
  ---
219
233
 
220
234
  ## Headless daemon: `cade serve`
221
235
 
222
- Run Cade as a long-lived daemon that replies through adapters. Telegram is supported for personal bot workflows, and Desktop exposes a local WebSocket for native clients. Each conversation gets its own persistent thread — persona, memory, and tools carry across messages.
236
+ Run Cade as a long-lived daemon that replies through adapters. Telegram is supported for personal bot workflows, and Desktop exposes a local WebSocket for native clients. Each conversation gets its own persistent thread — model, memory, and tools carry across messages.
223
237
 
224
238
  ```bash
225
239
  cade serve init # wizard: bot token, allowed senders
226
- cade serve # foreground
240
+ cade serve # foreground (current agent)
241
+ cade serve --agent ops # serve a specific agent (one daemon per agent)
242
+ cade serve list # agents with a running daemon
227
243
  cade serve --install launchd # macOS LaunchAgent (or --install systemd)
228
244
  cade serve status / stop # health, uptime; SIGTERM running daemon
229
245
  ```
230
246
 
231
- Config lives at `~/.cade/config/contexts/<context>.toml [serve]`. Edit and `kill -HUP $(cat ~/.cade/run/serve.pid)` to reload without restart.
247
+ Each agent's serve config lives in `~/.cade/config/agents/<name>.toml [serve]`. Edit and `kill -HUP $(cat ~/.cade/run/agents/<name>/serve.pid)` to reload without restart.
232
248
 
233
249
  **Security defaults are fail-closed:** `allowed_senders = []` blocks everyone; tools are default-deny against `[serve.tools].allow` (globs / regex / pipe lists supported); `deny` always wins.
234
250
 
@@ -236,18 +252,19 @@ The MCP transport is fully bidirectional, so tools running inside the daemon can
236
252
 
237
253
  ---
238
254
 
239
- ## Extensibility: hooks, tasks, cron, channels
255
+ ## Extensibility: hooks, tasks, cron
240
256
 
241
- Four primitives the agent uses directly (as `Local_*` tools) and you can drive from the CLI:
257
+ Three primitives the agent uses directly (as `Local_*` tools) and you can drive from the CLI:
242
258
 
243
259
  | Surface | What it is | CLI |
244
260
  |---|---|---|
245
261
  | **Hooks** | Lifecycle event handlers (pre/post tool, user prompt submit) | `cade hooks list / add / remove / test` |
246
- | **Tasks** | File-backed durable work units that survive turn boundaries | `cade tasks list / get / create / update / delete` |
262
+ | **Tasks** | Durable work units that survive turn boundaries | `cade tasks list / get / create / update / delete` |
247
263
  | **Cron** | Scheduled prompts the agent runs on a timer | `cade cron list / add / remove / enable / disable / run-now` |
248
- | **Channels** | JSONL-backed inter-session pub/sub | `cade channels list / send / recv / clear` |
249
264
 
250
- See [`docs/channels.md`](./docs/channels.md) for the channels protocol; hooks and tasks/cron details live in their respective `cade <subcommand> --help` outputs.
265
+ Cross-agent messaging is set up with `cade link` / `cade channel` (an agent can only
266
+ reach another it's been linked to). Hooks and tasks/cron details live in their
267
+ respective `cade <subcommand> --help` outputs.
251
268
 
252
269
  ---
253
270
 
@@ -259,9 +276,9 @@ Cade works with any OpenAI-compatible endpoint. Three ways to wire one in (CLI f
259
276
  # CLI flag for Ollama. Use a model from `ollama list`.
260
277
  cade chat -L --endpoint http://localhost:11434 --model qwen3:4b
261
278
 
262
- # Environment for one-shot mode
263
- cade context create local-qwen --model qwen3:4b
264
- cade context use local-qwen
279
+ # Or create a dedicated agent for the local model
280
+ cade new local-qwen --model qwen3:4b
281
+ cade use local-qwen
265
282
  export OLLAMA_BASE_URL="http://localhost:11434"
266
283
  CADE_LOCAL_ONLY=1 cade -m "hello from a local model"
267
284
 
@@ -281,12 +298,11 @@ All state lives under `~/.cade/`. Override the location with `CADE_HOME=/path/to
281
298
 
282
299
  | File | Purpose |
283
300
  |---|---|
284
- | `config/cade.toml` | Model / provider / UI settings |
285
- | `data/contexts/<context>/history.db` | Thread + message storage |
301
+ | `config/cade.toml` | Global settings + `[agent_defaults]` (model, provider, UI, …) |
302
+ | `config/agents/<name>.toml` | Per-agent config (model, prompt, `[[mcp]]`, `[serve]`, hooks) |
303
+ | `data/agents/<id>/` | Per-agent state: `threads/ memory/ tasks/ inbox/` |
304
+ | `run/agents/<name>/` | Per-agent daemon runtime: `serve.pid`, mcp-services, cron lease |
286
305
  | `logs/cade.log` | Rotating log file |
287
- | `config/contexts/<context>.toml [[mcp]]` | User MCP server registry |
288
- | `config/contexts/<context>.toml [serve]` | `cade serve` daemon config |
289
- | `personas/`, `memory/`, `tasks/`, `channels/` | Persona-scoped state |
290
306
 
291
307
  Full layout, env vars, and TOML schema in [`docs/configuration.md`](./docs/configuration.md).
292
308
 
@@ -3,7 +3,7 @@
3
3
  The CLI agent from [Arcade.dev](https://arcade.dev). Coding, research, and everyday automation — driven from a terminal, a single shell pipe, or a long-lived daemon that replies over Telegram.
4
4
 
5
5
  ```bash
6
- brew install ArcadeAI/tap/cade # or: uv tool install cade-cli | pip install cade-cli
6
+ curl -fsSL https://arcadeagent.dev/install | sh # or: uv tool install cade-cli | pip install cade-cli
7
7
  cade login
8
8
  cade
9
9
  ```
@@ -13,10 +13,10 @@ cade
13
13
  ## Highlights
14
14
 
15
15
  - **Three deployment modes from the same binary.** Interactive chat (`cade`), one-shot or pipe (`cade -m "…"`), or a headless daemon that replies over messaging (`cade serve`).
16
- - **Tools from anywhere.** Built-in local tools (filesystem / shell / git / search / tasks / channels / memory), [Arcade Cloud](https://arcade.dev) tools (Slack, GitHub, Gmail, calendars, …), and any [MCP](https://modelcontextprotocol.io/) server you register — all unified under one tool surface.
16
+ - **Tools from anywhere.** Built-in local tools (filesystem / shell / git / search / tasks / memory), [Arcade Cloud](https://arcade.dev) tools (Slack, GitHub, Gmail, calendars, …), and any [MCP](https://modelcontextprotocol.io/) server you register — all unified under one tool surface.
17
17
  - **Bidirectional MCP.** Tools can call `context.ui.elicit(…)` for structured input, `context.log.*` for live operator logs, and `context.progress.report(…)` for editable progress UI — routed end-to-end through whichever adapter is active (Telegram inline keyboard, terminal prompt).
18
- - **Personas + per-persona memory.** Multiple agent profiles with their own system prompt and an indexed memory store backed by [agent-library](https://pypi.org/project/agent-library/).
19
- - **Extensibility surface.** Hooks (lifecycle events), tasks (file-backed durable work), cron (scheduled prompts), channels (cross-session pub/sub) — all available to the agent as `Local_*` tools and to you as `cade <subcommand>`.
18
+ - **Agents + per-agent memory.** Multiple agents, each with their own model, system prompt, tools, and an indexed memory store backed by [agent-library](https://pypi.org/project/agent-library/).
19
+ - **Extensibility surface.** Hooks (lifecycle events), tasks (durable work), cron (scheduled prompts) — all available to the agent as `Local_*` tools and to you as `cade <subcommand>`.
20
20
  - **Bring your own LLM.** OpenAI, Anthropic, or any OpenAI-compatible endpoint (Ollama, vLLM, Together, Groq, Fireworks, …). `--local-only` skips Arcade Cloud entirely.
21
21
 
22
22
  ---
@@ -25,12 +25,21 @@ cade
25
25
 
26
26
  | Source | Command |
27
27
  |---|---|
28
- | Homebrew | `brew install ArcadeAI/tap/cade` |
28
+ | **Install script** (recommended) | `curl -fsSL https://arcadeagent.dev/install \| sh` |
29
29
  | uv | `uv tool install cade-cli` |
30
30
  | pip | `pip install cade-cli` |
31
31
  | From source | `git clone https://github.com/arcadeai-labs/cade.git && cd cade && uv sync` |
32
32
 
33
- Homebrew installs from a private release feed. Export `HOMEBREW_GITHUB_API_TOKEN` (a token with read access to `arcadeai-labs/cade`) before running `brew install`.
33
+ The install script detects your OS/arch, downloads the matching prebuilt binary
34
+ (macOS arm64, Linux x64), verifies its checksum, and drops `cade` in
35
+ `~/.local/bin` — no GitHub token required. Pin a version or install location:
36
+
37
+ ```bash
38
+ CADE_VERSION=0.14.0 CADE_INSTALL_DIR=/usr/local/bin \
39
+ sh -c "$(curl -fsSL https://arcadeagent.dev/install)"
40
+ ```
41
+
42
+ (Windows: grab the `.zip` from the releases page, or `pip install cade-cli`.)
34
43
 
35
44
  **Prerequisites:** Python 3.11+, an Arcade account ([arcade.dev](https://arcade.dev)) for cloud tools, and an LLM provider key (`OPENAI_API_KEY` or `ANTHROPIC_API_KEY`). Skip the Arcade account with `--local-only` or `CADE_LOCAL_ONLY=1`.
36
45
 
@@ -50,9 +59,9 @@ Full install and first-run docs: [`docs/install.md`](./docs/install.md) and
50
59
  cade # interactive chat
51
60
  cade -m "What changed in HEAD?" # single message, then exit
52
61
  cade -m "What went wrong?" < error.log # prompt + file/stdin
53
- cade -r # resume the most recent thread
62
+ cade resume # resume the most recent thread
54
63
  cade resume "auth-rewrite" # resume a thread by name
55
- cade --persona reviewer # use a saved persona's system prompt
64
+ cade use reviewer # switch the current agent
56
65
  cade --voice # speak / hear (requires cade-cli[voice])
57
66
  ```
58
67
 
@@ -60,10 +69,8 @@ cade --voice # speak / hear (requires cade-cli[voi
60
69
 
61
70
  | Flag | Description |
62
71
  |---|---|
63
- | `-r`, `--resume` | Resume most recent thread |
64
72
  | `-m`, `--message` | Single-message mode; piped stdin is appended to the prompt |
65
- | `-P`, `--persona` | Use a saved persona |
66
- | `-V`, `--voice` | Voice mode; install `cade-cli[voice]` first |
73
+ | `--voice` | Voice mode; install `cade-cli[voice]` first |
67
74
  | `-v`, `--verbose` | Debug logging |
68
75
  | `--version` | Print version |
69
76
 
@@ -77,7 +84,7 @@ cade --voice # speak / hear (requires cade-cli[voi
77
84
  | `/logs` | Recent log entries |
78
85
  | `/thread`, `/history` | Current thread info |
79
86
  | `/pin`, `/unpin` | Pin reference material into the session |
80
- | `/tasks`, `/cron`, `/hooks`, `/channels`, `/notify` | Coordination surfaces (mirrored as `cade tasks` / `cade cron` / `cade hooks` / `cade channels`) |
87
+ | `/tasks`, `/cron`, `/hooks`, `/notify` | Coordination surfaces (mirrored as `cade tasks` / `cade cron` / `cade hooks`) |
81
88
  | `/usage` | Context-window status and token usage |
82
89
  | `/cd`, `/pwd`, `/!` | Shell shortcuts |
83
90
  | `Ctrl+C` | Exit |
@@ -89,7 +96,7 @@ cade --voice # speak / hear (requires cade-cli[voi
89
96
  Tools come from three sources and are addressed uniformly by their registered name:
90
97
 
91
98
  - **`Local_*`** — built-in: filesystem (`ReadFile`, `WriteFile`, `Edit`, `ListFiles`), shell (`Bash`), `Search`, `Git`, `Task*`, `AskUserQuestion`, `RetrieveToolResult`, `ToolSchema`, `PinContext`, `PushNotification`, `WebFetch`, and `WebSearch`.
92
- - **`Memory_*`** — agent-library backed, per-persona indexed knowledge store.
99
+ - **`Memory_*`** — agent-library backed, per-agent indexed knowledge store.
93
100
  - **Arcade Cloud + user MCP servers** — anything you register.
94
101
 
95
102
  ```bash
@@ -110,37 +117,46 @@ cade mcp authorize my-server # OAuth flow (browser)
110
117
  cade mcp list / status / test / enable / disable / rm
111
118
  ```
112
119
 
113
- User MCP servers register at `~/.cade/config/contexts/<context>.toml [[mcp]]`. Servers with large catalogs are auto-deferred (parameter schemas stripped to keep tool-list bytes down) and fetched on demand via `Local_ToolSchema`.
120
+ User MCP servers register on the agent's `~/.cade/config/agents/<name>.toml [[mcp]]` list (with `cade.toml [agent_defaults].mcp` as the shared default). Servers with large catalogs are auto-deferred (parameter schemas stripped to keep tool-list bytes down) and fetched on demand via `Local_ToolSchema`.
114
121
 
115
122
  ---
116
123
 
117
- ## Personas + memory
124
+ ## Agents + memory
125
+
126
+ Each **agent** bundles a model, system prompt, tools, and memory. The current
127
+ agent is ambient — most commands act on it.
118
128
 
119
129
  ```bash
120
- cade persona list / create / get / edit / delete / default # manage system prompts
121
- cade --persona reviewer # use one for a session
130
+ cade new reviewer --prompt "You are a meticulous code reviewer." # create + switch
131
+ cade list # all agents
132
+ cade use reviewer # switch the current agent
133
+ cade info / cade edit reviewer # inspect / change config
122
134
 
123
- cade mem list # sources indexed for the active persona
135
+ cade mem # the current agent's memory (status)
124
136
  cade mem add ~/notes # index a directory
125
137
  cade mem search "auth design" # semantic search
126
138
  ```
127
139
 
128
- Memory is persona-scoped — each persona has its own `~/.cade/data/contexts/<context>/memory/<persona>/.librarian/` index, so a `reviewer` persona's notes never leak into `default`.
140
+ Memory is per-agent — each agent has its own
141
+ `~/.cade/data/agents/<id>/memory/.librarian/` index, so a `reviewer` agent's
142
+ notes never leak into another.
129
143
 
130
144
  ---
131
145
 
132
146
  ## Headless daemon: `cade serve`
133
147
 
134
- Run Cade as a long-lived daemon that replies through adapters. Telegram is supported for personal bot workflows, and Desktop exposes a local WebSocket for native clients. Each conversation gets its own persistent thread — persona, memory, and tools carry across messages.
148
+ Run Cade as a long-lived daemon that replies through adapters. Telegram is supported for personal bot workflows, and Desktop exposes a local WebSocket for native clients. Each conversation gets its own persistent thread — model, memory, and tools carry across messages.
135
149
 
136
150
  ```bash
137
151
  cade serve init # wizard: bot token, allowed senders
138
- cade serve # foreground
152
+ cade serve # foreground (current agent)
153
+ cade serve --agent ops # serve a specific agent (one daemon per agent)
154
+ cade serve list # agents with a running daemon
139
155
  cade serve --install launchd # macOS LaunchAgent (or --install systemd)
140
156
  cade serve status / stop # health, uptime; SIGTERM running daemon
141
157
  ```
142
158
 
143
- Config lives at `~/.cade/config/contexts/<context>.toml [serve]`. Edit and `kill -HUP $(cat ~/.cade/run/serve.pid)` to reload without restart.
159
+ Each agent's serve config lives in `~/.cade/config/agents/<name>.toml [serve]`. Edit and `kill -HUP $(cat ~/.cade/run/agents/<name>/serve.pid)` to reload without restart.
144
160
 
145
161
  **Security defaults are fail-closed:** `allowed_senders = []` blocks everyone; tools are default-deny against `[serve.tools].allow` (globs / regex / pipe lists supported); `deny` always wins.
146
162
 
@@ -148,18 +164,19 @@ The MCP transport is fully bidirectional, so tools running inside the daemon can
148
164
 
149
165
  ---
150
166
 
151
- ## Extensibility: hooks, tasks, cron, channels
167
+ ## Extensibility: hooks, tasks, cron
152
168
 
153
- Four primitives the agent uses directly (as `Local_*` tools) and you can drive from the CLI:
169
+ Three primitives the agent uses directly (as `Local_*` tools) and you can drive from the CLI:
154
170
 
155
171
  | Surface | What it is | CLI |
156
172
  |---|---|---|
157
173
  | **Hooks** | Lifecycle event handlers (pre/post tool, user prompt submit) | `cade hooks list / add / remove / test` |
158
- | **Tasks** | File-backed durable work units that survive turn boundaries | `cade tasks list / get / create / update / delete` |
174
+ | **Tasks** | Durable work units that survive turn boundaries | `cade tasks list / get / create / update / delete` |
159
175
  | **Cron** | Scheduled prompts the agent runs on a timer | `cade cron list / add / remove / enable / disable / run-now` |
160
- | **Channels** | JSONL-backed inter-session pub/sub | `cade channels list / send / recv / clear` |
161
176
 
162
- See [`docs/channels.md`](./docs/channels.md) for the channels protocol; hooks and tasks/cron details live in their respective `cade <subcommand> --help` outputs.
177
+ Cross-agent messaging is set up with `cade link` / `cade channel` (an agent can only
178
+ reach another it's been linked to). Hooks and tasks/cron details live in their
179
+ respective `cade <subcommand> --help` outputs.
163
180
 
164
181
  ---
165
182
 
@@ -171,9 +188,9 @@ Cade works with any OpenAI-compatible endpoint. Three ways to wire one in (CLI f
171
188
  # CLI flag for Ollama. Use a model from `ollama list`.
172
189
  cade chat -L --endpoint http://localhost:11434 --model qwen3:4b
173
190
 
174
- # Environment for one-shot mode
175
- cade context create local-qwen --model qwen3:4b
176
- cade context use local-qwen
191
+ # Or create a dedicated agent for the local model
192
+ cade new local-qwen --model qwen3:4b
193
+ cade use local-qwen
177
194
  export OLLAMA_BASE_URL="http://localhost:11434"
178
195
  CADE_LOCAL_ONLY=1 cade -m "hello from a local model"
179
196
 
@@ -193,12 +210,11 @@ All state lives under `~/.cade/`. Override the location with `CADE_HOME=/path/to
193
210
 
194
211
  | File | Purpose |
195
212
  |---|---|
196
- | `config/cade.toml` | Model / provider / UI settings |
197
- | `data/contexts/<context>/history.db` | Thread + message storage |
213
+ | `config/cade.toml` | Global settings + `[agent_defaults]` (model, provider, UI, …) |
214
+ | `config/agents/<name>.toml` | Per-agent config (model, prompt, `[[mcp]]`, `[serve]`, hooks) |
215
+ | `data/agents/<id>/` | Per-agent state: `threads/ memory/ tasks/ inbox/` |
216
+ | `run/agents/<name>/` | Per-agent daemon runtime: `serve.pid`, mcp-services, cron lease |
198
217
  | `logs/cade.log` | Rotating log file |
199
- | `config/contexts/<context>.toml [[mcp]]` | User MCP server registry |
200
- | `config/contexts/<context>.toml [serve]` | `cade serve` daemon config |
201
- | `personas/`, `memory/`, `tasks/`, `channels/` | Persona-scoped state |
202
218
 
203
219
  Full layout, env vars, and TOML schema in [`docs/configuration.md`](./docs/configuration.md).
204
220
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "cade-cli"
3
- version = "0.13.3"
3
+ version = "0.14.0"
4
4
  description = "Cade - The CLI Agent from Arcade.dev"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -19,6 +19,9 @@ patch_frozen_return_detection()
19
19
 
20
20
  from cade_mcp_local.resources import register_resources # noqa: E402
21
21
  from cade_mcp_local.tools import ( # noqa: E402
22
+ agent_list_tool,
23
+ agent_send_tool,
24
+ agent_spawn_tool,
22
25
  ask_user_question_tool,
23
26
  bash_tool,
24
27
  edit_tool,
@@ -54,6 +57,10 @@ is running. Use these tools when you need to:
54
57
  TaskUpdate, TaskDelete) — the host registers them as Local_* names
55
58
  - PushNotification to inject a structured notice into the agent context at the next
56
59
  tool boundary
60
+ - AgentSend / AgentList to coordinate with other agents the user has linked to this
61
+ one (ACL-gated; delivered to the target agent's inbox)
62
+ - AgentSpawn to delegate a self-contained sub-task to a fresh child agent and get
63
+ back just its result (requires this agent to allow spawning)
57
64
  - AskUserQuestion when you need structured clarification from the user (host:
58
65
  Local_AskUserQuestion)
59
66
  - WebFetch to read an external URL (Firecrawl via Arcade by default, httpx
@@ -112,6 +119,12 @@ def create_app() -> MCPApp:
112
119
  # Notifications (inject XML into context at next tool boundary)
113
120
  app.add_tool(push_notification_tool)
114
121
 
122
+ # Cross-agent coordination (ACL-gated; delivers to another agent's inbox)
123
+ app.add_tool(agent_send_tool)
124
+ app.add_tool(agent_list_tool)
125
+ # Spawn an ephemeral child task-agent (opt-in via the agent's allow_spawn)
126
+ app.add_tool(agent_spawn_tool)
127
+
115
128
  # Structured clarification question for the user
116
129
  app.add_tool(ask_user_question_tool)
117
130
 
@@ -5,6 +5,7 @@ is running. Use these tools when you need to read, write, search, or execute
5
5
  commands on the same machine as the running cade process.
6
6
  """
7
7
 
8
+ from cade_mcp_local.tools.agents import agent_list_tool, agent_send_tool, agent_spawn_tool
8
9
  from cade_mcp_local.tools.context import search_recent_context_tool
9
10
  from cade_mcp_local.tools.filesystem import (
10
11
  edit_tool,
@@ -62,6 +63,10 @@ __all__ = [
62
63
  "task_delete_tool",
63
64
  # Notifications
64
65
  "push_notification_tool",
66
+ # Cross-agent coordination
67
+ "agent_send_tool",
68
+ "agent_list_tool",
69
+ "agent_spawn_tool",
65
70
  # Interactive
66
71
  "ask_user_question_tool",
67
72
  # Web
@@ -0,0 +1,151 @@
1
+ """MCP tools for cross-agent coordination.
2
+
3
+ Lets the model address other agents the user has explicitly linked. Delivery
4
+ rides the durable per-agent inbox (so the message survives until the target
5
+ agent's next turn), and the user-provisioned channel ACL gates every send:
6
+ two top-level agents can talk only if a user ran ``cade link`` / added them to
7
+ a shared channel. The default is isolation.
8
+ """
9
+
10
+ import logging
11
+ from typing import Annotated, Any
12
+
13
+ from arcade_mcp_server import Context, tool
14
+ from typing_extensions import TypedDict
15
+
16
+ from cade_mcp_local._metadata import CREATE_META, READ_META
17
+ from cade_mcp_local.errors import InvalidInputError
18
+ from cadecoder.core import agent as agent_mod
19
+ from cadecoder.core import comms as comms_mod
20
+ from cadecoder.core.inbox import inbox_for_path
21
+ from cadecoder.core.paths import get_paths
22
+
23
+ log = logging.getLogger(__name__)
24
+
25
+
26
+ class AgentSendOutput(TypedDict):
27
+ delivered: bool
28
+ target: str
29
+ target_id: str
30
+
31
+
32
+ class AgentSpawnOutput(TypedDict):
33
+ agent: str
34
+ id: str
35
+ result: str
36
+
37
+
38
+ class AgentListOutput(TypedDict):
39
+ agents: list[dict[str, Any]]
40
+ count: int
41
+
42
+
43
+ def _agent_from_request_meta() -> str | None:
44
+ """Per-request acting agent from MCP ``_meta['cade/agent']``, if the host set it.
45
+
46
+ The cade host stamps this on every built-in ``tools/call`` so the agent
47
+ resolves per-request rather than from this subprocess's env/state. Returns
48
+ ``None`` when running outside a request context (tests, one-shot CLI).
49
+ """
50
+ try:
51
+ from arcade_mcp_server.request_context import get_request_meta
52
+ except Exception:
53
+ return None
54
+ meta = get_request_meta()
55
+ if meta is None:
56
+ return None
57
+ return meta.__dict__.get("cade/agent")
58
+
59
+
60
+ def _current_agent_name() -> str:
61
+ name = _agent_from_request_meta() or agent_mod.get_active_agent_name()
62
+ if not name:
63
+ raise InvalidInputError("agent", "no current agent is set")
64
+ return name
65
+
66
+
67
+ @tool(
68
+ name="AgentSend",
69
+ desc=(
70
+ "Send a message to another agent's inbox. Only works for agents a user "
71
+ "has linked to this one (via `cade link` or a shared channel); otherwise "
72
+ "the send is refused. The message is delivered at the target agent's next "
73
+ "turn. Use AgentList first to see who you can reach."
74
+ ),
75
+ metadata=CREATE_META,
76
+ )
77
+ def agent_send_tool(
78
+ context: Context,
79
+ target: Annotated[str, "Target agent name, id, or unique id prefix."],
80
+ message: Annotated[str, "Message to deliver to the target agent."],
81
+ ) -> Annotated[AgentSendOutput, "Delivery result."]:
82
+ if not message.strip():
83
+ raise InvalidInputError("message", "cannot be empty")
84
+ sender = _current_agent_name()
85
+ target_agent = agent_mod.resolve(target)
86
+ if target_agent is None:
87
+ raise InvalidInputError("target", f"agent '{target}' not found")
88
+ if not comms_mod.can_communicate(sender, target_agent.name):
89
+ raise InvalidInputError(
90
+ "target",
91
+ f"not linked with '{target_agent.name}'. A user must run: "
92
+ f"cade link {sender} {target_agent.name}",
93
+ )
94
+ inbox = inbox_for_path(get_paths().agent_data(target_agent.id))
95
+ inbox.enqueue_notification(message, source=f"agent:{sender}")
96
+ return {"delivered": True, "target": target_agent.name, "target_id": target_agent.id}
97
+
98
+
99
+ @tool(
100
+ name="AgentSpawn",
101
+ desc=(
102
+ "Delegate a focused sub-task to a fresh child agent that runs in its own "
103
+ "process and context, returning just the result (keeps your context "
104
+ "clean). Only works if this agent was created with --allow-spawn. Blocks "
105
+ "until the child finishes."
106
+ ),
107
+ metadata=CREATE_META,
108
+ )
109
+ async def agent_spawn_tool(
110
+ context: Context,
111
+ task: Annotated[str, "The self-contained sub-task for the child agent."],
112
+ ) -> Annotated[AgentSpawnOutput, "The child agent and its result."]:
113
+ from cadecoder.core.spawn import SpawnError, spawn_task_agent
114
+
115
+ if not task.strip():
116
+ raise InvalidInputError("task", "cannot be empty")
117
+ # Resolve the parent from the per-request agent identity so the child is
118
+ # attributed to the calling agent, not this subprocess's env/state.
119
+ parent_name = _agent_from_request_meta()
120
+ parent = agent_mod.resolve(parent_name) if parent_name else None
121
+ try:
122
+ return await spawn_task_agent(task, parent=parent) # type: ignore[return-value]
123
+ except SpawnError as e:
124
+ raise InvalidInputError("task", str(e)) from e
125
+
126
+
127
+ @tool(
128
+ name="AgentList",
129
+ desc=(
130
+ "List the agents you can message — i.e. agents a user has linked to this "
131
+ "one through a shared channel. Returns an empty list when you are isolated."
132
+ ),
133
+ metadata=READ_META,
134
+ )
135
+ def agent_list_tool(
136
+ context: Context,
137
+ ) -> Annotated[AgentListOutput, "Reachable agents."]:
138
+ sender = _current_agent_name()
139
+ reachable: list[dict[str, Any]] = []
140
+ for candidate in agent_mod.list_agents():
141
+ if candidate.name == sender:
142
+ continue
143
+ if comms_mod.can_communicate(sender, candidate.name):
144
+ reachable.append(
145
+ {
146
+ "name": candidate.name,
147
+ "id": candidate.id,
148
+ "description": candidate.description,
149
+ }
150
+ )
151
+ return {"agents": reachable, "count": len(reachable)}
@@ -9,7 +9,7 @@ from typing_extensions import TypedDict
9
9
 
10
10
  from cade_mcp_local._metadata import CREATE_META
11
11
  from cade_mcp_local.errors import InvalidInputError
12
- from cadecoder.tasks import NotificationQueue
12
+ from cadecoder.core.inbox import current_inbox
13
13
 
14
14
  log = logging.getLogger(__name__)
15
15
 
@@ -45,5 +45,5 @@ def push_notification_tool(
45
45
  raise InvalidInputError("message", "cannot be empty")
46
46
  level_value = level.value if isinstance(level, NotificationLevel) else str(level)
47
47
  xml = f"<notification>\n <level>{level_value}</level>\n <message>{message}</message>\n</notification>"
48
- NotificationQueue.get().enqueue(xml)
48
+ current_inbox().enqueue(xml)
49
49
  return {"queued": True, "level": level_value}