cade-cli 0.13.4__tar.gz → 0.14.1__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.4 → cade_cli-0.14.1}/PKG-INFO +56 -36
  2. {cade_cli-0.13.4 → cade_cli-0.14.1}/README.md +55 -35
  3. {cade_cli-0.13.4 → cade_cli-0.14.1}/pyproject.toml +1 -1
  4. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/server.py +13 -0
  5. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/tools/__init__.py +5 -0
  6. cade_cli-0.14.1/src/cade_mcp_local/tools/agents.py +151 -0
  7. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/tools/notifications.py +2 -2
  8. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/ai/prompts.py +33 -19
  9. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/cli/app.py +156 -115
  10. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/cli/commands/account.py +3 -1
  11. cade_cli-0.14.1/src/cadecoder/cli/commands/agents.py +440 -0
  12. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/cli/commands/auth.py +0 -19
  13. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/cli/commands/chat.py +4 -23
  14. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/cli/commands/hooks.py +60 -59
  15. cade_cli-0.14.1/src/cadecoder/cli/commands/mem.py +221 -0
  16. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/cli/commands/serve.py +64 -3
  17. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/cli/commands/tasks.py +19 -7
  18. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/cli/commands/thread.py +1 -1
  19. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/cli/commands/tools.py +48 -31
  20. cade_cli-0.14.1/src/cadecoder/core/agent.py +501 -0
  21. cade_cli-0.14.1/src/cadecoder/core/comms.py +177 -0
  22. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/core/config.py +25 -203
  23. cade_cli-0.14.1/src/cadecoder/core/inbox.py +138 -0
  24. cade_cli-0.14.1/src/cadecoder/core/memory.py +76 -0
  25. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/core/paths.py +57 -19
  26. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/core/runtime.py +27 -10
  27. {cade_cli-0.13.4/src/cadecoder/serve → cade_cli-0.14.1/src/cadecoder/core}/secrets.py +15 -5
  28. cade_cli-0.14.1/src/cadecoder/core/spawn.py +215 -0
  29. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/execution/orchestrator.py +2 -2
  30. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/hooks/__init__.py +9 -3
  31. cade_cli-0.14.1/src/cadecoder/hooks/config.py +193 -0
  32. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/providers/__init__.py +8 -3
  33. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/serve/__init__.py +1 -1
  34. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/serve/allowlist.py +2 -2
  35. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/serve/config.py +52 -53
  36. cade_cli-0.14.1/src/cadecoder/serve/cron.py +37 -0
  37. cade_cli-0.14.1/src/cadecoder/serve/daemon.py +661 -0
  38. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/serve/install.py +50 -27
  39. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/serve/observability.py +3 -1
  40. cade_cli-0.14.1/src/cadecoder/serve/owner.py +44 -0
  41. cade_cli-0.14.1/src/cadecoder/serve/secrets.py +24 -0
  42. cade_cli-0.14.1/src/cadecoder/serve/services.py +309 -0
  43. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/serve/worker.py +65 -0
  44. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/tasks/__init__.py +1 -8
  45. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/tasks/store.py +4 -4
  46. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/tasks/types.py +0 -9
  47. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/templates/serve/launchd.plist.tmpl +1 -1
  48. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/templates/serve/systemd.service.tmpl +2 -2
  49. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/tools/manager/composite.py +279 -132
  50. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/tools/manager/config.py +25 -20
  51. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/tools/manager/mcp.py +230 -94
  52. cade_cli-0.14.1/src/cadecoder/ui/completion.py +74 -0
  53. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/ui/display.py +13 -7
  54. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/ui/input.py +49 -13
  55. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/ui/session.py +219 -116
  56. cade_cli-0.14.1/src/cadecoder/ui/slash.py +84 -0
  57. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/voice/session.py +22 -2
  58. cade_cli-0.13.4/src/cadecoder/cli/commands/channels.py +0 -79
  59. cade_cli-0.13.4/src/cadecoder/cli/commands/context.py +0 -205
  60. cade_cli-0.13.4/src/cadecoder/cli/commands/mem.py +0 -176
  61. cade_cli-0.13.4/src/cadecoder/cli/commands/model.py +0 -255
  62. cade_cli-0.13.4/src/cadecoder/cli/commands/persona.py +0 -572
  63. cade_cli-0.13.4/src/cadecoder/hooks/config.py +0 -151
  64. cade_cli-0.13.4/src/cadecoder/serve/daemon.py +0 -383
  65. cade_cli-0.13.4/src/cadecoder/storage/personas.py +0 -243
  66. cade_cli-0.13.4/src/cadecoder/tasks/channels.py +0 -89
  67. cade_cli-0.13.4/src/cadecoder/tasks/notifications.py +0 -100
  68. cade_cli-0.13.4/src/cadecoder/ui/slash.py +0 -47
  69. {cade_cli-0.13.4 → cade_cli-0.14.1}/.gitignore +0 -0
  70. {cade_cli-0.13.4 → cade_cli-0.14.1}/LICENSE +0 -0
  71. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/__init__.py +0 -0
  72. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/__main__.py +0 -0
  73. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/_metadata.py +0 -0
  74. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/config.py +0 -0
  75. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/errors.py +0 -0
  76. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/resources.py +0 -0
  77. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/tools/_read_cache.py +0 -0
  78. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/tools/context.py +0 -0
  79. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/tools/filesystem.py +0 -0
  80. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/tools/git.py +0 -0
  81. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/tools/questions.py +0 -0
  82. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/tools/results.py +0 -0
  83. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/tools/schemas.py +0 -0
  84. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/tools/search.py +0 -0
  85. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/tools/shell.py +0 -0
  86. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/tools/snippets.py +0 -0
  87. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/tools/tasks.py +0 -0
  88. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/tools/web_fetch.py +0 -0
  89. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/tools/web_search.py +0 -0
  90. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/utils.py +0 -0
  91. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/web/__init__.py +0 -0
  92. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/web/arcade_client.py +0 -0
  93. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/web/cache.py +0 -0
  94. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/web/extract.py +0 -0
  95. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/web/markdown.py +0 -0
  96. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/web/preapproved.py +0 -0
  97. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/web/prompts.py +0 -0
  98. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/web/scrape.py +0 -0
  99. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/web/search/__init__.py +0 -0
  100. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/web/search/arcade.py +0 -0
  101. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/web/search/base.py +0 -0
  102. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/web/search/http.py +0 -0
  103. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/__init__.py +0 -0
  104. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/ai/__init__.py +0 -0
  105. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/cli/__init__.py +0 -0
  106. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/cli/auth.py +0 -0
  107. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/cli/commands/__init__.py +0 -0
  108. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/cli/commands/cron.py +0 -0
  109. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/cli/commands/mcp.py +0 -0
  110. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/core/__init__.py +0 -0
  111. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/core/constants.py +0 -0
  112. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/core/errors.py +0 -0
  113. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/core/frozen.py +0 -0
  114. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/core/git.py +0 -0
  115. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/core/logging.py +0 -0
  116. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/core/model_specs.py +0 -0
  117. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/core/names.py +0 -0
  118. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/core/types.py +0 -0
  119. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/execution/__init__.py +0 -0
  120. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/execution/context_window.py +0 -0
  121. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/execution/mcp_schema_index.py +0 -0
  122. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/execution/parallel.py +0 -0
  123. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/execution/tool_result_store.py +0 -0
  124. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/execution/tool_schema_cache.py +0 -0
  125. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/hooks/engine.py +0 -0
  126. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/hooks/executors/__init__.py +0 -0
  127. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/hooks/executors/callback.py +0 -0
  128. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/hooks/executors/command.py +0 -0
  129. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/hooks/executors/http.py +0 -0
  130. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/hooks/executors/prompt.py +0 -0
  131. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/hooks/executors/ssrf_guard.py +0 -0
  132. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/hooks/matchers.py +0 -0
  133. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/hooks/registry.py +0 -0
  134. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/hooks/types.py +0 -0
  135. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/providers/anthropic.py +0 -0
  136. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/providers/base.py +0 -0
  137. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/providers/ollama.py +0 -0
  138. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/providers/openai.py +0 -0
  139. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/serve/adapters/__init__.py +0 -0
  140. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/serve/adapters/base.py +0 -0
  141. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/serve/adapters/desktop.py +0 -0
  142. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/serve/adapters/registry.py +0 -0
  143. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/serve/adapters/stub.py +0 -0
  144. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/serve/adapters/telegram.py +0 -0
  145. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/serve/chunker.py +0 -0
  146. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/serve/commands.py +0 -0
  147. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/serve/elicitation.py +0 -0
  148. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/serve/format.py +0 -0
  149. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/serve/lock.py +0 -0
  150. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/serve/progress_sink.py +0 -0
  151. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/serve/router.py +0 -0
  152. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/serve/sinks.py +0 -0
  153. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/storage/__init__.py +0 -0
  154. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/storage/threads.py +0 -0
  155. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/tasks/lock.py +0 -0
  156. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/tasks/scheduler.py +0 -0
  157. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/templates/login_failed.html +0 -0
  158. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/templates/login_success.html +0 -0
  159. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/templates/serve/serve.toml.example +0 -0
  160. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/templates/styles.css +0 -0
  161. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/tools/__init__.py +0 -0
  162. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/tools/manager/__init__.py +0 -0
  163. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/tools/manager/_request_ctx.py +0 -0
  164. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/tools/manager/base.py +0 -0
  165. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/tools/search/__init__.py +0 -0
  166. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/tools/search/discovered.py +0 -0
  167. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/tools/search/scoring.py +0 -0
  168. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/tools/search/service.py +0 -0
  169. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/ui/__init__.py +0 -0
  170. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/ui/elicitation.py +0 -0
  171. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/voice/__init__.py +0 -0
  172. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/voice/audio.py +0 -0
  173. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/voice/cleanup.py +0 -0
  174. {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/voice/stt.py +0 -0
  175. {cade_cli-0.13.4 → cade_cli-0.14.1}/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.4
3
+ Version: 0.14.1
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,25 @@ 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.1 CADE_INSTALL_DIR=/usr/local/bin \
127
+ sh -c "$(curl -fsSL https://arcadeagent.dev/install)"
128
+ ```
129
+
130
+ On Linux the installer auto-picks a **cpu** or **gpu** build (GPU when
131
+ `nvidia-smi` detects a card; the GPU build bundles the CUDA stack and is a much
132
+ larger download). Force it with `CADE_VARIANT=cpu` or `CADE_VARIANT=gpu`.
133
+
134
+ (Windows: grab the `.zip` from the releases page, or `pip install cade-cli`.)
122
135
 
123
136
  **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
137
 
@@ -138,9 +151,9 @@ Full install and first-run docs: [`docs/install.md`](./docs/install.md) and
138
151
  cade # interactive chat
139
152
  cade -m "What changed in HEAD?" # single message, then exit
140
153
  cade -m "What went wrong?" < error.log # prompt + file/stdin
141
- cade -r # resume the most recent thread
154
+ cade resume # resume the most recent thread
142
155
  cade resume "auth-rewrite" # resume a thread by name
143
- cade --persona reviewer # use a saved persona's system prompt
156
+ cade use reviewer # switch the current agent
144
157
  cade --voice # speak / hear (requires cade-cli[voice])
145
158
  ```
146
159
 
@@ -148,10 +161,8 @@ cade --voice # speak / hear (requires cade-cli[voi
148
161
 
149
162
  | Flag | Description |
150
163
  |---|---|
151
- | `-r`, `--resume` | Resume most recent thread |
152
164
  | `-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 |
165
+ | `--voice` | Voice mode; install `cade-cli[voice]` first |
155
166
  | `-v`, `--verbose` | Debug logging |
156
167
  | `--version` | Print version |
157
168
 
@@ -165,7 +176,7 @@ cade --voice # speak / hear (requires cade-cli[voi
165
176
  | `/logs` | Recent log entries |
166
177
  | `/thread`, `/history` | Current thread info |
167
178
  | `/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`) |
179
+ | `/tasks`, `/cron`, `/hooks`, `/notify` | Coordination surfaces (mirrored as `cade tasks` / `cade cron` / `cade hooks`) |
169
180
  | `/usage` | Context-window status and token usage |
170
181
  | `/cd`, `/pwd`, `/!` | Shell shortcuts |
171
182
  | `Ctrl+C` | Exit |
@@ -177,7 +188,7 @@ cade --voice # speak / hear (requires cade-cli[voi
177
188
  Tools come from three sources and are addressed uniformly by their registered name:
178
189
 
179
190
  - **`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.
191
+ - **`Memory_*`** — agent-library backed, per-agent indexed knowledge store.
181
192
  - **Arcade Cloud + user MCP servers** — anything you register.
182
193
 
183
194
  ```bash
@@ -198,37 +209,46 @@ cade mcp authorize my-server # OAuth flow (browser)
198
209
  cade mcp list / status / test / enable / disable / rm
199
210
  ```
200
211
 
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`.
212
+ 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
213
 
203
214
  ---
204
215
 
205
- ## Personas + memory
216
+ ## Agents + memory
217
+
218
+ Each **agent** bundles a model, system prompt, tools, and memory. The current
219
+ agent is ambient — most commands act on it.
206
220
 
207
221
  ```bash
208
- cade persona list / create / get / edit / delete / default # manage system prompts
209
- cade --persona reviewer # use one for a session
222
+ cade new reviewer --prompt "You are a meticulous code reviewer." # create + switch
223
+ cade list # all agents
224
+ cade use reviewer # switch the current agent
225
+ cade info / cade edit reviewer # inspect / change config
210
226
 
211
- cade mem list # sources indexed for the active persona
227
+ cade mem # the current agent's memory (status)
212
228
  cade mem add ~/notes # index a directory
213
229
  cade mem search "auth design" # semantic search
214
230
  ```
215
231
 
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`.
232
+ Memory is per-agent — each agent has its own
233
+ `~/.cade/data/agents/<id>/memory/.librarian/` index, so a `reviewer` agent's
234
+ notes never leak into another.
217
235
 
218
236
  ---
219
237
 
220
238
  ## Headless daemon: `cade serve`
221
239
 
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.
240
+ 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
241
 
224
242
  ```bash
225
243
  cade serve init # wizard: bot token, allowed senders
226
- cade serve # foreground
244
+ cade serve # foreground (current agent)
245
+ cade serve --agent ops # serve a specific agent (one daemon per agent)
246
+ cade serve list # agents with a running daemon
227
247
  cade serve --install launchd # macOS LaunchAgent (or --install systemd)
228
248
  cade serve status / stop # health, uptime; SIGTERM running daemon
229
249
  ```
230
250
 
231
- Config lives at `~/.cade/config/contexts/<context>.toml [serve]`. Edit and `kill -HUP $(cat ~/.cade/run/serve.pid)` to reload without restart.
251
+ 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
252
 
233
253
  **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
254
 
@@ -236,18 +256,19 @@ The MCP transport is fully bidirectional, so tools running inside the daemon can
236
256
 
237
257
  ---
238
258
 
239
- ## Extensibility: hooks, tasks, cron, channels
259
+ ## Extensibility: hooks, tasks, cron
240
260
 
241
- Four primitives the agent uses directly (as `Local_*` tools) and you can drive from the CLI:
261
+ Three primitives the agent uses directly (as `Local_*` tools) and you can drive from the CLI:
242
262
 
243
263
  | Surface | What it is | CLI |
244
264
  |---|---|---|
245
265
  | **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` |
266
+ | **Tasks** | Durable work units that survive turn boundaries | `cade tasks list / get / create / update / delete` |
247
267
  | **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
268
 
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.
269
+ Cross-agent messaging is set up with `cade link` / `cade channel` (an agent can only
270
+ reach another it's been linked to). Hooks and tasks/cron details live in their
271
+ respective `cade <subcommand> --help` outputs.
251
272
 
252
273
  ---
253
274
 
@@ -259,9 +280,9 @@ Cade works with any OpenAI-compatible endpoint. Three ways to wire one in (CLI f
259
280
  # CLI flag for Ollama. Use a model from `ollama list`.
260
281
  cade chat -L --endpoint http://localhost:11434 --model qwen3:4b
261
282
 
262
- # Environment for one-shot mode
263
- cade context create local-qwen --model qwen3:4b
264
- cade context use local-qwen
283
+ # Or create a dedicated agent for the local model
284
+ cade new local-qwen --model qwen3:4b
285
+ cade use local-qwen
265
286
  export OLLAMA_BASE_URL="http://localhost:11434"
266
287
  CADE_LOCAL_ONLY=1 cade -m "hello from a local model"
267
288
 
@@ -281,12 +302,11 @@ All state lives under `~/.cade/`. Override the location with `CADE_HOME=/path/to
281
302
 
282
303
  | File | Purpose |
283
304
  |---|---|
284
- | `config/cade.toml` | Model / provider / UI settings |
285
- | `data/contexts/<context>/history.db` | Thread + message storage |
305
+ | `config/cade.toml` | Global settings + `[agent_defaults]` (model, provider, UI, …) |
306
+ | `config/agents/<name>.toml` | Per-agent config (model, prompt, `[[mcp]]`, `[serve]`, hooks) |
307
+ | `data/agents/<id>/` | Per-agent state: `threads/ memory/ tasks/ inbox/` |
308
+ | `run/agents/<name>/` | Per-agent daemon runtime: `serve.pid`, mcp-services, cron lease |
286
309
  | `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
310
 
291
311
  Full layout, env vars, and TOML schema in [`docs/configuration.md`](./docs/configuration.md).
292
312
 
@@ -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,25 @@ 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.1 CADE_INSTALL_DIR=/usr/local/bin \
39
+ sh -c "$(curl -fsSL https://arcadeagent.dev/install)"
40
+ ```
41
+
42
+ On Linux the installer auto-picks a **cpu** or **gpu** build (GPU when
43
+ `nvidia-smi` detects a card; the GPU build bundles the CUDA stack and is a much
44
+ larger download). Force it with `CADE_VARIANT=cpu` or `CADE_VARIANT=gpu`.
45
+
46
+ (Windows: grab the `.zip` from the releases page, or `pip install cade-cli`.)
34
47
 
35
48
  **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
49
 
@@ -50,9 +63,9 @@ Full install and first-run docs: [`docs/install.md`](./docs/install.md) and
50
63
  cade # interactive chat
51
64
  cade -m "What changed in HEAD?" # single message, then exit
52
65
  cade -m "What went wrong?" < error.log # prompt + file/stdin
53
- cade -r # resume the most recent thread
66
+ cade resume # resume the most recent thread
54
67
  cade resume "auth-rewrite" # resume a thread by name
55
- cade --persona reviewer # use a saved persona's system prompt
68
+ cade use reviewer # switch the current agent
56
69
  cade --voice # speak / hear (requires cade-cli[voice])
57
70
  ```
58
71
 
@@ -60,10 +73,8 @@ cade --voice # speak / hear (requires cade-cli[voi
60
73
 
61
74
  | Flag | Description |
62
75
  |---|---|
63
- | `-r`, `--resume` | Resume most recent thread |
64
76
  | `-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 |
77
+ | `--voice` | Voice mode; install `cade-cli[voice]` first |
67
78
  | `-v`, `--verbose` | Debug logging |
68
79
  | `--version` | Print version |
69
80
 
@@ -77,7 +88,7 @@ cade --voice # speak / hear (requires cade-cli[voi
77
88
  | `/logs` | Recent log entries |
78
89
  | `/thread`, `/history` | Current thread info |
79
90
  | `/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`) |
91
+ | `/tasks`, `/cron`, `/hooks`, `/notify` | Coordination surfaces (mirrored as `cade tasks` / `cade cron` / `cade hooks`) |
81
92
  | `/usage` | Context-window status and token usage |
82
93
  | `/cd`, `/pwd`, `/!` | Shell shortcuts |
83
94
  | `Ctrl+C` | Exit |
@@ -89,7 +100,7 @@ cade --voice # speak / hear (requires cade-cli[voi
89
100
  Tools come from three sources and are addressed uniformly by their registered name:
90
101
 
91
102
  - **`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.
103
+ - **`Memory_*`** — agent-library backed, per-agent indexed knowledge store.
93
104
  - **Arcade Cloud + user MCP servers** — anything you register.
94
105
 
95
106
  ```bash
@@ -110,37 +121,46 @@ cade mcp authorize my-server # OAuth flow (browser)
110
121
  cade mcp list / status / test / enable / disable / rm
111
122
  ```
112
123
 
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`.
124
+ 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
125
 
115
126
  ---
116
127
 
117
- ## Personas + memory
128
+ ## Agents + memory
129
+
130
+ Each **agent** bundles a model, system prompt, tools, and memory. The current
131
+ agent is ambient — most commands act on it.
118
132
 
119
133
  ```bash
120
- cade persona list / create / get / edit / delete / default # manage system prompts
121
- cade --persona reviewer # use one for a session
134
+ cade new reviewer --prompt "You are a meticulous code reviewer." # create + switch
135
+ cade list # all agents
136
+ cade use reviewer # switch the current agent
137
+ cade info / cade edit reviewer # inspect / change config
122
138
 
123
- cade mem list # sources indexed for the active persona
139
+ cade mem # the current agent's memory (status)
124
140
  cade mem add ~/notes # index a directory
125
141
  cade mem search "auth design" # semantic search
126
142
  ```
127
143
 
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`.
144
+ Memory is per-agent — each agent has its own
145
+ `~/.cade/data/agents/<id>/memory/.librarian/` index, so a `reviewer` agent's
146
+ notes never leak into another.
129
147
 
130
148
  ---
131
149
 
132
150
  ## Headless daemon: `cade serve`
133
151
 
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.
152
+ 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
153
 
136
154
  ```bash
137
155
  cade serve init # wizard: bot token, allowed senders
138
- cade serve # foreground
156
+ cade serve # foreground (current agent)
157
+ cade serve --agent ops # serve a specific agent (one daemon per agent)
158
+ cade serve list # agents with a running daemon
139
159
  cade serve --install launchd # macOS LaunchAgent (or --install systemd)
140
160
  cade serve status / stop # health, uptime; SIGTERM running daemon
141
161
  ```
142
162
 
143
- Config lives at `~/.cade/config/contexts/<context>.toml [serve]`. Edit and `kill -HUP $(cat ~/.cade/run/serve.pid)` to reload without restart.
163
+ 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
164
 
145
165
  **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
166
 
@@ -148,18 +168,19 @@ The MCP transport is fully bidirectional, so tools running inside the daemon can
148
168
 
149
169
  ---
150
170
 
151
- ## Extensibility: hooks, tasks, cron, channels
171
+ ## Extensibility: hooks, tasks, cron
152
172
 
153
- Four primitives the agent uses directly (as `Local_*` tools) and you can drive from the CLI:
173
+ Three primitives the agent uses directly (as `Local_*` tools) and you can drive from the CLI:
154
174
 
155
175
  | Surface | What it is | CLI |
156
176
  |---|---|---|
157
177
  | **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` |
178
+ | **Tasks** | Durable work units that survive turn boundaries | `cade tasks list / get / create / update / delete` |
159
179
  | **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
180
 
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.
181
+ Cross-agent messaging is set up with `cade link` / `cade channel` (an agent can only
182
+ reach another it's been linked to). Hooks and tasks/cron details live in their
183
+ respective `cade <subcommand> --help` outputs.
163
184
 
164
185
  ---
165
186
 
@@ -171,9 +192,9 @@ Cade works with any OpenAI-compatible endpoint. Three ways to wire one in (CLI f
171
192
  # CLI flag for Ollama. Use a model from `ollama list`.
172
193
  cade chat -L --endpoint http://localhost:11434 --model qwen3:4b
173
194
 
174
- # Environment for one-shot mode
175
- cade context create local-qwen --model qwen3:4b
176
- cade context use local-qwen
195
+ # Or create a dedicated agent for the local model
196
+ cade new local-qwen --model qwen3:4b
197
+ cade use local-qwen
177
198
  export OLLAMA_BASE_URL="http://localhost:11434"
178
199
  CADE_LOCAL_ONLY=1 cade -m "hello from a local model"
179
200
 
@@ -193,12 +214,11 @@ All state lives under `~/.cade/`. Override the location with `CADE_HOME=/path/to
193
214
 
194
215
  | File | Purpose |
195
216
  |---|---|
196
- | `config/cade.toml` | Model / provider / UI settings |
197
- | `data/contexts/<context>/history.db` | Thread + message storage |
217
+ | `config/cade.toml` | Global settings + `[agent_defaults]` (model, provider, UI, …) |
218
+ | `config/agents/<name>.toml` | Per-agent config (model, prompt, `[[mcp]]`, `[serve]`, hooks) |
219
+ | `data/agents/<id>/` | Per-agent state: `threads/ memory/ tasks/ inbox/` |
220
+ | `run/agents/<name>/` | Per-agent daemon runtime: `serve.pid`, mcp-services, cron lease |
198
221
  | `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
222
 
203
223
  Full layout, env vars, and TOML schema in [`docs/configuration.md`](./docs/configuration.md).
204
224
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "cade-cli"
3
- version = "0.13.4"
3
+ version = "0.14.1"
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}