fix: show 'forge' binary name in user-facing messages for forgecode

Addresses Copilot PR feedback: Users should see the actual executable
name 'forge' in status and error messages, not the agent key 'forgecode'.

Changes:
- Added 'cli_binary' field to forgecode AGENT_CONFIG (set to 'forge')
- Updated check_tool() to accept optional display_key parameter
- Updated check_tool() to use cli_binary from AGENT_CONFIG when available
- Updated check() command to display cli_binary in StepTracker
- Updated init() error message to show cli_binary instead of agent key

UX improvements:
- 'specify check' now shows: '● forge (available/not found)'
- 'specify init --ai forgecode' error shows: 'forge not found'
  (instead of confusing 'forgecode not found')

This makes it clear to users that they need to install the 'forge'
binary, even though they selected the 'forgecode' agent.
This commit is contained in:
ericnoam
2026-03-31 19:15:06 +02:00
parent b46bf656fd
commit c69893c1f7

View File

@@ -308,6 +308,7 @@ AGENT_CONFIG = {
"commands_subdir": "commands",
"install_url": "https://forgecode.dev/docs/",
"requires_cli": True,
"cli_binary": "forge", # The actual executable users must install
},
"generic": {
"name": "Generic (bring your own agent)",
@@ -603,16 +604,20 @@ def run_command(cmd: list[str], check_return: bool = True, capture: bool = False
raise
return None
def check_tool(tool: str, tracker: StepTracker = None) -> bool:
def check_tool(tool: str, tracker: StepTracker = None, display_key: str = None) -> bool:
"""Check if a tool is installed. Optionally update tracker.
Args:
tool: Name of the tool to check
tool: Name of the tool to check (agent key from AGENT_CONFIG)
tracker: Optional StepTracker to update with results
display_key: Optional key to use for tracker display (defaults to tool)
Returns:
True if tool is found, False otherwise
"""
# Use display_key for tracker if provided, otherwise use tool
tracker_key = display_key if display_key else tool
# Special handling for Claude CLI local installs
# See: https://github.com/github/spec-kit/issues/123
# See: https://github.com/github/spec-kit/issues/550
@@ -623,24 +628,25 @@ def check_tool(tool: str, tracker: StepTracker = None) -> bool:
if tool == "claude":
if CLAUDE_LOCAL_PATH.is_file() or CLAUDE_NPM_LOCAL_PATH.is_file():
if tracker:
tracker.complete(tool, "available")
tracker.complete(tracker_key, "available")
return True
if tool == "kiro-cli":
# Kiro currently supports both executable names. Prefer kiro-cli and
# accept kiro as a compatibility fallback.
found = shutil.which("kiro-cli") is not None or shutil.which("kiro") is not None
elif tool == "forgecode":
# The forgecode agent key is 'forgecode' but the CLI binary is 'forge'.
found = shutil.which("forge") is not None
else:
found = shutil.which(tool) is not None
# Check if this tool has a custom cli_binary name in AGENT_CONFIG
cli_binary = tool
if tool in AGENT_CONFIG and "cli_binary" in AGENT_CONFIG[tool]:
cli_binary = AGENT_CONFIG[tool]["cli_binary"]
found = shutil.which(cli_binary) is not None
if tracker:
if found:
tracker.complete(tool, "available")
tracker.complete(tracker_key, "available")
else:
tracker.error(tool, "not found")
tracker.error(tracker_key, "not found")
return found
@@ -2009,9 +2015,10 @@ def init(
agent_config = AGENT_CONFIG.get(selected_ai)
if agent_config and agent_config["requires_cli"]:
install_url = agent_config["install_url"]
cli_binary = agent_config.get("cli_binary", selected_ai)
if not check_tool(selected_ai):
error_panel = Panel(
f"[cyan]{selected_ai}[/cyan] not found\n"
f"[cyan]{cli_binary}[/cyan] not found\n"
f"Install from: [cyan]{install_url}[/cyan]\n"
f"{agent_config['name']} is required to continue with this project type.\n\n"
"Tip: Use [cyan]--ignore-agent-tools[/cyan] to skip this check",
@@ -2410,14 +2417,17 @@ def check():
continue # Generic is not a real agent to check
agent_name = agent_config["name"]
requires_cli = agent_config["requires_cli"]
# Use cli_binary for display if specified, otherwise use agent_key
display_key = agent_config.get("cli_binary", agent_key)
tracker.add(agent_key, agent_name)
tracker.add(display_key, agent_name)
if requires_cli:
agent_results[agent_key] = check_tool(agent_key, tracker=tracker)
agent_results[agent_key] = check_tool(agent_key, tracker=tracker, display_key=display_key)
else:
# IDE-based agent - skip CLI check and mark as optional
tracker.skip(agent_key, "IDE-based, no CLI check")
tracker.skip(display_key, "IDE-based, no CLI check")
agent_results[agent_key] = False # Don't count IDE agents as "found"
# Check VS Code variants (not in agent config)