Improve cmdforge add UX for locally-installed tools

- Check if tool is already installed locally before trying registry
- Show clear message: "Already installed globally/locally: <tool>"
- Better error messages for VERSION_NOT_FOUND vs TOOL_NOT_FOUND
- Skip unnecessary registry calls when tool is already available

This fixes confusing UX where `cmdforge add` would show an error for
unpublished tools that were actually satisfied by local installation.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
rob 2026-01-26 23:34:40 -04:00
parent 9be0ab4551
commit df29b28167
1 changed files with 28 additions and 16 deletions

View File

@ -374,6 +374,9 @@ def cmd_add(args):
parsed = ToolSpec.parse(tool_spec) parsed = ToolSpec.parse(tool_spec)
full_name = parsed.full_name full_name = parsed.full_name
# Check if already installed locally before trying registry
local_tool = find_tool(tool_spec)
# Add dependency # Add dependency
manifest.add_dependency(full_name, version) manifest.add_dependency(full_name, version)
@ -383,23 +386,32 @@ def cmd_add(args):
# Install if requested # Install if requested
if not args.no_install: if not args.no_install:
print(f"Installing {full_name}...") # If already installed locally, no need to fetch from registry
try: if local_tool:
resolved = install_from_registry(tool_spec, version if version != "*" else None) source_label = "locally" if local_tool.source == "local" else "globally"
print(f"Installed: {resolved.full_name}@{resolved.version}") version_info = f"@{local_tool.version}" if local_tool.version else ""
except RegistryError as e: print(f"Already installed {source_label}: {local_tool.full_name}{version_info}")
if e.code == "TOOL_NOT_FOUND": else:
print(f"Tool not found in registry.", file=sys.stderr) print(f"Installing {full_name}...")
print(f"It's been added to your dependencies - you can install it manually later.", file=sys.stderr) try:
elif e.code == "CONNECTION_ERROR": resolved = install_from_registry(tool_spec, version if version != "*" else None)
print(f"Could not connect to registry.", file=sys.stderr) print(f"Installed: {resolved.full_name}@{resolved.version}")
print("Run 'cmdforge install' to try again later.", file=sys.stderr) except RegistryError as e:
else: if e.code == "TOOL_NOT_FOUND":
print(f"Install failed: {e.message}", file=sys.stderr) print(f"Not found in registry: {full_name}", file=sys.stderr)
print(f"Dependency added - install manually or create the tool locally.", file=sys.stderr)
elif e.code == "VERSION_NOT_FOUND":
print(f"No published version of '{full_name}' found in registry.", file=sys.stderr)
print(f"Dependency added - publish the tool or install manually.", file=sys.stderr)
elif e.code == "CONNECTION_ERROR":
print(f"Could not connect to registry.", file=sys.stderr)
print("Run 'cmdforge install' to try again later.", file=sys.stderr)
else:
print(f"Install failed: {e.message}", file=sys.stderr)
print("Run 'cmdforge install' to try again.", file=sys.stderr)
except Exception as e:
print(f"Install failed: {e}", file=sys.stderr)
print("Run 'cmdforge install' to try again.", file=sys.stderr) print("Run 'cmdforge install' to try again.", file=sys.stderr)
except Exception as e:
print(f"Install failed: {e}", file=sys.stderr)
print("Run 'cmdforge install' to try again.", file=sys.stderr)
return 0 return 0