Quickstart: Unified Python CLI for Agents
Path: kitty-specs/008-unified-python-cli/quickstart.md
Overview
This guide helps developers work on migrating spec-kitty's bash scripts to a unified Python CLI. The migration eliminates ~2,600 lines of bash code and provides AI agents with a reliable, location-aware spec-kitty agent command interface.
Prerequisites
- Python 3.11+
- Git with worktree support
- spec-kitty development environment set up
- Access to the
008-unified-python-clibranch - Familiarity with Typer CLI framework
Getting Started
1. Set Up Your Worktree
# From main spec-kitty repo
git worktree add .worktrees/008-unified-python-cli 008-unified-python-cli
cd .worktrees/008-unified-python-cli
2. Understand Parallel Work Streams
This feature is implemented in 7 phases with maximum parallelization:
- Phase 1 (Days 1-2): Foundation - SEQUENTIAL (one person)
- Phases 2-5 (Days 3-8): Command Implementation - PARALLEL (4 agents)
- Stream A (Agent Alpha): Feature commands
- Stream B (Agent Beta): Task commands
- Stream C (Agent Gamma): Context commands
- Stream D (Agent Delta): Release commands
- Phase 6 (Days 9-10): Cleanup & Migration - SEQUENTIAL (one person)
- Phase 7 (Day 11): Validation - SEQUENTIAL (one person)
3. Review Your Assignment
Check plan.md for your work stream assignment. Each stream owns specific files with no conflicts:
Stream A (Agent Alpha): Feature Commands
- Files:
src/specify_cli/cli/commands/agent/feature.py,src/specify_cli/core/worktree.py - Dependencies: Phase 1 complete
- Duration: 2 days
Stream B (Agent Beta): Task Commands
- Files:
src/specify_cli/cli/commands/agent/tasks.py - Dependencies: Phase 1 complete
- Duration: 2 days
Stream C (Agent Gamma): Context Commands
- Files:
src/specify_cli/cli/commands/agent/context.py,src/specify_cli/core/agent_context.py - Dependencies: Phase 1 complete
- Duration: 1 day
Stream D (Agent Delta): Release Commands
- Files:
src/specify_cli/cli/commands/agent/release.py,src/specify_cli/core/release.py - Dependencies: Phase 1 complete
- Duration: 1 day
Development Workflow
Phase 1: Foundation Setup (Required Before Parallel Work)
If you're working on Phase 1, complete ALL foundation items before parallel streams begin:
# 1. Create agent namespace structure
mkdir -p src/specify_cli/cli/commands/agent
touch src/specify_cli/cli/commands/agent/__init__.py
touch src/specify_cli/cli/commands/agent/feature.py
touch src/specify_cli/cli/commands/agent/context.py
touch src/specify_cli/cli/commands/agent/tasks.py
touch src/specify_cli/cli/commands/agent/release.py
# 2. Create test infrastructure
mkdir -p tests/unit/agent
mkdir -p tests/integration
# 3. Test foundation
spec-kitty agent --help # Should display help text
Checkpoint: Foundation complete when spec-kitty agent --help works.
Parallel Streams: Implementation Pattern
Each stream follows this pattern:
Step 1: Read Bash Script Being Replaced
# Example for Stream A
cat .kittify/scripts/bash/create-new-feature.sh | head -100
Understand the bash logic before migrating to Python.
Step 2: Implement Python Equivalent
Pattern for all agent commands:
# src/specify_cli/cli/commands/agent/<module>.py
import json
import typer
from typing_extensions import Annotated
from specify_cli.core.paths import locate_project_root
from specify_cli.cli import console
app = typer.Typer(
name="<module>",
help="<Module> commands for AI agents",
no_args_is_help=True
)
@app.command(name="<command-name>")
def command_name(
arg: Annotated[str, typer.Argument(help="Description")],
json_output: Annotated[bool, typer.Option("--json")] = False,
) -> None:
"""
Command description.
This command is designed for AI agents to call programmatically.
Examples:
spec-kitty agent <command-name> "value" --json
"""
try:
repo_root = locate_project_root()
# ... implementation ...
if json_output:
print(json.dumps({"result": "success", "data": {}}))
else:
console.print("[green]✓[/green] Success message")
except Exception as e:
if json_output:
print(json.dumps({"error": str(e)}))
raise typer.Exit(1)
else:
console.print(f"[red]Error:[/red] {e}")
raise typer.Exit(1)
Step 3: Write Tests
Unit test pattern:
# tests/unit/agent/test_<module>.py
import pytest
from pathlib import Path
from specify_cli.cli.commands.agent.<module> import command_name
def test_command_name_basic():
"""Test command succeeds with valid input."""
# Arrange
test_input = "test-value"
# Act
result = command_name(test_input, json_output=True)
# Assert
assert result["result"] == "success"
def test_command_name_from_worktree(tmp_path):
"""Test command works when executed from worktree."""
# Arrange: Create mock worktree structure
worktree = tmp_path / ".worktrees" / "test-feature"
worktree.mkdir(parents=True)
# Act
result = command_name_from_worktree(worktree)
# Assert
assert result is not None
Integration test pattern:
# tests/integration/test_agent_workflows.py
def test_feature_creation_workflow(tmp_repo):
"""Test full feature creation from main repo and worktree."""
# Arrange
repo_root = setup_test_repo(tmp_repo)
# Act: Create feature from main repo
result = run_command(["spec-kitty", "agent", "create-feature", "test", "--json"])
# Assert
assert result["feature"] == "001-test"
assert Path(result["feature_dir"]).exists()
Step 4: Verify No Conflicts
Before committing, verify you haven't modified files owned by other streams:
git status
# Should only show files in your assigned modules
Coordination Points
Daily Sync (Required): 1. Push your changes to feature branch 2. Run integration tests: pytest tests/integration/ 3. Report status: "Stream X complete" or "Stream X blocked on Y" 4. Pull changes from other streams
Sync Checkpoints:
- Sync 1 (Day 2): Foundation complete, parallel streams begin
- Sync 2 (Day 6): Streams A+B complete
- Sync 3 (Day 8): All streams complete, begin cleanup
- Sync 4 (Day 10): Cleanup complete, begin validation
Testing Your Work
Unit Tests (Run Frequently)
# Test only your module
pytest tests/unit/agent/test_<your_module>.py -v
# Test with coverage
pytest tests/unit/agent/test_<your_module>.py --cov=src/specify_cli/cli/commands/agent/<your_module> --cov-report=term-missing
Target: 90%+ coverage for your module
Integration Tests (Run Before Sync)
# Run all integration tests
pytest tests/integration/ -v
# Run specific workflow test
pytest tests/integration/test_agent_workflows.py::test_<your_workflow> -v
Manual Testing
# Test from main repo
cd /Users/robert/Code/spec-kitty
spec-kitty agent <your-command> <args> --json
# Test from worktree
cd .worktrees/008-unified-python-cli
spec-kitty agent <your-command> <args> --json
Verify: Command works identically from both locations
Common Patterns
Path Resolution
Always use the path resolution utilities:
from specify_cli.core.paths import locate_project_root, resolve_feature_dir
# Get repo root (works from anywhere)
repo_root = locate_project_root()
# Resolve feature directory (worktree-aware)
feature_dir = resolve_feature_dir(repo_root, feature_slug)
JSON Output Mode
Always support both JSON and rich output:
if json_output:
print(json.dumps({"key": "value"}))
else:
console.print("[green]✓[/green] Human-readable message")
Error Handling
Always handle errors gracefully with appropriate output:
try:
# ... operation ...
except FileNotFoundError as e:
if json_output:
print(json.dumps({"error": f"File not found: {e}"}))
raise typer.Exit(1)
else:
console.print(f"[red]Error:[/red] File not found: {e}")
raise typer.Exit(1)
Debugging
Check Agent Command Registration
spec-kitty agent --help
# Should show all subcommands
Verify Path Resolution
# Quick test script
from specify_cli.core.paths import locate_project_root
print(locate_project_root())
# Should work from main repo or worktree
Test JSON Parsing
result=$(spec-kitty agent <command> --json)
echo "$result" | python -m json.tool # Pretty-print JSON
Migration Reference
When migrating bash scripts, refer to these equivalents:
| Bash Pattern | Python Equivalent |
|---|---|
$(get_repo_root) | locate_project_root() |
eval $(get_feature_paths) | resolve_feature_dir(repo_root, feature_slug) |
git rev-parse --show-toplevel | subprocess.run(["git", "rev-parse", "--show-toplevel"]) |
if [ -f "$file" ] | if Path(file).exists() |
if [ -L "$file" ] | if Path(file).is_symlink() |
mkdir -p "$dir" | Path(dir).mkdir(parents=True, exist_ok=True) |
basename "$path" | Path(path).name |
dirname "$path" | Path(path).parent |
Troubleshooting
"Module not found" errors
# Verify you're in correct location
pwd # Should be in worktree
# Install in development mode
pip install -e .
Path resolution failures
# Check .kittify marker exists
ls .kittify/
# Verify git worktree
git worktree list
Test failures
# Run with verbose output
pytest -vv -s tests/unit/agent/test_<module>.py
# Run specific test
pytest tests/unit/agent/test_<module>.py::test_name -vv
Resources
- Spec:
kitty-specs/008-unified-python-cli/spec.md - Plan:
kitty-specs/008-unified-python-cli/plan.md - Research:
kitty-specs/008-unified-python-cli/research.md - Data Model:
kitty-specs/008-unified-python-cli/data-model.md - Typer Docs: https://typer.tiangolo.com/
- pathlib Docs: https://docs.python.org/3/library/pathlib.html
Need Help?
- Check plan.md for phase details and dependencies
- Review research.md for validation findings
- Check data-model.md for entity relationships
- Ask in coordination sync if blocked by another stream