List installed step types (built-in and custom).
()
| 1046 | |
| 1047 | @workflow_step_app.command("list") |
| 1048 | def workflow_step_list(): |
| 1049 | """List installed step types (built-in and custom).""" |
| 1050 | from . import STEP_REGISTRY |
| 1051 | from .catalog import StepRegistry |
| 1052 | |
| 1053 | project_root = _require_specify_project() |
| 1054 | specify_dir = project_root / ".specify" |
| 1055 | |
| 1056 | # Read installed custom steps from registry only — no dynamic imports |
| 1057 | installed: dict = {} |
| 1058 | if specify_dir.exists(): |
| 1059 | registry = StepRegistry(project_root) |
| 1060 | installed = registry.list() |
| 1061 | |
| 1062 | console.print("\n[bold cyan]Installed Step Types:[/bold cyan]\n") |
| 1063 | |
| 1064 | built_in = sorted(k for k in STEP_REGISTRY if k not in installed) |
| 1065 | if built_in: |
| 1066 | console.print(" [bold]Built-in:[/bold]") |
| 1067 | for key in built_in: |
| 1068 | console.print(f" • {key}") |
| 1069 | console.print() |
| 1070 | |
| 1071 | if installed: |
| 1072 | console.print(" [bold]Custom (installed):[/bold]") |
| 1073 | for key in sorted(installed): |
| 1074 | meta = installed[key] or {} |
| 1075 | name = meta.get("name", key) |
| 1076 | version = meta.get("version", "?") |
| 1077 | console.print(f" • [bold]{name}[/bold] ({key}) v{version}") |
| 1078 | console.print() |
| 1079 | |
| 1080 | if not built_in and not installed: |
| 1081 | console.print("[yellow]No step types found.[/yellow]") |
| 1082 | |
| 1083 | if specify_dir.exists(): |
| 1084 | console.print( |
| 1085 | " Install a new step type with: [cyan]specify workflow step add <id>[/cyan]" |
| 1086 | ) |
| 1087 | |
| 1088 | |
| 1089 | # IDs that map to internal names used under .specify/workflows/steps/ and must |
nothing calls this directly
no test coverage detected