Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 25 additions & 4 deletions codeframe/cli/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
from codeframe.cli.auth_commands import auth_app
from codeframe.cli.pr_commands import pr_app
from codeframe.cli.env_commands import env_app
from codeframe.cli.engines_commands import engines_app

# Load environment variables from .env files
# Priority: workspace .env > home .env
Expand Down Expand Up @@ -1994,8 +1995,8 @@ def work_start(
"--stub",
help="Run stub agent (for testing, does nothing real)",
),
engine: str = typer.Option(
"react",
engine: Optional[str] = typer.Option(
None,
"--engine",
help="Agent engine: react (default), plan (legacy), claude-code, opencode, or built-in",
),
Expand Down Expand Up @@ -2029,6 +2030,15 @@ def work_start(

path = workspace_path or Path.cwd()

# Resolve engine: CLI flag → env var → workspace config → default "react"
if engine is None:
import os
engine = os.environ.get("CODEFRAME_ENGINE")
if engine is None:
from codeframe.core.config import load_environment_config
env_config = load_environment_config(path)
engine = env_config.engine if env_config else "react"

try:
workspace = get_workspace(path)

Expand Down Expand Up @@ -2875,8 +2885,8 @@ def batch_run(
"--review",
help="Run verification gates (pytest, ruff) after successful batch completion",
),
engine: str = typer.Option(
"react",
engine: Optional[str] = typer.Option(
None,
"--engine",
help="Agent engine: react (default), plan (legacy), claude-code, opencode, or built-in",
),
Expand Down Expand Up @@ -2913,6 +2923,15 @@ def batch_run(

path = workspace_path or Path.cwd()

# Resolve engine: CLI flag → env var → workspace config → default "react"
if engine is None:
import os
engine = os.environ.get("CODEFRAME_ENGINE")
if engine is None:
from codeframe.core.config import load_environment_config
env_config = load_environment_config(path)
engine = env_config.engine if env_config else "react"

try:
workspace = get_workspace(path)

Expand Down Expand Up @@ -4824,6 +4843,8 @@ def templates_apply(
app.add_typer(pr_app, name="pr")
app.add_typer(env_app, name="env")

app.add_typer(engines_app, name="engines")


# =============================================================================
# Version command
Expand Down
84 changes: 84 additions & 0 deletions codeframe/cli/engines_commands.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
"""CLI engine management commands.

Usage:
codeframe engines list # Show available engines
codeframe engines check <name> # Check engine requirements
"""

import typer
from rich.console import Console
from rich.table import Table

console = Console()

engines_app = typer.Typer(
name="engines",
help="Engine management commands",
no_args_is_help=True,
)


@engines_app.command("list")
def engines_list() -> None:
"""List all available execution engines and their requirement status."""
from codeframe.core.engine_registry import VALID_ENGINES, EXTERNAL_ENGINES, check_requirements

table = Table(title="Available Engines")
table.add_column("Engine", style="cyan")
table.add_column("Type", style="dim")
table.add_column("Requirements", style="green")

for engine in sorted(VALID_ENGINES):
engine_type = "external" if engine in EXTERNAL_ENGINES else "builtin"
if engine == "built-in":
engine_type = "alias → react"

try:
reqs = check_requirements(engine)
except ValueError:
reqs = {}

if not reqs:
req_display = "[green]Ready[/green]"
else:
parts = []
for key, satisfied in reqs.items():
mark = "[green]✓[/green]" if satisfied else "[red]✗[/red]"
parts.append(f"{mark} {key}")
req_display = ", ".join(parts)

table.add_row(engine, engine_type, req_display)

console.print(table)


@engines_app.command("check")
def engines_check(
name: str = typer.Argument(..., help="Engine name to check"),
) -> None:
"""Check if an engine's requirements are satisfied."""
from codeframe.core.engine_registry import check_requirements

try:
reqs = check_requirements(name)
except ValueError as e:
console.print(f"[red]Error:[/red] {e}")
raise typer.Exit(1)

if not reqs:
console.print(f"[green]Engine '{name}' has no additional requirements.[/green]")
return

all_satisfied = True
for key, satisfied in reqs.items():
if satisfied:
console.print(f" [green]✓[/green] {key}")
else:
console.print(f" [red]✗[/red] {key} — not set")
all_satisfied = False

if all_satisfied:
console.print(f"\n[green]Engine '{name}' is ready.[/green]")
else:
console.print(f"\n[red]Engine '{name}' has unmet requirements.[/red]")
raise typer.Exit(1)
Loading
Loading