How the StepTracker Class Provides Live Progress Updates in the Spec-Kit CLI
The StepTracker class uses Rich's Live context manager with a refresh callback mechanism to render real-time hierarchical progress trees in the terminal.
The StepTracker class in the github/spec-kit repository powers the command-line interface’s live progress reporting. By combining an internal state machine with Rich’s terminal UI capabilities, it delivers smooth, self-updating step trees without blocking the main execution thread.
StepTracker Architecture and State Management
The StepTracker class is defined in src/specify_cli/__init__.py (lines 304–389). It maintains a list of step dictionaries, each containing key, label, status, and detail fields.
Core state methods include:
add(key, label)– Registers a new step withpendingstatus.start(key)– Marks a step asrunning.complete(key, detail=None)– Sets status todoneand attaches optional completion details.error(key, message)– Records an error state with a message.skip(key)– Marks the step asskipped.
Each mutating method triggers _maybe_refresh(), which invokes a registered callback only when a live display is active.
The Refresh Callback Mechanism
Live updates rely on a callback pattern rather than polling. The StepTracker exposes attach_refresh(cb) (line 340) to register a callable that redraws the UI.
When state changes occur, _maybe_refresh() executes:
def _maybe_refresh(self):
if self._refresh_cb:
try:
self._refresh_cb()
except Exception:
pass
This design decouples the tracker from the rendering layer. The CLI attaches a lambda that calls live.update(tracker.render()), ensuring the terminal redraws instantly after every state transition without manual intervention.
Rendering Real-Time Progress Trees
The render() method (lines 360–389) constructs a Rich Tree object. It maps internal status values to colored symbols:
pending→ dimmed circlerunning→ blue spinner arrowdone→ green checkmarkerror→ red crossskipped→ yellow dash
The CLI consumes this tree inside Rich’s Live context manager (lines 1460–1470):
tracker = StepTracker("Initialize Specify Project")
with Live(tracker.render(), console=console,
refresh_per_second=8, transient=True) as live:
tracker.attach_refresh(lambda: live.update(tracker.render()))
# ... perform work, updating tracker state ...
The transient=True parameter ensures the progress tree disappears after completion, leaving a clean terminal.
Practical Implementation Examples
Project Initialization Workflow
The init command demonstrates the full lifecycle. It instantiates StepTracker with the operation title, attaches the refresh callback, then sequences through validation, API calls, and file generation, updating the tracker at each phase.
Tool Verification Steps
In check_tool (lines 544–558), the tracker reports binary availability checks:
tracker.add("git", "Check Git installation")
tracker.start("git")
if shutil.which("git"):
tracker.complete("git", shutil.which("git"))
else:
tracker.error("git", "Not found in PATH")
Template Download Operations
The download_and_extract_template function (lines 2220–2270) uses granular steps for network and disk operations:
fetch– Resolve release metadatadownload– Stream archive bytesextract– Unzip to target directorycleanup– Remove temporary files
Each step transitions through start → complete or error, giving users immediate visibility into long-running I/O.
Summary
- StepTracker maintains hierarchical step state in
src/specify_cli/__init__.py(lines 304–389). - Live updates are driven by a callback registered via
attach_refresh(), triggered after every state mutation. - Rich integration occurs through the
render()method, which builds a coloredTreedisplayed inside aLivecontext manager (lines 1460–1470). - Usage patterns include tool checking (lines 544–558), project initialization, and template downloads (lines 2220–2270).
Frequently Asked Questions
What is the StepTracker class in Spec-Kit?
The StepTracker class is a state management utility in the Spec-Kit CLI that tracks the lifecycle of discrete operations. It stores step metadata—such as labels, statuses, and completion details—and provides methods to transition steps through pending, running, done, error, and skipped states.
How does StepTracker integrate with the Rich library?
StepTracker integrates with Rich through its render() method, which constructs a Rich Tree object decorated with status symbols and colors. The CLI wraps this tree in Rich’s Live context manager and attaches a refresh callback to StepTracker. Whenever a step’s state changes, the callback triggers live.update(), causing Rich to redraw the terminal display instantly.
Can I use StepTracker outside of the Spec-Kit CLI?
While StepTracker is designed for the Spec-Kit CLI, the class is self-contained and can be reused in any Python project requiring hierarchical progress tracking. You would need to install the rich library separately and provide your own rendering logic or use the built-in render() method if you want the same tree-style output.
Where is the StepTracker class defined in the source code?
The StepTracker class is defined in src/specify_cli/__init__.py between lines 304 and 389. Key integration points that use the class—such as the project initialization command and the check_tool function—appear at lines 1460–1470 and 544–558 respectively.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →