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.
- {cade_cli-0.13.4 → cade_cli-0.14.1}/PKG-INFO +56 -36
- {cade_cli-0.13.4 → cade_cli-0.14.1}/README.md +55 -35
- {cade_cli-0.13.4 → cade_cli-0.14.1}/pyproject.toml +1 -1
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/server.py +13 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/tools/__init__.py +5 -0
- cade_cli-0.14.1/src/cade_mcp_local/tools/agents.py +151 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/tools/notifications.py +2 -2
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/ai/prompts.py +33 -19
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/cli/app.py +156 -115
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/cli/commands/account.py +3 -1
- cade_cli-0.14.1/src/cadecoder/cli/commands/agents.py +440 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/cli/commands/auth.py +0 -19
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/cli/commands/chat.py +4 -23
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/cli/commands/hooks.py +60 -59
- cade_cli-0.14.1/src/cadecoder/cli/commands/mem.py +221 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/cli/commands/serve.py +64 -3
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/cli/commands/tasks.py +19 -7
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/cli/commands/thread.py +1 -1
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/cli/commands/tools.py +48 -31
- cade_cli-0.14.1/src/cadecoder/core/agent.py +501 -0
- cade_cli-0.14.1/src/cadecoder/core/comms.py +177 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/core/config.py +25 -203
- cade_cli-0.14.1/src/cadecoder/core/inbox.py +138 -0
- cade_cli-0.14.1/src/cadecoder/core/memory.py +76 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/core/paths.py +57 -19
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/core/runtime.py +27 -10
- {cade_cli-0.13.4/src/cadecoder/serve → cade_cli-0.14.1/src/cadecoder/core}/secrets.py +15 -5
- cade_cli-0.14.1/src/cadecoder/core/spawn.py +215 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/execution/orchestrator.py +2 -2
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/hooks/__init__.py +9 -3
- cade_cli-0.14.1/src/cadecoder/hooks/config.py +193 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/providers/__init__.py +8 -3
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/serve/__init__.py +1 -1
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/serve/allowlist.py +2 -2
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/serve/config.py +52 -53
- cade_cli-0.14.1/src/cadecoder/serve/cron.py +37 -0
- cade_cli-0.14.1/src/cadecoder/serve/daemon.py +661 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/serve/install.py +50 -27
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/serve/observability.py +3 -1
- cade_cli-0.14.1/src/cadecoder/serve/owner.py +44 -0
- cade_cli-0.14.1/src/cadecoder/serve/secrets.py +24 -0
- cade_cli-0.14.1/src/cadecoder/serve/services.py +309 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/serve/worker.py +65 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/tasks/__init__.py +1 -8
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/tasks/store.py +4 -4
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/tasks/types.py +0 -9
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/templates/serve/launchd.plist.tmpl +1 -1
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/templates/serve/systemd.service.tmpl +2 -2
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/tools/manager/composite.py +279 -132
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/tools/manager/config.py +25 -20
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/tools/manager/mcp.py +230 -94
- cade_cli-0.14.1/src/cadecoder/ui/completion.py +74 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/ui/display.py +13 -7
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/ui/input.py +49 -13
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/ui/session.py +219 -116
- cade_cli-0.14.1/src/cadecoder/ui/slash.py +84 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/voice/session.py +22 -2
- cade_cli-0.13.4/src/cadecoder/cli/commands/channels.py +0 -79
- cade_cli-0.13.4/src/cadecoder/cli/commands/context.py +0 -205
- cade_cli-0.13.4/src/cadecoder/cli/commands/mem.py +0 -176
- cade_cli-0.13.4/src/cadecoder/cli/commands/model.py +0 -255
- cade_cli-0.13.4/src/cadecoder/cli/commands/persona.py +0 -572
- cade_cli-0.13.4/src/cadecoder/hooks/config.py +0 -151
- cade_cli-0.13.4/src/cadecoder/serve/daemon.py +0 -383
- cade_cli-0.13.4/src/cadecoder/storage/personas.py +0 -243
- cade_cli-0.13.4/src/cadecoder/tasks/channels.py +0 -89
- cade_cli-0.13.4/src/cadecoder/tasks/notifications.py +0 -100
- cade_cli-0.13.4/src/cadecoder/ui/slash.py +0 -47
- {cade_cli-0.13.4 → cade_cli-0.14.1}/.gitignore +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/LICENSE +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/__init__.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/__main__.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/_metadata.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/config.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/errors.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/resources.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/tools/_read_cache.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/tools/context.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/tools/filesystem.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/tools/git.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/tools/questions.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/tools/results.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/tools/schemas.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/tools/search.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/tools/shell.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/tools/snippets.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/tools/tasks.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/tools/web_fetch.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/tools/web_search.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/utils.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/web/__init__.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/web/arcade_client.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/web/cache.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/web/extract.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/web/markdown.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/web/preapproved.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/web/prompts.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/web/scrape.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/web/search/__init__.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/web/search/arcade.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/web/search/base.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cade_mcp_local/web/search/http.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/__init__.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/ai/__init__.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/cli/__init__.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/cli/auth.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/cli/commands/__init__.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/cli/commands/cron.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/cli/commands/mcp.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/core/__init__.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/core/constants.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/core/errors.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/core/frozen.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/core/git.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/core/logging.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/core/model_specs.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/core/names.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/core/types.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/execution/__init__.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/execution/context_window.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/execution/mcp_schema_index.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/execution/parallel.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/execution/tool_result_store.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/execution/tool_schema_cache.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/hooks/engine.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/hooks/executors/__init__.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/hooks/executors/callback.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/hooks/executors/command.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/hooks/executors/http.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/hooks/executors/prompt.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/hooks/executors/ssrf_guard.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/hooks/matchers.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/hooks/registry.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/hooks/types.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/providers/anthropic.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/providers/base.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/providers/ollama.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/providers/openai.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/serve/adapters/__init__.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/serve/adapters/base.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/serve/adapters/desktop.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/serve/adapters/registry.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/serve/adapters/stub.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/serve/adapters/telegram.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/serve/chunker.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/serve/commands.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/serve/elicitation.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/serve/format.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/serve/lock.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/serve/progress_sink.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/serve/router.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/serve/sinks.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/storage/__init__.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/storage/threads.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/tasks/lock.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/tasks/scheduler.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/templates/login_failed.html +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/templates/login_success.html +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/templates/serve/serve.toml.example +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/templates/styles.css +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/tools/__init__.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/tools/manager/__init__.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/tools/manager/_request_ctx.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/tools/manager/base.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/tools/search/__init__.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/tools/search/discovered.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/tools/search/scoring.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/tools/search/service.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/ui/__init__.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/ui/elicitation.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/voice/__init__.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/voice/audio.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/voice/cleanup.py +0 -0
- {cade_cli-0.13.4 → cade_cli-0.14.1}/src/cadecoder/voice/stt.py +0 -0
- {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.
|
|
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
|
-
|
|
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 /
|
|
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
|
-
- **
|
|
107
|
-
- **Extensibility surface.** Hooks (lifecycle events), tasks (
|
|
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
|
-
|
|
|
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
|
-
|
|
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
|
|
154
|
+
cade resume # resume the most recent thread
|
|
142
155
|
cade resume "auth-rewrite" # resume a thread by name
|
|
143
|
-
cade
|
|
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
|
-
|
|
|
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`, `/
|
|
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-
|
|
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
|
|
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
|
-
##
|
|
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
|
|
209
|
-
cade
|
|
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
|
|
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
|
|
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 —
|
|
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
|
-
|
|
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
|
|
259
|
+
## Extensibility: hooks, tasks, cron
|
|
240
260
|
|
|
241
|
-
|
|
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** |
|
|
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
|
-
|
|
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
|
-
#
|
|
263
|
-
cade
|
|
264
|
-
cade
|
|
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` |
|
|
285
|
-
| `
|
|
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
|
-
|
|
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 /
|
|
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
|
-
- **
|
|
19
|
-
- **Extensibility surface.** Hooks (lifecycle events), tasks (
|
|
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
|
-
|
|
|
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
|
-
|
|
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
|
|
66
|
+
cade resume # resume the most recent thread
|
|
54
67
|
cade resume "auth-rewrite" # resume a thread by name
|
|
55
|
-
cade
|
|
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
|
-
|
|
|
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`, `/
|
|
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-
|
|
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
|
|
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
|
-
##
|
|
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
|
|
121
|
-
cade
|
|
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
|
|
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
|
|
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 —
|
|
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
|
-
|
|
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
|
|
171
|
+
## Extensibility: hooks, tasks, cron
|
|
152
172
|
|
|
153
|
-
|
|
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** |
|
|
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
|
-
|
|
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
|
-
#
|
|
175
|
-
cade
|
|
176
|
-
cade
|
|
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` |
|
|
197
|
-
| `
|
|
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
|
|
|
@@ -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.
|
|
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
|
-
|
|
48
|
+
current_inbox().enqueue(xml)
|
|
49
49
|
return {"queued": True, "level": level_value}
|