cade-cli 0.3.4__tar.gz → 0.4.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. {cade_cli-0.3.4 → cade_cli-0.4.0}/.gitignore +3 -0
  2. {cade_cli-0.3.4 → cade_cli-0.4.0}/PKG-INFO +93 -7
  3. {cade_cli-0.3.4 → cade_cli-0.4.0}/README.md +91 -5
  4. {cade_cli-0.3.4 → cade_cli-0.4.0}/pyproject.toml +2 -2
  5. cade_cli-0.4.0/src/cadecoder/__init__.py +1 -0
  6. {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/cli/app.py +7 -0
  7. {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/cli/commands/chat.py +99 -29
  8. cade_cli-0.4.0/src/cadecoder/cli/commands/context.py +323 -0
  9. {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/cli/commands/model.py +5 -2
  10. {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/cli/commands/thread.py +46 -30
  11. cade_cli-0.4.0/src/cadecoder/cli/commands/tools.py +339 -0
  12. {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/core/config.py +16 -17
  13. {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/core/constants.py +0 -2
  14. {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/core/errors.py +19 -0
  15. {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/execution/orchestrator.py +5 -2
  16. {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/providers/__init__.py +35 -15
  17. {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/providers/base.py +1 -0
  18. cade_cli-0.4.0/src/cadecoder/providers/ollama.py +308 -0
  19. {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/providers/openai.py +5 -2
  20. {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/tools/__init__.py +9 -21
  21. {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/tools/manager/__init__.py +3 -10
  22. cade_cli-0.4.0/src/cadecoder/tools/manager/composite.py +267 -0
  23. {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/tools/manager/config.py +21 -0
  24. {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/tools/manager/mcp.py +207 -4
  25. {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/ui/session.py +23 -7
  26. cade_cli-0.3.4/src/cadecoder/__init__.py +0 -1
  27. cade_cli-0.3.4/src/cadecoder/cli/commands/tools.py +0 -226
  28. cade_cli-0.3.4/src/cadecoder/tools/manager/arcade.py +0 -277
  29. cade_cli-0.3.4/src/cadecoder/tools/manager/cache.py +0 -129
  30. cade_cli-0.3.4/src/cadecoder/tools/manager/composite.py +0 -157
  31. cade_cli-0.3.4/src/cadecoder/tools/manager/local.py +0 -122
  32. {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/ai/__init__.py +0 -0
  33. {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/ai/prompts.py +0 -0
  34. {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/cli/__init__.py +0 -0
  35. {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/cli/auth.py +0 -0
  36. {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/cli/commands/__init__.py +0 -0
  37. {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/cli/commands/auth.py +0 -0
  38. {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/cli/commands/mcp.py +0 -0
  39. {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/core/__init__.py +0 -0
  40. {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/core/logging.py +0 -0
  41. {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/core/names.py +0 -0
  42. {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/core/types.py +0 -0
  43. {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/execution/__init__.py +0 -0
  44. {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/execution/context_window.py +0 -0
  45. {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/execution/parallel.py +0 -0
  46. {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/providers/anthropic.py +0 -0
  47. {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/storage/__init__.py +0 -0
  48. {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/storage/threads.py +0 -0
  49. {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/templates/login_failed.html +0 -0
  50. {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/templates/login_success.html +0 -0
  51. {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/templates/styles.css +0 -0
  52. {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/tools/local/__init__.py +0 -0
  53. {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/tools/local/filesystem.py +0 -0
  54. {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/tools/local/git.py +0 -0
  55. {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/tools/local/search.py +0 -0
  56. {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/tools/local/shell.py +0 -0
  57. {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/tools/manager/base.py +0 -0
  58. {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/ui/__init__.py +0 -0
  59. {cade_cli-0.3.4 → cade_cli-0.4.0}/src/cadecoder/ui/display.py +0 -0
@@ -41,3 +41,6 @@ build/
41
41
  .venv
42
42
  activate.sh
43
43
  docs/
44
+
45
+ # uv
46
+ uv.lock
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cade-cli
3
- Version: 0.3.4
3
+ Version: 0.4.0
4
4
  Summary: Cade - The CLI Agent from Arcade.dev
5
5
  Project-URL: Homepage, https://arcade.dev
6
6
  Project-URL: Documentation, https://docs.arcade.dev
@@ -24,8 +24,8 @@ Classifier: Typing :: Typed
24
24
  Requires-Python: >=3.11
25
25
  Requires-Dist: anthropic<1.0.0,>=0.34.0
26
26
  Requires-Dist: arcade-core<5.0.0,>=4.1.0
27
+ Requires-Dist: arcade-mcp-server>=1.0.0
27
28
  Requires-Dist: arcade-tdk>=2.0.0
28
- Requires-Dist: arcadepy>=1.3.1
29
29
  Requires-Dist: authlib<2.0.0,>=1.6.0
30
30
  Requires-Dist: httpx<1.0.0,>=0.27.0
31
31
  Requires-Dist: openai<2.0.0,>=1.0.0
@@ -75,7 +75,7 @@ brew install cade
75
75
 
76
76
  ```bash
77
77
  curl -LsSf https://astral.sh/uv/install.sh | sh
78
- uv pip install cade-cli
78
+ uv tool install cade-cli
79
79
  ```
80
80
 
81
81
  ### Install with pip
@@ -115,6 +115,27 @@ cade -r # Resume most recent
115
115
  cade resume "my-project" # Resume by name
116
116
  ```
117
117
 
118
+ ### Authentication
119
+
120
+ Cade uses Arcade Cloud for authentication and shares credentials with arcade-cli.
121
+
122
+ ```bash
123
+ cade login # Log in to Arcade Cloud
124
+ cade logout # Log out
125
+ cade whoami # Show current login status
126
+ ```
127
+
128
+ ### Context Management
129
+
130
+ Switch between organizations and projects for Arcade Cloud features.
131
+
132
+ ```bash
133
+ cade context show # Show current org/project
134
+ cade context list # List available orgs and projects
135
+ cade context switch -i # Interactive selection
136
+ cade context switch --org my-org --project my-project
137
+ ```
138
+
118
139
  ### Single Message Mode
119
140
 
120
141
  ```bash
@@ -128,6 +149,7 @@ cat error.log | cade -m "What went wrong?"
128
149
  |--------|-------------|
129
150
  | `-r`, `--resume` | Resume the most recent thread |
130
151
  | `-m`, `--message` | Single message mode (non-interactive) |
152
+ | `-L`, `--local-only` | Disable remote tools (use only local tools) |
131
153
  | `-v`, `--verbose` | Enable debug logging |
132
154
  | `--version` | Show version |
133
155
 
@@ -205,9 +227,11 @@ Config is stored in `~/.cadecoder/`:
205
227
  | Variable | Description |
206
228
  |----------|-------------|
207
229
  | `OPENAI_API_KEY` | OpenAI API key |
230
+ | `OPENAI_BASE_URL` | Custom OpenAI-compatible API endpoint |
208
231
  | `ANTHROPIC_API_KEY` | Anthropic API key |
209
232
  | `ARCADE_API_KEY` | Arcade API key (alternative to OAuth) |
210
233
  | `ARCADE_BASE_URL` | Custom Arcade API endpoint |
234
+ | `CADE_LOCAL_ONLY` | Set to `1` to disable remote tools |
211
235
  | `CADECODER_HOME` | Override config directory |
212
236
 
213
237
  ### Example Config
@@ -228,9 +252,73 @@ provider = "openai"
228
252
  model = "gpt-4.1"
229
253
 
230
254
  [tool_settings]
231
- disabled_tools = []
255
+ # Tool filtering is managed via MCP server configuration
256
+ # See: cade mcp add --help
232
257
  ```
233
258
 
259
+ ## Using Local or Custom LLMs
260
+
261
+ Cade works with any OpenAI-compatible API, including local servers (Ollama, vLLM, llama.cpp) and alternative cloud providers (Together AI, Groq, Fireworks).
262
+
263
+ ### Local-Only Mode
264
+
265
+ When using local LLMs, you can skip Arcade Cloud authentication entirely with `--local-only`:
266
+
267
+ ```bash
268
+ # Local Ollama server without Arcade Cloud
269
+ cade chat --local-only --endpoint "http://localhost:11434/v1" --model "llama3"
270
+
271
+ # Or via environment variable
272
+ CADE_LOCAL_ONLY=1 cade chat --endpoint "http://localhost:11434/v1" --model "llama3"
273
+ ```
274
+
275
+ This disables remote tools and uses only local tools. Cade will also gracefully fall back to local-only mode if Arcade Cloud authentication is not configured.
276
+
277
+ ### Via CLI Flags
278
+
279
+ ```bash
280
+ # Local Ollama server
281
+ cade chat --endpoint "http://localhost:11434/v1" --model "glm-4.7-flash:latest"
282
+
283
+ # vLLM server
284
+ cade chat -e http://localhost:8000/v1 -m mistral-7b
285
+ ```
286
+
287
+ ### Via Environment Variables
288
+
289
+ ```bash
290
+ export OPENAI_BASE_URL="http://localhost:11434/v1"
291
+ export OPENAI_API_KEY="ollama" # Dummy key for local model
292
+ cade chat --model glm-4.7-flash:latest
293
+ ```
294
+
295
+ ### Via Config File
296
+
297
+ ```toml
298
+ # ~/.cadecoder/cadecoder.toml
299
+
300
+ default_model = "glm-4.7-flash:latest"
301
+
302
+ [model_settings]
303
+ host = "http://localhost:11434/v1"
304
+ api_key = "ollama"
305
+ ```
306
+
307
+ After configuring the TOML file:
308
+
309
+ ```bash
310
+ cade chat
311
+ ```
312
+
313
+ ### `cade chat` Configuration Precedence
314
+
315
+ Settings are resolved in this order (first is used):
316
+
317
+ 1. CLI flags (`--endpoint`, `--model`)
318
+ 2. Environment variables (`OPENAI_BASE_URL`, `OPENAI_API_KEY`)
319
+ 3. Config file (`model_settings.host`, `model_settings.api_key`)
320
+ 4. Hardcoded defaults
321
+
234
322
  ## Contributing
235
323
 
236
324
  ### Development Setup
@@ -238,9 +326,7 @@ disabled_tools = []
238
326
  ```bash
239
327
  git clone https://github.com/arcadeai-labs/cade.git
240
328
  cd cade
241
- uv venv --python 3.11
242
- source .venv/bin/activate
243
- uv pip install -e '.[dev]'
329
+ uv sync --extra dev
244
330
  ```
245
331
 
246
332
  ### Run Tests
@@ -21,7 +21,7 @@ brew install cade
21
21
 
22
22
  ```bash
23
23
  curl -LsSf https://astral.sh/uv/install.sh | sh
24
- uv pip install cade-cli
24
+ uv tool install cade-cli
25
25
  ```
26
26
 
27
27
  ### Install with pip
@@ -61,6 +61,27 @@ cade -r # Resume most recent
61
61
  cade resume "my-project" # Resume by name
62
62
  ```
63
63
 
64
+ ### Authentication
65
+
66
+ Cade uses Arcade Cloud for authentication and shares credentials with arcade-cli.
67
+
68
+ ```bash
69
+ cade login # Log in to Arcade Cloud
70
+ cade logout # Log out
71
+ cade whoami # Show current login status
72
+ ```
73
+
74
+ ### Context Management
75
+
76
+ Switch between organizations and projects for Arcade Cloud features.
77
+
78
+ ```bash
79
+ cade context show # Show current org/project
80
+ cade context list # List available orgs and projects
81
+ cade context switch -i # Interactive selection
82
+ cade context switch --org my-org --project my-project
83
+ ```
84
+
64
85
  ### Single Message Mode
65
86
 
66
87
  ```bash
@@ -74,6 +95,7 @@ cat error.log | cade -m "What went wrong?"
74
95
  |--------|-------------|
75
96
  | `-r`, `--resume` | Resume the most recent thread |
76
97
  | `-m`, `--message` | Single message mode (non-interactive) |
98
+ | `-L`, `--local-only` | Disable remote tools (use only local tools) |
77
99
  | `-v`, `--verbose` | Enable debug logging |
78
100
  | `--version` | Show version |
79
101
 
@@ -151,9 +173,11 @@ Config is stored in `~/.cadecoder/`:
151
173
  | Variable | Description |
152
174
  |----------|-------------|
153
175
  | `OPENAI_API_KEY` | OpenAI API key |
176
+ | `OPENAI_BASE_URL` | Custom OpenAI-compatible API endpoint |
154
177
  | `ANTHROPIC_API_KEY` | Anthropic API key |
155
178
  | `ARCADE_API_KEY` | Arcade API key (alternative to OAuth) |
156
179
  | `ARCADE_BASE_URL` | Custom Arcade API endpoint |
180
+ | `CADE_LOCAL_ONLY` | Set to `1` to disable remote tools |
157
181
  | `CADECODER_HOME` | Override config directory |
158
182
 
159
183
  ### Example Config
@@ -174,9 +198,73 @@ provider = "openai"
174
198
  model = "gpt-4.1"
175
199
 
176
200
  [tool_settings]
177
- disabled_tools = []
201
+ # Tool filtering is managed via MCP server configuration
202
+ # See: cade mcp add --help
178
203
  ```
179
204
 
205
+ ## Using Local or Custom LLMs
206
+
207
+ Cade works with any OpenAI-compatible API, including local servers (Ollama, vLLM, llama.cpp) and alternative cloud providers (Together AI, Groq, Fireworks).
208
+
209
+ ### Local-Only Mode
210
+
211
+ When using local LLMs, you can skip Arcade Cloud authentication entirely with `--local-only`:
212
+
213
+ ```bash
214
+ # Local Ollama server without Arcade Cloud
215
+ cade chat --local-only --endpoint "http://localhost:11434/v1" --model "llama3"
216
+
217
+ # Or via environment variable
218
+ CADE_LOCAL_ONLY=1 cade chat --endpoint "http://localhost:11434/v1" --model "llama3"
219
+ ```
220
+
221
+ This disables remote tools and uses only local tools. Cade will also gracefully fall back to local-only mode if Arcade Cloud authentication is not configured.
222
+
223
+ ### Via CLI Flags
224
+
225
+ ```bash
226
+ # Local Ollama server
227
+ cade chat --endpoint "http://localhost:11434/v1" --model "glm-4.7-flash:latest"
228
+
229
+ # vLLM server
230
+ cade chat -e http://localhost:8000/v1 -m mistral-7b
231
+ ```
232
+
233
+ ### Via Environment Variables
234
+
235
+ ```bash
236
+ export OPENAI_BASE_URL="http://localhost:11434/v1"
237
+ export OPENAI_API_KEY="ollama" # Dummy key for local model
238
+ cade chat --model glm-4.7-flash:latest
239
+ ```
240
+
241
+ ### Via Config File
242
+
243
+ ```toml
244
+ # ~/.cadecoder/cadecoder.toml
245
+
246
+ default_model = "glm-4.7-flash:latest"
247
+
248
+ [model_settings]
249
+ host = "http://localhost:11434/v1"
250
+ api_key = "ollama"
251
+ ```
252
+
253
+ After configuring the TOML file:
254
+
255
+ ```bash
256
+ cade chat
257
+ ```
258
+
259
+ ### `cade chat` Configuration Precedence
260
+
261
+ Settings are resolved in this order (first is used):
262
+
263
+ 1. CLI flags (`--endpoint`, `--model`)
264
+ 2. Environment variables (`OPENAI_BASE_URL`, `OPENAI_API_KEY`)
265
+ 3. Config file (`model_settings.host`, `model_settings.api_key`)
266
+ 4. Hardcoded defaults
267
+
180
268
  ## Contributing
181
269
 
182
270
  ### Development Setup
@@ -184,9 +272,7 @@ disabled_tools = []
184
272
  ```bash
185
273
  git clone https://github.com/arcadeai-labs/cade.git
186
274
  cd cade
187
- uv venv --python 3.11
188
- source .venv/bin/activate
189
- uv pip install -e '.[dev]'
275
+ uv sync --extra dev
190
276
  ```
191
277
 
192
278
  ### Run Tests
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "cade-cli"
3
- version = "0.3.4"
3
+ version = "0.4.0"
4
4
  description = "Cade - The CLI Agent from Arcade.dev"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -28,11 +28,11 @@ dependencies = [
28
28
  "pydantic[email]>=2.0.0,<3.0.0",
29
29
  "toml>=0.10.0,<1.0.0",
30
30
  "pyyaml>=6.0,<7.0.0",
31
- "arcadepy>=1.3.1",
32
31
  "openai>=1.0.0,<2.0.0",
33
32
  "anthropic>=0.34.0,<1.0.0",
34
33
  "ulid==1.1",
35
34
  "arcade-tdk>=2.0.0",
35
+ "arcade-mcp-server>=1.0.0",
36
36
  "arcade-core>=4.1.0,<5.0.0",
37
37
  "authlib>=1.6.0,<2.0.0",
38
38
  "pyperclip>=1.8.0,<2.0.0",
@@ -0,0 +1 @@
1
+ __version__ = "0.4.0"
@@ -13,6 +13,7 @@ from rich.console import Console
13
13
 
14
14
  from cadecoder import __version__
15
15
  from cadecoder.cli.commands import auth, chat
16
+ from cadecoder.cli.commands.context import context_app
16
17
  from cadecoder.cli.commands.mcp import mcp_app
17
18
  from cadecoder.cli.commands.model import model_app
18
19
  from cadecoder.cli.commands.thread import thread_app
@@ -41,6 +42,12 @@ app.command(name="resume", help="Resume the most recent thread or a specific thr
41
42
  )
42
43
 
43
44
  # Register sub-command groups
45
+ app.add_typer(
46
+ context_app,
47
+ name="context",
48
+ help="Manage organization and project context",
49
+ rich_help_panel="User",
50
+ )
44
51
  app.add_typer(mcp_app, name="mcp", help="Manage MCP servers", rich_help_panel="Tools")
45
52
  app.add_typer(model_app, name="model", help="Manage AI models", rich_help_panel="Tools")
46
53
  app.add_typer(tool_app, name="tools", help="View available tools", rich_help_panel="Tools")
@@ -1,16 +1,18 @@
1
1
  """Interactive chat command for CadeCoder CLI."""
2
2
 
3
+ import os
3
4
  from typing import Annotated
4
5
 
5
6
  import typer
6
7
  from rich.console import Console
7
8
  from rich.markup import escape
8
9
 
9
- from cadecoder.core.config import get_config
10
- from cadecoder.core.constants import DEFAULT_AI_MODEL
11
- from cadecoder.core.errors import CadeCoderError, StorageError
10
+ from cadecoder.core.config import get_config, is_local_only_mode
11
+ from cadecoder.core.errors import CadeCoderError, StorageError, get_provider_config_help
12
12
  from cadecoder.core.logging import log
13
13
  from cadecoder.execution.orchestrator import create_orchestrator
14
+ from cadecoder.providers import initialize_providers
15
+ from cadecoder.providers.base import provider_registry
14
16
  from cadecoder.storage.threads import get_thread_history
15
17
  from cadecoder.tools.local.git import get_current_branch_name
16
18
  from cadecoder.ui.session import main as run_tui_main
@@ -18,19 +20,59 @@ from cadecoder.ui.session import main as run_tui_main
18
20
  console = Console(stderr=True)
19
21
 
20
22
 
23
+ def _configure_custom_endpoint(endpoint: str) -> None:
24
+ """Configure a custom API endpoint for local LLMs.
25
+
26
+ Automatically detects Ollama endpoints and uses the native OllamaProvider
27
+ for full tool calling support. Falls back to OpenAI-compatible mode for
28
+ other endpoints.
29
+
30
+ Args:
31
+ endpoint: The custom API endpoint URL (e.g., http://localhost:11434/v1)
32
+ """
33
+ # Detect Ollama endpoint (port 11434 or contains "ollama")
34
+ is_ollama = ":11434" in endpoint or "ollama" in endpoint.lower()
35
+
36
+ if is_ollama:
37
+ # Use native Ollama provider for full tool calling support
38
+ # Remove /v1 suffix if present (native API doesn't use it)
39
+ ollama_base = endpoint.rstrip("/").replace("/v1", "").replace("/api", "")
40
+ os.environ["OLLAMA_BASE_URL"] = ollama_base
41
+ log.info(f"Detected Ollama endpoint, using native OllamaProvider at {ollama_base}")
42
+ else:
43
+ # Use OpenAI-compatible provider for other endpoints
44
+ os.environ["OPENAI_BASE_URL"] = endpoint
45
+ if not os.environ.get("OPENAI_API_KEY"):
46
+ os.environ["OPENAI_API_KEY"] = "local"
47
+ log.info(f"Using OpenAI-compatible provider with endpoint {endpoint}")
48
+
49
+ # Re-initialize providers with the new endpoint
50
+ provider_registry._providers.clear()
51
+ provider_registry._default_provider = None
52
+ initialize_providers()
53
+
54
+
21
55
  def chat(
22
56
  thread_or_name: Annotated[
23
57
  str | None,
24
58
  typer.Argument(help="Thread ID or Thread Name to resume (optional)"),
25
59
  ] = None,
26
60
  model: Annotated[
27
- str,
61
+ str | None,
28
62
  typer.Option(
29
63
  "--model",
30
64
  "-m",
31
65
  help="AI model to use for the conversation.",
32
66
  ),
33
- ] = DEFAULT_AI_MODEL,
67
+ ] = None,
68
+ endpoint: Annotated[
69
+ str | None,
70
+ typer.Option(
71
+ "--endpoint",
72
+ "-e",
73
+ help="Custom API endpoint URL (for OpenAI-compatible APIs like Ollama, vLLM, etc.)",
74
+ ),
75
+ ] = None,
34
76
  name: Annotated[
35
77
  str | None,
36
78
  typer.Option(
@@ -47,6 +89,14 @@ def chat(
47
89
  help="System prompt to guide the AI assistant's behavior.",
48
90
  ),
49
91
  ] = None,
92
+ local_only: Annotated[
93
+ bool,
94
+ typer.Option(
95
+ "--local-only",
96
+ "-L",
97
+ help="Disable Arcade Cloud tools (use only local tools).",
98
+ ),
99
+ ] = False,
50
100
  ) -> None:
51
101
  """
52
102
  Start an interactive chat session with AI.
@@ -56,17 +106,18 @@ def chat(
56
106
  """
57
107
  command_name = "chat"
58
108
  try:
109
+ # Figure out which model to use: CLI flag > config > constant
110
+ resolved_model = model or get_config().settings.default_model
111
+ if endpoint:
112
+ _configure_custom_endpoint(endpoint)
113
+
114
+ effective_local_only = local_only or is_local_only_mode()
115
+
59
116
  # Preflight: ensure provider/API keys are configured before entering TUI
60
117
  try:
61
- _ = create_orchestrator()
62
- except Exception as e:
63
- console.print(
64
- "[bold red]Provider configuration error:[/bold red] "
65
- "Failed to initialize the AI provider.\n"
66
- "Set required API keys (e.g., OPENAI_API_KEY or ANTHROPIC_API_KEY) "
67
- "or configure the provider, then try again.\n"
68
- f"Details: {str(e)}"
69
- )
118
+ _ = create_orchestrator(local_only=effective_local_only)
119
+ except Exception:
120
+ console.print(f"[bold red]Error:[/bold red] {get_provider_config_help()}")
70
121
  raise typer.Exit(code=1)
71
122
 
72
123
  # Get the thread history manager
@@ -110,7 +161,7 @@ def chat(
110
161
  thread = history_manager.create_thread(
111
162
  name=thread_or_name,
112
163
  git_branch=current_branch,
113
- model=model,
164
+ model=resolved_model,
114
165
  user_id=user_id,
115
166
  )
116
167
  log.info(
@@ -136,7 +187,7 @@ def chat(
136
187
  thread = history_manager.create_thread(
137
188
  name=name,
138
189
  git_branch=current_branch,
139
- model=model,
190
+ model=resolved_model,
140
191
  user_id=user_id,
141
192
  )
142
193
  selected_thread_id = thread.thread_id
@@ -157,9 +208,10 @@ def chat(
157
208
  # Launch TUI
158
209
  run_tui_main(
159
210
  thread_id_to_run=str(selected_thread_id),
160
- model=model,
211
+ model=resolved_model,
161
212
  stream=True,
162
213
  system_prompt=prompt,
214
+ local_only=effective_local_only,
163
215
  )
164
216
  except (StorageError, CadeCoderError) as e:
165
217
  console.print(":x: [bold red]Error:[/bold red] " + escape(str(e)))
@@ -179,13 +231,21 @@ def resume(
179
231
  typer.Argument(help="Thread name to resume (optional)"),
180
232
  ] = None,
181
233
  model: Annotated[
182
- str,
234
+ str | None,
183
235
  typer.Option(
184
236
  "--model",
185
237
  "-m",
186
238
  help="AI model to use for the conversation.",
187
239
  ),
188
- ] = DEFAULT_AI_MODEL,
240
+ ] = None,
241
+ endpoint: Annotated[
242
+ str | None,
243
+ typer.Option(
244
+ "--endpoint",
245
+ "-e",
246
+ help="Custom API endpoint URL (for OpenAI-compatible APIs like Ollama, vLLM).",
247
+ ),
248
+ ] = None,
189
249
  prompt: Annotated[
190
250
  str | None,
191
251
  typer.Option(
@@ -194,6 +254,14 @@ def resume(
194
254
  help="System prompt to guide the AI assistant's behavior.",
195
255
  ),
196
256
  ] = None,
257
+ local_only: Annotated[
258
+ bool,
259
+ typer.Option(
260
+ "--local-only",
261
+ "-L",
262
+ help="Only use local tools.",
263
+ ),
264
+ ] = False,
197
265
  ) -> None:
198
266
  """Resume a saved chat thread.
199
267
 
@@ -208,17 +276,18 @@ def resume(
208
276
  """
209
277
  command_name = "resume"
210
278
  try:
279
+ # Figure out which model to use: CLI flag > config > constant
280
+ resolved_model = model or get_config().settings.default_model
281
+ if endpoint:
282
+ _configure_custom_endpoint(endpoint)
283
+
284
+ effective_local_only = local_only or is_local_only_mode()
285
+
211
286
  # Preflight provider before entering TUI
212
287
  try:
213
- _ = create_orchestrator()
214
- except Exception as e:
215
- console.print(
216
- "[bold red]Provider configuration error:[/bold red] "
217
- "Failed to initialize the AI provider.\n"
218
- "Set required API keys (e.g., OPENAI_API_KEY or ANTHROPIC_API_KEY) "
219
- "or configure the provider, then try again.\n"
220
- f"Details: {str(e)}"
221
- )
288
+ _ = create_orchestrator(local_only=effective_local_only)
289
+ except Exception:
290
+ console.print(f"[bold red]Error:[/bold red] {get_provider_config_help()}")
222
291
  raise typer.Exit(code=1)
223
292
 
224
293
  history_manager = get_thread_history()
@@ -267,9 +336,10 @@ def resume(
267
336
 
268
337
  run_tui_main(
269
338
  thread_id_to_run=str(target_thread.thread_id),
270
- model=model,
339
+ model=resolved_model,
271
340
  stream=True,
272
341
  system_prompt=prompt,
342
+ local_only=effective_local_only,
273
343
  )
274
344
  except (StorageError, CadeCoderError) as e:
275
345
  console.print(":x: [bold red]Error:[/bold red] " + escape(str(e)))