MCPcopy
hub / github.com/github/spec-kit / CommandStep

Class CommandStep

src/specify_cli/workflows/steps/command/__init__.py:13–158  ·  view source on GitHub ↗

Default step type — invokes a Spec Kit command via the integration CLI. The command files (skills, markdown, TOML) are already installed in the integration's directory on disk. This step tells the CLI to execute the command by name (e.g. ``/speckit.specify`` or ``/speckit-specify``

Source from the content-addressed store, hash-verified

11
12
13class CommandStep(StepBase):
14 """Default step type — invokes a Spec Kit command via the integration CLI.
15
16 The command files (skills, markdown, TOML) are already installed in
17 the integration's directory on disk. This step tells the CLI to
18 execute the command by name (e.g. ``/speckit.specify`` or
19 ``/speckit-specify``) rather than reading the file contents.
20
21 .. note::
22
23 CLI output is streamed to the terminal for live progress.
24 ``output.exit_code`` is always captured and can be referenced
25 by later steps (e.g. ``{{ steps.specify.output.exit_code }}``).
26 Full ``stdout``/``stderr`` capture is a planned enhancement.
27 """
28
29 type_key = "command"
30
31 def execute(self, config: dict[str, Any], context: StepContext) -> StepResult:
32 command = config.get("command", "")
33 input_data = config.get("input", {})
34
35 # Resolve expressions in input
36 resolved_input: dict[str, Any] = {}
37 for key, value in input_data.items():
38 resolved_input[key] = evaluate_expression(value, context)
39
40 # Resolve integration (step → workflow default → project default)
41 integration = config.get("integration") or context.default_integration
42 if integration and isinstance(integration, str) and "{{" in integration:
43 integration = evaluate_expression(integration, context)
44
45 # Resolve model
46 model = config.get("model") or context.default_model
47 if model and isinstance(model, str) and "{{" in model:
48 model = evaluate_expression(model, context)
49
50 # Merge options (workflow defaults ← step overrides)
51 options = dict(context.default_options)
52 step_options = config.get("options", {})
53 if step_options:
54 options.update(step_options)
55
56 # Attempt CLI dispatch
57 args_str = str(resolved_input.get("args", ""))
58 dispatch_result = self._try_dispatch(
59 command, integration, model, args_str, context
60 )
61
62 output: dict[str, Any] = {
63 "command": command,
64 "integration": integration,
65 "model": model,
66 "options": options,
67 "input": resolved_input,
68 }
69
70 if dispatch_result is not None:

Calls

no outgoing calls