Main entry point for CCProxy API Server.
Adds per-invocation debug logging of CLI argv and relevant environment
variables (masked) so every command emits its context consistently.
version_callback
Print version and exit.
Source code in ccproxy/cli/main.py
| def version_callback(value: bool) -> None:
"""Print version and exit."""
if value:
toolkit = get_rich_toolkit()
toolkit.print(f"ccproxy {__version__}", tag="version")
raise typer.Exit()
|
register_plugin_cli_extensions
register_plugin_cli_extensions(app)
Register plugin CLI commands and arguments during app creation.
Source code in ccproxy/cli/main.py
| def register_plugin_cli_extensions(app: typer.Typer) -> None:
"""Register plugin CLI commands and arguments during app creation."""
try:
# Load settings to apply plugin filtering
try:
from ccproxy.config.settings import Settings
settings = Settings.from_config()
except Exception as e:
# Graceful degradation - use no filtering if settings fail to load
logger.debug("settings_load_failed_for_cli_discovery", error=str(e))
settings = None
plugin_manifests = discover_plugin_cli_extensions(settings)
logger.debug(
"plugin_cli_discovery_complete",
plugin_count=len(plugin_manifests),
plugins=[name for name, _ in plugin_manifests],
)
# Register new commands first
for plugin_name, manifest in plugin_manifests:
for cmd_spec in manifest.cli_commands:
_register_plugin_command(app, plugin_name, cmd_spec)
# Batch extend existing commands with new arguments
arg_batches: dict[str, list[tuple[str, CliArgumentSpec]]] = {}
for plugin_name, manifest in plugin_manifests:
for arg_spec in manifest.cli_arguments:
arg_batches.setdefault(arg_spec.target_command, []).append(
(plugin_name, arg_spec)
)
for target, pairs in arg_batches.items():
_extend_command_with_arguments(app, target, pairs)
except Exception as e:
# Graceful degradation - CLI still works without plugin extensions
logger.debug("plugin_cli_extension_registration_failed", error=str(e))
|
ensure_plugin_cli_extensions_registered
ensure_plugin_cli_extensions_registered(app)
Register plugin CLI extensions once, after logging is configured.
Source code in ccproxy/cli/main.py
| def ensure_plugin_cli_extensions_registered(app: typer.Typer) -> None:
"""Register plugin CLI extensions once, after logging is configured."""
global _plugins_registered
if _plugins_registered:
return
register_plugin_cli_extensions(app)
_plugins_registered = True
|
app_main
app_main(ctx, version=False, config=None)
CCProxy API Server - Anthropic and OpenAI compatible interface for Claude.
Source code in ccproxy/cli/main.py
| @app.callback()
def app_main(
ctx: typer.Context,
version: Annotated[
bool,
typer.Option(
"--version",
"-V",
callback=version_callback,
is_eager=True,
help="Show version and exit.",
),
] = False,
config: Annotated[
Path | None,
typer.Option(
"--config",
"-c",
help="Path to configuration file (TOML, JSON, or YAML)",
exists=True,
file_okay=True,
dir_okay=False,
readable=True,
),
] = None,
) -> None:
"""CCProxy API Server - Anthropic and OpenAI compatible interface for Claude."""
# Store config path and initialize plugin arg bucket
ctx.ensure_object(dict)
ctx.obj["config_path"] = config
if "plugin_cli_args" not in ctx.obj or not isinstance(
ctx.obj.get("plugin_cli_args"), dict
):
ctx.obj["plugin_cli_args"] = {}
# If no command is invoked, run the serve command by default
if ctx.invoked_subcommand is None:
# Import here to avoid circular imports
from .commands.serve import api
# Invoke the serve command
ctx.invoke(api)
|
main
Entry point for the CLI application.
Source code in ccproxy/cli/main.py
| def main() -> None:
"""Entry point for the CLI application."""
# Bind a command-wide correlation ID so all logs have `cmd_id`
set_command_context()
# Early logging bootstrap from env/argv; safe to reconfigure later
bootstrap_cli_logging()
# Register plugin-supplied CLI commands after logging honors env overrides
ensure_plugin_cli_extensions_registered(app)
# Log invocation context (argv + env) for all commands
_log_cli_invocation_context()
app()
|