alishahryar1--free-claude-code
5305bd7e08
## Problem
FCC still publishes `fcc-init` and the `free-claude-code` server alias
from an obsolete installation flow. Configuration creation now belongs
to the Admin UI, while `fcc-server` owns startup and legacy migration.
## Changes
| Before | After |
| --- | --- |
| The package installs six console commands. | The package installs only
`fcc-server`, `fcc-claude`, `fcc-codex`, and `fcc-pi`. |
| `fcc-init` duplicates configuration creation outside the Admin UI. |
The Admin UI exclusively creates managed configuration, and server
startup retains legacy migration. |
| Smoke contracts and architecture describe the retired commands. |
Smoke contracts and architecture describe the supported command surface.
|
| Installer safety lists contain unexplained retired names. | Installer
safety lists document why retired names remain detectable during updates
and uninstall. |
| The package version is `4.11.4`. | The package version is `4.11.5`. |
<!-- greptile_comment -->
<details open><summary><h3>Greptile Summary</h3></summary>
This PR retires the obsolete initialization command and server alias.
The main changes are:
- Removes `fcc-init` and `free-claude-code` from package scripts.
- Moves fresh configuration creation exclusively to the Admin UI.
- Keeps legacy environment migration in `fcc-server` startup.
- Updates smoke coverage, installer comments, documentation, and package
metadata.
</details>
<h3>Confidence Score: 4/5</h3>
The CLI removal needs a compatible release version or temporary aliases
before merging.
Existing automation can lose `fcc-init` and `free-claude-code` after a
patch upgrade. Fresh installs can still start the server and create
configuration through the Admin UI.
pyproject.toml and uv.lock; legacy configuration migration remains
before settings loading.
<details><summary><h3><a href="https://www.greptile.com/trex"><img
alt="T-Rex"
src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg"
height="20" align="absmiddle"></a> T-Rex Logs</h3></summary>
**What T-Rex did**
- I reproduced the patch upgrade path by installing base revision
d37b34b02f in an isolated Python 3.14
environment and verified that fcc-init --version and free-claude-code
--version reported 4.11.4 with exit code 0. After upgrading to head
revision 9a65f654f5e06c0ca96a31d3ad03db8c63d8dec7, the installed version
changed to 4.11.5 and both entrypoints disappeared, with subsequent
invocations yielding command-not-found errors (exit code 127).
- Local smoke tests and server migrations completed successfully: the
CLI local smoke test exited with code 0, the installed-entrypoints
checks passed, and the server migrated to a healthy state with the
health endpoint responding.
<a
href="https://app.greptile.com/trex/runs/15196662/artifacts"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifactsDark.svg?v=4"><source
media="(prefers-color-scheme: light)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"><img
alt="View all artifacts"
src="https://greptile-static-assets.s3.amazonaws.com/badges/ViewAllArtifacts.svg?v=4"></picture></a>
<sub><a href="https://www.greptile.com/trex"><img alt="T-Rex"
src="https://greptile-static-assets.s3.amazonaws.com/trex/trex_green.svg"
height="14" align="absmiddle"></a> Ran code and verified through
T-Rex</sub>
</details>
<details open><summary><h3>Important Files Changed</h3></summary>
| Filename | Overview |
|----------|----------|
| pyproject.toml | Removes two public console commands while applying a
patch version bump. |
| src/free_claude_code/cli/commands.py | Removes template-based
initialization while preserving startup migration. |
| src/free_claude_code/cli/entrypoints.py | Removes the retired
initialization entrypoint and retains server version handling. |
| smoke/lib/child_process.py | Removes the init helper and renames the
server helper consistently. |
| scripts/install.sh | Keeps retired names in process detection for safe
upgrades. |
| scripts/uninstall.sh | Keeps retired names in removal checks for older
installations. |
| uv.lock | Tracks the patch version that must change if the command
removal remains breaking. |
</details>
<a
href="https://app.greptile.com/api/ide/codex?prompt=IMPORTANT%3A%20Work%20in%20the%20repository%20%22alishahryar1%2Ffree-claude-code%22%20on%20the%20existing%20branch%20%22remove-obsolete-cli-commands%22.%20Checkout%20that%20branch%20%E2%80%94%20do%20NOT%20create%20a%20new%20branch%20or%20open%20a%20new%20PR.%20Push%20your%20changes%20to%20%22remove-obsolete-cli-commands%22.%0A%0AFix%20the%20following%201%20code%20review%20issue.%20Work%20through%20them%20one%20at%20a%20time%2C%20proposing%20concise%20fixes.%0A%0A---%0A%0A%23%23%23%20Issue%201%20of%201%0Apyproject.toml%3A7%0A**Breaking%20Commands%20Ship%20as%20Patch**%0A%0AUpgrading%20from%204.11.4%20removes%20the%20published%20%60fcc-init%60%20and%20%60free-claude-code%60%20commands%2C%20so%20existing%20scripts%20fail%20with%20%E2%80%9Ccommand%20not%20found.%E2%80%9D%20The%20repository%20policy%20classifies%20incompatible%20CLI%20removals%20as%20major%20changes%3B%20keep%20compatibility%20aliases%20for%204.x%20or%20publish%20this%20removal%20as%205.0.0.%0A%0A&repo=alishahryar1%2Ffree-claude-code&pr=1220&platform=github"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInCodexDark.svg?v=6"><source
media="(prefers-color-scheme: light)"
srcset="https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInCodex.svg?v=6"><img
alt="Fix All in Codex"
src="https://greptile-static-assets.s3.amazonaws.com/badges/FixAllInCodex.svg?v=6"></picture></a>
<sub>Reviews (1): Last reviewed commit: ["Remove obsolete CLI entry
points"](https://github.com/alishahryar1/free-claude-code/commit/9a65f654f5e06c0ca96a31d3ad03db8c63d8dec7)
| [Re-trigger
Greptile](https://app.greptile.com/api/retrigger?id=45848525)</sub>
> Greptile also left **1 inline comment** on this PR.
<!-- /greptile_comment -->
525 行
20 KiB
Python
525 行
20 KiB
Python
"""Hierarchical public capability map.
|
|
|
|
This module is the architectural companion to ``smoke.features``. The feature
|
|
inventory says which public features must be covered; this map records the
|
|
subfeature contracts, owning module boundary, and coverage owners that protect
|
|
them while the internals are refactored.
|
|
"""
|
|
|
|
from dataclasses import dataclass
|
|
|
|
|
|
@dataclass(frozen=True, slots=True)
|
|
class CapabilityContract:
|
|
capability: str
|
|
subfeature: str
|
|
feature_id: str
|
|
owner: str
|
|
inputs: str
|
|
outputs: str
|
|
failure: str
|
|
pytest_tests: tuple[str, ...]
|
|
smoke_tests: tuple[str, ...] = ()
|
|
|
|
|
|
CAPABILITY_CONTRACTS: tuple[CapabilityContract, ...] = (
|
|
CapabilityContract(
|
|
"api_compatibility",
|
|
"routes_and_probes",
|
|
"anthropic_api_routes",
|
|
"free_claude_code.api.routes",
|
|
"Anthropic-compatible HTTP requests",
|
|
"JSON or Anthropic SSE responses",
|
|
"HTTPException or Anthropic error payload",
|
|
("tests/api/test_api.py",),
|
|
("test_probe_and_models_routes", "test_stop_endpoint_reports_no_messaging"),
|
|
),
|
|
CapabilityContract(
|
|
"api_compatibility",
|
|
"head_options_probes",
|
|
"probe_routes",
|
|
"free_claude_code.api.routes",
|
|
"HEAD/OPTIONS probe requests",
|
|
"204 with Allow header",
|
|
"auth failure when configured",
|
|
("tests/api/test_api.py::test_probe_endpoints_return_204_with_allow_headers",),
|
|
("test_probe_and_models_routes",),
|
|
),
|
|
CapabilityContract(
|
|
"api_compatibility",
|
|
"client_request_shapes",
|
|
"drop_in_claude_code_replacement",
|
|
"free_claude_code.api.handlers.messages.MessagesHandler",
|
|
"Claude Code, VS Code, and JetBrains shaped requests",
|
|
"compatible streaming response",
|
|
"provider or validation error in Anthropic shape",
|
|
("tests/api/test_api.py", "tests/cli/test_cli.py"),
|
|
("test_vscode_and_jetbrains_shaped_requests",),
|
|
),
|
|
CapabilityContract(
|
|
"api_compatibility",
|
|
"responses_api",
|
|
"drop_in_codex_replacement",
|
|
"free_claude_code.api.handlers.responses.ResponsesHandler",
|
|
"OpenAI Responses requests from Codex",
|
|
"Responses SSE or JSON response",
|
|
"OpenAI-shaped error or conversion error",
|
|
(
|
|
"tests/api/test_openai_responses.py",
|
|
"tests/core/openai_responses/test_sse.py",
|
|
"tests/cli/test_entrypoints.py",
|
|
"tests/cli/test_codex_model_catalog.py",
|
|
),
|
|
(
|
|
"test_probe_and_models_routes",
|
|
"test_provider_codex_responses_text_e2e",
|
|
),
|
|
),
|
|
CapabilityContract(
|
|
"api_compatibility",
|
|
"client_extensions",
|
|
"vscode_extension",
|
|
"free_claude_code.api.handlers.messages.MessagesHandler",
|
|
"VS Code beta query/header variants",
|
|
"accepted Anthropic-compatible response",
|
|
"HTTP error only for auth/provider failures",
|
|
(),
|
|
("test_vscode_and_jetbrains_shaped_requests",),
|
|
),
|
|
CapabilityContract(
|
|
"api_compatibility",
|
|
"client_extensions",
|
|
"intellij_extension",
|
|
"free_claude_code.api.handlers.messages.MessagesHandler",
|
|
"JetBrains/ACP request variants",
|
|
"accepted Anthropic-compatible response",
|
|
"HTTP error only for auth/provider failures",
|
|
(),
|
|
("test_vscode_and_jetbrains_shaped_requests",),
|
|
),
|
|
CapabilityContract(
|
|
"auth",
|
|
"bearer_authorization",
|
|
"optional_authentication",
|
|
"free_claude_code.api.dependencies.require_proxy_auth",
|
|
"authorization: bearer token",
|
|
"request accepted or 401",
|
|
"401 missing/invalid proxy authentication token",
|
|
("tests/api/test_auth.py",),
|
|
("test_bearer_auth_is_the_only_supported_header_shape",),
|
|
),
|
|
CapabilityContract(
|
|
"provider_routing",
|
|
"provider_runtime",
|
|
"provider_matrix",
|
|
"free_claude_code.runtime.provider_manager.ProviderRuntimeManager",
|
|
"provider id and Settings",
|
|
"configured BaseProvider instance",
|
|
"503 for missing credentials; invalid_request_error for unknown provider",
|
|
("tests/api/test_dependencies.py", "tests/providers/test_provider_runtime.py"),
|
|
(
|
|
"test_configured_provider_models_stream_successfully",
|
|
"test_provider_matrix_presence_e2e",
|
|
),
|
|
),
|
|
CapabilityContract(
|
|
"provider_routing",
|
|
"claude_model_resolution",
|
|
"per_model_mapping",
|
|
"free_claude_code.application.routing.ModelRouter",
|
|
"Claude model name and configured MODEL_* values",
|
|
"provider id plus provider model name",
|
|
"settings validation rejects invalid provider prefixes",
|
|
("tests/application/test_routing.py", "tests/config/test_config.py"),
|
|
("test_model_mapping_configuration_is_consistent",),
|
|
),
|
|
CapabilityContract(
|
|
"provider_routing",
|
|
"mixed_provider_resolution",
|
|
"mixed_provider_mapping",
|
|
"free_claude_code.application.routing.ModelRouter",
|
|
"Fable/Opus/Sonnet/Haiku/fallback model config",
|
|
"distinct provider selections per request",
|
|
"skip live execution when providers are not configured",
|
|
("tests/application/test_routing.py", "tests/config/test_config.py"),
|
|
("test_mixed_provider_model_mapping_when_configured",),
|
|
),
|
|
CapabilityContract(
|
|
"provider_routing",
|
|
"provider_runtime_config",
|
|
"provider_proxy_timeout_config",
|
|
"free_claude_code.providers.runtime.ProviderRuntime",
|
|
"provider proxy, timeout, and rate-limit settings",
|
|
"provider client and generation-owned admission config",
|
|
"provider construction failure",
|
|
(
|
|
"tests/api/test_dependencies.py",
|
|
"tests/providers/test_provider_runtime.py",
|
|
"tests/providers/test_provider_admission.py",
|
|
),
|
|
),
|
|
CapabilityContract(
|
|
"provider_routing",
|
|
"zero_cost_backends",
|
|
"zero_cost_provider_access",
|
|
"free_claude_code.providers.runtime.ProviderRuntime",
|
|
"configured free/local provider",
|
|
"streaming response from selected backend",
|
|
"missing env or upstream unavailable skip in smoke",
|
|
("tests/api/test_dependencies.py", "tests/providers/"),
|
|
("test_configured_provider_models_stream_successfully",),
|
|
),
|
|
CapabilityContract(
|
|
"streaming_conversion",
|
|
"anthropic_sse_lifecycle",
|
|
"streaming_error_mapping",
|
|
"free_claude_code.core.failures.ExecutionFailure",
|
|
"provider stream failures before or after the HTTP commit boundary",
|
|
"protocol-specific JSON failure or terminal stream event",
|
|
"ordinary request failures remain distinct from terminal execution",
|
|
(
|
|
"tests/api/test_execution_failure_contract.py",
|
|
"tests/api/test_ordinary_error_phases.py",
|
|
"tests/core/test_failure_protocol_mapping.py",
|
|
"tests/providers/test_execution_failure_boundary.py",
|
|
"tests/providers/test_failure_policy.py",
|
|
),
|
|
),
|
|
CapabilityContract(
|
|
"streaming_conversion",
|
|
"thinking_blocks",
|
|
"thinking_token_support",
|
|
"free_claude_code.core.anthropic.thinking",
|
|
"reasoning_content, reasoning_details, <think> text, native thinking",
|
|
"Claude thinking blocks or suppression",
|
|
"thinking hidden when disabled",
|
|
(
|
|
"tests/contracts/test_stream_contracts.py",
|
|
"tests/providers/test_converter.py",
|
|
"tests/providers/test_deepseek.py",
|
|
"tests/providers/test_nvidia_nim_request.py",
|
|
"tests/providers/test_open_router.py",
|
|
),
|
|
(
|
|
"test_route_reasoning_config_e2e",
|
|
"test_provider_reasoning_tool_continuation_e2e",
|
|
),
|
|
),
|
|
CapabilityContract(
|
|
"streaming_conversion",
|
|
"heuristic_tools",
|
|
"heuristic_tool_parser",
|
|
"free_claude_code.core.anthropic.tools",
|
|
"textual tool-call output",
|
|
"structured Anthropic tool_use blocks",
|
|
"text fallback when malformed",
|
|
("tests/providers/test_parsers.py", "tests/contracts/test_stream_contracts.py"),
|
|
(
|
|
"test_live_tool_use_when_configured_model_supports_tools",
|
|
"test_provider_reasoning_tool_continuation_e2e",
|
|
),
|
|
),
|
|
CapabilityContract(
|
|
"streaming_conversion",
|
|
"subagent_task_control",
|
|
"subagent_control",
|
|
"free_claude_code.core.anthropic.streaming.AnthropicStreamLedger",
|
|
"Task tool call arguments",
|
|
"run_in_background=false",
|
|
"invalid JSON flushed as safe object",
|
|
("tests/providers/test_subagent_interception.py",),
|
|
),
|
|
CapabilityContract(
|
|
"request_behavior",
|
|
"local_optimizations",
|
|
"request_optimization",
|
|
"free_claude_code.api.optimization_handlers",
|
|
"Claude Code probe/title/suggestion/filepath requests",
|
|
"local MessagesResponse without provider call",
|
|
"falls through to provider when unmatched/disabled",
|
|
(
|
|
"tests/api/test_optimization_handlers.py",
|
|
"tests/api/test_routes_optimizations.py",
|
|
),
|
|
("test_optimization_fast_paths_do_not_need_provider",),
|
|
),
|
|
CapabilityContract(
|
|
"request_behavior",
|
|
"token_counting",
|
|
"count_tokens_contract",
|
|
"free_claude_code.core.anthropic.get_token_count",
|
|
"messages, system blocks, tools, images, thinking, tool results",
|
|
"positive input token estimate",
|
|
"500 with readable detail on unexpected failure",
|
|
("tests/api/test_request_utils.py",),
|
|
("test_count_tokens_accepts_thinking_tools_and_results",),
|
|
),
|
|
CapabilityContract(
|
|
"config",
|
|
"env_precedence",
|
|
"config_env_precedence",
|
|
"free_claude_code.config.settings.Settings",
|
|
"process env, user env file, repo env file, FCC_ENV_FILE",
|
|
"deterministic settings values",
|
|
"validation error for invalid settings",
|
|
("tests/config/test_config.py",),
|
|
),
|
|
CapabilityContract(
|
|
"config",
|
|
"removed_env_migration",
|
|
"removed_env_migration",
|
|
"free_claude_code.config.settings.Settings",
|
|
"retired ENABLE_MODEL_THINKING or tier override in an FCC-owned dotenv",
|
|
"owned dotenv is migrated to the typed reasoning policy",
|
|
"explicit dotenv receives an actionable warning",
|
|
("tests/config/test_env_migrations.py", "tests/config/test_config.py"),
|
|
("test_removed_env_migration_e2e",),
|
|
),
|
|
CapabilityContract(
|
|
"provider_runtime",
|
|
"rate_limit_and_disconnect",
|
|
"smart_rate_limiting",
|
|
"free_claude_code.providers.admission.ProviderAdmissionController",
|
|
"concurrent provider requests and transient upstream/disconnect failures",
|
|
"provider-specific classification, proactive throttle, coordinated retry, cleanup",
|
|
"mapped provider error or smoke skip for upstream disconnect",
|
|
(
|
|
"tests/providers/test_provider_admission.py",
|
|
"tests/providers/test_nvidia_nim_degraded_retry.py",
|
|
),
|
|
("test_client_disconnect_mid_stream_does_not_crash_server",),
|
|
),
|
|
CapabilityContract(
|
|
"provider_runtime",
|
|
"generation_hot_swap",
|
|
"provider_hot_swap",
|
|
"free_claude_code.runtime.provider_manager.ProviderRuntimeManager",
|
|
"validated Admin provider config and concurrent request streams",
|
|
"atomic generation publication with old-stream completion",
|
|
"failed candidate or persistence leaves current generation unchanged",
|
|
(
|
|
"tests/runtime/test_provider_manager.py",
|
|
"tests/api/test_response_streams.py",
|
|
"tests/api/test_admin.py",
|
|
),
|
|
("test_provider_hot_swap_preserves_inflight_stream_e2e",),
|
|
),
|
|
CapabilityContract(
|
|
"local_providers",
|
|
"lmstudio_messages",
|
|
"lmstudio_endpoint",
|
|
"free_claude_code.providers.lmstudio.LMStudioProvider",
|
|
"Anthropic Messages request and local LM Studio URL",
|
|
"Anthropic SSE converted from an OpenAI Chat upstream",
|
|
"typed provider failure for local upstream errors",
|
|
("tests/providers/test_lmstudio.py",),
|
|
("test_lmstudio_messages_e2e",),
|
|
),
|
|
CapabilityContract(
|
|
"local_providers",
|
|
"llamacpp_openai_chat",
|
|
"llamacpp_endpoint",
|
|
"free_claude_code.providers.openai_chat.OpenAIChatProvider",
|
|
"OpenAI Chat request and llama.cpp URL",
|
|
"Anthropic SSE converted from OpenAI Chat chunks",
|
|
"typed provider failure for local upstream errors",
|
|
("tests/providers/test_llamacpp.py",),
|
|
("test_llamacpp_models_endpoint_when_available",),
|
|
),
|
|
CapabilityContract(
|
|
"local_providers",
|
|
"ollama_openai_chat",
|
|
"ollama_endpoint",
|
|
"free_claude_code.providers.openai_chat.OpenAIChatProvider",
|
|
"OpenAI Chat request and local Ollama root URL",
|
|
"Anthropic SSE converted from OpenAI Chat chunks",
|
|
"typed provider failure for local upstream errors",
|
|
("tests/providers/test_ollama.py",),
|
|
("test_ollama_models_endpoint_when_available",),
|
|
),
|
|
CapabilityContract(
|
|
"openrouter",
|
|
"openai_chat_provider",
|
|
"provider_matrix",
|
|
"free_claude_code.providers.open_router.OpenRouterProvider",
|
|
"OpenAI Chat request for OpenRouter",
|
|
"OpenAI stream mapped to Anthropic SSE",
|
|
"Anthropic SSE error shape",
|
|
(
|
|
"tests/providers/test_open_router.py",
|
|
"tests/providers/test_openai_compat_5xx_retry.py",
|
|
),
|
|
("test_configured_provider_models_stream_successfully",),
|
|
),
|
|
CapabilityContract(
|
|
"messaging",
|
|
"discord_telegram_platforms",
|
|
"discord_telegram_bot",
|
|
"free_claude_code.messaging.workflow.MessagingWorkflow",
|
|
"Discord/Telegram incoming messages and API callbacks",
|
|
"live progress edits and final transcript",
|
|
"platform retry/fallback or user-facing error",
|
|
(
|
|
"tests/messaging/test_discord_platform.py",
|
|
"tests/messaging/test_telegram.py",
|
|
"tests/messaging/test_limiter.py",
|
|
"tests/messaging/test_platform_outbox.py",
|
|
"tests/runtime/test_application_runtime.py",
|
|
),
|
|
("test_telegram_bot_api_permissions", "test_discord_bot_api_permissions"),
|
|
),
|
|
CapabilityContract(
|
|
"messaging",
|
|
"commands",
|
|
"messaging_commands",
|
|
"free_claude_code.messaging.commands",
|
|
"/stop, /clear, /stats command messages",
|
|
"chat-wide cleanup or literal reply-subtree deletion",
|
|
"terminal status edit, no-op feedback, or best-effort platform cleanup",
|
|
(
|
|
"tests/messaging/test_handler.py",
|
|
"tests/messaging/test_handler_integration.py",
|
|
"tests/messaging/test_tree_ownership_concurrency.py",
|
|
),
|
|
(
|
|
"test_messaging_commands_stop_clear_stats_e2e",
|
|
"test_reply_clear_uses_literal_platform_subtree_e2e",
|
|
"test_messaging_startup_notice_is_clearable_e2e",
|
|
"test_messaging_active_stop_uses_status_only_e2e",
|
|
"test_messaging_queued_scoped_cancel_e2e",
|
|
),
|
|
),
|
|
CapabilityContract(
|
|
"messaging",
|
|
"tree_threading",
|
|
"tree_threading",
|
|
"free_claude_code.messaging.trees.TreeQueueManager",
|
|
"reply-based message graph",
|
|
"queued branches and scoped cancellation",
|
|
"node error propagation",
|
|
(
|
|
"tests/messaging/test_tree_queue.py",
|
|
"tests/messaging/test_tree_concurrency.py",
|
|
"tests/messaging/test_message_tree_transitions.py",
|
|
"tests/messaging/test_tree_ownership_concurrency.py",
|
|
),
|
|
(
|
|
"test_tree_threading_e2e",
|
|
"test_messaging_queued_scoped_cancel_e2e",
|
|
"test_same_message_ids_are_isolated_by_chat_e2e",
|
|
),
|
|
),
|
|
CapabilityContract(
|
|
"persistence",
|
|
"restart_restore",
|
|
"restart_restore",
|
|
"free_claude_code.messaging.session.SessionStore",
|
|
"stored tree JSON",
|
|
"restored scoped reply lookup",
|
|
"stale pending work marked lost",
|
|
("tests/messaging/test_restart_reply_restore.py",),
|
|
),
|
|
CapabilityContract(
|
|
"persistence",
|
|
"session_store",
|
|
"session_persistence",
|
|
"free_claude_code.messaging.session.SessionStore",
|
|
"scoped tree data and message log",
|
|
"JSON persistence compatible with existing files",
|
|
"best-effort flush error logging",
|
|
("tests/messaging/test_session_store_edge_cases.py",),
|
|
),
|
|
CapabilityContract(
|
|
"voice",
|
|
"voice_transcription",
|
|
"voice_notes",
|
|
"free_claude_code.messaging.voice.Transcriber",
|
|
"Discord/Telegram audio file and voice backend settings",
|
|
"transcribed prompt routed to handler",
|
|
"missing optional extra or backend error shown to user",
|
|
(
|
|
"tests/messaging/test_voice_handlers.py",
|
|
"tests/messaging/test_transcription.py",
|
|
"tests/messaging/test_transcription_nim.py",
|
|
"tests/messaging/test_platform_voice_flow.py",
|
|
),
|
|
("test_voice_transcription_backend_when_explicitly_enabled",),
|
|
),
|
|
CapabilityContract(
|
|
"cli",
|
|
"package_entrypoints",
|
|
"package_cli_entrypoints",
|
|
"free_claude_code.cli.entrypoints",
|
|
"installed console scripts",
|
|
"package version or uvicorn server startup",
|
|
"process cleanup in finally",
|
|
("tests/cli/test_entrypoints.py", "tests/core/test_version.py"),
|
|
(
|
|
"test_fcc_server_entrypoint_starts_server",
|
|
"test_entrypoint_version_e2e",
|
|
),
|
|
),
|
|
CapabilityContract(
|
|
"cli",
|
|
"claude_cli_drop_in",
|
|
"claude_cli_drop_in",
|
|
"free_claude_code.cli.managed.session.ManagedClaudeSession",
|
|
"Claude CLI binary and proxy env",
|
|
"stream-json events and session id mapping",
|
|
"stderr/error event and process cleanup",
|
|
("tests/cli/test_cli.py",),
|
|
(
|
|
"test_claude_cli_prompt_when_available",
|
|
"test_claude_cli_provider_error_e2e",
|
|
"test_nvidia_nim_cli_matrix_e2e",
|
|
"test_openrouter_free_cli_matrix_e2e",
|
|
),
|
|
),
|
|
CapabilityContract(
|
|
"cli",
|
|
"codex_cli_drop_in",
|
|
"drop_in_codex_replacement",
|
|
"free_claude_code.cli.launchers.codex",
|
|
"Codex CLI binary and fcc provider env",
|
|
"Responses config, auth env, and native /model catalog injection",
|
|
"proxy preflight and catalog fail-open warning",
|
|
(
|
|
"tests/cli/test_codex_model_catalog.py",
|
|
"tests/cli/test_entrypoints.py",
|
|
),
|
|
(),
|
|
),
|
|
CapabilityContract(
|
|
"cli",
|
|
"pi_cli_integration",
|
|
"pi_cli_integration",
|
|
"free_claude_code.cli.launchers.pi",
|
|
"Pi CLI binary, bundled extension, and FCC child-process environment",
|
|
"Anthropic Messages provider with an FCC-scoped live model catalog",
|
|
"proxy preflight, missing extension, or catalog failure exits without fallback",
|
|
("tests/cli/test_entrypoints.py",),
|
|
("test_pi_cli_prompt_e2e",),
|
|
),
|
|
CapabilityContract(
|
|
"extensibility",
|
|
"provider_platform_abcs",
|
|
"extensible_provider_platform_abcs",
|
|
"free_claude_code.providers.runtime and free_claude_code.messaging.platforms.factory",
|
|
"new provider/platform implementations",
|
|
"registered BaseProvider or messaging component bundle",
|
|
"unknown platform returns None; unknown provider errors",
|
|
(
|
|
"tests/contracts/test_feature_manifest.py",
|
|
"tests/providers/test_provider_runtime.py",
|
|
),
|
|
),
|
|
)
|
|
|
|
|
|
def capability_names() -> set[str]:
|
|
return {contract.capability for contract in CAPABILITY_CONTRACTS}
|
|
|
|
|
|
def contracted_feature_ids() -> set[str]:
|
|
return {contract.feature_id for contract in CAPABILITY_CONTRACTS}
|