Add system dependencies support for tools

Tools can now declare system-level package dependencies (apt, brew, pacman, dnf)
that get checked and optionally installed when the tool is installed or run.

Features:
- SystemDependency dataclass with short form (string) and long form (dict)
- New system_deps.py module with platform detection and installation
- `cmdforge system-deps <tool>` command to check/install system packages
- `cmdforge check` now shows both CmdForge and system dependencies
- `cmdforge registry install` prompts for system dep installation
- GUI: System Dependencies section in Tool Builder with add/edit dialog
- Runner warns about missing system deps before execution
- Integration with project install (manifest and lock-based)

Also includes:
- Quote paths in wrapper scripts for spaces support
- Tests for value type preservation in code steps
- Unskip invalid tool name test

Co-Authored-By: Claude Opus 4.5 <[email protected]>
This commit is contained in:
rob
2026-01-28 16:31:37 -04:00
co-authored by Claude Opus 4.5
parent 8eff55ed1e
commit 071ade0ffb
15 changed files with 1399 additions and 62 deletions
+9
View File
@@ -190,9 +190,12 @@ def _cmd_registry_install(args):
"""Install a tool from the registry."""
from ..registry_client import RegistryError
from ..tool import BIN_DIR
from ..system_deps import prompt_install_missing
tool_spec = args.tool
version = args.version
auto_yes = getattr(args, 'yes', False)
skip_sys_deps = getattr(args, 'no_system_deps', False)
print(f"Installing {tool_spec}...")
@@ -211,6 +214,12 @@ def _cmd_registry_install(args):
print(f"\nRun with: {wrapper_name}")
# Check system dependencies unless skipped
if not skip_sys_deps and resolved.tool.system_dependencies:
print()
tool_ref = f"{resolved.owner}/{resolved.tool.name}" if resolved.owner else resolved.tool.name
prompt_install_missing(resolved.tool.system_dependencies, tool_ref, auto_yes=auto_yes)
except RegistryError as e:
if e.code == "TOOL_NOT_FOUND":
print(f"Tool '{tool_spec}' not found in the registry.", file=sys.stderr)