lite-kits 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. lite_kits/__init__.py +9 -0
  2. lite_kits/cli.py +481 -0
  3. lite_kits/installer.py +417 -0
  4. lite_kits/kits/README.md +191 -0
  5. lite_kits/kits/git/README.md +374 -0
  6. lite_kits/kits/git/claude/commands/cleanup.md +361 -0
  7. lite_kits/kits/git/claude/commands/commit.md +612 -0
  8. lite_kits/kits/git/claude/commands/pr.md +593 -0
  9. lite_kits/kits/git/github/prompts/cleanup.prompt.md +382 -0
  10. lite_kits/kits/git/github/prompts/commit.prompt.md +591 -0
  11. lite_kits/kits/git/github/prompts/pr.prompt.md +603 -0
  12. lite_kits/kits/git/scripts/bash/get-git-context.sh +208 -0
  13. lite_kits/kits/git/scripts/powershell/Get-GitContext.ps1 +242 -0
  14. lite_kits/kits/multiagent/README.md +395 -0
  15. lite_kits/kits/multiagent/claude/commands/sync.md +331 -0
  16. lite_kits/kits/multiagent/github/prompts/sync.prompt.md +331 -0
  17. lite_kits/kits/multiagent/memory/git-worktrees-protocol.md +370 -0
  18. lite_kits/kits/multiagent/memory/parallel-work-protocol.md +536 -0
  19. lite_kits/kits/multiagent/memory/pr-workflow-guide.md +281 -0
  20. lite_kits/kits/multiagent/templates/collaboration-structure/README.md +166 -0
  21. lite_kits/kits/multiagent/templates/decision.md +79 -0
  22. lite_kits/kits/multiagent/templates/handoff.md +95 -0
  23. lite_kits/kits/multiagent/templates/session-log.md +68 -0
  24. lite_kits/kits/project/README.md +244 -0
  25. lite_kits/kits/project/claude/commands/orient.md +163 -0
  26. lite_kits/kits/project/github/prompts/orient.prompt.md +163 -0
  27. lite_kits-0.1.0.dist-info/METADATA +415 -0
  28. lite_kits-0.1.0.dist-info/RECORD +31 -0
  29. lite_kits-0.1.0.dist-info/WHEEL +4 -0
  30. lite_kits-0.1.0.dist-info/entry_points.txt +2 -0
  31. lite_kits-0.1.0.dist-info/licenses/LICENSE +21 -0
lite_kits/__init__.py ADDED
@@ -0,0 +1,9 @@
1
+ """
2
+ spec-kit-multiagent: Lightweight multi-agent coordination add-on for GitHub spec-kit
3
+
4
+ This package adds multi-agent coordination capabilities to vanilla spec-kit projects
5
+ without forking or replacing any core files.
6
+ """
7
+
8
+ __version__ = "0.1.0"
9
+ __all__ = ["__version__"]
lite_kits/cli.py ADDED
@@ -0,0 +1,481 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ CLI for lite-kits
4
+
5
+ Provides commands to add/remove enhancement kits for vanilla dev tools.
6
+ """
7
+
8
+ import sys
9
+ from pathlib import Path
10
+ from typing import Optional
11
+
12
+ import typer
13
+ from rich.console import Console
14
+ from rich.panel import Panel
15
+ from rich.table import Table
16
+
17
+ from . import __version__
18
+ from .installer import Installer
19
+
20
+ # Constants
21
+ APP_NAME = "lite-kits"
22
+ APP_DESCRIPTION = "Lightweight enhancement kits for vanilla dev tools"
23
+ HELP_TIP = "Tip: Run 'lite-kits COMMAND --help' for detailed help on each command"
24
+
25
+ # Kit names
26
+ KIT_PROJECT = "project"
27
+ KIT_GIT = "git"
28
+ KIT_MULTIAGENT = "multiagent"
29
+ KITS_ALL = [KIT_PROJECT, KIT_GIT, KIT_MULTIAGENT]
30
+ KITS_RECOMMENDED = [KIT_PROJECT, KIT_GIT]
31
+
32
+ # Help panel names
33
+ PANEL_KIT_MANAGEMENT = "Kit Management"
34
+ PANEL_PACKAGE_MANAGEMENT = "Package Management"
35
+
36
+ # Kit descriptions
37
+ KIT_DESC_PROJECT = "/orient command, project orientation features"
38
+ KIT_DESC_GIT = "/commit, /pr, /cleanup commands with smart workflows"
39
+ KIT_DESC_MULTIAGENT = "/sync, collaboration directories, memory guides"
40
+
41
+ # Status indicators
42
+ STATUS_OK = "[green][OK][/green]"
43
+ STATUS_NOT_FOUND = "[dim][--][/dim]"
44
+ STATUS_ERROR = "[red][X][/red]"
45
+
46
+ # Marker files for kit detection
47
+ MARKER_PROJECT_KIT = ".claude/commands/orient.md"
48
+ MARKER_GIT_KIT = ".claude/commands/commit.md"
49
+ MARKER_MULTIAGENT_KIT = ".specify/memory/pr-workflow-guide.md"
50
+
51
+ # Error messages
52
+ ERROR_NO_TARGET = "Either --here or a target directory must be specified"
53
+ ERROR_NOT_SPEC_KIT = "does not appear to be a spec-kit project"
54
+ ERROR_SPEC_KIT_HINT = "Looking for one of: .specify/, .claude/, or .github/prompts/"
55
+
56
+ app = typer.Typer(
57
+ name=APP_NAME,
58
+ help=f"{APP_DESCRIPTION}\n\n[dim]{HELP_TIP}[/dim]",
59
+ no_args_is_help=True,
60
+ add_completion=False, # Disable shell completion to avoid modifying user profiles
61
+ add_help_option=False, # Don't show --help in command help (redundant)
62
+ rich_markup_mode="rich",
63
+ )
64
+ console = Console()
65
+
66
+
67
+ def version_callback(value: bool):
68
+ """Print version and exit."""
69
+ if value:
70
+ console.print(f"{APP_NAME} version {__version__}")
71
+ raise typer.Exit()
72
+
73
+
74
+ @app.callback()
75
+ def main(
76
+ version: Optional[bool] = typer.Option(
77
+ None,
78
+ "--version",
79
+ "-v",
80
+ help="Show version and exit",
81
+ callback=version_callback,
82
+ is_eager=True,
83
+ ),
84
+ ):
85
+ f"""{APP_NAME}: {APP_DESCRIPTION}"""
86
+ pass
87
+
88
+
89
+ @app.command(name="add", rich_help_panel=PANEL_KIT_MANAGEMENT)
90
+ def add_kits(
91
+ here: bool = typer.Option(
92
+ False,
93
+ "--here",
94
+ help="Add to current directory",
95
+ ),
96
+ dry_run: bool = typer.Option(
97
+ False,
98
+ "--dry-run",
99
+ help="Preview changes without applying them",
100
+ ),
101
+ kit: Optional[str] = typer.Option(
102
+ None,
103
+ "--kit",
104
+ help=f"Comma-separated list of kits to add: {','.join(KITS_ALL)} (default: {KIT_PROJECT})",
105
+ ),
106
+ recommended: bool = typer.Option(
107
+ False,
108
+ "--recommended",
109
+ help=f"Add recommended kits: {' + '.join(KITS_RECOMMENDED)}",
110
+ ),
111
+ target: Optional[Path] = typer.Argument(
112
+ None,
113
+ help="Target directory (defaults to current directory)",
114
+ ),
115
+ ):
116
+ """Add enhancement kits to a spec-kit project."""
117
+ if not here and target is None:
118
+ console.print(
119
+ f"[red]Error:[/red] {ERROR_NO_TARGET}",
120
+ style="bold",
121
+ )
122
+ raise typer.Exit(1)
123
+
124
+ target_dir = Path.cwd() if here else target
125
+
126
+ # Determine which kits to install
127
+ kits = None
128
+ if recommended:
129
+ kits = KITS_RECOMMENDED
130
+ elif kit:
131
+ kits = [k.strip() for k in kit.split(',')]
132
+ # else: kits=None will use default [KIT_PROJECT] in Installer
133
+
134
+ try:
135
+ installer = Installer(target_dir, kits=kits)
136
+ except ValueError as e:
137
+ console.print(f"[red]Error:[/red] {e}", style="bold")
138
+ raise typer.Exit(1)
139
+
140
+ # Validate target is a spec-kit project
141
+ if not installer.is_spec_kit_project():
142
+ console.print(
143
+ f"[red]Error:[/red] {target_dir} {ERROR_NOT_SPEC_KIT}",
144
+ style="bold",
145
+ )
146
+ console.print(
147
+ f"\n{ERROR_SPEC_KIT_HINT}",
148
+ style="dim",
149
+ )
150
+ raise typer.Exit(1)
151
+
152
+ # Check if already installed
153
+ if installer.is_multiagent_installed():
154
+ console.print(
155
+ "[yellow]Warning:[/yellow] Enhancement kits appear to be already installed",
156
+ style="bold",
157
+ )
158
+ if not typer.confirm("Reinstall anyway?"):
159
+ raise typer.Exit(0)
160
+
161
+ # Preview or install
162
+ if dry_run:
163
+ console.print("\n[bold cyan]Dry run - no changes will be made[/bold cyan]\n")
164
+ changes = installer.preview_installation()
165
+ _display_changes(changes)
166
+ else:
167
+ console.print(f"\n[bold green]Adding enhancement kits to {target_dir}[/bold green]\n")
168
+
169
+ with console.status("[bold green]Adding kits..."):
170
+ result = installer.install()
171
+
172
+ if result["success"]:
173
+ console.print("\n[bold green][OK] Kits added successfully![/bold green]\n")
174
+ _display_installation_summary(result)
175
+ else:
176
+ console.print(f"\n[bold red][X] Failed to add kits:[/bold red] {result['error']}\n")
177
+ raise typer.Exit(1)
178
+
179
+
180
+ @app.command(rich_help_panel=PANEL_KIT_MANAGEMENT)
181
+ def remove(
182
+ here: bool = typer.Option(
183
+ False,
184
+ "--here",
185
+ help="Remove from current directory",
186
+ ),
187
+ kit: Optional[str] = typer.Option(
188
+ None,
189
+ "--kit",
190
+ help=f"Comma-separated list of kits to remove: {','.join(KITS_ALL)}",
191
+ ),
192
+ all_kits: bool = typer.Option(
193
+ False,
194
+ "--all",
195
+ help="Remove all kits",
196
+ ),
197
+ target: Optional[Path] = typer.Argument(
198
+ None,
199
+ help="Target directory (defaults to current directory)",
200
+ ),
201
+ ):
202
+ """
203
+ Remove enhancement kits from a spec-kit project.
204
+
205
+ Returns the project to vanilla spec-kit state.
206
+
207
+ Examples:
208
+ lite-kits remove --here --kit git # Remove git-kit only
209
+ lite-kits remove --here --kit project,git # Remove specific kits
210
+ lite-kits remove --here --all # Remove all kits
211
+ """
212
+ if not here and target is None:
213
+ console.print(
214
+ "[red]Error:[/red] Either --here or a target directory must be specified",
215
+ style="bold",
216
+ )
217
+ raise typer.Exit(1)
218
+
219
+ target_dir = Path.cwd() if here else target
220
+
221
+ # Determine which kits to remove
222
+ kits = None
223
+ if all_kits:
224
+ kits = KITS_ALL
225
+ elif kit:
226
+ kits = [k.strip() for k in kit.split(',')]
227
+ else:
228
+ console.print("[yellow]Error:[/yellow] Specify --kit or --all", style="bold")
229
+ console.print("\nExamples:", style="dim")
230
+ console.print(f" {APP_NAME} remove --here --kit {KIT_GIT}", style="dim")
231
+ console.print(f" {APP_NAME} remove --here --all", style="dim")
232
+ raise typer.Exit(1)
233
+
234
+ try:
235
+ installer = Installer(target_dir, kits=kits)
236
+ except ValueError as e:
237
+ console.print(f"[red]Error:[/red] {e}", style="bold")
238
+ raise typer.Exit(1)
239
+
240
+ # Check if kits are installed
241
+ if not installer.is_multiagent_installed():
242
+ console.print("[yellow]Warning:[/yellow] No kits detected to remove", style="bold")
243
+ raise typer.Exit(0)
244
+
245
+ # Confirm removal
246
+ console.print(f"\n[bold yellow]Remove kits from {target_dir}[/bold yellow]")
247
+ console.print(f"Kits to remove: {', '.join(kits)}\n")
248
+
249
+ if not typer.confirm("Continue with removal?"):
250
+ console.print("Cancelled")
251
+ raise typer.Exit(0)
252
+
253
+ # Remove kits
254
+ console.print("\n[bold]Removing kits...[/bold]\n")
255
+ with console.status("[bold yellow]Removing..."):
256
+ result = installer.remove()
257
+
258
+ if result["success"]:
259
+ console.print("[bold green]Removal complete![/bold green]\n")
260
+ if result["removed"]:
261
+ console.print("[bold]Removed:[/bold]")
262
+ for item in result["removed"]:
263
+ console.print(f" - {item}")
264
+ else:
265
+ console.print("[dim]No files found to remove[/dim]")
266
+ else:
267
+ console.print(f"\n[bold red]Removal failed:[/bold red] {result['error']}\n")
268
+ raise typer.Exit(1)
269
+
270
+
271
+ @app.command(rich_help_panel=PANEL_KIT_MANAGEMENT)
272
+ def validate(
273
+ here: bool = typer.Option(
274
+ False,
275
+ "--here",
276
+ help="Validate current directory",
277
+ ),
278
+ target: Optional[Path] = typer.Argument(
279
+ None,
280
+ help="Target directory (defaults to current directory)",
281
+ ),
282
+ ):
283
+ """
284
+ Validate enhancement kit installation.
285
+
286
+ Checks:
287
+ - Kit files are present and correctly installed
288
+ - Collaboration directory structure (if multiagent-kit installed)
289
+ - Required files present
290
+ - Cross-kit consistency
291
+
292
+ Example:
293
+ lite-kits validate --here
294
+ """
295
+ # Default to current directory if no target specified
296
+ if here or target is None:
297
+ target_dir = Path.cwd()
298
+ else:
299
+ target_dir = target
300
+
301
+ # For validation, we don't know which kits are installed yet, so check for all
302
+ installer = Installer(target_dir, kits=KITS_ALL)
303
+
304
+ console.print(f"\n[bold cyan]Validating {target_dir}[/bold cyan]\n")
305
+
306
+ # Check if it's a spec-kit project
307
+ if not installer.is_spec_kit_project():
308
+ console.print("[red][X] Not a spec-kit project[/red]")
309
+ raise typer.Exit(1)
310
+
311
+ # Check if any kits are installed
312
+ if not installer.is_multiagent_installed():
313
+ console.print("[yellow]⚠ No enhancement kits installed[/yellow]")
314
+ console.print(f" Run: {APP_NAME} add --here --recommended", style="dim")
315
+ raise typer.Exit(1)
316
+
317
+ # Validate structure
318
+ with console.status("[bold cyan]Validating..."):
319
+ validation_result = installer.validate()
320
+
321
+ _display_validation_results(validation_result)
322
+
323
+ if validation_result["valid"]:
324
+ console.print("\n[bold green][OK] Validation passed![/bold green]")
325
+ raise typer.Exit(0)
326
+ else:
327
+ console.print("\n[bold red][X] Validation failed[/bold red]")
328
+ raise typer.Exit(1)
329
+
330
+
331
+ @app.command(rich_help_panel=PANEL_KIT_MANAGEMENT)
332
+ def status(
333
+ here: bool = typer.Option(
334
+ False,
335
+ "--here",
336
+ help="Check current directory",
337
+ ),
338
+ target: Optional[Path] = typer.Argument(
339
+ None,
340
+ help="Target directory (defaults to current directory)",
341
+ ),
342
+ ):
343
+ """
344
+ Show enhancement kit installation status for the project.
345
+
346
+ Displays:
347
+ - Spec-kit project detection
348
+ - Installed kits
349
+ - Installation health
350
+
351
+ Example:
352
+ lite-kits status --here
353
+ """
354
+ # Default to current directory if no target specified
355
+ if here or target is None:
356
+ target_dir = Path.cwd()
357
+ else:
358
+ target_dir = target
359
+
360
+ # For status, check for all possible kits
361
+ installer = Installer(target_dir, kits=KITS_ALL)
362
+
363
+ console.print(f"\n[bold cyan]Project Status: {target_dir}[/bold cyan]\n")
364
+
365
+ # Basic checks
366
+ is_spec_kit = installer.is_spec_kit_project()
367
+
368
+ # Check individual kits
369
+ project_kit_installed = (target_dir / MARKER_PROJECT_KIT).exists()
370
+ git_kit_installed = (target_dir / MARKER_GIT_KIT).exists()
371
+ multiagent_kit_installed = (target_dir / MARKER_MULTIAGENT_KIT).exists()
372
+
373
+ table = Table(show_header=False, box=None)
374
+ table.add_column("Item", style="cyan")
375
+ table.add_column("Status")
376
+
377
+ table.add_row("Spec-kit project", STATUS_OK if is_spec_kit else STATUS_ERROR)
378
+ table.add_row(f"{KIT_PROJECT}-kit", STATUS_OK if project_kit_installed else STATUS_NOT_FOUND)
379
+ table.add_row(f"{KIT_GIT}-kit", STATUS_OK if git_kit_installed else STATUS_NOT_FOUND)
380
+ table.add_row(f"{KIT_MULTIAGENT}-kit", STATUS_OK if multiagent_kit_installed else STATUS_NOT_FOUND)
381
+
382
+ console.print(table)
383
+ console.print()
384
+
385
+
386
+ def _display_changes(changes: dict):
387
+ """Display preview of changes."""
388
+ console.print("[bold]Files to be created:[/bold]")
389
+ for file in changes.get("new_files", []):
390
+ console.print(f" [green]+[/green] {file}")
391
+
392
+ console.print("\n[bold]Files to be modified:[/bold]")
393
+ for file in changes.get("modified_files", []):
394
+ console.print(f" [yellow]~[/yellow] {file}")
395
+
396
+ console.print("\n[bold]Directories to be created:[/bold]")
397
+ for dir in changes.get("new_directories", []):
398
+ console.print(f" [blue]+[/blue] {dir}")
399
+
400
+
401
+ def _display_installation_summary(result: dict):
402
+ """Display kit addition summary."""
403
+ console.print("[bold]Added:[/bold]")
404
+ for item in result.get("installed", []):
405
+ console.print(f" [OK] {item}")
406
+
407
+ console.print("\n[bold cyan]Next steps:[/bold cyan]")
408
+ console.print(" 1. Run: /orient (in your AI assistant)")
409
+ console.print(f" 2. Check: {MARKER_PROJECT_KIT} or .github/prompts/orient.prompt.md")
410
+ console.print(f" 3. Validate: {APP_NAME} validate --here")
411
+
412
+
413
+ def _display_validation_results(result: dict):
414
+ """Display validation results."""
415
+ for check_name, check_result in result.get("checks", {}).items():
416
+ status = "[OK]" if check_result["passed"] else "[X]"
417
+ color = "green" if check_result["passed"] else "red"
418
+ console.print(f"[{color}]{status}[/{color}] {check_name}")
419
+
420
+ if not check_result["passed"] and "message" in check_result:
421
+ console.print(f" {check_result['message']}", style="dim")
422
+
423
+
424
+ @app.command(name="info", rich_help_panel=PANEL_PACKAGE_MANAGEMENT)
425
+ def package_info():
426
+ """Show package information and installation details."""
427
+ # Use __version__ from package instead of importlib.metadata
428
+ console.print(f"\n[bold cyan]{APP_NAME} v{__version__}[/bold cyan]")
429
+ console.print(f"[dim]{APP_DESCRIPTION}[/dim]\n")
430
+
431
+ # Package info
432
+ info_table = Table(show_header=False, box=None, padding=(0, 2))
433
+ info_table.add_column("Key", style="cyan")
434
+ info_table.add_column("Value")
435
+
436
+ info_table.add_row("Version", __version__)
437
+ info_table.add_row("Repository", "https://github.com/tmorgan181/lite-kits")
438
+ info_table.add_row("License", "MIT")
439
+
440
+ console.print(info_table)
441
+ console.print()
442
+
443
+ # Available kits
444
+ console.print("[bold]Available Kits:[/bold]")
445
+ console.print(f" • [cyan]{KIT_PROJECT}[/cyan]: {KIT_DESC_PROJECT}")
446
+ console.print(f" • [cyan]{KIT_GIT}[/cyan]: {KIT_DESC_GIT}")
447
+ console.print(f" • [cyan]{KIT_MULTIAGENT}[/cyan]: {KIT_DESC_MULTIAGENT}")
448
+ console.print()
449
+
450
+ # Quick start
451
+ console.print("[bold]Quick Start:[/bold]")
452
+ console.print(f" 1. [cyan]{APP_NAME} add --here --recommended[/cyan] # Add project + git kits")
453
+ console.print(f" 2. [cyan]{APP_NAME} status --here[/cyan] # Check installation")
454
+ console.print(f" 3. [cyan]/orient[/cyan] # Run in your AI assistant")
455
+ console.print()
456
+
457
+ # Package management
458
+ console.print("[bold]Package Management:[/bold]")
459
+ console.print(f" Install: [dim]uv tool install {APP_NAME}[/dim]")
460
+ console.print(f" Update: [dim]uv tool install --upgrade {APP_NAME}[/dim]")
461
+ console.print(f" Uninstall: [dim]uv tool uninstall {APP_NAME}[/dim]")
462
+ console.print()
463
+
464
+
465
+ @app.command(name="uninstall", rich_help_panel=PANEL_PACKAGE_MANAGEMENT)
466
+ def package_uninstall():
467
+ """Instructions for uninstalling the lite-kits package."""
468
+ console.print(f"\n[bold yellow]Uninstall {APP_NAME}[/bold yellow]\n")
469
+
470
+ console.print("To uninstall the package, run:\n")
471
+ console.print(f" [cyan]uv tool uninstall {APP_NAME}[/cyan]\n")
472
+
473
+ console.print("[dim]Or with pip:[/dim]\n")
474
+ console.print(f" [dim]pip uninstall {APP_NAME}[/dim]\n")
475
+
476
+ console.print("[bold]Note:[/bold] This will remove the package but NOT the kits you've added to projects.")
477
+ console.print(f"To remove kits from a project, first run: [cyan]{APP_NAME} remove --here --all[/cyan]\n")
478
+
479
+
480
+ if __name__ == "__main__":
481
+ app()