Files
mlx-knife/mlxk2/cli.py
T
The BROKE Team c5777a3e7a MLX-Knife 2.0 Session 2 Complete + Session 3 Major Progress: Production-Ready Alpha
Session 2 Achievements (100% Complete):
• All 5 operations implemented: list, health, show, pull, rm
• CLI compatibility: fuzzy matching, @hash syntax, short names
• Lock detection: New safety feature replacing interactive prompts
• Pull corruption recovery: Clean rm→pull workflow
• Hash fuzzy matching: show "model@3df9bfd" works with short hashes

Session 3 Major Progress (70% Complete):
• JSON API Specification v0.1.1: Complete and production-ready
• Full SHA hashes: 40-char hashes in list output for broke-cluster
• Show command: --files and --config options fully implemented
• JSON-flag enforcement: --json required in alpha for correct usage

Key Features:
• Broke-cluster integration ready with enforced --json flag
• Real-world tested: rm→pull workflow validated with corrupted cache
• Lock cleanup: 9 lock files properly cleaned during rm operations
• Sanitized JSON: No cache paths or implementation details exposed

Testing Status: Basic unit tests implemented, manual validation successful
Note: Test suite requires update for JSON API Specification v0.1.1

Package: Installable as mlxk-json alongside 1.1.0

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-27 21:36:35 +02:00

117 lines
4.4 KiB
Python

#!/usr/bin/env python3
"""MLX-Knife 2.0 CLI - JSON-first architecture."""
import argparse
import json
import sys
from typing import Dict, Any
from . import __version__
from .operations.list import list_models
from .operations.health import health_check_operation
from .operations.pull import pull_operation
from .operations.rm import rm_operation
from .operations.show import show_model_operation
def format_json_output(data: Dict[str, Any]) -> str:
"""Format output as JSON."""
return json.dumps(data, indent=2)
def handle_error(error_type: str, message: str) -> Dict[str, Any]:
"""Format error as JSON response."""
return {
"status": "error",
"command": None,
"data": None,
"error": {
"type": error_type,
"message": message
}
}
def main():
"""Main CLI entry point."""
parser = argparse.ArgumentParser(
prog="mlxk2",
description="MLX-Knife 2.0 - JSON-first model management"
)
# Add version argument
parser.add_argument(
"--version",
action="version",
version=f"mlxk2 {__version__}"
)
subparsers = parser.add_subparsers(dest="command", help="Available commands")
# List command
list_parser = subparsers.add_parser("list", help="List all cached models")
list_parser.add_argument("pattern", nargs="?", help="Filter models by pattern (optional)")
list_parser.add_argument("--json", action="store_true", help="Output in JSON format (default in alpha)")
# Health command
health_parser = subparsers.add_parser("health", help="Check model health")
health_parser.add_argument("model", nargs="?", help="Model pattern to check (optional)")
health_parser.add_argument("--json", action="store_true", help="Output in JSON format (default in alpha)")
# Show command
show_parser = subparsers.add_parser("show", help="Show detailed model information")
show_parser.add_argument("model", help="Model name to show")
show_parser.add_argument("--files", action="store_true", help="Include file listing")
show_parser.add_argument("--config", action="store_true", help="Include config.json content")
show_parser.add_argument("--json", action="store_true", help="Output in JSON format (default in alpha)")
# Pull command
pull_parser = subparsers.add_parser("pull", help="Download a model")
pull_parser.add_argument("model", help="Model name to download")
pull_parser.add_argument("--json", action="store_true", help="Output in JSON format (default in alpha)")
# Remove command
rm_parser = subparsers.add_parser("rm", help="Delete a model")
rm_parser.add_argument("model", help="Model name to delete")
rm_parser.add_argument("-f", "--force", action="store_true", help="Delete without confirmation")
rm_parser.add_argument("--json", action="store_true", help="Output in JSON format (default in alpha)")
args = parser.parse_args()
try:
# In alpha version, --json flag is required for broke-cluster compatibility
if args.command and not hasattr(args, 'json'):
result = handle_error("CommandError", "Internal error: --json flag not found")
elif args.command and not args.json:
result = handle_error("JsonRequired", "MLX-Knife 2.0-alpha requires --json flag. Use: mlxk2 " + args.command + " --json")
elif args.command == "list":
result = list_models(pattern=args.pattern)
elif args.command == "health":
result = health_check_operation(args.model)
elif args.command == "show":
result = show_model_operation(args.model, args.files, args.config)
elif args.command == "pull":
result = pull_operation(args.model)
elif args.command == "rm":
result = rm_operation(args.model, args.force)
elif args.command is None:
result = handle_error("CommandError", "No command specified")
else:
result = handle_error("CommandError", f"Unknown command: {args.command}")
print(format_json_output(result))
# Exit with appropriate code
if result["status"] == "error":
sys.exit(1)
else:
sys.exit(0)
except Exception as e:
error_result = handle_error("InternalError", str(e))
print(format_json_output(error_result))
sys.exit(1)
if __name__ == "__main__":
main()