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 -->
68 行
2.2 KiB
Python
68 行
2.2 KiB
Python
import os
|
|
import shutil
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
from free_claude_code.cli.claude_env import build_claude_proxy_env
|
|
from smoke.lib.child_process import (
|
|
cmd_fcc_server,
|
|
run_captured_text,
|
|
)
|
|
from smoke.lib.config import SmokeConfig
|
|
from smoke.lib.server import start_server
|
|
from smoke.lib.skips import skip_upstream_unavailable
|
|
|
|
pytestmark = [pytest.mark.live, pytest.mark.smoke_target("cli")]
|
|
|
|
|
|
def test_fcc_server_entrypoint_starts_server(smoke_config: SmokeConfig) -> None:
|
|
with start_server(
|
|
smoke_config,
|
|
command=cmd_fcc_server(),
|
|
env_overrides={"MESSAGING_PLATFORM": "none"},
|
|
name="entrypoint",
|
|
) as server:
|
|
assert server.process.poll() is None
|
|
|
|
|
|
def test_claude_cli_prompt_when_available(
|
|
smoke_config: SmokeConfig, tmp_path: Path
|
|
) -> None:
|
|
claude_bin = shutil.which(smoke_config.claude_bin)
|
|
if not claude_bin:
|
|
pytest.skip(f"Claude CLI not found: {smoke_config.claude_bin}")
|
|
models = smoke_config.provider_models()
|
|
if not models:
|
|
pytest.skip("no configured provider model available for Claude CLI smoke")
|
|
|
|
with start_server(
|
|
smoke_config,
|
|
env_overrides={"MODEL": models[0].full_model, "MESSAGING_PLATFORM": "none"},
|
|
name="claude-cli",
|
|
) as server:
|
|
env = build_claude_proxy_env(
|
|
proxy_root_url=server.base_url,
|
|
auth_token=smoke_config.settings.anthropic_auth_token,
|
|
base_env=os.environ,
|
|
)
|
|
result = run_captured_text(
|
|
[claude_bin, "-p", "Reply with exactly FCC_SMOKE_PONG"],
|
|
cwd=tmp_path,
|
|
env=env,
|
|
timeout=smoke_config.timeout_s,
|
|
check=False,
|
|
)
|
|
server_log = server.log_path.read_text(encoding="utf-8", errors="replace")
|
|
assert result.returncode == 0, result.stderr or result.stdout
|
|
assert "GET /v1/models" in server_log, (
|
|
"Claude CLI did not discover models from the local gateway"
|
|
)
|
|
assert "POST /v1/messages" in server_log, (
|
|
"Claude CLI did not call the local Anthropic-compatible endpoint"
|
|
)
|
|
if "FCC_SMOKE_PONG" not in result.stdout:
|
|
skip_upstream_unavailable(
|
|
"Claude CLI reached the local proxy but returned no smoke token"
|
|
)
|