diff --git a/benchmark/benchmark.py b/benchmark/benchmark.py
index 3c83ba0b0a6..243c6aff8f9 100755
--- a/benchmark/benchmark.py
+++ b/benchmark/benchmark.py
@@ -40,7 +40,7 @@
# Cache for commit-hash -> version lookup
_VERSION_CACHE = {}
-BENCHMARK_DNAME = Path(os.environ.get("CECLIBENCHMARK_DIR", "tmp.benchmarks"))
+BENCHMARK_DNAME = Path(os.environ.get("CECLI_BENCHMARK_DIR", "tmp.benchmarks"))
EXERCISES_DIR_DEFAULT = "cecli-cat"
RESULTS_DIR_DEFAULT = "cat-results"
@@ -209,9 +209,11 @@ def main(
return 1
results_dir = resolved_results_dir
- if not dry and "CECLIDOCKER" not in os.environ:
+ if not dry and "CECLI_DOCKER" not in os.environ:
logger.warning("Warning: Benchmarking runs unvetted code. Run in a docker container.")
- logger.warning("Set CECLIDOCKER in the environment to by-pass this check at your own risk.")
+ logger.warning(
+ "Set CECLI_DOCKER in the environment to by-pass this check at your own risk."
+ )
return
# Check dirs exist
diff --git a/benchmark/benchmark_classic.py b/benchmark/benchmark_classic.py
index b6e79240b69..89ee057a860 100755
--- a/benchmark/benchmark_classic.py
+++ b/benchmark/benchmark_classic.py
@@ -34,7 +34,7 @@
# Cache for commit-hash -> version lookup
_VERSION_CACHE = {}
-BENCHMARK_DNAME = Path(os.environ.get("CECLIBENCHMARK_DIR", "tmp.benchmarks"))
+BENCHMARK_DNAME = Path(os.environ.get("CECLI_BENCHMARK_DIR", "tmp.benchmarks"))
EXERCISES_DIR_DEFAULT = "polyglot-benchmark"
@@ -267,7 +267,7 @@ def main(
if repo.is_dirty():
commit_hash += "-dirty"
- if "CECLIDOCKER" not in os.environ:
+ if "CECLI_DOCKER" not in os.environ:
print("Warning: benchmarking runs unvetted code from GPT, run in a docker container")
return
diff --git a/cecli/__init__.py b/cecli/__init__.py
index 67dfd72b26a..c4d6fec1512 100644
--- a/cecli/__init__.py
+++ b/cecli/__init__.py
@@ -1,6 +1,6 @@
from packaging import version
-__version__ = "0.92.0.dev"
+__version__ = "0.92.1.dev"
safe_version = __version__
try:
diff --git a/cecli/args.py b/cecli/args.py
index b62a6c3cf9f..4c0434672ce 100644
--- a/cecli/args.py
+++ b/cecli/args.py
@@ -38,7 +38,7 @@ def get_parser(default_config_files, git_root):
add_config_file_help=True,
default_config_files=default_config_files,
config_file_parser_class=configargparse.YAMLConfigFileParser,
- auto_env_var_prefix="CECLI",
+ auto_env_var_prefix="CECLI_",
)
# List of valid edit formats for argparse validation & shtab completion.
# Dynamically gather them from the registered coder classes so the list
@@ -567,7 +567,7 @@ def get_parser(default_config_files, git_root):
group.add_argument(
"--cecli-ignore",
- metavar="CECLIIGNORE",
+ metavar="CECLI_IGNORE",
type=lambda path_str: resolve_cecli_ignore_path(path_str, git_root),
default=default_cecli_ignore_file,
help="Specify the cecli ignore file (default: .cecli.ignore in git root)",
diff --git a/cecli/coders/architect_coder.py b/cecli/coders/architect_coder.py
index a5382f44aa8..75a1d7f4156 100644
--- a/cecli/coders/architect_coder.py
+++ b/cecli/coders/architect_coder.py
@@ -1,6 +1,6 @@
import asyncio
-from ..commands import SwitchCoder
+from ..commands import SwitchCoderSignal
from .ask_coder import AskCoder
from .base_coder import Coder
@@ -60,4 +60,4 @@ async def reply_completed(self):
except Exception as e:
self.io.tool_error(e)
- raise SwitchCoder(main_model=self.main_model, edit_format="architect")
+ raise SwitchCoderSignal(main_model=self.main_model, edit_format="architect")
diff --git a/cecli/coders/base_coder.py b/cecli/coders/base_coder.py
index fa2d262c911..039b194420c 100755
--- a/cecli/coders/base_coder.py
+++ b/cecli/coders/base_coder.py
@@ -36,7 +36,7 @@
import cecli.prompts.utils.system as prompts
from cecli import __version__, models, urls, utils
-from cecli.commands import Commands, SwitchCoder
+from cecli.commands import Commands, SwitchCoderSignal
from cecli.exceptions import LiteLLMExceptions
from cecli.helpers import coroutines
from cecli.helpers.profiler import TokenProfiler
@@ -1370,7 +1370,7 @@ async def _run_parallel(self, with_message=None, preproc=True):
if task.exception():
raise task.exception()
- except (SwitchCoder, SystemExit):
+ except (SwitchCoderSignal, SystemExit):
# Re-raise SwitchCoder to be handled by outer try block
raise
except KeyboardInterrupt:
@@ -1461,7 +1461,7 @@ async def input_task(self, preproc):
self.io.set_placeholder("")
self.keyboard_interrupt()
await self.io.stop_task_streams()
- except (SwitchCoder, SystemExit):
+ except (SwitchCoderSignal, SystemExit):
raise
except Exception as e:
if self.verbose or self.args.debug:
@@ -1496,7 +1496,7 @@ async def output_task(self, preproc):
if self.io.output_task.done():
exception = self.io.output_task.exception()
if exception:
- if isinstance(exception, SwitchCoder):
+ if isinstance(exception, SwitchCoderSignal):
await self.io.output_task
raise exception
@@ -1519,7 +1519,7 @@ async def output_task(self, preproc):
self.io.stop_spinner()
self.keyboard_interrupt()
await self.io.stop_task_streams()
- except (SwitchCoder, SystemExit):
+ except (SwitchCoderSignal, SystemExit):
raise
except Exception as e:
if self.verbose or self.args.debug:
@@ -2138,7 +2138,7 @@ def warm_cache(self, chunks):
return
delay = 5 * 60 - 5
- delay = float(os.environ.get("CECLICACHE_KEEPALIVE_DELAY", delay))
+ delay = float(os.environ.get("CECLI_CACHE_KEEPALIVE_DELAY", delay))
self.next_cache_warm = time.time() + delay
self.warming_pings_left = self.num_cache_warming_pings
self.cache_warming_chunks = chunks
@@ -2741,7 +2741,7 @@ async def get_server_tools(server):
)
return (server.name, server_tools)
except Exception as e:
- if server.name != "unnamed-server" and server.name != "local_tools":
+ if server.name != "unnamed-server" and server.name != "Local":
self.io.tool_warning(f"Error initializing MCP server {server.name}: {e}")
return None
diff --git a/cecli/commands/__init__.py b/cecli/commands/__init__.py
index 183a13e1aec..6b118475204 100644
--- a/cecli/commands/__init__.py
+++ b/cecli/commands/__init__.py
@@ -5,10 +5,6 @@
BaseCommand pattern for modular, testable command execution.
"""
-import sys
-import traceback
-from pathlib import Path
-
from .add import AddCommand
from .agent import AgentCommand
from .architect import ArchitectCommand
@@ -22,6 +18,7 @@
from .context_management import ContextManagementCommand
from .copy import CopyCommand
from .copy_context import CopyContextCommand
+from .core import Commands, SwitchCoderSignal
from .diff import DiffCommand
# Import and register commands
@@ -127,50 +124,6 @@
CommandRegistry.register(LoadSkillCommand)
CommandRegistry.register(RemoveSkillCommand)
-# Import SwitchCoder and Commands directly from commands.py
-# We need to handle the circular import carefully
-
-# Add parent directory to path to import commands.py directly
-parent_dir = str(Path(__file__).parent.parent)
-if parent_dir not in sys.path:
- sys.path.insert(0, parent_dir)
-
-# Import the commands module directly
-try:
- import importlib.util
-
- spec = importlib.util.spec_from_file_location(
- "cecli.commands_module", Path(__file__).parent.parent / "commands.py"
- )
- commands_module = importlib.util.module_from_spec(spec)
- sys.modules["cecli.commands_module"] = commands_module
- spec.loader.exec_module(commands_module)
-
- # Get the classes from the module
- Commands = getattr(commands_module, "Commands", None)
- SwitchCoder = getattr(commands_module, "SwitchCoder", None)
-
- if Commands is None or SwitchCoder is None:
- raise ImportError("Commands or SwitchCoder not found in commands.py")
-
-except Exception as e:
- # Print the error for debugging
- print(f"Error importing commands.py: {e}")
- traceback.print_exc()
-
- # Fallback: define simple placeholder classes
- class SwitchCoder(Exception):
- def __init__(self, placeholder=None, **kwargs):
- self.kwargs = kwargs
- self.placeholder = placeholder
-
- class Commands:
- """Placeholder for Commands class defined in original commands.py"""
-
- def __init__(self, *args, **kwargs):
- # Accept any arguments but do nothing
- pass
-
__all__ = [
"BaseCommand",
@@ -234,6 +187,6 @@ def __init__(self, *args, **kwargs):
"CommandPrefixCommand",
"LoadSkillCommand",
"RemoveSkillCommand",
- "SwitchCoder",
+ "SwitchCoderSignal",
"Commands",
]
diff --git a/cecli/commands/add.py b/cecli/commands/add.py
index c3e6b620efd..00ea6cb9073 100644
--- a/cecli/commands/add.py
+++ b/cecli/commands/add.py
@@ -137,9 +137,9 @@ async def execute(cls, io, coder, args, **kwargs):
map_tokens = 0
map_mul_no_files = 1
- from cecli.commands import SwitchCoder
+ from cecli.commands import SwitchCoderSignal
- raise SwitchCoder(
+ raise SwitchCoderSignal(
edit_format=coder.edit_format,
summarize_from_coder=False,
from_coder=coder,
diff --git a/cecli/commands.py b/cecli/commands/core.py
similarity index 89%
rename from cecli/commands.py
rename to cecli/commands/core.py
index 6e2d65a94d4..7a6d5aead1e 100644
--- a/cecli/commands.py
+++ b/cecli/commands/core.py
@@ -3,16 +3,32 @@
import sys
from pathlib import Path
+from cecli.commands.utils.registry import CommandRegistry
from cecli.helpers.file_searcher import handle_core_files
from cecli.repo import ANY_GIT_ERROR
-from .commands.utils.registry import CommandRegistry
+class SwitchCoderSignal(BaseException):
+ """
+ Signal to switch the current Coder instance to a new configuration.
+
+ This is NOT an error - it's a control flow signal used to propagate
+ coder switching requests up through the async call stack. It carries
+ the kwargs needed to create a new Coder instance.
+
+ Note: Inherits from BaseException (like KeyboardInterrupt and SystemExit)
+ to avoid being caught by generic `except Exception` handlers, making the
+ non-error nature of this signal explicit.
+
+ Attributes:
+ kwargs: Configuration dict passed to Coder.create() for the new instance
+ placeholder: Optional placeholder text for the input prompt
+ """
-class SwitchCoder(Exception):
def __init__(self, placeholder=None, **kwargs):
self.kwargs = kwargs
self.placeholder = placeholder
+ super().__init__()
class Commands:
@@ -119,7 +135,7 @@ async def do_run(self, cmd_name, args, **kwargs):
except ANY_GIT_ERROR as err:
self.io.tool_error(f"Unable to complete {cmd_name}: {err}")
return
- except SwitchCoder as e:
+ except SwitchCoderSignal as e:
raise e
except Exception as e:
self.io.tool_error(f"Error executing command {cmd_name}: {str(e)}")
diff --git a/cecli/commands/drop.py b/cecli/commands/drop.py
index d438d50998c..13d72951852 100644
--- a/cecli/commands/drop.py
+++ b/cecli/commands/drop.py
@@ -82,7 +82,7 @@ async def execute(cls, io, coder, args, **kwargs):
return format_command_result(io, "drop", "Removed files from chat")
finally:
- # This mimics the SwitchCoder behavior in the original cmd_drop
+ # This mimics the SwitchCoderSignal behavior in the original cmd_drop
if coder.repo_map:
map_tokens = coder.repo_map.max_map_tokens
map_mul_no_files = coder.repo_map.map_mul_no_files
@@ -90,10 +90,10 @@ async def execute(cls, io, coder, args, **kwargs):
map_tokens = 0
map_mul_no_files = 1
- # Raise SwitchCoder to trigger coder recreation
- from . import SwitchCoder
+ # Raise SwitchCoderSignal to trigger coder recreation
+ from . import SwitchCoderSignal
- raise SwitchCoder(
+ raise SwitchCoderSignal(
edit_format=coder.edit_format,
summarize_from_coder=False,
from_coder=coder,
diff --git a/cecli/commands/help.py b/cecli/commands/help.py
index 3a943bdd456..0a344a20db2 100644
--- a/cecli/commands/help.py
+++ b/cecli/commands/help.py
@@ -70,9 +70,9 @@ async def execute(cls, io, coder, args, **kwargs):
map_tokens = 0
map_mul_no_files = 1
- from cecli.commands import SwitchCoder
+ from cecli.commands import SwitchCoderSignal
- raise SwitchCoder(
+ raise SwitchCoderSignal(
edit_format=coder.edit_format,
summarize_from_coder=False,
from_coder=help_coder,
diff --git a/cecli/commands/load.py b/cecli/commands/load.py
index a32655dd402..80fb743d040 100644
--- a/cecli/commands/load.py
+++ b/cecli/commands/load.py
@@ -46,9 +46,9 @@ async def execute(cls, io, coder, args, **kwargs):
try:
await commands_instance.run(cmd)
except Exception as e:
- # Handle SwitchCoder exception specifically
- if type(e).__name__ == "SwitchCoder":
- # SwitchCoder is raised when switching between coder types (e.g., /architect, /ask).
+ # Handle SwitchCoderSignal exception specifically
+ if type(e).__name__ == "SwitchCoderSignal":
+ # SwitchCoderSignal is raised when switching between coder types (e.g., /architect, /ask).
# This is expected behavior, not an error. But this gets in the way when running `/load` so we
# ignore it and continue processing remaining commands.
should_raise_at_end = e
diff --git a/cecli/commands/model.py b/cecli/commands/model.py
index 5bb6edeac34..028a4d6736e 100644
--- a/cecli/commands/model.py
+++ b/cecli/commands/model.py
@@ -73,23 +73,25 @@ async def execute(cls, io, coder, args, **kwargs):
coder.coder_commit_hashes = temp_coder.coder_commit_hashes
# Restore the original model configuration
- from cecli.commands import SwitchCoder
+ from cecli.commands import SwitchCoderSignal
- raise SwitchCoder(main_model=original_main_model, edit_format=original_edit_format)
+ raise SwitchCoderSignal(
+ main_model=original_main_model, edit_format=original_edit_format
+ )
except Exception as e:
# If there's an error, still restore the original model
- if not isinstance(e, SwitchCoder):
+ if not isinstance(e, SwitchCoderSignal):
io.tool_error(str(e))
- raise SwitchCoder(
+ raise SwitchCoderSignal(
main_model=original_main_model, edit_format=original_edit_format
)
else:
- # Re-raise SwitchCoder if that's what was thrown
+ # Re-raise SwitchCoderSignal if that's what was thrown
raise
else:
- from cecli.commands import SwitchCoder
+ from cecli.commands import SwitchCoderSignal
- raise SwitchCoder(main_model=model, edit_format=new_edit_format)
+ raise SwitchCoderSignal(main_model=model, edit_format=new_edit_format)
@classmethod
def get_completions(cls, io, coder, args) -> List[str]:
diff --git a/cecli/commands/reset.py b/cecli/commands/reset.py
index 608123345d6..d01e2b4a835 100644
--- a/cecli/commands/reset.py
+++ b/cecli/commands/reset.py
@@ -40,10 +40,10 @@ async def execute(cls, io, coder, args, **kwargs):
map_tokens = 0
map_mul_no_files = 1
- # Raise SwitchCoder to trigger coder recreation
- from . import SwitchCoder
+ # Raise SwitchCoderSignal to trigger coder recreation
+ from . import SwitchCoderSignal
- raise SwitchCoder(
+ raise SwitchCoderSignal(
edit_format=coder.edit_format,
summarize_from_coder=False,
from_coder=coder,
diff --git a/cecli/commands/utils/base_command.py b/cecli/commands/utils/base_command.py
index b36ea5cd59a..c94206ee45c 100644
--- a/cecli/commands/utils/base_command.py
+++ b/cecli/commands/utils/base_command.py
@@ -96,9 +96,9 @@ async def _generic_chat_command(cls, io, coder, args, edit_format, placeholder=N
"""
if not args.strip():
# Switch to the corresponding chat mode
- from cecli.commands import SwitchCoder
+ from cecli.commands import SwitchCoderSignal
- raise SwitchCoder(edit_format=edit_format)
+ raise SwitchCoderSignal(edit_format=edit_format)
from cecli.coders.base_coder import Coder
@@ -121,9 +121,9 @@ async def _generic_chat_command(cls, io, coder, args, edit_format, placeholder=N
await new_coder.generate(user_message=user_msg, preproc=False)
coder.coder_commit_hashes = new_coder.coder_commit_hashes
- from cecli.commands import SwitchCoder
+ from cecli.commands import SwitchCoderSignal
- raise SwitchCoder(
+ raise SwitchCoderSignal(
main_model=original_main_model,
edit_format=original_edit_format,
done_messages=new_coder.done_messages,
diff --git a/cecli/commands/weak_model.py b/cecli/commands/weak_model.py
index be1a1ead4aa..01437c1e000 100644
--- a/cecli/commands/weak_model.py
+++ b/cecli/commands/weak_model.py
@@ -70,23 +70,25 @@ async def execute(cls, io, coder, args, **kwargs):
coder.coder_commit_hashes = temp_coder.coder_commit_hashes
# Restore the original model configuration
- from cecli.commands import SwitchCoder
+ from cecli.commands import SwitchCoderSignal
- raise SwitchCoder(main_model=original_main_model, edit_format=original_edit_format)
+ raise SwitchCoderSignal(
+ main_model=original_main_model, edit_format=original_edit_format
+ )
except Exception as e:
# If there's an error, still restore the original model
- if not isinstance(e, SwitchCoder):
+ if not isinstance(e, SwitchCoderSignal):
io.tool_error(str(e))
- raise SwitchCoder(
+ raise SwitchCoderSignal(
main_model=original_main_model, edit_format=original_edit_format
)
else:
- # Re-raise SwitchCoder if that's what was thrown
+ # Re-raise SwitchCoderSignal if that's what was thrown
raise
else:
- from cecli.commands import SwitchCoder
+ from cecli.commands import SwitchCoderSignal
- raise SwitchCoder(main_model=model, edit_format=coder.edit_format)
+ raise SwitchCoderSignal(main_model=model, edit_format=coder.edit_format)
@classmethod
def get_completions(cls, io, coder, args) -> List[str]:
diff --git a/cecli/main.py b/cecli/main.py
index 8d1f46d934d..f82c665d8c5 100644
--- a/cecli/main.py
+++ b/cecli/main.py
@@ -3,7 +3,7 @@
from cecli.helpers.file_searcher import handle_core_files
try:
- if not os.getenv("CECLIDEFAULT_TLS"):
+ if not os.getenv("CECLI_DEFAULT_TLS"):
import truststore
truststore.inject_into_ssl()
@@ -39,7 +39,7 @@
from cecli.args import get_parser
from cecli.coders import Coder
from cecli.coders.base_coder import UnknownEditFormat
-from cecli.commands import Commands, SwitchCoder
+from cecli.commands import Commands, SwitchCoderSignal
from cecli.deprecated_args import handle_deprecated_model_args
from cecli.format_settings import format_settings, scrub_sensitive_info
from cecli.helpers.copypaste import ClipboardWatcher
@@ -1127,7 +1127,7 @@ def apply_model_overrides(model_name):
io.tool_output()
try:
await coder.run(with_message=args.message)
- except (SwitchCoder, KeyboardInterrupt, SystemExit):
+ except (SwitchCoderSignal, KeyboardInterrupt, SystemExit):
pass
return await graceful_exit(coder)
if args.message_file:
@@ -1135,7 +1135,7 @@ def apply_model_overrides(model_name):
message_from_file = io.read_text(args.message_file)
io.tool_output()
await coder.run(with_message=message_from_file)
- except (SwitchCoder, KeyboardInterrupt, SystemExit):
+ except (SwitchCoderSignal, KeyboardInterrupt, SystemExit):
pass
except FileNotFoundError:
io.tool_error(f"Message file not found: {args.message_file}")
@@ -1167,7 +1167,7 @@ def apply_model_overrides(model_name):
coder.ok_to_warm_cache = bool(args.cache_keepalive_pings)
await coder.run()
return await graceful_exit(coder)
- except SwitchCoder as switch:
+ except SwitchCoderSignal as switch:
coder.ok_to_warm_cache = False
if hasattr(switch, "placeholder") and switch.placeholder is not None:
io.placeholder = switch.placeholder
diff --git a/cecli/mcp/__init__.py b/cecli/mcp/__init__.py
index f40c27af978..44d1e6a5f15 100644
--- a/cecli/mcp/__init__.py
+++ b/cecli/mcp/__init__.py
@@ -11,7 +11,7 @@ def _parse_mcp_servers_from_json_string(json_string, io, verbose=False, mcp_tran
try:
config = json.loads(json_string)
if verbose:
- io.tool_output("Loading MCP servers from provided JSON string")
+ io.tool_output("Loading MCP servers from provided JSON")
if "mcpServers" in config:
for name, server_config in config["mcpServers"].items():
@@ -22,21 +22,21 @@ def _parse_mcp_servers_from_json_string(json_string, io, verbose=False, mcp_tran
server_config["name"] = name
transport = server_config.get("transport", mcp_transport)
if transport == "stdio":
- servers.append(McpServer(server_config))
+ servers.append(McpServer(server_config, io=io, verbose=verbose))
elif transport == "http":
- servers.append(HttpStreamingServer(server_config))
+ servers.append(HttpStreamingServer(server_config, io=io, verbose=verbose))
elif transport == "sse":
- servers.append(SseServer(server_config))
+ servers.append(SseServer(server_config, io=io, verbose=verbose))
if verbose:
- io.tool_output(f"Loaded {len(servers)} MCP servers from JSON string")
+ io.tool_output(f"Loaded {len(servers)} MCP servers")
return servers
else:
- io.tool_warning("No 'mcpServers' key found in MCP config JSON string")
+ io.tool_warning("No 'mcpServers' key found in MCP config")
except json.JSONDecodeError:
- io.tool_error("Invalid JSON in MCP config string")
+ io.tool_error("Invalid JSON in MCP config")
except Exception as e:
- io.tool_error(f"Error loading MCP config from string: {e}")
+ io.tool_error(f"Error loading MCP config: {e}")
return servers
@@ -100,44 +100,24 @@ def _resolve_mcp_config_path(file_path, io, verbose=False):
def _parse_mcp_servers_from_file(file_path, io, verbose=False, mcp_transport="stdio"):
"""Parse MCP servers from a JSON file."""
- servers = []
-
# Resolve the file path relative to closest cecli.conf.yml, git directory, or CWD
resolved_file_path = _resolve_mcp_config_path(file_path, io, verbose)
try:
with open(resolved_file_path, "r") as f:
- config = json.load(f)
+ json_string = f.read()
if verbose:
io.tool_output(f"Loading MCP servers from file: {file_path}")
- if "mcpServers" in config:
- for name, server_config in config["mcpServers"].items():
- if verbose:
- io.tool_output(f"Loading MCP server: {name}")
+ return _parse_mcp_servers_from_json_string(json_string, io, verbose, mcp_transport)
- # Create a server config with name included
- server_config["name"] = name
- transport = server_config.get("transport", mcp_transport)
- if transport == "stdio":
- servers.append(McpServer(server_config))
- elif transport == "http":
- servers.append(HttpStreamingServer(server_config))
-
- if verbose:
- io.tool_output(f"Loaded {len(servers)} MCP servers from {file_path}")
- return servers
- else:
- io.tool_warning(f"No 'mcpServers' key found in MCP config file: {file_path}")
except FileNotFoundError:
io.tool_warning(f"MCP config file not found: {file_path}")
- except json.JSONDecodeError:
- io.tool_error(f"Invalid JSON in MCP config file: {file_path}")
except Exception as e:
- io.tool_error(f"Error loading MCP config from file: {e}")
+ io.tool_error(f"Error reading MCP config file: {e}")
- return servers
+ return []
def load_mcp_servers(mcp_servers, mcp_servers_file, io, verbose=False, mcp_transport="stdio"):
@@ -169,6 +149,6 @@ def load_mcp_servers(mcp_servers, mcp_servers_file, io, verbose=False, mcp_trans
# and maybe it is actually prompt_toolkit's fault
# but this hack works swimmingly because ???
# so sure! why not
- servers = [McpServer(json.loads('{"cecli_default": {}}'))]
+ servers = [McpServer(json.loads('{"cecli_default": {}}'), io=io, verbose=verbose)]
return servers
diff --git a/cecli/mcp/oauth.py b/cecli/mcp/oauth.py
new file mode 100644
index 00000000000..c9d9897116f
--- /dev/null
+++ b/cecli/mcp/oauth.py
@@ -0,0 +1,250 @@
+import asyncio
+import base64
+import hashlib
+import http.server
+import json
+import os
+import secrets
+import socketserver
+import threading
+import time
+from pathlib import Path
+from typing import Awaitable, Callable, Optional, Tuple
+from urllib.parse import parse_qs, urlparse
+
+from mcp.client.auth import TokenStorage
+from mcp.shared.auth import OAuthClientInformationFull, OAuthToken
+
+
+def find_available_port(start_port=8484, end_port=8584):
+ """Find an available port in the given range."""
+ for port in range(start_port, end_port + 1):
+ try:
+ # Check if the port is available by trying to bind to it
+ with socketserver.TCPServer(("localhost", port), None):
+ return port
+ except OSError:
+ # Port is likely already in use
+ continue
+ return None
+
+
+def create_oauth_callback_server(
+ port, path="/callback"
+) -> Tuple[Callable[[], Awaitable[Tuple[str, str]]], Callable[[], None]]:
+ """
+ Create a local HTTP server to handle OAuth callback.
+
+ Returns:
+ Tuple of (async callback handler function, shutdown function)
+ """
+ auth_code = None
+ state = None
+ server_error = None
+ callback_received = threading.Event()
+ server = None
+
+ class OAuthCallbackHandler(http.server.SimpleHTTPRequestHandler):
+ def do_GET(self):
+ nonlocal auth_code, state, server_error
+ parsed_path = urlparse(self.path)
+
+ if parsed_path.path == path:
+ query_params = parse_qs(parsed_path.query)
+ if "code" in query_params:
+ auth_code = query_params["code"][0]
+ if "state" in query_params:
+ state = query_params["state"][0]
+
+ self.send_response(200)
+ self.send_header("Content-type", "text/html")
+ self.end_headers()
+ self.wfile.write(
+ b"
Success!
"
+ b"Authentication successful. You can close this browser tab.
"
+ b""
+ )
+ callback_received.set()
+ elif "error" in query_params:
+ error = query_params["error"][0]
+ error_desc = query_params.get("error_description", [""])[0]
+ server_error = f"OAuth error: {error} - {error_desc}"
+
+ self.send_response(400)
+ self.send_header("Content-type", "text/html")
+ self.end_headers()
+ self.wfile.write(
+ "Authentication Failed
"
+ f"{error}: {error_desc}
".encode()
+ )
+ callback_received.set()
+ else:
+ self.send_response(400)
+ self.send_header("Content-type", "text/html")
+ self.end_headers()
+ self.wfile.write(b"Invalid Request
")
+ else:
+ self.send_response(404)
+ self.send_header("Content-type", "text/html")
+ self.end_headers()
+ self.wfile.write(b"Not Found
")
+
+ def log_message(self, format, *args):
+ pass
+
+ # Start server in a separate thread
+ def start_server():
+ nonlocal server
+ try:
+ server = socketserver.TCPServer(("localhost", port), OAuthCallbackHandler)
+ server.serve_forever()
+ except Exception as e:
+ server_error = f"Server error: {e}" # noqa
+ callback_received.set()
+
+ server_thread = threading.Thread(target=start_server, daemon=True)
+ server_thread.start()
+
+ # Shutdown function
+ def shutdown():
+ nonlocal server
+ if server:
+ server.shutdown()
+ server = None
+
+ async def get_auth_code() -> Tuple[str, str]:
+ # Wait for callback to be received
+ MINUTES = 5
+ timeout = MINUTES * 60
+
+ start_time = time.time()
+ while not callback_received.is_set():
+ if time.time() - start_time > timeout:
+ shutdown()
+ raise Exception(f"OAuth callback timed out after {MINUTES} minutes")
+
+ # Small sleep to avoid busy waiting
+ await asyncio.sleep(0.1)
+
+ if server_error:
+ shutdown()
+ raise Exception(server_error)
+
+ if not auth_code:
+ shutdown()
+ raise Exception("No authorization code received")
+
+ return auth_code, state
+
+ return get_auth_code, shutdown
+
+
+def generate_pkce_codes():
+ """Generate PKCE code verifier and challenge."""
+ code_verifier = secrets.token_urlsafe(64)
+ hasher = hashlib.sha256()
+ hasher.update(code_verifier.encode("utf-8"))
+ code_challenge = base64.urlsafe_b64encode(hasher.digest()).rstrip(b"=").decode("utf-8")
+ return code_verifier, code_challenge
+
+
+def get_token_file_path():
+ """Get the path to the MCP OAuth tokens file."""
+ config_dir = Path.home() / ".cecli"
+ config_dir.mkdir(parents=True, exist_ok=True)
+ return config_dir / "mcp-oauth-tokens.json"
+
+
+def load_mcp_oauth_tokens():
+ """Load stored OAuth tokens from file."""
+ token_file = get_token_file_path()
+ if not token_file.exists():
+ return {}
+
+ try:
+ with open(token_file, "r", encoding="utf-8") as f:
+ # File might be empty
+ return json.load(f) or {}
+ except Exception:
+ return {}
+
+
+def save_mcp_oauth_token(server_name, token_data):
+ """Save OAuth token for an MCP server."""
+ tokens = load_mcp_oauth_tokens()
+ tokens[server_name] = token_data
+
+ token_file = get_token_file_path()
+ try:
+ with open(token_file, "w", encoding="utf-8") as f:
+ json.dump(tokens, f, indent=2)
+ # Set restrictive permissions (owner read/write only)
+ os.chmod(token_file, 0o600)
+ except Exception as e:
+ raise Exception(f"Failed to save OAuth token: {e}")
+
+
+def save_mcp_oauth_tokens(tokens_dict):
+ """Save all OAuth tokens to file."""
+ token_file = get_token_file_path()
+ try:
+ with open(token_file, "w", encoding="utf-8") as f:
+ json.dump(tokens_dict, f, indent=2)
+ # Set restrictive permissions (owner read/write only)
+ os.chmod(token_file, 0o600)
+ except Exception as e:
+ raise Exception(f"Failed to save OAuth tokens: {e}")
+
+
+def get_mcp_oauth_token(server_name):
+ """Retrieve stored OAuth token for an MCP server."""
+ tokens = load_mcp_oauth_tokens()
+ return tokens.get(server_name, {})
+
+
+class FileBasedTokenStorage(TokenStorage):
+ """File-based token storage for MCP OAuth using the SDK's TokenStorage interface."""
+
+ def __init__(self, server_name: str):
+ self.server_name = server_name
+
+ async def get_tokens(self) -> Optional[OAuthToken]:
+ """Get stored tokens for this server."""
+ all_tokens = load_mcp_oauth_tokens()
+ server_data = all_tokens.get(self.server_name, {})
+
+ if "tokens" not in server_data:
+ return None
+
+ return OAuthToken.model_validate(server_data["tokens"])
+
+ async def set_tokens(self, tokens: OAuthToken) -> None:
+ """Store tokens for this server."""
+ all_tokens = load_mcp_oauth_tokens()
+
+ if self.server_name not in all_tokens:
+ all_tokens[self.server_name] = {}
+
+ tokens_dict = tokens.model_dump()
+ all_tokens[self.server_name]["tokens"] = tokens_dict
+ save_mcp_oauth_tokens(all_tokens)
+
+ async def get_client_info(self) -> Optional[OAuthClientInformationFull]:
+ """Get stored client information."""
+ all_tokens = load_mcp_oauth_tokens()
+ server_data = all_tokens.get(self.server_name, {})
+
+ if "client_info" not in server_data:
+ return None
+
+ return OAuthClientInformationFull.model_validate(server_data["client_info"])
+
+ async def set_client_info(self, client_info: OAuthClientInformationFull) -> None:
+ """Store client information."""
+ all_tokens = load_mcp_oauth_tokens()
+
+ if self.server_name not in all_tokens:
+ all_tokens[self.server_name] = {}
+
+ all_tokens[self.server_name]["client_info"] = json.loads(client_info.model_dump_json())
+ save_mcp_oauth_tokens(all_tokens)
diff --git a/cecli/mcp/server.py b/cecli/mcp/server.py
index 9d4162fb666..58c2bcb661e 100644
--- a/cecli/mcp/server.py
+++ b/cecli/mcp/server.py
@@ -1,12 +1,25 @@
import asyncio
import logging
import os
+import webbrowser
from contextlib import AsyncExitStack
+from urllib.parse import urlparse
+import httpx
from mcp import ClientSession, StdioServerParameters
+from mcp.client.auth import OAuthClientProvider
from mcp.client.sse import sse_client
from mcp.client.stdio import stdio_client
-from mcp.client.streamable_http import streamablehttp_client
+from mcp.client.streamable_http import streamable_http_client
+from mcp.shared.auth import OAuthClientMetadata
+
+from cecli.mcp.oauth import (
+ FileBasedTokenStorage,
+ create_oauth_callback_server,
+ find_available_port,
+ get_mcp_oauth_token,
+ save_mcp_oauth_token,
+)
class McpServer:
@@ -17,14 +30,18 @@ class McpServer:
Uses the mcp library to create and initialize ClientSession objects.
"""
- def __init__(self, server_config):
+ def __init__(self, server_config, io=None, verbose=False):
"""Initialize the MCP tool provider.
Args:
server_config: Configuration for the MCP server
+ io: InputOutput object for user interaction
+ verbose: Whether to output verbose logging
"""
self.config = server_config
self.name = server_config.get("name", "unnamed-server")
+ self.io = io
+ self.verbose = verbose
self.session = None
self._cleanup_lock: asyncio.Lock = asyncio.Lock()
self.exit_stack = AsyncExitStack()
@@ -39,15 +56,21 @@ async def connect(self):
ClientSession: The active session
"""
if self.session is not None:
- logging.info(f"Using existing session for MCP server: {self.name}")
+ if self.verbose and self.io:
+ self.io.tool_output(f"Using existing session for MCP server: {self.name}")
return self.session
- logging.info(f"Establishing new connection to MCP server: {self.name}")
+ if self.verbose and self.io:
+ self.io.tool_output(f"Establishing new connection to MCP server: {self.name}")
+
command = self.config["command"]
+
+ env = {**os.environ, **self.config["env"]} if self.config.get("env") else None
+
server_params = StdioServerParameters(
command=command,
args=self.config.get("args"),
- env={**os.environ, **self.config["env"]} if self.config.get("env") else None,
+ env=env,
)
try:
@@ -76,58 +99,163 @@ async def disconnect(self):
logging.error(f"Error during cleanup of server {self.name}: {e}")
-class HttpStreamingServer(McpServer):
- """HTTP streaming MCP server using mcp.client.streamablehttp_client."""
+class HttpBasedMcpServer(McpServer):
+ """Base class for HTTP-based MCP servers (HTTP streaming and SSE)."""
- async def connect(self):
- if self.session is not None:
- logging.info(f"Using existing session for MCP server: {self.name}")
- return self.session
+ async def _create_oauth_provider(self):
+ """Create an OAuthClientProvider using the MCP SDK."""
+ parsed = urlparse(self.config.get("url"))
+ server_url = f"{parsed.scheme}://{parsed.netloc}"
+ if self.verbose and self.io:
+ self.io.tool_output(f"Auto-derived OAuth server URL: {server_url}", log_only=True)
- logging.info(f"Establishing new connection to HTTP MCP server: {self.name}")
- try:
- url = self.config.get("url")
- headers = self.config.get("headers", {})
- http_transport = await self.exit_stack.enter_async_context(
- streamablehttp_client(url, headers=headers)
- )
- read, write, _response = http_transport
+ # Check if we have existing client info with a redirect URI
+ server_info = get_mcp_oauth_token(self.name)
+ existing_redirect_uri = None
- session = await self.exit_stack.enter_async_context(ClientSession(read, write))
- await session.initialize()
- self.session = session
- return session
- except Exception as e:
- logging.error(f"Error initializing HTTP server {self.name}: {e}")
- await self.disconnect()
- raise
+ if "client_info" in server_info and "redirect_uris" in server_info["client_info"]:
+ redirect_uris = server_info["client_info"].get("redirect_uris", [])
+ if redirect_uris:
+ existing_redirect_uri = redirect_uris[0]
+ if self.verbose and self.io:
+ self.io.tool_output(
+ f"Found existing redirect URI: {existing_redirect_uri}", log_only=True
+ )
+
+ # If we have an existing redirect URI, parse it to get the port
+ if existing_redirect_uri:
+ try:
+ parsed_uri = urlparse(existing_redirect_uri)
+ port = int(parsed_uri.netloc.split(":")[1])
+ if self.verbose and self.io:
+ self.io.tool_output(f"Reusing existing port: {port}", log_only=True)
+ except (ValueError, IndexError):
+ # If we can't parse the port, find a new one
+ port = find_available_port()
+ else:
+ # No existing redirect URI, find an available port
+ port = find_available_port()
+ if not port:
+ raise Exception("Could not find available port for OAuth callback")
-class SseServer(McpServer):
- """SSE (Server-Sent Events) MCP server using mcp.client.sse_client."""
+ redirect_uri = f"http://localhost:{port}/callback"
+
+ get_auth_code, shutdown = create_oauth_callback_server(port)
+
+ # Store shutdown function for cleanup
+ self._oauth_shutdown = shutdown
+
+ async def handle_redirect(auth_url: str) -> None:
+ if self.io:
+ self.io.tool_output(f"\nAuthentication required for MCP server: {self.name}")
+ self.io.tool_output("\nPlease open this URL in your browser to authenticate:")
+ self.io.tool_output(f"\n{auth_url}\n")
+ self.io.tool_output("\nWaiting for you to complete authentication...")
+ self.io.tool_output("Use Control-C to interrupt.")
+ try:
+ webbrowser.open(auth_url)
+ except Exception:
+ pass
+
+ client_metadata = OAuthClientMetadata(
+ client_name="Cecli",
+ redirect_uris=[redirect_uri],
+ grant_types=["authorization_code", "refresh_token"],
+ )
+ oauth_provider = OAuthClientProvider(
+ server_url=server_url,
+ client_metadata=client_metadata,
+ storage=FileBasedTokenStorage(self.name),
+ redirect_handler=handle_redirect,
+ callback_handler=get_auth_code,
+ )
+
+ return oauth_provider
+
+ def _create_transport(self, url, http_client):
+ """
+ Create the transport for this server type.
+ Must be implemented by subclasses.
+ """
+ raise NotImplementedError("Subclasses must implement _create_transport")
async def connect(self):
if self.session is not None:
- logging.info(f"Using existing session for SSE MCP server: {self.name}")
+ if self.verbose and self.io:
+ self.io.tool_output(f"Using existing session for {self.name}")
return self.session
- logging.info(f"Establishing new connection to SSE MCP server: {self.name}")
+ if self.verbose and self.io:
+ self.io.tool_output(f"Establishing new connection to {self.name}")
+
try:
url = self.config.get("url")
headers = self.config.get("headers", {})
- sse_transport = await self.exit_stack.enter_async_context(
- sse_client(url, headers=headers)
+ oauth_provider = await self._create_oauth_provider()
+
+ http_client = await self.exit_stack.enter_async_context(
+ httpx.AsyncClient(
+ auth=oauth_provider,
+ follow_redirects=True,
+ headers=headers,
+ timeout=30,
+ )
+ )
+
+ transport = await self.exit_stack.enter_async_context(
+ self._create_transport(url, http_client=http_client)
)
- read, write, _response = sse_transport
+
+ read, write, _ = transport
+
session = await self.exit_stack.enter_async_context(ClientSession(read, write))
await session.initialize()
self.session = session
+
+ if oauth_provider.context.oauth_metadata:
+ token_endpoint = oauth_provider._get_token_endpoint()
+ server_info = get_mcp_oauth_token(self.name)
+ if "client_info" not in server_info:
+ server_info["client_info"] = {}
+
+ server_info["client_info"]["token_endpoint"] = token_endpoint
+
+ save_mcp_oauth_token(self.name, server_info)
+
return session
except Exception as e:
- logging.error(f"Error initializing SSE server {self.name}: {e}")
+ logging.error(f"Error initializing {self.name}: {e}")
await self.disconnect()
raise
+ async def disconnect(self):
+ """Disconnect from the MCP server and clean up resources."""
+ async with self._cleanup_lock:
+ try:
+ if hasattr(self, "_oauth_shutdown"):
+ self._oauth_shutdown()
+ await self.exit_stack.aclose()
+ self.session = None
+ except Exception as e:
+ logging.error(f"Error during cleanup of server {self.name}: {e}")
+
+
+class HttpStreamingServer(HttpBasedMcpServer):
+ """HTTP streaming MCP server using mcp.client.streamable_http_client."""
+
+ def _create_transport(self, url, http_client):
+ """Create the HTTP streaming transport."""
+ return streamable_http_client(url, http_client=http_client)
+
+
+class SseServer(HttpBasedMcpServer):
+ """SSE (Server-Sent Events) MCP server using mcp.client.sse_client."""
+
+ def _create_transport(self, url, http_client):
+ """Create the SSE transport."""
+ return sse_client(url, http_client=http_client)
+
class LocalServer(McpServer):
"""
@@ -138,7 +266,8 @@ class LocalServer(McpServer):
async def connect(self):
"""Local tools don't need a connection."""
if self.session is not None:
- logging.info(f"Using existing session for local tools: {self.name}")
+ if self.verbose and self.io:
+ self.io.tool_output(f"Using existing session for local tools: {self.name}")
return self.session
self.session = object() # Dummy session object
diff --git a/cecli/models.py b/cecli/models.py
index 04c035ab0c8..42410231d8b 100644
--- a/cecli/models.py
+++ b/cecli/models.py
@@ -892,7 +892,7 @@ def is_ollama(self):
async def send_completion(
self, messages, functions, stream, temperature=None, tools=None, max_tokens=None
):
- if os.environ.get("CECLISANITY_CHECK_TURNS"):
+ if os.environ.get("CECLI_SANITY_CHECK_TURNS"):
sanity_check_messages(messages)
messages = model_request_parser(self, messages)
if self.verbose:
@@ -1169,7 +1169,39 @@ def print_matching_models(io, search):
if matches:
io.tool_output(f'Models which match "{search}":')
for model in matches:
- io.tool_output(f"- {model}")
+ # Get model info to check for prices
+ info = model_info_manager.get_model_info(model)
+
+ # Build price string
+ price_parts = []
+
+ # Check for input cost
+ input_cost = info.get("input_cost_per_token")
+ if input_cost is not None:
+ # Convert from per-token to per-1M tokens
+ input_cost_per_1m = input_cost * 1000000
+ price_parts.append(f"${input_cost_per_1m:.2f}/1m/input")
+
+ # Check for output cost
+ output_cost = info.get("output_cost_per_token")
+ if output_cost is not None:
+ # Convert from per-token to per-1M tokens
+ output_cost_per_1m = output_cost * 1000000
+ price_parts.append(f"${output_cost_per_1m:.2f}/1m/output")
+
+ # Check for cache cost (if available)
+ cache_cost = info.get("cache_cost_per_token")
+ if cache_cost is not None:
+ # Convert from per-token to per-1M tokens
+ cache_cost_per_1m = cache_cost * 1000000
+ price_parts.append(f"${cache_cost_per_1m:.2f}/1m/cache")
+
+ # Format the output
+ if price_parts:
+ price_str = " (" + ", ".join(price_parts) + ")"
+ io.tool_output(f"- {model}{price_str}")
+ else:
+ io.tool_output(f"- {model}")
else:
io.tool_output(f'No models match "{search}".')
diff --git a/cecli/onboarding.py b/cecli/onboarding.py
index 72d49ff4c51..a0037520d1f 100644
--- a/cecli/onboarding.py
+++ b/cecli/onboarding.py
@@ -1,8 +1,5 @@
-import base64
-import hashlib
import http.server
import os
-import secrets
import socketserver
import threading
import time
@@ -13,6 +10,7 @@
from cecli import urls
from cecli.io import InputOutput
+from cecli.mcp.oauth import find_available_port, generate_pkce_codes
def check_openrouter_tier(api_key):
@@ -117,24 +115,7 @@ async def select_default_model(args, io):
await io.offer_url(urls.models_and_keys, "Open documentation URL for more info?")
-def find_available_port(start_port=8484, end_port=8584):
- for port in range(start_port, end_port + 1):
- try:
- with socketserver.TCPServer(("localhost", port), None):
- return port
- except OSError:
- continue
- return None
-
-
-def generate_pkce_codes():
- code_verifier = secrets.token_urlsafe(64)
- hasher = hashlib.sha256()
- hasher.update(code_verifier.encode("utf-8"))
- code_challenge = base64.urlsafe_b64encode(hasher.digest()).rstrip(b"=").decode("utf-8")
- return code_verifier, code_challenge
-
-
+# Function to exchange the authorization code for an API key
def exchange_code_for_key(code, code_verifier, io):
try:
response = requests.post(
diff --git a/cecli/tools/context_manager.py b/cecli/tools/context_manager.py
index 216dca67750..652185c8780 100644
--- a/cecli/tools/context_manager.py
+++ b/cecli/tools/context_manager.py
@@ -102,10 +102,10 @@ def _remove(coder, file_path):
coder.abs_read_only_fnames.remove(abs_path)
removed = True
if not removed:
- coder.io.tool_output("⚠️ File '{file_path}' not in context")
+ coder.io.tool_output(f"⚠️ File '{file_path}' not in context")
return f"File not in context: {file_path}"
coder.recently_removed[rel_path] = {"removed_at": time.time()}
- coder.io.tool_output("🗑️ Removed '{file_path}' from context")
+ coder.io.tool_output(f"🗑️ Removed '{file_path}' from context")
return f"Removed: {file_path}"
except Exception as e:
coder.io.tool_error(f"Error removing file '{file_path}': {str(e)}")
@@ -117,10 +117,10 @@ def _editable(coder, file_path):
try:
abs_path = coder.abs_root_path(file_path)
if abs_path in coder.abs_fnames:
- coder.io.tool_output("📝 File '{file_path}' is already editable")
+ coder.io.tool_output(f"📝 File '{file_path}' is already editable")
return f"Already editable: {file_path}"
if not os.path.isfile(abs_path):
- coder.io.tool_output("⚠️ File '{file_path}' not found on disk")
+ coder.io.tool_output(f"⚠️ File '{file_path}' not found on disk")
return f"File not found: {file_path}"
was_read_only = False
if abs_path in coder.abs_read_only_fnames:
@@ -128,10 +128,10 @@ def _editable(coder, file_path):
was_read_only = True
coder.abs_fnames.add(abs_path)
if was_read_only:
- coder.io.tool_output("📝 Moved '{file_path}' from read-only to editable")
+ coder.io.tool_output(f"📝 Moved '{file_path}' from read-only to editable")
return f"Made editable (moved): {file_path}"
else:
- coder.io.tool_output("📝 Added '{file_path}' directly to editable context")
+ coder.io.tool_output(f"📝 Added '{file_path}' directly to editable context")
return f"Made editable (added): {file_path}"
except Exception as e:
coder.io.tool_error(f"Error making editable '{file_path}': {str(e)}")
@@ -154,7 +154,7 @@ def _create(coder, file_path):
# Check if file already exists
if os.path.exists(abs_path):
- coder.io.tool_output("⚠️ File '{file_path}' already exists")
+ coder.io.tool_output(f"⚠️ File '{file_path}' already exists")
return f"File already exists: {file_path}"
# Create parent directories if they don't exist
@@ -167,7 +167,7 @@ def _create(coder, file_path):
# Add the file to editable context
coder.abs_fnames.add(abs_path)
- coder.io.tool_output("📝 Created '{file_path}' and made it editable")
+ coder.io.tool_output(f"📝 Created '{file_path}' and made it editable")
return f"Created and made editable: {file_path}"
except Exception as e:
diff --git a/cecli/tui/worker.py b/cecli/tui/worker.py
index 551c4047ed1..68c08775b0e 100644
--- a/cecli/tui/worker.py
+++ b/cecli/tui/worker.py
@@ -7,7 +7,7 @@
from typing import Optional
from cecli.coders import Coder
-from cecli.commands import SwitchCoder
+from cecli.commands import SwitchCoderSignal
# Suppress asyncio task destroyed warnings during shutdown
logging.getLogger("asyncio").setLevel(logging.CRITICAL)
@@ -91,7 +91,7 @@ async def _async_run(self):
break # Normal exit
except asyncio.CancelledError:
break
- except SwitchCoder as switch:
+ except SwitchCoderSignal as switch:
# Handle chat mode switches (e.g., /chat-mode architect)
try:
kwargs = dict(io=self.coder.io, from_coder=self.coder)
diff --git a/cecli/versioncheck.py b/cecli/versioncheck.py
index 5e099b40a7c..0563cd618d6 100644
--- a/cecli/versioncheck.py
+++ b/cecli/versioncheck.py
@@ -34,7 +34,7 @@ async def install_upgrade(io, latest_version=None):
new_ver_text = f"Newer cecli version v{latest_version} is available."
else:
new_ver_text = "Install latest version of cecli?"
- docker_image = os.environ.get("CECLIDOCKER_IMAGE")
+ docker_image = os.environ.get("CECLI_DOCKER_IMAGE")
if docker_image:
text = f"\n{new_ver_text} To upgrade, run:\n\n docker pull {docker_image}\n"
io.tool_warning(text)
@@ -60,7 +60,7 @@ async def check_version(io, just_check=False, verbose=False):
import requests
try:
- response = requests.get("https://pypi.org/pypi/cecli-ce/json")
+ response = requests.get("https://pypi.org/pypi/aider-ce/json")
data = response.json()
latest_version = data["info"]["version"]
current_version = cecli.__version__
diff --git a/cecli/website/HISTORY.md b/cecli/website/HISTORY.md
index d32a1215ac1..f3354c25312 100644
--- a/cecli/website/HISTORY.md
+++ b/cecli/website/HISTORY.md
@@ -696,7 +696,7 @@ versions.
- Still auto-completes the full paths of the repo files like `/add`.
- Now supports globs like `src/**/*.py`
- Renamed `--yes` to `--yes-always`.
- - Now uses `AIDER_YES_ALWAYS` env var and `yes-always:` YAML key.
+ - Now uses `CECLI_YES_ALWAYS` env var and `yes-always:` YAML key.
- Existing YAML and .env files will need to be updated.
- Can still abbreviate to `--yes` on the command line.
- Config file now uses standard YAML list syntax with ` - list entries`, one per line.
@@ -1125,7 +1125,7 @@ versions.
### Aider v0.39.0
- Use `--sonnet` for Claude 3.5 Sonnet, which is the top model on [aider's LLM code editing leaderboard](https://aider.chat/docs/leaderboards/#claude-35-sonnet-takes-the-top-spot).
-- All `AIDER_xxx` environment variables can now be set in `.env` (by @jpshack-at-palomar).
+- All `CECLI_xxx` environment variables can now be set in `.env` (by @jpshack-at-palomar).
- Use `--llm-history-file` to log raw messages sent to the LLM (by @daniel-vainsencher).
- Commit messages are no longer prefixed with "aider:". Instead the git author and committer names have "(aider)" added.
diff --git a/cecli/website/docs/config.md b/cecli/website/docs/config.md
index 299ec5979eb..5a12fcb0eb9 100644
--- a/cecli/website/docs/config.md
+++ b/cecli/website/docs/config.md
@@ -11,7 +11,7 @@ command line switches.
Most options can also be set in an `.aider.conf.yml` file
which can be placed in your home directory or at the root of
your git repo.
-Or by setting environment variables like `AIDER_xxx`
+Or by setting environment variables like `CECLI_xxx`
either in your shell or a `.env` file.
Here are 4 equivalent ways of setting an option.
@@ -31,13 +31,13 @@ dark-mode: true
By setting an environment variable:
```
-export AIDER_DARK_MODE=true
+export CECLI_DARK_MODE=true
```
Using an `.env` file:
```
-AIDER_DARK_MODE=true
+CECLI_DARK_MODE=true
```
{% include keys.md %}
diff --git a/cecli/website/docs/config/agent-mode.md b/cecli/website/docs/config/agent-mode.md
index 30100782ced..2216b6492b5 100644
--- a/cecli/website/docs/config/agent-mode.md
+++ b/cecli/website/docs/config/agent-mode.md
@@ -41,9 +41,9 @@ This loop continues automatically until the `Finished` tool is called, or the ma
Agent Mode uses a centralized local tool registry that manages all available tools:
-- **File Discovery Tools**: `View`, `ViewFilesMatching`, `ViewFilesWithSymbol`, `Ls`, `Grep`
+- **File Discovery Tools**: `ViewFilesMatching`, `ViewFilesWithSymbol`, `Ls`, `Grep`
- **Editing Tools**: `ReplaceText`, `InsertBlock`, `DeleteBlock`, `ReplaceLines`, `DeleteLines`
-- **Context Management Tools**: `MakeEditable`, `MakeReadonly`, `Remove`
+- **Context Management Tools**: `ContextManager`
- **Git Tools**: `GitDiff`, `GitLog`, `GitShow`, `GitStatus`
- **Utility Tools**: `UpdateTodoList`, `ListChanges`, `UndoChange`, `Finished`
- **Skill Management**: `LoadSkill`, `RemoveSkill`
@@ -154,7 +154,7 @@ Agent Mode can also be configured directly in the relevant config.yml file:
agent: true
agent-config:
# Tool configuration
- tools_includelist: ["view", "makeeditable", "replacetext", "finished"] # Optional: Whitelist of tools
+ tools_includelist: [contextmanager", "replacetext", "finished"] # Optional: Whitelist of tools
tools_excludelist: ["command", "commandinteractive"] # Optional: Blacklist of tools
# Context blocks configuration
@@ -184,9 +184,8 @@ agent-config:
Certain tools are always available regardless of includelist/excludelist settings:
-- `makeeditable` - Make files editable
+- `ContextManager` - Add, drop, and make files editable in the context
- `replacetext` - Basic text replacement
-- `view` - View files
- `finished` - Complete the task
#### Context Blocks
@@ -202,7 +201,7 @@ The following context blocks are available by default and can be customized usin
When `include_context_blocks` is specified, only the listed blocks will be included. When `exclude_context_blocks` is specified, the listed blocks will be removed from the default set.
-#### Other CECLI CLI/Config Options for Agent Mode
+#### Other Cecli Config Options for Agent Mode
- `use-enhanced-map` - Use enhanced repo map that takes into account import relationships between files
@@ -221,7 +220,7 @@ agent: true
# Agent Mode configuration
agent-config:
# Tool configuration
- tools_includelist: ["view", "makeeditable", "replacetext", "finished"] # Optional: Whitelist of tools
+ tools_includelist: ["contextmanager", "replacetext", "finished"] # Optional: Whitelist of tools
tools_excludelist: ["command", "commandinteractive"] # Optional: Blacklist of tools
# Context blocks configuration
diff --git a/cecli/website/docs/config/dotenv.md b/cecli/website/docs/config/dotenv.md
index 5bd249f7c48..408255be1c0 100644
--- a/cecli/website/docs/config/dotenv.md
+++ b/cecli/website/docs/config/dotenv.md
@@ -62,432 +62,432 @@ cog.outl("```")
# Main model:
## Specify the model to use for the main chat
-#AIDER_MODEL=
+#CECLI_MODEL=
########################
# API Keys and settings:
## Specify the OpenAI API key
-#AIDER_OPENAI_API_KEY=
+#CECLI_OPENAI_API_KEY=
## Specify the Anthropic API key
-#AIDER_ANTHROPIC_API_KEY=
+#CECLI_ANTHROPIC_API_KEY=
## Specify the api base url
-#AIDER_OPENAI_API_BASE=
+#CECLI_OPENAI_API_BASE=
## (deprecated, use --set-env OPENAI_API_TYPE=)
-#AIDER_OPENAI_API_TYPE=
+#CECLI_OPENAI_API_TYPE=
## (deprecated, use --set-env OPENAI_API_VERSION=)
-#AIDER_OPENAI_API_VERSION=
+#CECLI_OPENAI_API_VERSION=
## (deprecated, use --set-env OPENAI_API_DEPLOYMENT_ID=)
-#AIDER_OPENAI_API_DEPLOYMENT_ID=
+#CECLI_OPENAI_API_DEPLOYMENT_ID=
## (deprecated, use --set-env OPENAI_ORGANIZATION=)
-#AIDER_OPENAI_ORGANIZATION_ID=
+#CECLI_OPENAI_ORGANIZATION_ID=
## Set an environment variable (to control API settings, can be used multiple times)
-#AIDER_SET_ENV=
+#CECLI_SET_ENV=
## Set an API key for a provider (eg: --api-key provider= sets PROVIDER_API_KEY=)
-#AIDER_API_KEY=
+#CECLI_API_KEY=
#################
# Model settings:
## List known models which match the (partial) MODEL name
-#AIDER_LIST_MODELS=
+#CECLI_LIST_MODELS=
## Specify a file with aider model settings for unknown models
-#AIDER_MODEL_SETTINGS_FILE=.aider.model.settings.yml
+#CECLI_MODEL_SETTINGS_FILE=.aider.model.settings.yml
## Specify a file with context window and costs for unknown models
-#AIDER_MODEL_METADATA_FILE=.aider.model.metadata.json
+#CECLI_MODEL_METADATA_FILE=.aider.model.metadata.json
## Add a model alias (can be used multiple times)
-#AIDER_ALIAS=
+#CECLI_ALIAS=
## Set the reasoning_effort API parameter (default: not set)
-#AIDER_REASONING_EFFORT=
+#CECLI_REASONING_EFFORT=
## Set the thinking token budget for models that support it. Use 0 to disable. (default: not set)
-#AIDER_THINKING_TOKENS=
+#CECLI_THINKING_TOKENS=
## Verify the SSL cert when connecting to models (default: True)
-#AIDER_VERIFY_SSL=true
+#CECLI_VERIFY_SSL=true
## Timeout in seconds for API calls (default: None)
-#AIDER_TIMEOUT=
+#CECLI_TIMEOUT=
## Specify what edit format the LLM should use (default depends on model)
-#AIDER_EDIT_FORMAT=
+#CECLI_EDIT_FORMAT=
## Use architect edit format for the main chat
-#AIDER_ARCHITECT=
+#CECLI_ARCHITECT=
## Enable/disable automatic acceptance of architect changes (default: True)
-#AIDER_AUTO_ACCEPT_ARCHITECT=true
+#CECLI_AUTO_ACCEPT_ARCHITECT=true
## Specify the model to use for commit messages and chat history summarization (default depends on --model)
-#AIDER_WEAK_MODEL=
+#CECLI_WEAK_MODEL=
## Specify the model to use for editor tasks (default depends on --model)
-#AIDER_EDITOR_MODEL=
+#CECLI_EDITOR_MODEL=
## Specify the edit format for the editor model (default: depends on editor model)
-#AIDER_EDITOR_EDIT_FORMAT=
+#CECLI_EDITOR_EDIT_FORMAT=
## Only work with models that have meta-data available (default: True)
-#AIDER_SHOW_MODEL_WARNINGS=true
+#CECLI_SHOW_MODEL_WARNINGS=true
## Check if model accepts settings like reasoning_effort/thinking_tokens (default: True)
-#AIDER_CHECK_MODEL_ACCEPTS_SETTINGS=true
+#CECLI_CHECK_MODEL_ACCEPTS_SETTINGS=true
## Soft limit on tokens for chat history, after which summarization begins. If unspecified, defaults to the model's max_chat_history_tokens.
-#AIDER_MAX_CHAT_HISTORY_TOKENS=
+#CECLI_MAX_CHAT_HISTORY_TOKENS=
#################
# Cache settings:
## Enable caching of prompts (default: False)
-#AIDER_CACHE_PROMPTS=false
+#CECLI_CACHE_PROMPTS=false
## Number of times to ping at 5min intervals to keep prompt cache warm (default: 0)
-#AIDER_CACHE_KEEPALIVE_PINGS=false
+#CECLI_CACHE_KEEPALIVE_PINGS=false
###################
# Repomap settings:
## Suggested number of tokens to use for repo map, use 0 to disable
-#AIDER_MAP_TOKENS=
+#CECLI_MAP_TOKENS=
## Control how often the repo map is refreshed. Options: auto, always, files, manual (default: auto)
-#AIDER_MAP_REFRESH=auto
+#CECLI_MAP_REFRESH=auto
## Multiplier for map tokens when no files are specified (default: 2)
-#AIDER_MAP_MULTIPLIER_NO_FILES=true
+#CECLI_MAP_MULTIPLIER_NO_FILES=true
## Maximum line length for the repo map code. Prevents sending crazy long lines of minified JS files etc. (default: 100)
-#AIDER_MAP_MAX_LINE_LENGTH=100
+#CECLI_MAP_MAX_LINE_LENGTH=100
################
# History Files:
## Specify the chat input history file (default: .aider.input.history)
-#AIDER_INPUT_HISTORY_FILE=.aider.input.history
+#CECLI_INPUT_HISTORY_FILE=.aider.input.history
## Specify the chat history file (default: .aider.chat.history.md)
-#AIDER_CHAT_HISTORY_FILE=.aider.chat.history.md
+#CECLI_CHAT_HISTORY_FILE=.aider.chat.history.md
## Restore the previous chat history messages (default: False)
-#AIDER_RESTORE_CHAT_HISTORY=false
+#CECLI_RESTORE_CHAT_HISTORY=false
## Log the conversation with the LLM to this file (for example, .aider.llm.history)
-#AIDER_LLM_HISTORY_FILE=
+#CECLI_LLM_HISTORY_FILE=
##################
# Output settings:
## Use colors suitable for a dark terminal background (default: False)
-#AIDER_DARK_MODE=false
+#CECLI_DARK_MODE=false
## Use colors suitable for a light terminal background (default: False)
-#AIDER_LIGHT_MODE=false
+#CECLI_LIGHT_MODE=false
## Enable/disable pretty, colorized output (default: True)
-#AIDER_PRETTY=true
+#CECLI_PRETTY=true
## Enable/disable streaming responses (default: True)
-#AIDER_STREAM=true
+#CECLI_STREAM=true
## Set the color for user input (default: #00cc00)
-#AIDER_USER_INPUT_COLOR=#00cc00
+#CECLI_USER_INPUT_COLOR=#00cc00
## Set the color for tool output (default: None)
-#AIDER_TOOL_OUTPUT_COLOR=
+#CECLI_TOOL_OUTPUT_COLOR=
## Set the color for tool error messages (default: #FF2222)
-#AIDER_TOOL_ERROR_COLOR=#FF2222
+#CECLI_TOOL_ERROR_COLOR=#FF2222
## Set the color for tool warning messages (default: #FFA500)
-#AIDER_TOOL_WARNING_COLOR=#FFA500
+#CECLI_TOOL_WARNING_COLOR=#FFA500
## Set the color for assistant output (default: #0088ff)
-#AIDER_ASSISTANT_OUTPUT_COLOR=#0088ff
+#CECLI_ASSISTANT_OUTPUT_COLOR=#0088ff
## Set the color for the completion menu (default: terminal's default text color)
-#AIDER_COMPLETION_MENU_COLOR=
+#CECLI_COMPLETION_MENU_COLOR=
## Set the background color for the completion menu (default: terminal's default background color)
-#AIDER_COMPLETION_MENU_BG_COLOR=
+#CECLI_COMPLETION_MENU_BG_COLOR=
## Set the color for the current item in the completion menu (default: terminal's default background color)
-#AIDER_COMPLETION_MENU_CURRENT_COLOR=
+#CECLI_COMPLETION_MENU_CURRENT_COLOR=
## Set the background color for the current item in the completion menu (default: terminal's default text color)
-#AIDER_COMPLETION_MENU_CURRENT_BG_COLOR=
+#CECLI_COMPLETION_MENU_CURRENT_BG_COLOR=
## Set the markdown code theme (default: default, other options include monokai, solarized-dark, solarized-light, or a Pygments builtin style, see https://pygments.org/styles for available themes)
-#AIDER_CODE_THEME=default
+#CECLI_CODE_THEME=default
## Show diffs when committing changes (default: False)
-#AIDER_SHOW_DIFFS=false
+#CECLI_SHOW_DIFFS=false
###############
# Git settings:
## Enable/disable looking for a git repo (default: True)
-#AIDER_GIT=true
+#CECLI_GIT=true
## Enable/disable adding .aider* to .gitignore (default: True)
-#AIDER_GITIGNORE=true
+#CECLI_GITIGNORE=true
## Enable/disable the addition of files listed in .gitignore to Aider's editing scope.
-#AIDER_ADD_GITIGNORE_FILES=false
+#CECLI_ADD_GITIGNORE_FILES=false
## Specify the aider ignore file (default: .aiderignore in git root)
-#AIDER_AIDERIGNORE=.aiderignore
+#CECLI_AIDERIGNORE=.aiderignore
## Only consider files in the current subtree of the git repository
-#AIDER_SUBTREE_ONLY=false
+#CECLI_SUBTREE_ONLY=false
## Enable/disable auto commit of LLM changes (default: True)
-#AIDER_AUTO_COMMITS=true
+#CECLI_AUTO_COMMITS=true
## Enable/disable commits when repo is found dirty (default: True)
-#AIDER_DIRTY_COMMITS=true
+#CECLI_DIRTY_COMMITS=true
## Attribute aider code changes in the git author name (default: True). If explicitly set to True, overrides --attribute-co-authored-by precedence.
-#AIDER_ATTRIBUTE_AUTHOR=
+#CECLI_ATTRIBUTE_AUTHOR=
## Attribute aider commits in the git committer name (default: True). If explicitly set to True, overrides --attribute-co-authored-by precedence for aider edits.
-#AIDER_ATTRIBUTE_COMMITTER=
+#CECLI_ATTRIBUTE_COMMITTER=
## Prefix commit messages with 'aider: ' if aider authored the changes (default: False)
-#AIDER_ATTRIBUTE_COMMIT_MESSAGE_AUTHOR=false
+#CECLI_ATTRIBUTE_COMMIT_MESSAGE_AUTHOR=false
## Prefix all commit messages with 'aider: ' (default: False)
-#AIDER_ATTRIBUTE_COMMIT_MESSAGE_COMMITTER=false
+#CECLI_ATTRIBUTE_COMMIT_MESSAGE_COMMITTER=false
## Attribute aider edits using the Co-authored-by trailer in the commit message (default: True). If True, this takes precedence over default --attribute-author and --attribute-committer behavior unless they are explicitly set to True.
-#AIDER_ATTRIBUTE_CO_AUTHORED_BY=true
+#CECLI_ATTRIBUTE_CO_AUTHORED_BY=true
## Enable/disable git pre-commit hooks with --no-verify (default: False)
-#AIDER_GIT_COMMIT_VERIFY=false
+#CECLI_GIT_COMMIT_VERIFY=false
## Commit all pending changes with a suitable commit message, then exit
-#AIDER_COMMIT=false
+#CECLI_COMMIT=false
## Specify a custom prompt for generating commit messages
-#AIDER_COMMIT_PROMPT=
+#CECLI_COMMIT_PROMPT=
## Perform a dry run without modifying files (default: False)
-#AIDER_DRY_RUN=false
+#CECLI_DRY_RUN=false
## Skip the sanity check for the git repository (default: False)
-#AIDER_SKIP_SANITY_CHECK_REPO=false
+#CECLI_SKIP_SANITY_CHECK_REPO=false
## Enable/disable watching files for ai coding comments (default: False)
-#AIDER_WATCH_FILES=false
+#CECLI_WATCH_FILES=false
########################
# Fixing and committing:
## Lint and fix provided files, or dirty files if none provided
-#AIDER_LINT=false
+#CECLI_LINT=false
## Specify lint commands to run for different languages, eg: "python: flake8 --select=..." (can be used multiple times)
-#AIDER_LINT_CMD=
+#CECLI_LINT_CMD=
## Enable/disable automatic linting after changes (default: True)
-#AIDER_AUTO_LINT=true
+#CECLI_AUTO_LINT=true
## Specify command to run tests
-#AIDER_TEST_CMD=
+#CECLI_TEST_CMD=
## Enable/disable automatic testing after changes (default: False)
-#AIDER_AUTO_TEST=false
+#CECLI_AUTO_TEST=false
## Run tests, fix problems found and then exit
-#AIDER_TEST=false
+#CECLI_TEST=false
############
# Analytics:
## Enable/disable analytics for current session (default: random)
-#AIDER_ANALYTICS=
+#CECLI_ANALYTICS=
## Specify a file to log analytics events
-#AIDER_ANALYTICS_LOG=
+#CECLI_ANALYTICS_LOG=
## Permanently disable analytics
-#AIDER_ANALYTICS_DISABLE=false
+#CECLI_ANALYTICS_DISABLE=false
## Send analytics to custom PostHog instance
-#AIDER_ANALYTICS_POSTHOG_HOST=
+#CECLI_ANALYTICS_POSTHOG_HOST=
## Send analytics to custom PostHog project
-#AIDER_ANALYTICS_POSTHOG_PROJECT_API_KEY=
+#CECLI_ANALYTICS_POSTHOG_PROJECT_API_KEY=
############
# Upgrading:
## Check for updates and return status in the exit code
-#AIDER_JUST_CHECK_UPDATE=false
+#CECLI_JUST_CHECK_UPDATE=false
## Check for new aider versions on launch
-#AIDER_CHECK_UPDATE=true
+#CECLI_CHECK_UPDATE=true
## Show release notes on first run of new version (default: None, ask user)
-#AIDER_SHOW_RELEASE_NOTES=
+#CECLI_SHOW_RELEASE_NOTES=
## Install the latest version from the main branch
-#AIDER_INSTALL_MAIN_BRANCH=false
+#CECLI_INSTALL_MAIN_BRANCH=false
## Upgrade aider to the latest version from PyPI
-#AIDER_UPGRADE=false
+#CECLI_UPGRADE=false
########
# Modes:
## Specify a single message to send the LLM, process reply then exit (disables chat mode)
-#AIDER_MESSAGE=
+#CECLI_MESSAGE=
## Specify a file containing the message to send the LLM, process reply, then exit (disables chat mode)
-#AIDER_MESSAGE_FILE=
+#CECLI_MESSAGE_FILE=
## Run aider in your browser (default: False)
-#AIDER_GUI=false
+#CECLI_GUI=false
## Enable automatic copy/paste of chat between aider and web UI (default: False)
-#AIDER_COPY_PASTE=false
+#CECLI_COPY_PASTE=false
## Apply the changes from the given file instead of running the chat (debug)
-#AIDER_APPLY=
+#CECLI_APPLY=
## Apply clipboard contents as edits using the main model's editor format
-#AIDER_APPLY_CLIPBOARD_EDITS=false
+#CECLI_APPLY_CLIPBOARD_EDITS=false
## Do all startup activities then exit before accepting user input (debug)
-#AIDER_EXIT=false
+#CECLI_EXIT=false
## Print the repo map and exit (debug)
-#AIDER_SHOW_REPO_MAP=false
+#CECLI_SHOW_REPO_MAP=false
## Print the system prompts and exit (debug)
-#AIDER_SHOW_PROMPTS=false
+#CECLI_SHOW_PROMPTS=false
#################
# Voice settings:
## Audio format for voice recording (default: wav). webm and mp3 require ffmpeg
-#AIDER_VOICE_FORMAT=wav
+#CECLI_VOICE_FORMAT=wav
## Specify the language for voice using ISO 639-1 code (default: auto)
-#AIDER_VOICE_LANGUAGE=en
+#CECLI_VOICE_LANGUAGE=en
## Specify the input device name for voice recording
-#AIDER_VOICE_INPUT_DEVICE=
+#CECLI_VOICE_INPUT_DEVICE=
#################
# Other settings:
## Never prompt for or attempt to install Playwright for web scraping (default: False).
-#AIDER_DISABLE_PLAYWRIGHT=false
+#CECLI_DISABLE_PLAYWRIGHT=false
## specify a file to edit (can be used multiple times)
-#AIDER_FILE=
+#CECLI_FILE=
## specify a read-only file (can be used multiple times)
-#AIDER_READ=
+#CECLI_READ=
## Use VI editing mode in the terminal (default: False)
-#AIDER_VIM=false
+#CECLI_VIM=false
## Specify the language to use in the chat (default: None, uses system settings)
-#AIDER_CHAT_LANGUAGE=
+#CECLI_CHAT_LANGUAGE=
## Specify the language to use in the commit message (default: None, user language)
-#AIDER_COMMIT_LANGUAGE=
+#CECLI_COMMIT_LANGUAGE=
## Always say yes to every confirmation
-#AIDER_YES_ALWAYS=
+#CECLI_YES_ALWAYS=
## Enable verbose output
-#AIDER_VERBOSE=false
+#CECLI_VERBOSE=false
## Load and execute /commands from a file on launch
-#AIDER_LOAD=
+#CECLI_LOAD=
## Specify the encoding for input and output (default: utf-8)
-#AIDER_ENCODING=utf-8
+#CECLI_ENCODING=utf-8
## Line endings to use when writing files (default: platform)
-#AIDER_LINE_ENDINGS=platform
+#CECLI_LINE_ENDINGS=platform
## Specify the .env file to load (default: .env in git root)
-#AIDER_ENV_FILE=.env
+#CECLI_ENV_FILE=.env
## Enable/disable suggesting shell commands (default: True)
-#AIDER_SUGGEST_SHELL_COMMANDS=true
+#CECLI_SUGGEST_SHELL_COMMANDS=true
## Enable/disable fancy input with history and completion (default: True)
-#AIDER_FANCY_INPUT=true
+#CECLI_FANCY_INPUT=true
## Enable/disable multi-line input mode with Meta-Enter to submit (default: False)
-#AIDER_MULTILINE=false
+#CECLI_MULTILINE=false
## Enable/disable terminal bell notifications when LLM responses are ready (default: False)
-#AIDER_NOTIFICATIONS=false
+#CECLI_NOTIFICATIONS=false
## Specify a command to run for notifications instead of the terminal bell. If not specified, a default command for your OS may be used.
-#AIDER_NOTIFICATIONS_COMMAND=
+#CECLI_NOTIFICATIONS_COMMAND=
## Enable/disable detection and offering to add URLs to chat (default: True)
-#AIDER_DETECT_URLS=true
+#CECLI_DETECT_URLS=true
## Specify which editor to use for the /editor command
-#AIDER_EDITOR=
+#CECLI_EDITOR=
## Print shell completion script for the specified SHELL and exit. Supported shells: bash, tcsh, zsh. Example: aider --shell-completions bash
-#AIDER_SHELL_COMPLETIONS=
+#CECLI_SHELL_COMPLETIONS=
############################
# Deprecated model settings:
## Use claude-3-opus-20240229 model for the main chat (deprecated, use --model)
-#AIDER_OPUS=false
+#CECLI_OPUS=false
## Use anthropic/claude-3-7-sonnet-20250219 model for the main chat (deprecated, use --model)
-#AIDER_SONNET=false
+#CECLI_SONNET=false
## Use claude-3-5-haiku-20241022 model for the main chat (deprecated, use --model)
-#AIDER_HAIKU=false
+#CECLI_HAIKU=false
## Use gpt-4-0613 model for the main chat (deprecated, use --model)
-#AIDER_4=false
+#CECLI_4=false
## Use gpt-4o model for the main chat (deprecated, use --model)
-#AIDER_4O=false
+#CECLI_4O=false
## Use gpt-4o-mini model for the main chat (deprecated, use --model)
-#AIDER_MINI=false
+#CECLI_MINI=false
## Use gpt-4-1106-preview model for the main chat (deprecated, use --model)
-#AIDER_4_TURBO=false
+#CECLI_4_TURBO=false
## Use gpt-3.5-turbo model for the main chat (deprecated, use --model)
-#AIDER_35TURBO=false
+#CECLI_35TURBO=false
## Use deepseek/deepseek-chat model for the main chat (deprecated, use --model)
-#AIDER_DEEPSEEK=false
+#CECLI_DEEPSEEK=false
## Use o1-mini model for the main chat (deprecated, use --model)
-#AIDER_O1_MINI=false
+#CECLI_O1_MINI=false
## Use o1-preview model for the main chat (deprecated, use --model)
-#AIDER_O1_PREVIEW=false
+#CECLI_O1_PREVIEW=false
```
diff --git a/cecli/website/docs/config/editor.md b/cecli/website/docs/config/editor.md
index dc1d74df866..1b3262e855c 100644
--- a/cecli/website/docs/config/editor.md
+++ b/cecli/website/docs/config/editor.md
@@ -18,7 +18,7 @@ You can specify the text editor with the `--editor` switch or using
Aider checks the following environment variables in order to determine which editor to use:
-1. `AIDER_EDITOR`
+1. `CECLI_EDITOR`
2. `VISUAL`
3. `EDITOR`
@@ -35,7 +35,7 @@ If no editor is configured, aider will use these platform-specific defaults:
You can set your preferred editor in your shell's configuration file (e.g., `.bashrc`, `.zshrc`):
```bash
-export AIDER_EDITOR=vim
+export CECLI_EDITOR=vim
```
## Popular Editors by Platform
@@ -44,71 +44,71 @@ export AIDER_EDITOR=vim
1. **vim**
```bash
- export AIDER_EDITOR=vim
+ export CECLI_EDITOR=vim
```
2. **Emacs**
```bash
- export AIDER_EDITOR=emacs
+ export CECLI_EDITOR=emacs
```
3. **VSCode**
```bash
- export AIDER_EDITOR="code --wait"
+ export CECLI_EDITOR="code --wait"
```
4. **Sublime Text**
```bash
- export AIDER_EDITOR="subl --wait"
+ export CECLI_EDITOR="subl --wait"
```
5. **BBEdit**
```bash
- export AIDER_EDITOR="bbedit --wait"
+ export CECLI_EDITOR="bbedit --wait"
```
### Linux
1. **vim**
```bash
- export AIDER_EDITOR=vim
+ export CECLI_EDITOR=vim
```
2. **Emacs**
```bash
- export AIDER_EDITOR=emacs
+ export CECLI_EDITOR=emacs
```
3. **nano**
```bash
- export AIDER_EDITOR=nano
+ export CECLI_EDITOR=nano
```
4. **VSCode**
```bash
- export AIDER_EDITOR="code --wait"
+ export CECLI_EDITOR="code --wait"
```
5. **Sublime Text**
```bash
- export AIDER_EDITOR="subl --wait"
+ export CECLI_EDITOR="subl --wait"
```
### Windows
1. **Notepad**
```bat
- set AIDER_EDITOR=notepad
+ set CECLI_EDITOR=notepad
```
2. **VSCode**
```bat
- set AIDER_EDITOR="code --wait"
+ set CECLI_EDITOR="code --wait"
```
3. **Notepad++**
```bat
- set AIDER_EDITOR="notepad++ -multiInst -notabbar -nosession -noPlugin -waitForClose"
+ set CECLI_EDITOR="notepad++ -multiInst -notabbar -nosession -noPlugin -waitForClose"
```
## Editor command arguments
@@ -123,5 +123,5 @@ If you encounter issues with your editor not blocking (returning to the prompt i
2. You've included the necessary command-line arguments for blocking mode
3. The editor command is properly quoted if it contains spaces or special characters, e.g.:
```bash
- export AIDER_EDITOR="code --wait"
+ export CECLI_EDITOR="code --wait"
```
diff --git a/cecli/website/docs/config/mcp.md b/cecli/website/docs/config/mcp.md
index 8d67ee28464..bd824b5c453 100644
--- a/cecli/website/docs/config/mcp.md
+++ b/cecli/website/docs/config/mcp.md
@@ -102,13 +102,13 @@ aider --mcp-transport http
You can also configure MCP servers using environment variables in your `.env` file using JSON or YAML format:
```
-AIDER_MCP_SERVERS={"mcpServers":{"git":{"transport": "stdio", "command":"uvx","args":["mcp-server-git"]}}}
+CECLI_MCP_SERVERS={"mcpServers":{"git":{"transport": "stdio", "command":"uvx","args":["mcp-server-git"]}}}
```
Or specify a configuration file:
```
-AIDER_MCP_SERVERS_FILE=/path/to/mcp.json
+CECLI_MCP_SERVERS_FILE=/path/to/mcp.json
```
## Troubleshooting
diff --git a/cecli/website/docs/config/options.md b/cecli/website/docs/config/options.md
index 974b2a5a007..e09260e647d 100644
--- a/cecli/website/docs/config/options.md
+++ b/cecli/website/docs/config/options.md
@@ -108,53 +108,53 @@ Aliases:
### `--model MODEL`
Specify the model to use for the main chat
-Environment variable: `AIDER_MODEL`
+Environment variable: `CECLI_MODEL`
## API Keys and settings:
### `--openai-api-key VALUE`
Specify the OpenAI API key
-Environment variable: `AIDER_OPENAI_API_KEY`
+Environment variable: `CECLI_OPENAI_API_KEY`
### `--anthropic-api-key VALUE`
Specify the Anthropic API key
-Environment variable: `AIDER_ANTHROPIC_API_KEY`
+Environment variable: `CECLI_ANTHROPIC_API_KEY`
### `--openai-api-base VALUE`
Specify the api base url
-Environment variable: `AIDER_OPENAI_API_BASE`
+Environment variable: `CECLI_OPENAI_API_BASE`
### `--openai-api-type VALUE`
(deprecated, use --set-env OPENAI_API_TYPE=)
-Environment variable: `AIDER_OPENAI_API_TYPE`
+Environment variable: `CECLI_OPENAI_API_TYPE`
### `--openai-api-version VALUE`
(deprecated, use --set-env OPENAI_API_VERSION=)
-Environment variable: `AIDER_OPENAI_API_VERSION`
+Environment variable: `CECLI_OPENAI_API_VERSION`
### `--openai-api-deployment-id VALUE`
(deprecated, use --set-env OPENAI_API_DEPLOYMENT_ID=)
-Environment variable: `AIDER_OPENAI_API_DEPLOYMENT_ID`
+Environment variable: `CECLI_OPENAI_API_DEPLOYMENT_ID`
### `--openai-organization-id VALUE`
(deprecated, use --set-env OPENAI_ORGANIZATION=)
-Environment variable: `AIDER_OPENAI_ORGANIZATION_ID`
+Environment variable: `CECLI_OPENAI_ORGANIZATION_ID`
### `--set-env ENV_VAR_NAME=value`
Set an environment variable (to control API settings, can be used multiple times)
Default: []
-Environment variable: `AIDER_SET_ENV`
+Environment variable: `CECLI_SET_ENV`
### `--api-key PROVIDER=KEY`
Set an API key for a provider (eg: --api-key provider= sets PROVIDER_API_KEY=)
Default: []
-Environment variable: `AIDER_API_KEY`
+Environment variable: `CECLI_API_KEY`
## Model settings:
### `--list-models MODEL`
List known models which match the (partial) MODEL name
-Environment variable: `AIDER_LIST_MODELS`
+Environment variable: `CECLI_LIST_MODELS`
Aliases:
- `--list-models MODEL`
- `--models MODEL`
@@ -162,72 +162,72 @@ Aliases:
### `--model-settings-file MODEL_SETTINGS_FILE`
Specify a file with aider model settings for unknown models
Default: .aider.model.settings.yml
-Environment variable: `AIDER_MODEL_SETTINGS_FILE`
+Environment variable: `CECLI_MODEL_SETTINGS_FILE`
### `--model-metadata-file MODEL_METADATA_FILE`
Specify a file with context window and costs for unknown models
Default: .aider.model.metadata.json
-Environment variable: `AIDER_MODEL_METADATA_FILE`
+Environment variable: `CECLI_MODEL_METADATA_FILE`
### `--alias ALIAS:MODEL`
Add a model alias (can be used multiple times)
-Environment variable: `AIDER_ALIAS`
+Environment variable: `CECLI_ALIAS`
### `--reasoning-effort VALUE`
Set the reasoning_effort API parameter (default: not set)
-Environment variable: `AIDER_REASONING_EFFORT`
+Environment variable: `CECLI_REASONING_EFFORT`
### `--thinking-tokens VALUE`
Set the thinking token budget for models that support it. Use 0 to disable. (default: not set)
-Environment variable: `AIDER_THINKING_TOKENS`
+Environment variable: `CECLI_THINKING_TOKENS`
### `--verify-ssl`
Verify the SSL cert when connecting to models (default: True)
Default: True
-Environment variable: `AIDER_VERIFY_SSL`
+Environment variable: `CECLI_VERIFY_SSL`
Aliases:
- `--verify-ssl`
- `--no-verify-ssl`
### `--timeout VALUE`
Timeout in seconds for API calls (default: None)
-Environment variable: `AIDER_TIMEOUT`
+Environment variable: `CECLI_TIMEOUT`
### `--edit-format EDIT_FORMAT`
Specify what edit format the LLM should use (default depends on model)
-Environment variable: `AIDER_EDIT_FORMAT`
+Environment variable: `CECLI_EDIT_FORMAT`
Aliases:
- `--edit-format EDIT_FORMAT`
- `--chat-mode EDIT_FORMAT`
### `--architect`
Use architect edit format for the main chat
-Environment variable: `AIDER_ARCHITECT`
+Environment variable: `CECLI_ARCHITECT`
### `--auto-accept-architect`
Enable/disable automatic acceptance of architect changes (default: True)
Default: True
-Environment variable: `AIDER_AUTO_ACCEPT_ARCHITECT`
+Environment variable: `CECLI_AUTO_ACCEPT_ARCHITECT`
Aliases:
- `--auto-accept-architect`
- `--no-auto-accept-architect`
### `--weak-model WEAK_MODEL`
Specify the model to use for commit messages and chat history summarization (default depends on --model)
-Environment variable: `AIDER_WEAK_MODEL`
+Environment variable: `CECLI_WEAK_MODEL`
### `--editor-model EDITOR_MODEL`
Specify the model to use for editor tasks (default depends on --model)
-Environment variable: `AIDER_EDITOR_MODEL`
+Environment variable: `CECLI_EDITOR_MODEL`
### `--editor-edit-format EDITOR_EDIT_FORMAT`
Specify the edit format for the editor model (default: depends on editor model)
-Environment variable: `AIDER_EDITOR_EDIT_FORMAT`
+Environment variable: `CECLI_EDITOR_EDIT_FORMAT`
### `--show-model-warnings`
Only work with models that have meta-data available (default: True)
Default: True
-Environment variable: `AIDER_SHOW_MODEL_WARNINGS`
+Environment variable: `CECLI_SHOW_MODEL_WARNINGS`
Aliases:
- `--show-model-warnings`
- `--no-show-model-warnings`
@@ -235,40 +235,40 @@ Aliases:
### `--check-model-accepts-settings`
Check if model accepts settings like reasoning_effort/thinking_tokens (default: True)
Default: True
-Environment variable: `AIDER_CHECK_MODEL_ACCEPTS_SETTINGS`
+Environment variable: `CECLI_CHECK_MODEL_ACCEPTS_SETTINGS`
Aliases:
- `--check-model-accepts-settings`
- `--no-check-model-accepts-settings`
### `--max-chat-history-tokens VALUE`
Soft limit on tokens for chat history, after which summarization begins. If unspecified, defaults to the model's max_chat_history_tokens.
-Environment variable: `AIDER_MAX_CHAT_HISTORY_TOKENS`
+Environment variable: `CECLI_MAX_CHAT_HISTORY_TOKENS`
## Context Compaction:
### `--enable-context-compaction`
Enable automatic compaction of chat history to conserve tokens (default: False)
Default: False
-Environment variable: `AIDER_ENABLE_CONTEXT_COMPACTION`
+Environment variable: `CECLI_ENABLE_CONTEXT_COMPACTION`
Aliases:
- `--enable-context-compaction`
- `--no-enable-context-compaction`
### `--context-compaction-max-tokens VALUE`
The maximum number of tokens in the conversation before context compaction is triggered. (default: 80% of model's context window)
-Environment variable: `AIDER_CONTEXT_COMPACTION_MAX_TOKENS`
+Environment variable: `CECLI_CONTEXT_COMPACTION_MAX_TOKENS`
### `--context-compaction-summary-tokens VALUE`
The target maximum number of tokens for the generated summary. (default: 4096)
Default: 4096
-Environment variable: `AIDER_CONTEXT_COMPACTION_SUMMARY_TOKENS`
+Environment variable: `CECLI_CONTEXT_COMPACTION_SUMMARY_TOKENS`
## Cache settings:
### `--cache-prompts`
Enable caching of prompts (default: False)
Default: False
-Environment variable: `AIDER_CACHE_PROMPTS`
+Environment variable: `CECLI_CACHE_PROMPTS`
Aliases:
- `--cache-prompts`
- `--no-cache-prompts`
@@ -276,69 +276,69 @@ Aliases:
### `--cache-keepalive-pings VALUE`
Number of times to ping at 5min intervals to keep prompt cache warm (default: 0)
Default: 0
-Environment variable: `AIDER_CACHE_KEEPALIVE_PINGS`
+Environment variable: `CECLI_CACHE_KEEPALIVE_PINGS`
## Repomap settings:
### `--map-tokens VALUE`
Suggested number of tokens to use for repo map, use 0 to disable
-Environment variable: `AIDER_MAP_TOKENS`
+Environment variable: `CECLI_MAP_TOKENS`
### `--map-refresh VALUE`
Control how often the repo map is refreshed. Options: auto, always, files, manual (default: auto)
Default: auto
-Environment variable: `AIDER_MAP_REFRESH`
+Environment variable: `CECLI_MAP_REFRESH`
### `--map-multiplier-no-files VALUE`
Multiplier for map tokens when no files are specified (default: 2)
Default: 2
-Environment variable: `AIDER_MAP_MULTIPLIER_NO_FILES`
+Environment variable: `CECLI_MAP_MULTIPLIER_NO_FILES`
### `--map-max-line-length VALUE`
Maximum line length for the repo map code. Prevents sending crazy long lines of minified JS files etc. (default: 100)
Default: 100
-Environment variable: `AIDER_MAP_MAX_LINE_LENGTH`
+Environment variable: `CECLI_MAP_MAX_LINE_LENGTH`
## History Files:
### `--input-history-file INPUT_HISTORY_FILE`
Specify the chat input history file (default: .aider.input.history)
Default: .aider.input.history
-Environment variable: `AIDER_INPUT_HISTORY_FILE`
+Environment variable: `CECLI_INPUT_HISTORY_FILE`
### `--chat-history-file CHAT_HISTORY_FILE`
Specify the chat history file (default: .aider.chat.history.md)
Default: .aider.chat.history.md
-Environment variable: `AIDER_CHAT_HISTORY_FILE`
+Environment variable: `CECLI_CHAT_HISTORY_FILE`
### `--restore-chat-history`
Restore the previous chat history messages (default: False)
Default: False
-Environment variable: `AIDER_RESTORE_CHAT_HISTORY`
+Environment variable: `CECLI_RESTORE_CHAT_HISTORY`
Aliases:
- `--restore-chat-history`
- `--no-restore-chat-history`
### `--llm-history-file LLM_HISTORY_FILE`
Log the conversation with the LLM to this file (for example, .aider.llm.history)
-Environment variable: `AIDER_LLM_HISTORY_FILE`
+Environment variable: `CECLI_LLM_HISTORY_FILE`
## Output settings:
### `--dark-mode`
Use colors suitable for a dark terminal background (default: False)
Default: False
-Environment variable: `AIDER_DARK_MODE`
+Environment variable: `CECLI_DARK_MODE`
### `--light-mode`
Use colors suitable for a light terminal background (default: False)
Default: False
-Environment variable: `AIDER_LIGHT_MODE`
+Environment variable: `CECLI_LIGHT_MODE`
### `--pretty`
Enable/disable pretty, colorized output (default: True)
Default: True
-Environment variable: `AIDER_PRETTY`
+Environment variable: `CECLI_PRETTY`
Aliases:
- `--pretty`
- `--no-pretty`
@@ -346,7 +346,7 @@ Aliases:
### `--stream`
Enable/disable streaming responses (default: True)
Default: True
-Environment variable: `AIDER_STREAM`
+Environment variable: `CECLI_STREAM`
Aliases:
- `--stream`
- `--no-stream`
@@ -354,59 +354,59 @@ Aliases:
### `--user-input-color VALUE`
Set the color for user input (default: #00cc00)
Default: #00cc00
-Environment variable: `AIDER_USER_INPUT_COLOR`
+Environment variable: `CECLI_USER_INPUT_COLOR`
### `--tool-output-color VALUE`
Set the color for tool output (default: None)
-Environment variable: `AIDER_TOOL_OUTPUT_COLOR`
+Environment variable: `CECLI_TOOL_OUTPUT_COLOR`
### `--tool-error-color VALUE`
Set the color for tool error messages (default: #FF2222)
Default: #FF2222
-Environment variable: `AIDER_TOOL_ERROR_COLOR`
+Environment variable: `CECLI_TOOL_ERROR_COLOR`
### `--tool-warning-color VALUE`
Set the color for tool warning messages (default: #FFA500)
Default: #FFA500
-Environment variable: `AIDER_TOOL_WARNING_COLOR`
+Environment variable: `CECLI_TOOL_WARNING_COLOR`
### `--assistant-output-color VALUE`
Set the color for assistant output (default: #0088ff)
Default: #0088ff
-Environment variable: `AIDER_ASSISTANT_OUTPUT_COLOR`
+Environment variable: `CECLI_ASSISTANT_OUTPUT_COLOR`
### `--completion-menu-color COLOR`
Set the color for the completion menu (default: terminal's default text color)
-Environment variable: `AIDER_COMPLETION_MENU_COLOR`
+Environment variable: `CECLI_COMPLETION_MENU_COLOR`
### `--completion-menu-bg-color COLOR`
Set the background color for the completion menu (default: terminal's default background color)
-Environment variable: `AIDER_COMPLETION_MENU_BG_COLOR`
+Environment variable: `CECLI_COMPLETION_MENU_BG_COLOR`
### `--completion-menu-current-color COLOR`
Set the color for the current item in the completion menu (default: terminal's default background color)
-Environment variable: `AIDER_COMPLETION_MENU_CURRENT_COLOR`
+Environment variable: `CECLI_COMPLETION_MENU_CURRENT_COLOR`
### `--completion-menu-current-bg-color COLOR`
Set the background color for the current item in the completion menu (default: terminal's default text color)
-Environment variable: `AIDER_COMPLETION_MENU_CURRENT_BG_COLOR`
+Environment variable: `CECLI_COMPLETION_MENU_CURRENT_BG_COLOR`
### `--code-theme VALUE`
Set the markdown code theme (default: default, other options include monokai, solarized-dark, solarized-light, or a Pygments builtin style, see https://pygments.org/styles for available themes)
Default: default
-Environment variable: `AIDER_CODE_THEME`
+Environment variable: `CECLI_CODE_THEME`
### `--show-diffs`
Show diffs when committing changes (default: False)
Default: False
-Environment variable: `AIDER_SHOW_DIFFS`
+Environment variable: `CECLI_SHOW_DIFFS`
## Git settings:
### `--git`
Enable/disable looking for a git repo (default: True)
Default: True
-Environment variable: `AIDER_GIT`
+Environment variable: `CECLI_GIT`
Aliases:
- `--git`
- `--no-git`
@@ -414,7 +414,7 @@ Aliases:
### `--gitignore`
Enable/disable adding .aider* to .gitignore (default: True)
Default: True
-Environment variable: `AIDER_GITIGNORE`
+Environment variable: `CECLI_GITIGNORE`
Aliases:
- `--gitignore`
- `--no-gitignore`
@@ -422,7 +422,7 @@ Aliases:
### `--add-gitignore-files`
Enable/disable the addition of files listed in .gitignore to Aider's editing scope.
Default: False
-Environment variable: `AIDER_ADD_GITIGNORE_FILES`
+Environment variable: `CECLI_ADD_GITIGNORE_FILES`
Aliases:
- `--add-gitignore-files`
- `--no-add-gitignore-files`
@@ -430,17 +430,17 @@ Aliases:
### `--aiderignore AIDERIGNORE`
Specify the aider ignore file (default: .aiderignore in git root)
Default: .aiderignore
-Environment variable: `AIDER_AIDERIGNORE`
+Environment variable: `CECLI_AIDERIGNORE`
### `--subtree-only`
Only consider files in the current subtree of the git repository
Default: False
-Environment variable: `AIDER_SUBTREE_ONLY`
+Environment variable: `CECLI_SUBTREE_ONLY`
### `--auto-commits`
Enable/disable auto commit of LLM changes (default: True)
Default: True
-Environment variable: `AIDER_AUTO_COMMITS`
+Environment variable: `CECLI_AUTO_COMMITS`
Aliases:
- `--auto-commits`
- `--no-auto-commits`
@@ -448,21 +448,21 @@ Aliases:
### `--dirty-commits`
Enable/disable commits when repo is found dirty (default: True)
Default: True
-Environment variable: `AIDER_DIRTY_COMMITS`
+Environment variable: `CECLI_DIRTY_COMMITS`
Aliases:
- `--dirty-commits`
- `--no-dirty-commits`
### `--attribute-author`
Attribute aider code changes in the git author name (default: True). If explicitly set to True, overrides --attribute-co-authored-by precedence.
-Environment variable: `AIDER_ATTRIBUTE_AUTHOR`
+Environment variable: `CECLI_ATTRIBUTE_AUTHOR`
Aliases:
- `--attribute-author`
- `--no-attribute-author`
### `--attribute-committer`
Attribute aider commits in the git committer name (default: True). If explicitly set to True, overrides --attribute-co-authored-by precedence for aider edits.
-Environment variable: `AIDER_ATTRIBUTE_COMMITTER`
+Environment variable: `CECLI_ATTRIBUTE_COMMITTER`
Aliases:
- `--attribute-committer`
- `--no-attribute-committer`
@@ -470,7 +470,7 @@ Aliases:
### `--attribute-commit-message-author`
Prefix commit messages with 'aider: ' if aider authored the changes (default: False)
Default: False
-Environment variable: `AIDER_ATTRIBUTE_COMMIT_MESSAGE_AUTHOR`
+Environment variable: `CECLI_ATTRIBUTE_COMMIT_MESSAGE_AUTHOR`
Aliases:
- `--attribute-commit-message-author`
- `--no-attribute-commit-message-author`
@@ -478,7 +478,7 @@ Aliases:
### `--attribute-commit-message-committer`
Prefix all commit messages with 'aider: ' (default: False)
Default: False
-Environment variable: `AIDER_ATTRIBUTE_COMMIT_MESSAGE_COMMITTER`
+Environment variable: `CECLI_ATTRIBUTE_COMMIT_MESSAGE_COMMITTER`
Aliases:
- `--attribute-commit-message-committer`
- `--no-attribute-commit-message-committer`
@@ -486,7 +486,7 @@ Aliases:
### `--attribute-co-authored-by`
Attribute aider edits using the Co-authored-by trailer in the commit message (default: True). If True, this takes precedence over default --attribute-author and --attribute-committer behavior unless they are explicitly set to True.
Default: True
-Environment variable: `AIDER_ATTRIBUTE_CO_AUTHORED_BY`
+Environment variable: `CECLI_ATTRIBUTE_CO_AUTHORED_BY`
Aliases:
- `--attribute-co-authored-by`
- `--no-attribute-co-authored-by`
@@ -494,7 +494,7 @@ Aliases:
### `--git-commit-verify`
Enable/disable git pre-commit hooks with --no-verify (default: False)
Default: False
-Environment variable: `AIDER_GIT_COMMIT_VERIFY`
+Environment variable: `CECLI_GIT_COMMIT_VERIFY`
Aliases:
- `--git-commit-verify`
- `--no-git-commit-verify`
@@ -502,16 +502,16 @@ Aliases:
### `--commit`
Commit all pending changes with a suitable commit message, then exit
Default: False
-Environment variable: `AIDER_COMMIT`
+Environment variable: `CECLI_COMMIT`
### `--commit-prompt PROMPT`
Specify a custom prompt for generating commit messages
-Environment variable: `AIDER_COMMIT_PROMPT`
+Environment variable: `CECLI_COMMIT_PROMPT`
### `--dry-run`
Perform a dry run without modifying files (default: False)
Default: False
-Environment variable: `AIDER_DRY_RUN`
+Environment variable: `CECLI_DRY_RUN`
Aliases:
- `--dry-run`
- `--no-dry-run`
@@ -519,12 +519,12 @@ Aliases:
### `--skip-sanity-check-repo`
Skip the sanity check for the git repository (default: False)
Default: False
-Environment variable: `AIDER_SKIP_SANITY_CHECK_REPO`
+Environment variable: `CECLI_SKIP_SANITY_CHECK_REPO`
### `--watch-files`
Enable/disable watching files for ai coding comments (default: False)
Default: False
-Environment variable: `AIDER_WATCH_FILES`
+Environment variable: `CECLI_WATCH_FILES`
Aliases:
- `--watch-files`
- `--no-watch-files`
@@ -534,17 +534,17 @@ Aliases:
### `--lint`
Lint and fix provided files, or dirty files if none provided
Default: False
-Environment variable: `AIDER_LINT`
+Environment variable: `CECLI_LINT`
### `--lint-cmd`
Specify lint commands to run for different languages, eg: "python: flake8 --select=..." (can be used multiple times)
Default: []
-Environment variable: `AIDER_LINT_CMD`
+Environment variable: `CECLI_LINT_CMD`
### `--auto-lint`
Enable/disable automatic linting after changes (default: True)
Default: True
-Environment variable: `AIDER_AUTO_LINT`
+Environment variable: `CECLI_AUTO_LINT`
Aliases:
- `--auto-lint`
- `--no-auto-lint`
@@ -552,12 +552,12 @@ Aliases:
### `--test-cmd VALUE`
Specify command to run tests
Default: []
-Environment variable: `AIDER_TEST_CMD`
+Environment variable: `CECLI_TEST_CMD`
### `--auto-test`
Enable/disable automatic testing after changes (default: False)
Default: False
-Environment variable: `AIDER_AUTO_TEST`
+Environment variable: `CECLI_AUTO_TEST`
Aliases:
- `--auto-test`
- `--no-auto-test`
@@ -565,52 +565,52 @@ Aliases:
### `--test`
Run tests, fix problems found and then exit
Default: False
-Environment variable: `AIDER_TEST`
+Environment variable: `CECLI_TEST`
## Analytics:
### `--analytics`
Enable/disable analytics for current session (default: random)
-Environment variable: `AIDER_ANALYTICS`
+Environment variable: `CECLI_ANALYTICS`
Aliases:
- `--analytics`
- `--no-analytics`
### `--analytics-log ANALYTICS_LOG_FILE`
Specify a file to log analytics events
-Environment variable: `AIDER_ANALYTICS_LOG`
+Environment variable: `CECLI_ANALYTICS_LOG`
### `--analytics-disable`
Permanently disable analytics
Default: False
-Environment variable: `AIDER_ANALYTICS_DISABLE`
+Environment variable: `CECLI_ANALYTICS_DISABLE`
### `--analytics-posthog-host ANALYTICS_POSTHOG_HOST`
Send analytics to custom PostHog instance
-Environment variable: `AIDER_ANALYTICS_POSTHOG_HOST`
+Environment variable: `CECLI_ANALYTICS_POSTHOG_HOST`
### `--analytics-posthog-project-api-key ANALYTICS_POSTHOG_PROJECT_API_KEY`
Send analytics to custom PostHog project
-Environment variable: `AIDER_ANALYTICS_POSTHOG_PROJECT_API_KEY`
+Environment variable: `CECLI_ANALYTICS_POSTHOG_PROJECT_API_KEY`
## Upgrading:
### `--just-check-update`
Check for updates and return status in the exit code
Default: False
-Environment variable: `AIDER_JUST_CHECK_UPDATE`
+Environment variable: `CECLI_JUST_CHECK_UPDATE`
### `--check-update`
Check for new aider versions on launch
Default: True
-Environment variable: `AIDER_CHECK_UPDATE`
+Environment variable: `CECLI_CHECK_UPDATE`
Aliases:
- `--check-update`
- `--no-check-update`
### `--show-release-notes`
Show release notes on first run of new version (default: None, ask user)
-Environment variable: `AIDER_SHOW_RELEASE_NOTES`
+Environment variable: `CECLI_SHOW_RELEASE_NOTES`
Aliases:
- `--show-release-notes`
- `--no-show-release-notes`
@@ -618,12 +618,12 @@ Aliases:
### `--install-main-branch`
Install the latest version from the main branch
Default: False
-Environment variable: `AIDER_INSTALL_MAIN_BRANCH`
+Environment variable: `CECLI_INSTALL_MAIN_BRANCH`
### `--upgrade`
Upgrade aider to the latest version from PyPI
Default: False
-Environment variable: `AIDER_UPGRADE`
+Environment variable: `CECLI_UPGRADE`
Aliases:
- `--upgrade`
- `--update`
@@ -635,7 +635,7 @@ Show the version number and exit
### `--message COMMAND`
Specify a single message to send the LLM, process reply then exit (disables chat mode)
-Environment variable: `AIDER_MESSAGE`
+Environment variable: `CECLI_MESSAGE`
Aliases:
- `--message COMMAND`
- `--msg COMMAND`
@@ -643,7 +643,7 @@ Aliases:
### `--message-file MESSAGE_FILE`
Specify a file containing the message to send the LLM, process reply, then exit (disables chat mode)
-Environment variable: `AIDER_MESSAGE_FILE`
+Environment variable: `CECLI_MESSAGE_FILE`
Aliases:
- `--message-file MESSAGE_FILE`
- `-f MESSAGE_FILE`
@@ -651,7 +651,7 @@ Aliases:
### `--gui`
Run aider in your browser (default: False)
Default: False
-Environment variable: `AIDER_GUI`
+Environment variable: `CECLI_GUI`
Aliases:
- `--gui`
- `--no-gui`
@@ -661,104 +661,104 @@ Aliases:
### `--copy-paste`
Enable automatic copy/paste of chat between aider and web UI (default: False)
Default: False
-Environment variable: `AIDER_COPY_PASTE`
+Environment variable: `CECLI_COPY_PASTE`
Aliases:
- `--copy-paste`
- `--no-copy-paste`
### `--apply FILE`
Apply the changes from the given file instead of running the chat (debug)
-Environment variable: `AIDER_APPLY`
+Environment variable: `CECLI_APPLY`
### `--apply-clipboard-edits`
Apply clipboard contents as edits using the main model's editor format
Default: False
-Environment variable: `AIDER_APPLY_CLIPBOARD_EDITS`
+Environment variable: `CECLI_APPLY_CLIPBOARD_EDITS`
### `--exit`
Do all startup activities then exit before accepting user input (debug)
Default: False
-Environment variable: `AIDER_EXIT`
+Environment variable: `CECLI_EXIT`
### `--show-repo-map`
Print the repo map and exit (debug)
Default: False
-Environment variable: `AIDER_SHOW_REPO_MAP`
+Environment variable: `CECLI_SHOW_REPO_MAP`
### `--show-prompts`
Print the system prompts and exit (debug)
Default: False
-Environment variable: `AIDER_SHOW_PROMPTS`
+Environment variable: `CECLI_SHOW_PROMPTS`
## Voice settings:
### `--voice-format VOICE_FORMAT`
Audio format for voice recording (default: wav). webm and mp3 require ffmpeg
Default: wav
-Environment variable: `AIDER_VOICE_FORMAT`
+Environment variable: `CECLI_VOICE_FORMAT`
### `--voice-language VOICE_LANGUAGE`
Specify the language for voice using ISO 639-1 code (default: auto)
Default: en
-Environment variable: `AIDER_VOICE_LANGUAGE`
+Environment variable: `CECLI_VOICE_LANGUAGE`
### `--voice-input-device VOICE_INPUT_DEVICE`
Specify the input device name for voice recording
-Environment variable: `AIDER_VOICE_INPUT_DEVICE`
+Environment variable: `CECLI_VOICE_INPUT_DEVICE`
## Other settings:
### `--disable-playwright`
Never prompt for or attempt to install Playwright for web scraping (default: False).
Default: False
-Environment variable: `AIDER_DISABLE_PLAYWRIGHT`
+Environment variable: `CECLI_DISABLE_PLAYWRIGHT`
### `--file FILE`
specify a file to edit (can be used multiple times)
-Environment variable: `AIDER_FILE`
+Environment variable: `CECLI_FILE`
### `--read FILE`
specify a read-only file (can be used multiple times)
-Environment variable: `AIDER_READ`
+Environment variable: `CECLI_READ`
### `--vim`
Use VI editing mode in the terminal (default: False)
Default: False
-Environment variable: `AIDER_VIM`
+Environment variable: `CECLI_VIM`
### `--chat-language CHAT_LANGUAGE`
Specify the language to use in the chat (default: None, uses system settings)
-Environment variable: `AIDER_CHAT_LANGUAGE`
+Environment variable: `CECLI_CHAT_LANGUAGE`
### `--commit-language COMMIT_LANGUAGE`
Specify the language to use in the commit message (default: None, user language)
-Environment variable: `AIDER_COMMIT_LANGUAGE`
+Environment variable: `CECLI_COMMIT_LANGUAGE`
### `--yes-always`
Always say yes to every confirmation
-Environment variable: `AIDER_YES_ALWAYS`
+Environment variable: `CECLI_YES_ALWAYS`
### `--verbose`
Enable verbose output
Default: False
-Environment variable: `AIDER_VERBOSE`
+Environment variable: `CECLI_VERBOSE`
Aliases:
- `-v`
- `--verbose`
### `--load LOAD_FILE`
Load and execute /commands from a file on launch
-Environment variable: `AIDER_LOAD`
+Environment variable: `CECLI_LOAD`
### `--encoding VALUE`
Specify the encoding for input and output (default: utf-8)
Default: utf-8
-Environment variable: `AIDER_ENCODING`
+Environment variable: `CECLI_ENCODING`
### `--line-endings VALUE`
Line endings to use when writing files (default: platform)
Default: platform
-Environment variable: `AIDER_LINE_ENDINGS`
+Environment variable: `CECLI_LINE_ENDINGS`
### `--config CONFIG_FILE`
Specify the config file (default: search for .aider.conf.yml in git root, cwd or home directory)
@@ -769,12 +769,12 @@ Aliases:
### `--env-file ENV_FILE`
Specify the .env file to load (default: .env in git root)
Default: .env
-Environment variable: `AIDER_ENV_FILE`
+Environment variable: `CECLI_ENV_FILE`
### `--suggest-shell-commands`
Enable/disable suggesting shell commands (default: True)
Default: True
-Environment variable: `AIDER_SUGGEST_SHELL_COMMANDS`
+Environment variable: `CECLI_SUGGEST_SHELL_COMMANDS`
Aliases:
- `--suggest-shell-commands`
- `--no-suggest-shell-commands`
@@ -782,7 +782,7 @@ Aliases:
### `--fancy-input`
Enable/disable fancy input with history and completion (default: True)
Default: True
-Environment variable: `AIDER_FANCY_INPUT`
+Environment variable: `CECLI_FANCY_INPUT`
Aliases:
- `--fancy-input`
- `--no-fancy-input`
@@ -790,7 +790,7 @@ Aliases:
### `--multiline`
Enable/disable multi-line input mode with Meta-Enter to submit (default: False)
Default: False
-Environment variable: `AIDER_MULTILINE`
+Environment variable: `CECLI_MULTILINE`
Aliases:
- `--multiline`
- `--no-multiline`
@@ -798,52 +798,52 @@ Aliases:
### `--notifications`
Enable/disable terminal bell notifications when LLM responses are ready (default: False)
Default: False
-Environment variable: `AIDER_NOTIFICATIONS`
+Environment variable: `CECLI_NOTIFICATIONS`
Aliases:
- `--notifications`
- `--no-notifications`
### `--notifications-command COMMAND`
Specify a command to run for notifications instead of the terminal bell. If not specified, a default command for your OS may be used.
-Environment variable: `AIDER_NOTIFICATIONS_COMMAND`
+Environment variable: `CECLI_NOTIFICATIONS_COMMAND`
### `--detect-urls`
Enable/disable detection and offering to add URLs to chat (default: True)
Default: True
-Environment variable: `AIDER_DETECT_URLS`
+Environment variable: `CECLI_DETECT_URLS`
Aliases:
- `--detect-urls`
- `--no-detect-urls`
### `--editor VALUE`
Specify which editor to use for the /editor command
-Environment variable: `AIDER_EDITOR`
+Environment variable: `CECLI_EDITOR`
### `--shell-completions SHELL`
Print shell completion script for the specified SHELL and exit. Supported shells: bash, tcsh, zsh. Example: aider --shell-completions bash
-Environment variable: `AIDER_SHELL_COMPLETIONS`
+Environment variable: `CECLI_SHELL_COMPLETIONS`
## Deprecated model settings:
### `--opus`
Use claude-3-opus-20240229 model for the main chat (deprecated, use --model)
Default: False
-Environment variable: `AIDER_OPUS`
+Environment variable: `CECLI_OPUS`
### `--sonnet`
Use anthropic/claude-3-7-sonnet-20250219 model for the main chat (deprecated, use --model)
Default: False
-Environment variable: `AIDER_SONNET`
+Environment variable: `CECLI_SONNET`
### `--haiku`
Use claude-3-5-haiku-20241022 model for the main chat (deprecated, use --model)
Default: False
-Environment variable: `AIDER_HAIKU`
+Environment variable: `CECLI_HAIKU`
### `--4`
Use gpt-4-0613 model for the main chat (deprecated, use --model)
Default: False
-Environment variable: `AIDER_4`
+Environment variable: `CECLI_4`
Aliases:
- `--4`
- `-4`
@@ -851,22 +851,22 @@ Aliases:
### `--4o`
Use gpt-4o model for the main chat (deprecated, use --model)
Default: False
-Environment variable: `AIDER_4O`
+Environment variable: `CECLI_4O`
### `--mini`
Use gpt-4o-mini model for the main chat (deprecated, use --model)
Default: False
-Environment variable: `AIDER_MINI`
+Environment variable: `CECLI_MINI`
### `--4-turbo`
Use gpt-4-1106-preview model for the main chat (deprecated, use --model)
Default: False
-Environment variable: `AIDER_4_TURBO`
+Environment variable: `CECLI_4_TURBO`
### `--35turbo`
Use gpt-3.5-turbo model for the main chat (deprecated, use --model)
Default: False
-Environment variable: `AIDER_35TURBO`
+Environment variable: `CECLI_35TURBO`
Aliases:
- `--35turbo`
- `--35-turbo`
@@ -876,15 +876,15 @@ Aliases:
### `--deepseek`
Use deepseek/deepseek-chat model for the main chat (deprecated, use --model)
Default: False
-Environment variable: `AIDER_DEEPSEEK`
+Environment variable: `CECLI_DEEPSEEK`
### `--o1-mini`
Use o1-mini model for the main chat (deprecated, use --model)
Default: False
-Environment variable: `AIDER_O1_MINI`
+Environment variable: `CECLI_O1_MINI`
### `--o1-preview`
Use o1-preview model for the main chat (deprecated, use --model)
Default: False
-Environment variable: `AIDER_O1_PREVIEW`
+Environment variable: `CECLI_O1_PREVIEW`
diff --git a/cecli/website/docs/scripting.md b/cecli/website/docs/scripting.md
index 71bb3282a59..30f2035e926 100644
--- a/cecli/website/docs/scripting.md
+++ b/cecli/website/docs/scripting.md
@@ -33,25 +33,25 @@ but these are useful for scripting:
```
--stream, --no-stream
Enable/disable streaming responses (default: True) [env var:
- AIDER_STREAM]
+ CECLI_STREAM]
--message COMMAND, --msg COMMAND, -m COMMAND
Specify a single message to send GPT, process reply then exit
- (disables chat mode) [env var: AIDER_MESSAGE]
+ (disables chat mode) [env var: CECLI_MESSAGE]
--message-file MESSAGE_FILE, -f MESSAGE_FILE
Specify a file containing the message to send GPT, process reply,
- then exit (disables chat mode) [env var: AIDER_MESSAGE_FILE]
---yes Always say yes to every confirmation [env var: AIDER_YES]
+ then exit (disables chat mode) [env var: CECLI_MESSAGE_FILE]
+--yes Always say yes to every confirmation [env var: CECLI_YES]
--auto-commits, --no-auto-commits
Enable/disable auto commit of GPT changes (default: True) [env var:
- AIDER_AUTO_COMMITS]
+ CECLI_AUTO_COMMITS]
--dirty-commits, --no-dirty-commits
Enable/disable commits when repo is found dirty (default: True) [env
- var: AIDER_DIRTY_COMMITS]
+ var: CECLI_DIRTY_COMMITS]
--dry-run, --no-dry-run
Perform a dry run without modifying files (default: False) [env var:
- AIDER_DRY_RUN]
+ CECLI_DRY_RUN]
--commit Commit all pending changes with a suitable commit message, then exit
- [env var: AIDER_COMMIT]
+ [env var: CECLI_COMMIT]
```
diff --git a/cecli/website/docs/usage/notifications.md b/cecli/website/docs/usage/notifications.md
index ee7febb72e7..8f11827b6fd 100644
--- a/cecli/website/docs/usage/notifications.md
+++ b/cecli/website/docs/usage/notifications.md
@@ -82,6 +82,6 @@ notifications_command: "your-custom-command"
Or in your `.env` file:
```
-AIDER_NOTIFICATIONS=true
-AIDER_NOTIFICATIONS_COMMAND=your-custom-command
+CECLI_NOTIFICATIONS=true
+CECLI_NOTIFICATIONS_COMMAND=your-custom-command
```
diff --git a/cecli/website/examples/update-docs.md b/cecli/website/examples/update-docs.md
index d0ff405f03a..b580ed528f8 100644
--- a/cecli/website/examples/update-docs.md
+++ b/cecli/website/examples/update-docs.md
@@ -16,21 +16,21 @@ In this chat transcript, the user asks to automatically update the Usage docs ba
```markdown
README.md
<<<<<<< ORIGINAL
-- `--history-file HISTORY_FILE`: Specify the chat input history file (default: .aider.history). Override the default with the environment variable `AIDER_HISTORY_FILE`.
-- `--model MODEL`: Specify the model to use for the main chat (default: gpt-4). Override the default with the environment variable `AIDER_MODEL`.
+- `--history-file HISTORY_FILE`: Specify the chat input history file (default: .aider.history). Override the default with the environment variable `CECLI_HISTORY_FILE`.
+- `--model MODEL`: Specify the model to use for the main chat (default: gpt-4). Override the default with the environment variable `CECLI_MODEL`.
- `-3`: Use gpt-3.5-turbo model for the main chat (basically won't work). No environment variable override.
-- `--no-pretty`: Disable pretty, colorized output. Override the default with the environment variable `AIDER_PRETTY` (default: 1 for enabled, 0 for disabled).
-- `--show-diffs`: Show diffs when committing changes (default: False). Override the default with the environment variable `AIDER_SHOW_DIFFS` (default: 0 for False, 1 for True).
-- `--no-auto-commits`: Disable auto commit of changes. Override the default with the environment variable `AIDER_AUTO_COMMITS` (default: 1 for enabled, 0 for disabled).
+- `--no-pretty`: Disable pretty, colorized output. Override the default with the environment variable `CECLI_PRETTY` (default: 1 for enabled, 0 for disabled).
+- `--show-diffs`: Show diffs when committing changes (default: False). Override the default with the environment variable `CECLI_SHOW_DIFFS` (default: 0 for False, 1 for True).
+- `--no-auto-commits`: Disable auto commit of changes. Override the default with the environment variable `CECLI_AUTO_COMMITS` (default: 1 for enabled, 0 for disabled).
=======
-- `--input-history-file INPUT_HISTORY_FILE`: Specify the chat input history file (default: .aider.input.history). Override the default with the environment variable `AIDER_INPUT_HISTORY_FILE`.
-- `--chat-history-file CHAT_HISTORY_FILE`: Specify the chat history file (default: .aider.chat.history.md). Override the default with the environment variable `AIDER_CHAT_HISTORY_FILE`.
-- `--model MODEL`: Specify the model to use for the main chat (default: gpt-4). Override the default with the environment variable `AIDER_MODEL`.
+- `--input-history-file INPUT_HISTORY_FILE`: Specify the chat input history file (default: .aider.input.history). Override the default with the environment variable `CECLI_INPUT_HISTORY_FILE`.
+- `--chat-history-file CHAT_HISTORY_FILE`: Specify the chat history file (default: .aider.chat.history.md). Override the default with the environment variable `CECLI_CHAT_HISTORY_FILE`.
+- `--model MODEL`: Specify the model to use for the main chat (default: gpt-4). Override the default with the environment variable `CECLI_MODEL`.
- `-3`: Use gpt-3.5-turbo model for the main chat (basically won't work). No environment variable override.
-- `--no-pretty`: Disable pretty, colorized output. Override the default with the environment variable `AIDER_PRETTY` (default: 1 for enabled, 0 for disabled).
+- `--no-pretty`: Disable pretty, colorized output. Override the default with the environment variable `CECLI_PRETTY` (default: 1 for enabled, 0 for disabled).
- `--apply FILE`: Apply the changes from the given file instead of running the chat (debug).
-- `--no-auto-commits`: Disable auto commit of changes. Override the default with the environment variable `AIDER_AUTO_COMMITS` (default: 1 for enabled, 0 for disabled).
-- `--show-diffs`: Show diffs when committing changes (default: False). Override the default with the environment variable `AIDER_SHOW_DIFFS` (default: 0 for False, 1 for True).
+- `--no-auto-commits`: Disable auto commit of changes. Override the default with the environment variable `CECLI_AUTO_COMMITS` (default: 1 for enabled, 0 for disabled).
+- `--show-diffs`: Show diffs when committing changes (default: False). Override the default with the environment variable `CECLI_SHOW_DIFFS` (default: 0 for False, 1 for True).
- `--yes`: Always say yes to every confirmation (default: False).
>>>>>>> UPDATED
```
diff --git a/requirements.txt b/requirements.txt
index 187e4ad233a..70573b62c5f 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -254,7 +254,7 @@ mccabe==0.7.0
# via
# -c requirements/common-constraints.txt
# flake8
-mcp==1.22.0
+mcp==1.25.0
# via
# -c requirements/common-constraints.txt
# -r requirements/requirements.in
diff --git a/requirements/common-constraints.txt b/requirements/common-constraints.txt
index f1e5ab20765..8ec0b86ea0b 100644
--- a/requirements/common-constraints.txt
+++ b/requirements/common-constraints.txt
@@ -259,7 +259,7 @@ matplotlib==3.10.7
# via -r requirements/requirements-dev.in
mccabe==0.7.0
# via flake8
-mcp==1.22.0
+mcp==1.25.0
# via -r requirements/requirements.in
mdit-py-plugins==0.5.0
# via textual
diff --git a/requirements/requirements.in b/requirements/requirements.in
index 306eda36193..1c9e9384e42 100644
--- a/requirements/requirements.in
+++ b/requirements/requirements.in
@@ -28,7 +28,7 @@ pillow>=11.3.0
shtab>=1.7.2
oslex>=0.1.3
google-generativeai>=0.8.5
-mcp>=1.12.3
+mcp>=1.24.0
textual>=6.0.0
truststore
diff --git a/scripts/30k-image.py b/scripts/30k-image.py
index c5e9d093d6b..6b7938c6cd2 100644
--- a/scripts/30k-image.py
+++ b/scripts/30k-image.py
@@ -12,8 +12,8 @@
from pathlib import Path
# Default colors for the celebration image
-CECLIGREEN = "#14b014"
-CECLIBLUE = "#4C6EF5"
+CECLI_GREEN = "#14b014"
+CECLI_BLUE = "#4C6EF5"
DARK_COLOR = "#212529"
LIGHT_COLOR = "#F8F9FA"
GOLD_COLOR = "#f1c40f"
@@ -46,7 +46,7 @@ def embed_font():
def generate_confetti(count=150, width=DEFAULT_WIDTH, height=DEFAULT_HEIGHT):
"""Generate SVG confetti elements for the celebration."""
confetti = []
- colors = [CECLIGREEN, CECLIBLUE, GOLD_COLOR, "#e74c3c", "#9b59b6", "#3498db", "#2ecc71"]
+ colors = [CECLI_GREEN, CECLI_BLUE, GOLD_COLOR, "#e74c3c", "#9b59b6", "#3498db", "#2ecc71"]
# Define text safe zones
# Main content safe zone (centered area)
@@ -169,7 +169,7 @@ def generate_celebration_svg(output_path=None, width=DEFAULT_WIDTH, height=DEFAU