cade-cli 0.10.0__tar.gz → 0.13.2__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 (165) hide show
  1. {cade_cli-0.10.0 → cade_cli-0.13.2}/PKG-INFO +51 -42
  2. {cade_cli-0.10.0 → cade_cli-0.13.2}/README.md +40 -32
  3. {cade_cli-0.10.0 → cade_cli-0.13.2}/pyproject.toml +15 -10
  4. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cade_mcp_local/__init__.py +10 -0
  5. cade_cli-0.13.2/src/cade_mcp_local/_metadata.py +84 -0
  6. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cade_mcp_local/errors.py +46 -0
  7. cade_cli-0.13.2/src/cade_mcp_local/resources.py +131 -0
  8. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cade_mcp_local/server.py +22 -17
  9. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cade_mcp_local/tools/__init__.py +5 -10
  10. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cade_mcp_local/tools/context.py +22 -4
  11. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cade_mcp_local/tools/filesystem.py +57 -104
  12. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cade_mcp_local/tools/git.py +26 -7
  13. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cade_mcp_local/tools/notifications.py +10 -2
  14. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cade_mcp_local/tools/questions.py +20 -6
  15. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cade_mcp_local/tools/results.py +76 -29
  16. cade_cli-0.13.2/src/cade_mcp_local/tools/schemas.py +128 -0
  17. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cade_mcp_local/tools/search.py +22 -5
  18. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cade_mcp_local/tools/shell.py +14 -2
  19. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cade_mcp_local/tools/snippets.py +16 -2
  20. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cade_mcp_local/tools/tasks.py +31 -19
  21. cade_cli-0.13.2/src/cade_mcp_local/tools/web_fetch.py +256 -0
  22. cade_cli-0.13.2/src/cade_mcp_local/tools/web_search.py +158 -0
  23. cade_cli-0.13.2/src/cade_mcp_local/web/__init__.py +1 -0
  24. cade_cli-0.13.2/src/cade_mcp_local/web/arcade_client.py +131 -0
  25. cade_cli-0.13.2/src/cade_mcp_local/web/cache.py +136 -0
  26. cade_cli-0.13.2/src/cade_mcp_local/web/extract.py +54 -0
  27. cade_cli-0.13.2/src/cade_mcp_local/web/markdown.py +64 -0
  28. cade_cli-0.13.2/src/cade_mcp_local/web/preapproved.py +57 -0
  29. cade_cli-0.13.2/src/cade_mcp_local/web/prompts.py +29 -0
  30. cade_cli-0.13.2/src/cade_mcp_local/web/scrape.py +77 -0
  31. cade_cli-0.13.2/src/cade_mcp_local/web/search/__init__.py +5 -0
  32. cade_cli-0.13.2/src/cade_mcp_local/web/search/arcade.py +103 -0
  33. cade_cli-0.13.2/src/cade_mcp_local/web/search/base.py +41 -0
  34. cade_cli-0.13.2/src/cade_mcp_local/web/search/http.py +129 -0
  35. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/ai/prompts.py +15 -19
  36. cade_cli-0.13.2/src/cadecoder/cli/app.py +342 -0
  37. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/cli/auth.py +34 -46
  38. cade_cli-0.13.2/src/cadecoder/cli/commands/account.py +203 -0
  39. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/cli/commands/auth.py +30 -38
  40. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/cli/commands/chat.py +20 -21
  41. cade_cli-0.13.2/src/cadecoder/cli/commands/context.py +191 -0
  42. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/cli/commands/mcp.py +1 -6
  43. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/cli/commands/mem.py +4 -6
  44. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/cli/commands/model.py +12 -9
  45. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/cli/commands/persona.py +15 -158
  46. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/cli/commands/serve.py +7 -15
  47. cade_cli-0.13.2/src/cadecoder/core/config.py +568 -0
  48. cade_cli-0.13.2/src/cadecoder/core/frozen.py +37 -0
  49. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/core/logging.py +5 -5
  50. cade_cli-0.13.2/src/cadecoder/core/paths.py +147 -0
  51. cade_cli-0.13.2/src/cadecoder/core/runtime.py +116 -0
  52. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/execution/context_window.py +3 -1
  53. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/execution/mcp_schema_index.py +4 -9
  54. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/execution/orchestrator.py +42 -25
  55. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/execution/parallel.py +102 -27
  56. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/execution/tool_result_store.py +8 -4
  57. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/execution/tool_schema_cache.py +39 -5
  58. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/hooks/__init__.py +1 -1
  59. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/hooks/config.py +33 -21
  60. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/providers/__init__.py +10 -4
  61. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/providers/ollama.py +36 -6
  62. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/serve/__init__.py +1 -1
  63. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/serve/adapters/__init__.py +4 -1
  64. cade_cli-0.13.2/src/cadecoder/serve/adapters/desktop.py +408 -0
  65. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/serve/allowlist.py +2 -3
  66. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/serve/config.py +49 -16
  67. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/serve/daemon.py +73 -37
  68. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/serve/install.py +4 -2
  69. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/serve/lock.py +2 -2
  70. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/serve/observability.py +8 -4
  71. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/serve/secrets.py +4 -4
  72. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/serve/worker.py +91 -15
  73. cade_cli-0.13.2/src/cadecoder/storage/personas.py +216 -0
  74. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/storage/threads.py +20 -14
  75. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/tasks/channels.py +4 -3
  76. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/tasks/lock.py +6 -7
  77. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/tasks/scheduler.py +6 -6
  78. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/tasks/store.py +3 -3
  79. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/tasks/types.py +1 -1
  80. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/templates/serve/launchd.plist.tmpl +4 -0
  81. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/templates/serve/serve.toml.example +18 -8
  82. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/templates/serve/systemd.service.tmpl +2 -0
  83. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/tools/manager/composite.py +280 -74
  84. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/tools/manager/config.py +20 -28
  85. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/tools/manager/mcp.py +51 -10
  86. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/tools/search/discovered.py +3 -3
  87. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/tools/search/service.py +62 -13
  88. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/ui/display.py +207 -33
  89. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/ui/input.py +4 -18
  90. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/ui/session.py +114 -24
  91. cade_cli-0.13.2/src/cadecoder/ui/slash.py +47 -0
  92. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/voice/__init__.py +7 -1
  93. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/voice/session.py +92 -39
  94. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/voice/tts.py +62 -37
  95. cade_cli-0.10.0/src/cade_mcp_local/tools/channels.py +0 -76
  96. cade_cli-0.10.0/src/cade_mcp_local/tools/schemas.py +0 -186
  97. cade_cli-0.10.0/src/cade_mcp_local/tools/sleep.py +0 -38
  98. cade_cli-0.10.0/src/cadecoder/cli/app.py +0 -250
  99. cade_cli-0.10.0/src/cadecoder/cli/commands/context.py +0 -338
  100. cade_cli-0.10.0/src/cadecoder/core/config.py +0 -444
  101. cade_cli-0.10.0/src/cadecoder/storage/personas.py +0 -403
  102. {cade_cli-0.10.0 → cade_cli-0.13.2}/.gitignore +0 -0
  103. {cade_cli-0.10.0 → cade_cli-0.13.2}/LICENSE +0 -0
  104. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cade_mcp_local/__main__.py +0 -0
  105. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cade_mcp_local/config.py +0 -0
  106. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cade_mcp_local/tools/_read_cache.py +0 -0
  107. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cade_mcp_local/utils.py +0 -0
  108. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/__init__.py +0 -0
  109. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/ai/__init__.py +0 -0
  110. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/cli/__init__.py +0 -0
  111. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/cli/commands/__init__.py +0 -0
  112. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/cli/commands/channels.py +0 -0
  113. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/cli/commands/cron.py +0 -0
  114. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/cli/commands/hooks.py +0 -0
  115. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/cli/commands/tasks.py +0 -0
  116. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/cli/commands/thread.py +0 -0
  117. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/cli/commands/tools.py +0 -0
  118. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/core/__init__.py +0 -0
  119. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/core/constants.py +0 -0
  120. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/core/errors.py +0 -0
  121. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/core/git.py +0 -0
  122. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/core/names.py +0 -0
  123. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/core/types.py +0 -0
  124. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/execution/__init__.py +0 -0
  125. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/hooks/engine.py +0 -0
  126. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/hooks/executors/__init__.py +0 -0
  127. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/hooks/executors/callback.py +0 -0
  128. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/hooks/executors/command.py +0 -0
  129. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/hooks/executors/http.py +0 -0
  130. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/hooks/executors/prompt.py +0 -0
  131. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/hooks/executors/ssrf_guard.py +0 -0
  132. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/hooks/matchers.py +0 -0
  133. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/hooks/registry.py +0 -0
  134. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/hooks/types.py +0 -0
  135. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/providers/anthropic.py +0 -0
  136. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/providers/base.py +0 -0
  137. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/providers/openai.py +0 -0
  138. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/serve/adapters/base.py +0 -0
  139. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/serve/adapters/registry.py +0 -0
  140. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/serve/adapters/stub.py +0 -0
  141. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/serve/adapters/telegram.py +0 -0
  142. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/serve/chunker.py +0 -0
  143. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/serve/commands.py +0 -0
  144. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/serve/elicitation.py +0 -0
  145. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/serve/format.py +0 -0
  146. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/serve/progress_sink.py +0 -0
  147. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/serve/router.py +0 -0
  148. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/serve/sinks.py +0 -0
  149. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/storage/__init__.py +0 -0
  150. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/tasks/__init__.py +0 -0
  151. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/tasks/notifications.py +0 -0
  152. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/templates/login_failed.html +0 -0
  153. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/templates/login_success.html +0 -0
  154. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/templates/styles.css +0 -0
  155. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/tools/__init__.py +0 -0
  156. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/tools/manager/__init__.py +0 -0
  157. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/tools/manager/_request_ctx.py +0 -0
  158. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/tools/manager/base.py +0 -0
  159. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/tools/search/__init__.py +0 -0
  160. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/tools/search/scoring.py +0 -0
  161. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/ui/__init__.py +0 -0
  162. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/ui/elicitation.py +0 -0
  163. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/voice/audio.py +0 -0
  164. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/voice/cleanup.py +0 -0
  165. {cade_cli-0.10.0 → cade_cli-0.13.2}/src/cadecoder/voice/stt.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cade-cli
3
- Version: 0.10.0
3
+ Version: 0.13.2
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
@@ -43,28 +43,29 @@ Classifier: Topic :: Software Development
43
43
  Classifier: Topic :: Software Development :: Code Generators
44
44
  Classifier: Typing :: Typed
45
45
  Requires-Python: >=3.11
46
- Requires-Dist: agent-library<1.0.0,>=0.12.0
46
+ Requires-Dist: agent-library<1.0.0,>=0.13.1
47
47
  Requires-Dist: anthropic<1.0.0,>=0.34.0
48
- Requires-Dist: arcade-core<5.0.0,>=4.1.0
49
- Requires-Dist: arcade-mcp-server>=1.0.0
50
- Requires-Dist: arcade-tdk>=2.0.0
48
+ Requires-Dist: arcade-core<5.0.0,>=4.7.0
49
+ Requires-Dist: arcade-mcp-server<2.0.0,>=1.22.0
50
+ Requires-Dist: arcade-tdk<4.0.0,>=3.8.0
51
+ Requires-Dist: arcadepy<2.0.0,>=1.10.0
51
52
  Requires-Dist: authlib<2.0.0,>=1.6.0
52
53
  Requires-Dist: croniter<4.0.0,>=2.0.0
53
54
  Requires-Dist: filelock<4.0.0,>=3.0.0
55
+ Requires-Dist: html2text>=2024.2.26
54
56
  Requires-Dist: httpx<1.0.0,>=0.27.0
55
57
  Requires-Dist: keyring<26.0,>=24.0
56
58
  Requires-Dist: openai<2.0.0,>=1.0.0
57
59
  Requires-Dist: prompt-toolkit<4.0.0,>=3.0.52
58
60
  Requires-Dist: pydantic[email]<3.0.0,>=2.0.0
59
- Requires-Dist: pyperclip<2.0.0,>=1.8.0
60
61
  Requires-Dist: python-telegram-bot<22.0,>=21.0
61
- Requires-Dist: pyyaml<7.0.0,>=6.0
62
62
  Requires-Dist: rich<14.0.0,>=13.0.0
63
- Requires-Dist: sounddevice>=0.5.5
64
- Requires-Dist: tiktoken<1.0.0,>=0.11.0
65
63
  Requires-Dist: toml<1.0.0,>=0.10.0
66
64
  Requires-Dist: typer>0.10.0
67
65
  Requires-Dist: ulid==1.1
66
+ Requires-Dist: websockets<16.0,>=14.0
67
+ Provides-Extra: build
68
+ Requires-Dist: pyinstaller<7.0.0,>=6.16.0; extra == 'build'
68
69
  Provides-Extra: dev
69
70
  Requires-Dist: mypy<2.0.0,>=1.10.0; extra == 'dev'
70
71
  Requires-Dist: pytest-asyncio<1.0.0,>=0.24.0; extra == 'dev'
@@ -81,7 +82,7 @@ Provides-Extra: voice
81
82
  Requires-Dist: mlx-audio<0.4.0,>=0.2.0; extra == 'voice'
82
83
  Requires-Dist: mlx-whisper>=0.1.0; extra == 'voice'
83
84
  Requires-Dist: numpy>=1.24.0; extra == 'voice'
84
- Requires-Dist: sounddevice>=0.4.0; extra == 'voice'
85
+ Requires-Dist: sounddevice<1.0.0,>=0.5.5; extra == 'voice'
85
86
  Requires-Dist: webrtcvad>=2.0.10; extra == 'voice'
86
87
  Description-Content-Type: text/markdown
87
88
 
@@ -117,6 +118,8 @@ cade
117
118
  | pip | `pip install cade-cli` |
118
119
  | From source | `git clone https://github.com/arcadeai-labs/cade.git && cd cade && uv sync` |
119
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`.
122
+
120
123
  **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`.
121
124
 
122
125
  ```bash
@@ -124,6 +127,9 @@ cade login # Arcade Cloud OAuth (skip with --local-only)
124
127
  cade --version
125
128
  ```
126
129
 
130
+ Full install and first-run docs: [`docs/install.md`](./docs/install.md) and
131
+ [`docs/quickstart.md`](./docs/quickstart.md).
132
+
127
133
  ---
128
134
 
129
135
  ## Quick start
@@ -131,11 +137,11 @@ cade --version
131
137
  ```bash
132
138
  cade # interactive chat
133
139
  cade -m "What changed in HEAD?" # single message, then exit
134
- cat error.log | cade -m "What went wrong?" # pipe input
140
+ cade -m "What went wrong?" < error.log # prompt + file/stdin
135
141
  cade -r # resume the most recent thread
136
142
  cade resume "auth-rewrite" # resume a thread by name
137
143
  cade --persona reviewer # use a saved persona's system prompt
138
- cade --voice # speak / hear (voice mode)
144
+ cade --voice # speak / hear (requires cade-cli[voice])
139
145
  ```
140
146
 
141
147
  ### Top-level options
@@ -143,9 +149,9 @@ cade --voice # speak / hear (voice mode)
143
149
  | Flag | Description |
144
150
  |---|---|
145
151
  | `-r`, `--resume` | Resume most recent thread |
146
- | `-m`, `--message` | Single-message mode (reads stdin if no arg) |
152
+ | `-m`, `--message` | Single-message mode; piped stdin is appended to the prompt |
147
153
  | `-P`, `--persona` | Use a saved persona |
148
- | `-V`, `--voice` | Voice mode |
154
+ | `-V`, `--voice` | Voice mode; install `cade-cli[voice]` first |
149
155
  | `-v`, `--verbose` | Debug logging |
150
156
  | `--version` | Print version |
151
157
 
@@ -159,7 +165,8 @@ cade --voice # speak / hear (voice mode)
159
165
  | `/logs` | Recent log entries |
160
166
  | `/thread`, `/history` | Current thread info |
161
167
  | `/pin`, `/unpin` | Pin reference material into the session |
162
- | `/task`, `/cron`, `/hooks`, `/channel`, `/notify` | Coordination surfaces |
168
+ | `/tasks`, `/cron`, `/hooks`, `/channels`, `/notify` | Coordination surfaces (mirrored as `cade tasks` / `cade cron` / `cade hooks` / `cade channels`) |
169
+ | `/usage` | Context-window status and token usage |
163
170
  | `/cd`, `/pwd`, `/!` | Shell shortcuts |
164
171
  | `Ctrl+C` | Exit |
165
172
 
@@ -169,7 +176,7 @@ cade --voice # speak / hear (voice mode)
169
176
 
170
177
  Tools come from three sources and are addressed uniformly by their registered name:
171
178
 
172
- - **`Local_*`** — built-in: filesystem (`ReadFile`, `WriteFile`, `Edit`, `ListFiles`), shell (`Bash` — async with progress reporting), `Search`, `Git`, `Task*`, `Channel`, `AskUserQuestion`, `RetrieveToolResult`, `ToolSchema`, `Sleep`, `PinContext`, `PushNotification`.
179
+ - **`Local_*`** — built-in: filesystem (`ReadFile`, `WriteFile`, `Edit`, `ListFiles`), shell (`Bash`), `Search`, `Git`, `Task*`, `AskUserQuestion`, `RetrieveToolResult`, `ToolSchema`, `PinContext`, `PushNotification`, `WebFetch`, and `WebSearch`.
173
180
  - **`Memory_*`** — agent-library backed, per-persona indexed knowledge store.
174
181
  - **Arcade Cloud + user MCP servers** — anything you register.
175
182
 
@@ -191,7 +198,7 @@ cade mcp authorize my-server # OAuth flow (browser)
191
198
  cade mcp list / status / test / enable / disable / rm
192
199
  ```
193
200
 
194
- User MCP servers register at `~/.cadecoder/mcp_servers.yaml`. Servers with large catalogs are auto-deferred (parameter schemas stripped to keep tool-list bytes down) and fetched on demand via `Local_ToolSchema`.
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`.
195
202
 
196
203
  ---
197
204
 
@@ -206,13 +213,13 @@ cade mem add ~/notes # index a directory
206
213
  cade mem search "auth design" # semantic search
207
214
  ```
208
215
 
209
- Memory is persona-scoped — each persona has its own `~/.cadecoder/memory/<persona>/.librarian/` index, so a `reviewer` persona's notes never leak into `default`.
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`.
210
217
 
211
218
  ---
212
219
 
213
220
  ## Headless daemon: `cade serve`
214
221
 
215
- Run Cade as a long-lived daemon that replies over messaging platforms (Telegram supported today; the adapter protocol is generic). Each chat gets its own persistent thread — persona, memory, and tools carry across messages.
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.
216
223
 
217
224
  ```bash
218
225
  cade serve init # wizard: bot token, allowed senders
@@ -221,11 +228,11 @@ cade serve --install launchd # macOS LaunchAgent (or --install syste
221
228
  cade serve status / stop # health, uptime; SIGTERM running daemon
222
229
  ```
223
230
 
224
- Config lives at `~/.cadecoder/serve.toml`. Edit and `kill -HUP $(cat ~/.cadecoder/serve.pid)` to reload without restart.
231
+ Config lives at `~/.cade/config/contexts/<context>.toml [serve]`. Edit and `kill -HUP $(cat ~/.cade/run/serve.pid)` to reload without restart.
225
232
 
226
- **Security defaults are fail-closed:** `allowed_senders = []` blocks everyone; tools are default-deny against `[tools].allow` (globs / regex / pipe lists supported); `deny` always wins.
233
+ **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.
227
234
 
228
- The MCP transport is fully bidirectional, so tools running inside the daemon can elicit structured input (rendered as Telegram inline keyboards), stream live progress (rendered as edited placeholder messages), and emit logs that flow into the daemon log. See [`docs/mcp.md`](./docs/mcp.md) for the protocol details, [`docs/configuration.md`](./docs/configuration.md) for the full daemon config reference.
235
+ The MCP transport is fully bidirectional, so tools running inside the daemon can elicit structured input, stream live progress, and emit logs through whichever adapter is active. See [`docs/adapters/`](./docs/adapters/) for adapter details, [`docs/mcp.md`](./docs/mcp.md) for protocol details, and [`docs/configuration.md`](./docs/configuration.md) for the full daemon config reference.
229
236
 
230
237
  ---
231
238
 
@@ -249,17 +256,18 @@ See [`docs/channels.md`](./docs/channels.md) for the channels protocol; hooks an
249
256
  Cade works with any OpenAI-compatible endpoint. Three ways to wire one in (CLI flag → env → config, first match wins):
250
257
 
251
258
  ```bash
252
- # CLI flag
253
- cade chat --endpoint http://localhost:11434/v1 --model llama3
259
+ # CLI flag for Ollama. Use a model from `ollama list`.
260
+ cade chat -L --endpoint http://localhost:11434 --model qwen3:4b
254
261
 
255
- # Environment
256
- export OPENAI_BASE_URL="http://localhost:11434/v1"
257
- export OPENAI_API_KEY="ollama" # any non-empty value
258
- cade chat --model llama3
262
+ # Environment for one-shot mode
263
+ cade context create local-qwen --model qwen3:4b
264
+ cade context use local-qwen
265
+ export OLLAMA_BASE_URL="http://localhost:11434"
266
+ CADE_LOCAL_ONLY=1 cade -m "hello from a local model"
259
267
 
260
- # Config — ~/.cadecoder/cadecoder.toml
268
+ # Config — ~/.cade/config/cade.toml
261
269
  [model_settings]
262
- host = "http://localhost:11434/v1"
270
+ host = "http://localhost:8000/v1"
263
271
  api_key = "ollama"
264
272
  ```
265
273
 
@@ -269,15 +277,15 @@ Skip Arcade Cloud authentication entirely with `--local-only` or `CADE_LOCAL_ONL
269
277
 
270
278
  ## Configuration
271
279
 
272
- All state lives under `~/.cadecoder/`. Override the location with `CADECODER_HOME=/path/to/alt`.
280
+ All state lives under `~/.cade/`. Override the location with `CADE_HOME=/path/to/alt`.
273
281
 
274
282
  | File | Purpose |
275
283
  |---|---|
276
- | `cadecoder.toml` | Model / provider / UI settings |
277
- | `cadecoder_history.db` | Thread + message storage |
278
- | `cadecoder.log` | Rotating log file |
279
- | `mcp_servers.yaml` | User MCP server registry |
280
- | `serve.toml` | `cade serve` daemon config |
284
+ | `config/cade.toml` | Model / provider / UI settings |
285
+ | `data/contexts/<context>/history.db` | Thread + message storage |
286
+ | `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 |
281
289
  | `personas/`, `memory/`, `tasks/`, `channels/` | Persona-scoped state |
282
290
 
283
291
  Full layout, env vars, and TOML schema in [`docs/configuration.md`](./docs/configuration.md).
@@ -290,7 +298,7 @@ Full layout, env vars, and TOML schema in [`docs/configuration.md`](./docs/confi
290
298
  | `OPENAI_BASE_URL` | Custom OpenAI-compatible endpoint |
291
299
  | `ARCADE_API_KEY`, `ARCADE_BASE_URL` | Arcade Cloud (alternative to OAuth) |
292
300
  | `CADE_LOCAL_ONLY=1` | Skip remote tools entirely |
293
- | `CADECODER_HOME` | Override config directory |
301
+ | `CADE_HOME` | Override config directory |
294
302
  | `CADE_PROJECT_ROOT` | Sandbox `Local_*` filesystem tools to this root |
295
303
 
296
304
  ---
@@ -300,14 +308,15 @@ Full layout, env vars, and TOML schema in [`docs/configuration.md`](./docs/confi
300
308
  ```bash
301
309
  git clone https://github.com/arcadeai-labs/cade.git
302
310
  cd cade
303
- uv sync --all-extras --dev
304
- pytest # full suite
305
- ruff check src/ tests/ && ruff format src/ tests/
311
+ uv sync --extra dev
312
+ uv run pytest
313
+ uv run ruff check src/ tests/
306
314
  ```
307
315
 
308
316
  Style: Python 3.11+ with modern type hints (`dict`, `list`, `| None`); ruff for lint + format; pytest with `asyncio_mode = "auto"`. Public functions and classes get docstrings.
309
317
 
310
- PRs welcome open an issue first for anything substantial.
318
+ Build/release docs live in [`docs/development.md`](./docs/development.md). PRs
319
+ welcome — open an issue first for anything substantial.
311
320
 
312
321
  ---
313
322
 
@@ -315,7 +324,7 @@ PRs welcome — open an issue first for anything substantial.
315
324
 
316
325
  - [arcade.dev](https://arcade.dev) — product
317
326
  - [docs.arcade.dev](https://docs.arcade.dev) — API and tool catalog
318
- - [`docs/`](./docs/) — `mcp.md` (tool protocol), `configuration.md`, `channels.md`, `install.md`
327
+ - [`docs/`](./docs/) — quickstart, examples, install, config, MCP, channels, voice, development, and adapters
319
328
  - [Issues](https://github.com/arcadeai-labs/cade/issues) · [Releases](https://github.com/arcadeai-labs/cade/releases)
320
329
 
321
330
  ## License
@@ -30,6 +30,8 @@ cade
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`.
34
+
33
35
  **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`.
34
36
 
35
37
  ```bash
@@ -37,6 +39,9 @@ cade login # Arcade Cloud OAuth (skip with --local-only)
37
39
  cade --version
38
40
  ```
39
41
 
42
+ Full install and first-run docs: [`docs/install.md`](./docs/install.md) and
43
+ [`docs/quickstart.md`](./docs/quickstart.md).
44
+
40
45
  ---
41
46
 
42
47
  ## Quick start
@@ -44,11 +49,11 @@ cade --version
44
49
  ```bash
45
50
  cade # interactive chat
46
51
  cade -m "What changed in HEAD?" # single message, then exit
47
- cat error.log | cade -m "What went wrong?" # pipe input
52
+ cade -m "What went wrong?" < error.log # prompt + file/stdin
48
53
  cade -r # resume the most recent thread
49
54
  cade resume "auth-rewrite" # resume a thread by name
50
55
  cade --persona reviewer # use a saved persona's system prompt
51
- cade --voice # speak / hear (voice mode)
56
+ cade --voice # speak / hear (requires cade-cli[voice])
52
57
  ```
53
58
 
54
59
  ### Top-level options
@@ -56,9 +61,9 @@ cade --voice # speak / hear (voice mode)
56
61
  | Flag | Description |
57
62
  |---|---|
58
63
  | `-r`, `--resume` | Resume most recent thread |
59
- | `-m`, `--message` | Single-message mode (reads stdin if no arg) |
64
+ | `-m`, `--message` | Single-message mode; piped stdin is appended to the prompt |
60
65
  | `-P`, `--persona` | Use a saved persona |
61
- | `-V`, `--voice` | Voice mode |
66
+ | `-V`, `--voice` | Voice mode; install `cade-cli[voice]` first |
62
67
  | `-v`, `--verbose` | Debug logging |
63
68
  | `--version` | Print version |
64
69
 
@@ -72,7 +77,8 @@ cade --voice # speak / hear (voice mode)
72
77
  | `/logs` | Recent log entries |
73
78
  | `/thread`, `/history` | Current thread info |
74
79
  | `/pin`, `/unpin` | Pin reference material into the session |
75
- | `/task`, `/cron`, `/hooks`, `/channel`, `/notify` | Coordination surfaces |
80
+ | `/tasks`, `/cron`, `/hooks`, `/channels`, `/notify` | Coordination surfaces (mirrored as `cade tasks` / `cade cron` / `cade hooks` / `cade channels`) |
81
+ | `/usage` | Context-window status and token usage |
76
82
  | `/cd`, `/pwd`, `/!` | Shell shortcuts |
77
83
  | `Ctrl+C` | Exit |
78
84
 
@@ -82,7 +88,7 @@ cade --voice # speak / hear (voice mode)
82
88
 
83
89
  Tools come from three sources and are addressed uniformly by their registered name:
84
90
 
85
- - **`Local_*`** — built-in: filesystem (`ReadFile`, `WriteFile`, `Edit`, `ListFiles`), shell (`Bash` — async with progress reporting), `Search`, `Git`, `Task*`, `Channel`, `AskUserQuestion`, `RetrieveToolResult`, `ToolSchema`, `Sleep`, `PinContext`, `PushNotification`.
91
+ - **`Local_*`** — built-in: filesystem (`ReadFile`, `WriteFile`, `Edit`, `ListFiles`), shell (`Bash`), `Search`, `Git`, `Task*`, `AskUserQuestion`, `RetrieveToolResult`, `ToolSchema`, `PinContext`, `PushNotification`, `WebFetch`, and `WebSearch`.
86
92
  - **`Memory_*`** — agent-library backed, per-persona indexed knowledge store.
87
93
  - **Arcade Cloud + user MCP servers** — anything you register.
88
94
 
@@ -104,7 +110,7 @@ cade mcp authorize my-server # OAuth flow (browser)
104
110
  cade mcp list / status / test / enable / disable / rm
105
111
  ```
106
112
 
107
- User MCP servers register at `~/.cadecoder/mcp_servers.yaml`. Servers with large catalogs are auto-deferred (parameter schemas stripped to keep tool-list bytes down) and fetched on demand via `Local_ToolSchema`.
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`.
108
114
 
109
115
  ---
110
116
 
@@ -119,13 +125,13 @@ cade mem add ~/notes # index a directory
119
125
  cade mem search "auth design" # semantic search
120
126
  ```
121
127
 
122
- Memory is persona-scoped — each persona has its own `~/.cadecoder/memory/<persona>/.librarian/` index, so a `reviewer` persona's notes never leak into `default`.
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`.
123
129
 
124
130
  ---
125
131
 
126
132
  ## Headless daemon: `cade serve`
127
133
 
128
- Run Cade as a long-lived daemon that replies over messaging platforms (Telegram supported today; the adapter protocol is generic). Each chat gets its own persistent thread — persona, memory, and tools carry across messages.
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.
129
135
 
130
136
  ```bash
131
137
  cade serve init # wizard: bot token, allowed senders
@@ -134,11 +140,11 @@ cade serve --install launchd # macOS LaunchAgent (or --install syste
134
140
  cade serve status / stop # health, uptime; SIGTERM running daemon
135
141
  ```
136
142
 
137
- Config lives at `~/.cadecoder/serve.toml`. Edit and `kill -HUP $(cat ~/.cadecoder/serve.pid)` to reload without restart.
143
+ Config lives at `~/.cade/config/contexts/<context>.toml [serve]`. Edit and `kill -HUP $(cat ~/.cade/run/serve.pid)` to reload without restart.
138
144
 
139
- **Security defaults are fail-closed:** `allowed_senders = []` blocks everyone; tools are default-deny against `[tools].allow` (globs / regex / pipe lists supported); `deny` always wins.
145
+ **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.
140
146
 
141
- The MCP transport is fully bidirectional, so tools running inside the daemon can elicit structured input (rendered as Telegram inline keyboards), stream live progress (rendered as edited placeholder messages), and emit logs that flow into the daemon log. See [`docs/mcp.md`](./docs/mcp.md) for the protocol details, [`docs/configuration.md`](./docs/configuration.md) for the full daemon config reference.
147
+ The MCP transport is fully bidirectional, so tools running inside the daemon can elicit structured input, stream live progress, and emit logs through whichever adapter is active. See [`docs/adapters/`](./docs/adapters/) for adapter details, [`docs/mcp.md`](./docs/mcp.md) for protocol details, and [`docs/configuration.md`](./docs/configuration.md) for the full daemon config reference.
142
148
 
143
149
  ---
144
150
 
@@ -162,17 +168,18 @@ See [`docs/channels.md`](./docs/channels.md) for the channels protocol; hooks an
162
168
  Cade works with any OpenAI-compatible endpoint. Three ways to wire one in (CLI flag → env → config, first match wins):
163
169
 
164
170
  ```bash
165
- # CLI flag
166
- cade chat --endpoint http://localhost:11434/v1 --model llama3
171
+ # CLI flag for Ollama. Use a model from `ollama list`.
172
+ cade chat -L --endpoint http://localhost:11434 --model qwen3:4b
167
173
 
168
- # Environment
169
- export OPENAI_BASE_URL="http://localhost:11434/v1"
170
- export OPENAI_API_KEY="ollama" # any non-empty value
171
- cade chat --model llama3
174
+ # Environment for one-shot mode
175
+ cade context create local-qwen --model qwen3:4b
176
+ cade context use local-qwen
177
+ export OLLAMA_BASE_URL="http://localhost:11434"
178
+ CADE_LOCAL_ONLY=1 cade -m "hello from a local model"
172
179
 
173
- # Config — ~/.cadecoder/cadecoder.toml
180
+ # Config — ~/.cade/config/cade.toml
174
181
  [model_settings]
175
- host = "http://localhost:11434/v1"
182
+ host = "http://localhost:8000/v1"
176
183
  api_key = "ollama"
177
184
  ```
178
185
 
@@ -182,15 +189,15 @@ Skip Arcade Cloud authentication entirely with `--local-only` or `CADE_LOCAL_ONL
182
189
 
183
190
  ## Configuration
184
191
 
185
- All state lives under `~/.cadecoder/`. Override the location with `CADECODER_HOME=/path/to/alt`.
192
+ All state lives under `~/.cade/`. Override the location with `CADE_HOME=/path/to/alt`.
186
193
 
187
194
  | File | Purpose |
188
195
  |---|---|
189
- | `cadecoder.toml` | Model / provider / UI settings |
190
- | `cadecoder_history.db` | Thread + message storage |
191
- | `cadecoder.log` | Rotating log file |
192
- | `mcp_servers.yaml` | User MCP server registry |
193
- | `serve.toml` | `cade serve` daemon config |
196
+ | `config/cade.toml` | Model / provider / UI settings |
197
+ | `data/contexts/<context>/history.db` | Thread + message storage |
198
+ | `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 |
194
201
  | `personas/`, `memory/`, `tasks/`, `channels/` | Persona-scoped state |
195
202
 
196
203
  Full layout, env vars, and TOML schema in [`docs/configuration.md`](./docs/configuration.md).
@@ -203,7 +210,7 @@ Full layout, env vars, and TOML schema in [`docs/configuration.md`](./docs/confi
203
210
  | `OPENAI_BASE_URL` | Custom OpenAI-compatible endpoint |
204
211
  | `ARCADE_API_KEY`, `ARCADE_BASE_URL` | Arcade Cloud (alternative to OAuth) |
205
212
  | `CADE_LOCAL_ONLY=1` | Skip remote tools entirely |
206
- | `CADECODER_HOME` | Override config directory |
213
+ | `CADE_HOME` | Override config directory |
207
214
  | `CADE_PROJECT_ROOT` | Sandbox `Local_*` filesystem tools to this root |
208
215
 
209
216
  ---
@@ -213,14 +220,15 @@ Full layout, env vars, and TOML schema in [`docs/configuration.md`](./docs/confi
213
220
  ```bash
214
221
  git clone https://github.com/arcadeai-labs/cade.git
215
222
  cd cade
216
- uv sync --all-extras --dev
217
- pytest # full suite
218
- ruff check src/ tests/ && ruff format src/ tests/
223
+ uv sync --extra dev
224
+ uv run pytest
225
+ uv run ruff check src/ tests/
219
226
  ```
220
227
 
221
228
  Style: Python 3.11+ with modern type hints (`dict`, `list`, `| None`); ruff for lint + format; pytest with `asyncio_mode = "auto"`. Public functions and classes get docstrings.
222
229
 
223
- PRs welcome open an issue first for anything substantial.
230
+ Build/release docs live in [`docs/development.md`](./docs/development.md). PRs
231
+ welcome — open an issue first for anything substantial.
224
232
 
225
233
  ---
226
234
 
@@ -228,7 +236,7 @@ PRs welcome — open an issue first for anything substantial.
228
236
 
229
237
  - [arcade.dev](https://arcade.dev) — product
230
238
  - [docs.arcade.dev](https://docs.arcade.dev) — API and tool catalog
231
- - [`docs/`](./docs/) — `mcp.md` (tool protocol), `configuration.md`, `channels.md`, `install.md`
239
+ - [`docs/`](./docs/) — quickstart, examples, install, config, MCP, channels, voice, development, and adapters
232
240
  - [Issues](https://github.com/arcadeai-labs/cade/issues) · [Releases](https://github.com/arcadeai-labs/cade/releases)
233
241
 
234
242
  ## License
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "cade-cli"
3
- version = "0.10.0"
3
+ version = "0.13.2"
4
4
  description = "Cade - The CLI Agent from Arcade.dev"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -27,24 +27,23 @@ dependencies = [
27
27
  "typer>0.10.0",
28
28
  "pydantic[email]>=2.0.0,<3.0.0",
29
29
  "toml>=0.10.0,<1.0.0",
30
- "pyyaml>=6.0,<7.0.0",
31
30
  "openai>=1.0.0,<2.0.0",
32
31
  "anthropic>=0.34.0,<1.0.0",
33
32
  "ulid==1.1",
34
- "arcade-tdk>=2.0.0",
35
- "arcade-mcp-server>=1.0.0",
36
- "arcade-core>=4.1.0,<5.0.0",
33
+ "arcade-tdk>=3.8.0,<4.0.0",
34
+ "arcade-mcp-server>=1.22.0,<2.0.0",
35
+ "arcade-core>=4.7.0,<5.0.0",
36
+ "arcadepy>=1.10.0,<2.0.0",
37
37
  "authlib>=1.6.0,<2.0.0",
38
- "pyperclip>=1.8.0,<2.0.0",
39
38
  "prompt-toolkit>=3.0.52,<4.0.0",
40
- "tiktoken>=0.11.0,<1.0.0",
41
39
  "httpx>=0.27.0,<1.0.0",
42
40
  "filelock>=3.0.0,<4.0.0",
43
- "agent-library>=0.12.0,<1.0.0",
44
- "sounddevice>=0.5.5",
41
+ "agent-library>=0.13.1,<1.0.0",
45
42
  "croniter>=2.0.0,<4.0.0",
46
43
  "python-telegram-bot>=21.0,<22.0",
47
44
  "keyring>=24.0,<26.0",
45
+ "html2text>=2024.2.26",
46
+ "websockets>=14.0,<16.0",
48
47
  ]
49
48
 
50
49
  [project.urls]
@@ -67,10 +66,13 @@ dev = [
67
66
  "pytest-cov>=4.0.0,<5.0.0",
68
67
  "mypy>=1.10.0,<2.0.0",
69
68
  ]
69
+ build = [
70
+ "pyinstaller>=6.16.0,<7.0.0",
71
+ ]
70
72
  voice = [
71
73
  "mlx-audio>=0.2.0,<0.4.0",
72
74
  "mlx-whisper>=0.1.0",
73
- "sounddevice>=0.4.0",
75
+ "sounddevice>=0.5.5,<1.0.0",
74
76
  "numpy>=1.24.0",
75
77
  "webrtcvad>=2.0.10",
76
78
  ]
@@ -98,6 +100,9 @@ packages = ["src/cadecoder", "src/cade_mcp_local"]
98
100
  testpaths = ["tests"]
99
101
  asyncio_mode = "auto"
100
102
  asyncio_default_fixture_loop_scope = "function"
103
+ markers = [
104
+ "integration: tests that cross process or network boundaries without external services",
105
+ ]
101
106
 
102
107
  [tool.ruff]
103
108
  line-length = 100
@@ -27,12 +27,17 @@ from cade_mcp_local.config import (
27
27
  from cade_mcp_local.errors import (
28
28
  CommandExecutionError,
29
29
  CommandTimeoutError,
30
+ ContentTooLargeError,
30
31
  FileOperationError,
31
32
  GitOperationError,
32
33
  InvalidInputError,
33
34
  PathNotFoundError,
34
35
  PathSecurityError,
36
+ RedirectError,
35
37
  SearchError,
38
+ WebFetchError,
39
+ WebSearchError,
40
+ WebTransientError,
36
41
  )
37
42
  from cade_mcp_local.server import app, create_app
38
43
 
@@ -67,6 +72,11 @@ __all__ = [
67
72
  "GitOperationError",
68
73
  "SearchError",
69
74
  "FileOperationError",
75
+ "WebFetchError",
76
+ "WebSearchError",
77
+ "RedirectError",
78
+ "ContentTooLargeError",
79
+ "WebTransientError",
70
80
  ]
71
81
 
72
82
  from cadecoder import __version__ as __version__ # noqa: E402
@@ -0,0 +1,84 @@
1
+ """Reusable :class:`ToolMetadata` builders for Local_* tools.
2
+
3
+ Local tools run in-process against the user's machine. None of them have a
4
+ ``ServiceDomain`` (those describe an external service like Slack or Gmail);
5
+ ``open_world`` is therefore ``False`` for everything in this package, and
6
+ the per-tool metadata below only varies on operation/read-only/destructive/
7
+ idempotent.
8
+
9
+ Web tools (``WebFetch`` / ``WebSearch``) are the exception — they declare
10
+ ``ServiceDomain.WEB_SCRAPING`` and ``open_world=True`` inline, since their
11
+ backing data lives on the open internet.
12
+ """
13
+
14
+ from arcade_mcp_server.metadata import (
15
+ Behavior,
16
+ Classification,
17
+ Operation,
18
+ ToolMetadata,
19
+ )
20
+
21
+
22
+ def _meta(
23
+ *,
24
+ operations: list[Operation],
25
+ read_only: bool,
26
+ destructive: bool = False,
27
+ idempotent: bool = False,
28
+ ) -> ToolMetadata:
29
+ """All Local_* tools share open_world=False and no service_domains."""
30
+ return ToolMetadata(
31
+ classification=Classification(service_domains=None),
32
+ behavior=Behavior(
33
+ operations=operations,
34
+ read_only=read_only,
35
+ destructive=destructive,
36
+ idempotent=idempotent,
37
+ open_world=False,
38
+ ),
39
+ )
40
+
41
+
42
+ READ_META = _meta(operations=[Operation.READ], read_only=True, idempotent=True)
43
+ """Pure read of local state. Idempotent."""
44
+
45
+ READ_VOLATILE_META = _meta(operations=[Operation.READ], read_only=True, idempotent=False)
46
+ """Reads local state that changes under the agent's feet (e.g. compaction backups)."""
47
+
48
+ CREATE_META = _meta(operations=[Operation.CREATE], read_only=False, idempotent=False)
49
+ """Creates a new local resource (file, task, snippet, notification)."""
50
+
51
+ UPDATE_META = _meta(operations=[Operation.UPDATE], read_only=False, idempotent=False)
52
+ """Modifies an existing local resource."""
53
+
54
+ CREATE_OR_UPDATE_META = _meta(operations=[Operation.CREATE, Operation.UPDATE], read_only=False)
55
+ """Upsert-style write that may create or update."""
56
+
57
+ DELETE_META = _meta(
58
+ operations=[Operation.DELETE], read_only=False, destructive=True, idempotent=True
59
+ )
60
+ """Removes a local resource. Destructive."""
61
+
62
+ OPAQUE_META = ToolMetadata(
63
+ classification=Classification(service_domains=None),
64
+ behavior=Behavior(
65
+ operations=[Operation.OPAQUE],
66
+ read_only=False,
67
+ destructive=False,
68
+ idempotent=False,
69
+ open_world=False,
70
+ ),
71
+ strict=False, # Bash/Channel can do anything; we keep destructive=False per "best case"
72
+ )
73
+ """Action depends on runtime inputs (e.g. Bash, Channel multiplexer)."""
74
+
75
+
76
+ __all__ = (
77
+ "CREATE_META",
78
+ "CREATE_OR_UPDATE_META",
79
+ "DELETE_META",
80
+ "OPAQUE_META",
81
+ "READ_META",
82
+ "READ_VOLATILE_META",
83
+ "UPDATE_META",
84
+ )
@@ -120,3 +120,49 @@ class FileOperationError(FatalToolError):
120
120
  self.operation = operation
121
121
  self.path = path
122
122
  super().__init__(f"Failed to {operation} '{path}': {message}")
123
+
124
+
125
+ class WebFetchError(FatalToolError):
126
+ """Generic non-retriable WebFetch failure (DNS, 4xx, blocked host)."""
127
+
128
+ def __init__(self, url: str, message: str):
129
+ self.url = url
130
+ super().__init__(f"WebFetch failed for {url}: {message}")
131
+
132
+
133
+ class RedirectError(FatalToolError):
134
+ """Cross-host redirect; the agent should re-fetch the new URL explicitly."""
135
+
136
+ def __init__(self, from_url: str, to_url: str):
137
+ self.from_url = from_url
138
+ self.to_url = to_url
139
+ super().__init__(
140
+ f"Cross-host redirect from {from_url} to {to_url}; re-call WebFetch with the new URL."
141
+ )
142
+
143
+
144
+ class ContentTooLargeError(FatalToolError):
145
+ """Body exceeded max_bytes."""
146
+
147
+ def __init__(self, url: str, limit_bytes: int):
148
+ self.url = url
149
+ self.limit_bytes = limit_bytes
150
+ super().__init__(f"Body for {url} exceeded {limit_bytes} bytes; aborted.")
151
+
152
+
153
+ class WebSearchError(FatalToolError):
154
+ """Backend misconfigured or returned an unparseable response."""
155
+
156
+ def __init__(self, backend: str, message: str):
157
+ self.backend = backend
158
+ super().__init__(f"WebSearch ({backend}) failed: {message}")
159
+
160
+
161
+ class WebTransientError(RetryableToolError):
162
+ """5xx, network reset, rate-limit. Agent may retry."""
163
+
164
+ def __init__(self, url: str, status: int | None, message: str):
165
+ self.url = url
166
+ self.status = status
167
+ detail = f" (HTTP {status})" if status else ""
168
+ super().__init__(f"Transient web error for {url}{detail}: {message}")