shotgun-sh 0.4.0.dev1__py3-none-any.whl β†’ 0.6.2__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 (135) hide show
  1. shotgun/agents/agent_manager.py +307 -8
  2. shotgun/agents/cancellation.py +103 -0
  3. shotgun/agents/common.py +12 -0
  4. shotgun/agents/config/README.md +0 -1
  5. shotgun/agents/config/manager.py +10 -7
  6. shotgun/agents/config/models.py +5 -27
  7. shotgun/agents/config/provider.py +44 -27
  8. shotgun/agents/conversation/history/token_counting/base.py +51 -9
  9. shotgun/agents/file_read.py +176 -0
  10. shotgun/agents/messages.py +15 -3
  11. shotgun/agents/models.py +24 -1
  12. shotgun/agents/router/models.py +8 -0
  13. shotgun/agents/router/tools/delegation_tools.py +55 -1
  14. shotgun/agents/router/tools/plan_tools.py +88 -7
  15. shotgun/agents/runner.py +17 -2
  16. shotgun/agents/tools/__init__.py +8 -0
  17. shotgun/agents/tools/codebase/directory_lister.py +27 -39
  18. shotgun/agents/tools/codebase/file_read.py +26 -35
  19. shotgun/agents/tools/codebase/query_graph.py +9 -0
  20. shotgun/agents/tools/codebase/retrieve_code.py +9 -0
  21. shotgun/agents/tools/file_management.py +32 -2
  22. shotgun/agents/tools/file_read_tools/__init__.py +7 -0
  23. shotgun/agents/tools/file_read_tools/multimodal_file_read.py +167 -0
  24. shotgun/agents/tools/markdown_tools/__init__.py +62 -0
  25. shotgun/agents/tools/markdown_tools/insert_section.py +148 -0
  26. shotgun/agents/tools/markdown_tools/models.py +86 -0
  27. shotgun/agents/tools/markdown_tools/remove_section.py +114 -0
  28. shotgun/agents/tools/markdown_tools/replace_section.py +119 -0
  29. shotgun/agents/tools/markdown_tools/utils.py +453 -0
  30. shotgun/agents/tools/registry.py +44 -6
  31. shotgun/agents/tools/web_search/openai.py +42 -23
  32. shotgun/attachments/__init__.py +41 -0
  33. shotgun/attachments/errors.py +60 -0
  34. shotgun/attachments/models.py +107 -0
  35. shotgun/attachments/parser.py +257 -0
  36. shotgun/attachments/processor.py +193 -0
  37. shotgun/build_constants.py +4 -7
  38. shotgun/cli/clear.py +2 -2
  39. shotgun/cli/codebase/commands.py +181 -65
  40. shotgun/cli/compact.py +2 -2
  41. shotgun/cli/context.py +2 -2
  42. shotgun/cli/error_handler.py +2 -2
  43. shotgun/cli/run.py +90 -0
  44. shotgun/cli/spec/backup.py +2 -1
  45. shotgun/codebase/__init__.py +2 -0
  46. shotgun/codebase/benchmarks/__init__.py +35 -0
  47. shotgun/codebase/benchmarks/benchmark_runner.py +309 -0
  48. shotgun/codebase/benchmarks/exporters.py +119 -0
  49. shotgun/codebase/benchmarks/formatters/__init__.py +49 -0
  50. shotgun/codebase/benchmarks/formatters/base.py +34 -0
  51. shotgun/codebase/benchmarks/formatters/json_formatter.py +106 -0
  52. shotgun/codebase/benchmarks/formatters/markdown.py +136 -0
  53. shotgun/codebase/benchmarks/models.py +129 -0
  54. shotgun/codebase/core/__init__.py +4 -0
  55. shotgun/codebase/core/call_resolution.py +91 -0
  56. shotgun/codebase/core/change_detector.py +11 -6
  57. shotgun/codebase/core/errors.py +159 -0
  58. shotgun/codebase/core/extractors/__init__.py +23 -0
  59. shotgun/codebase/core/extractors/base.py +138 -0
  60. shotgun/codebase/core/extractors/factory.py +63 -0
  61. shotgun/codebase/core/extractors/go/__init__.py +7 -0
  62. shotgun/codebase/core/extractors/go/extractor.py +122 -0
  63. shotgun/codebase/core/extractors/javascript/__init__.py +7 -0
  64. shotgun/codebase/core/extractors/javascript/extractor.py +132 -0
  65. shotgun/codebase/core/extractors/protocol.py +109 -0
  66. shotgun/codebase/core/extractors/python/__init__.py +7 -0
  67. shotgun/codebase/core/extractors/python/extractor.py +141 -0
  68. shotgun/codebase/core/extractors/rust/__init__.py +7 -0
  69. shotgun/codebase/core/extractors/rust/extractor.py +139 -0
  70. shotgun/codebase/core/extractors/types.py +15 -0
  71. shotgun/codebase/core/extractors/typescript/__init__.py +7 -0
  72. shotgun/codebase/core/extractors/typescript/extractor.py +92 -0
  73. shotgun/codebase/core/gitignore.py +252 -0
  74. shotgun/codebase/core/ingestor.py +644 -354
  75. shotgun/codebase/core/kuzu_compat.py +119 -0
  76. shotgun/codebase/core/language_config.py +239 -0
  77. shotgun/codebase/core/manager.py +256 -46
  78. shotgun/codebase/core/metrics_collector.py +310 -0
  79. shotgun/codebase/core/metrics_types.py +347 -0
  80. shotgun/codebase/core/parallel_executor.py +424 -0
  81. shotgun/codebase/core/work_distributor.py +254 -0
  82. shotgun/codebase/core/worker.py +768 -0
  83. shotgun/codebase/indexing_state.py +86 -0
  84. shotgun/codebase/models.py +94 -0
  85. shotgun/codebase/service.py +13 -0
  86. shotgun/exceptions.py +9 -9
  87. shotgun/main.py +3 -16
  88. shotgun/posthog_telemetry.py +165 -24
  89. shotgun/prompts/agents/file_read.j2 +48 -0
  90. shotgun/prompts/agents/partials/common_agent_system_prompt.j2 +19 -47
  91. shotgun/prompts/agents/partials/content_formatting.j2 +12 -33
  92. shotgun/prompts/agents/partials/interactive_mode.j2 +9 -32
  93. shotgun/prompts/agents/partials/router_delegation_mode.j2 +21 -22
  94. shotgun/prompts/agents/plan.j2 +14 -0
  95. shotgun/prompts/agents/router.j2 +531 -258
  96. shotgun/prompts/agents/specify.j2 +14 -0
  97. shotgun/prompts/agents/state/codebase/codebase_graphs_available.j2 +14 -1
  98. shotgun/prompts/agents/state/system_state.j2 +13 -11
  99. shotgun/prompts/agents/tasks.j2 +14 -0
  100. shotgun/settings.py +49 -10
  101. shotgun/tui/app.py +149 -18
  102. shotgun/tui/commands/__init__.py +9 -1
  103. shotgun/tui/components/attachment_bar.py +87 -0
  104. shotgun/tui/components/prompt_input.py +25 -28
  105. shotgun/tui/components/status_bar.py +14 -7
  106. shotgun/tui/dependencies.py +3 -8
  107. shotgun/tui/protocols.py +18 -0
  108. shotgun/tui/screens/chat/chat.tcss +15 -0
  109. shotgun/tui/screens/chat/chat_screen.py +766 -235
  110. shotgun/tui/screens/chat/codebase_index_prompt_screen.py +8 -4
  111. shotgun/tui/screens/chat_screen/attachment_hint.py +40 -0
  112. shotgun/tui/screens/chat_screen/command_providers.py +0 -10
  113. shotgun/tui/screens/chat_screen/history/chat_history.py +54 -14
  114. shotgun/tui/screens/chat_screen/history/formatters.py +22 -0
  115. shotgun/tui/screens/chat_screen/history/user_question.py +25 -3
  116. shotgun/tui/screens/database_locked_dialog.py +219 -0
  117. shotgun/tui/screens/database_timeout_dialog.py +158 -0
  118. shotgun/tui/screens/kuzu_error_dialog.py +135 -0
  119. shotgun/tui/screens/model_picker.py +1 -3
  120. shotgun/tui/screens/models.py +11 -0
  121. shotgun/tui/state/processing_state.py +19 -0
  122. shotgun/tui/widgets/widget_coordinator.py +18 -0
  123. shotgun/utils/file_system_utils.py +4 -1
  124. {shotgun_sh-0.4.0.dev1.dist-info β†’ shotgun_sh-0.6.2.dist-info}/METADATA +87 -34
  125. {shotgun_sh-0.4.0.dev1.dist-info β†’ shotgun_sh-0.6.2.dist-info}/RECORD +128 -79
  126. shotgun/cli/export.py +0 -81
  127. shotgun/cli/plan.py +0 -73
  128. shotgun/cli/research.py +0 -93
  129. shotgun/cli/specify.py +0 -70
  130. shotgun/cli/tasks.py +0 -78
  131. shotgun/sentry_telemetry.py +0 -232
  132. shotgun/tui/screens/onboarding.py +0 -584
  133. {shotgun_sh-0.4.0.dev1.dist-info β†’ shotgun_sh-0.6.2.dist-info}/WHEEL +0 -0
  134. {shotgun_sh-0.4.0.dev1.dist-info β†’ shotgun_sh-0.6.2.dist-info}/entry_points.txt +0 -0
  135. {shotgun_sh-0.4.0.dev1.dist-info β†’ shotgun_sh-0.6.2.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,135 @@
1
+ """Error dialog for Windows kuzu/graph database import failures."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from textual.app import ComposeResult
6
+ from textual.containers import Container, Horizontal
7
+ from textual.screen import ModalScreen
8
+ from textual.widgets import Button, Label, Static
9
+
10
+ from shotgun.codebase.core.kuzu_compat import (
11
+ _VC_INSTALL_SCRIPT,
12
+ _VC_REDIST_URL,
13
+ copy_vcpp_script_to_clipboard,
14
+ open_vcpp_download_page,
15
+ )
16
+ from shotgun.logging_config import get_logger
17
+
18
+ logger = get_logger(__name__)
19
+
20
+
21
+ class KuzuErrorDialog(ModalScreen[bool]):
22
+ """Error dialog for Windows kuzu import failures with copy/open buttons."""
23
+
24
+ DEFAULT_CSS = """
25
+ KuzuErrorDialog {
26
+ align: center middle;
27
+ background: rgba(0, 0, 0, 0.5);
28
+ }
29
+
30
+ KuzuErrorDialog > #dialog-container {
31
+ width: 90%;
32
+ max-width: 100;
33
+ height: auto;
34
+ max-height: 90%;
35
+ border: wide $error;
36
+ padding: 1 2;
37
+ layout: vertical;
38
+ background: $surface;
39
+ }
40
+
41
+ #error-title {
42
+ text-style: bold;
43
+ color: $error;
44
+ padding-bottom: 1;
45
+ }
46
+
47
+ #error-message {
48
+ padding: 1 0;
49
+ }
50
+
51
+ #script-display {
52
+ padding: 1;
53
+ margin: 1 0;
54
+ background: $surface-darken-1;
55
+ border: round $primary;
56
+ overflow-x: auto;
57
+ }
58
+
59
+ #status-label {
60
+ color: $success;
61
+ padding: 1 0;
62
+ min-height: 1;
63
+ }
64
+
65
+ #dialog-buttons {
66
+ layout: horizontal;
67
+ align-horizontal: center;
68
+ height: auto;
69
+ padding-top: 1;
70
+ }
71
+
72
+ #dialog-buttons Button {
73
+ margin: 0 1;
74
+ }
75
+ """
76
+
77
+ BINDINGS = [
78
+ ("escape", "close", "Close"),
79
+ ]
80
+
81
+ def compose(self) -> ComposeResult:
82
+ with Container(id="dialog-container"):
83
+ yield Label("Code Indexing Requires Visual C++", id="error-title")
84
+ yield Static(
85
+ "The graph database library requires the Visual C++ Redistributable "
86
+ "to be installed on Windows.\n\n"
87
+ "Run this PowerShell script as Administrator:",
88
+ id="error-message",
89
+ )
90
+ yield Static(_VC_INSTALL_SCRIPT, id="script-display")
91
+ yield Static("", id="status-label")
92
+ with Horizontal(id="dialog-buttons"):
93
+ yield Button(
94
+ "Copy Script to Clipboard", id="copy-btn", variant="primary"
95
+ )
96
+ yield Button("Open Download Page", id="open-btn", variant="default")
97
+ yield Button("Close", id="close-btn", variant="default")
98
+
99
+ def on_button_pressed(self, event: Button.Pressed) -> None:
100
+ """Handle button presses."""
101
+ event.stop()
102
+
103
+ if event.button.id == "copy-btn":
104
+ self._copy_script()
105
+ elif event.button.id == "open-btn":
106
+ self._open_download()
107
+ elif event.button.id == "close-btn":
108
+ self.dismiss(True)
109
+
110
+ def _copy_script(self) -> None:
111
+ """Copy the PowerShell installation script to clipboard."""
112
+ status_label = self.query_one("#status-label", Static)
113
+
114
+ if copy_vcpp_script_to_clipboard():
115
+ status_label.update("Copied script to clipboard!")
116
+ self.query_one("#copy-btn", Button).label = "Copied!"
117
+ logger.debug("Copied VC++ installation script to clipboard")
118
+ else:
119
+ status_label.update(f"Could not copy. Download from: {_VC_REDIST_URL}")
120
+ logger.warning("Failed to copy VC++ script to clipboard")
121
+
122
+ def _open_download(self) -> None:
123
+ """Open the download page in the default browser."""
124
+ status_label = self.query_one("#status-label", Static)
125
+
126
+ if open_vcpp_download_page():
127
+ status_label.update("Opened download page in browser")
128
+ logger.debug(f"Opened VC++ download page: {_VC_REDIST_URL}")
129
+ else:
130
+ status_label.update(f"Could not open browser. URL: {_VC_REDIST_URL}")
131
+ logger.warning("Failed to open VC++ download page")
132
+
133
+ def action_close(self) -> None:
134
+ """Close the dialog."""
135
+ self.dismiss(True)
@@ -326,10 +326,8 @@ class ModelPickerScreen(Screen[ModelConfigUpdated | None]):
326
326
  """Get human-readable model name."""
327
327
  names = {
328
328
  ModelName.GPT_5_1: "GPT-5.1 (OpenAI)",
329
- ModelName.GPT_5_1_CODEX: "GPT-5.1 Codex (OpenAI)",
330
- ModelName.GPT_5_1_CODEX_MINI: "GPT-5.1 Codex Mini (OpenAI)",
329
+ ModelName.GPT_5_2: "GPT-5.2 (OpenAI)",
331
330
  ModelName.CLAUDE_OPUS_4_5: "Claude Opus 4.5 (Anthropic)",
332
- ModelName.CLAUDE_SONNET_4: "Claude Sonnet 4 (Anthropic)",
333
331
  ModelName.CLAUDE_SONNET_4_5: "Claude Sonnet 4.5 (Anthropic)",
334
332
  ModelName.CLAUDE_HAIKU_4_5: "Claude Haiku 4.5 (Anthropic)",
335
333
  ModelName.GEMINI_2_5_PRO: "Gemini 2.5 Pro (Google)",
@@ -0,0 +1,11 @@
1
+ """Models and enums for TUI screens."""
2
+
3
+ from enum import StrEnum
4
+
5
+
6
+ class LockedDialogAction(StrEnum):
7
+ """Actions available in the database locked dialog."""
8
+
9
+ RETRY = "retry"
10
+ DELETE = "delete"
11
+ QUIT = "quit"
@@ -7,6 +7,7 @@ This module provides centralized management of processing state including:
7
7
  - Providing clean cancellation API
8
8
  """
9
9
 
10
+ import asyncio
10
11
  from typing import TYPE_CHECKING, Any
11
12
 
12
13
  from shotgun.logging_config import get_logger
@@ -61,6 +62,7 @@ class ProcessingStateManager:
61
62
  self._spinner_widget: Spinner | None = None
62
63
  self._default_spinner_text = "Processing..."
63
64
  self._telemetry_context = telemetry_context or {}
65
+ self._cancellation_event: asyncio.Event | None = None
64
66
 
65
67
  @property
66
68
  def is_working(self) -> bool:
@@ -71,6 +73,15 @@ class ProcessingStateManager:
71
73
  """
72
74
  return self._working
73
75
 
76
+ @property
77
+ def cancellation_event(self) -> asyncio.Event | None:
78
+ """Get the current cancellation event for agent deps.
79
+
80
+ Returns:
81
+ The cancellation event for the current operation, or None if not processing
82
+ """
83
+ return self._cancellation_event
84
+
74
85
  def bind_spinner(self, spinner: "Spinner") -> None:
75
86
  """Bind a spinner widget for state coordination.
76
87
 
@@ -95,6 +106,9 @@ class ProcessingStateManager:
95
106
  self._working = True
96
107
  text = spinner_text or self._default_spinner_text
97
108
 
109
+ # Create a new cancellation event for this operation
110
+ self._cancellation_event = asyncio.Event()
111
+
98
112
  # Update screen's reactive working state
99
113
  if hasattr(self.screen, "working"):
100
114
  self.screen.working = True
@@ -113,6 +127,7 @@ class ProcessingStateManager:
113
127
 
114
128
  self._working = False
115
129
  self._current_worker = None
130
+ self._cancellation_event = None
116
131
 
117
132
  # Update screen's reactive working state
118
133
  if hasattr(self.screen, "working"):
@@ -151,6 +166,10 @@ class ProcessingStateManager:
151
166
  return False
152
167
 
153
168
  try:
169
+ # Set the cancellation event first for immediate effect on streaming
170
+ if self._cancellation_event:
171
+ self._cancellation_event.set()
172
+
154
173
  self._current_worker.cancel()
155
174
  logger.info("Operation cancelled successfully")
156
175
 
@@ -24,6 +24,7 @@ from shotgun.tui.screens.chat_screen.history.chat_history import ChatHistory
24
24
 
25
25
  if TYPE_CHECKING:
26
26
  from shotgun.agents.context_analyzer.models import ContextAnalysis
27
+ from shotgun.attachments import FileAttachment
27
28
  from shotgun.tui.screens.chat import ChatScreen
28
29
  from shotgun.tui.screens.chat_screen.hint_message import HintMessage
29
30
 
@@ -261,3 +262,20 @@ class WidgetCoordinator:
261
262
  context_indicator.set_streaming(streaming)
262
263
  except Exception as e:
263
264
  logger.exception(f"Failed to set context streaming: {e}")
265
+
266
+ def update_attachment_bar(self, attachment: "FileAttachment | None") -> None:
267
+ """Update the attachment bar with pending attachment.
268
+
269
+ Args:
270
+ attachment: FileAttachment to display, or None to hide bar.
271
+ """
272
+ if not self.screen.is_mounted:
273
+ return
274
+
275
+ try:
276
+ from shotgun.tui.components.attachment_bar import AttachmentBar
277
+
278
+ attachment_bar = self.screen.query_one(AttachmentBar)
279
+ attachment_bar.update_attachment(attachment)
280
+ except Exception as e:
281
+ logger.exception(f"Failed to update attachment bar: {e}")
@@ -1,5 +1,6 @@
1
1
  """File system utility functions."""
2
2
 
3
+ import os
3
4
  from pathlib import Path
4
5
 
5
6
  import aiofiles
@@ -24,7 +25,9 @@ def get_shotgun_home() -> Path:
24
25
  if custom_home := settings.dev.home:
25
26
  return Path(custom_home)
26
27
 
27
- return Path.home() / ".shotgun-sh"
28
+ # Use os.path.join for explicit path separator handling on Windows
29
+ # This avoids potential edge cases with pathlib's / operator
30
+ return Path(os.path.join(os.path.expanduser("~"), ".shotgun-sh"))
28
31
 
29
32
 
30
33
  def ensure_shotgun_directory_exists() -> Path:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: shotgun-sh
3
- Version: 0.4.0.dev1
3
+ Version: 0.6.2
4
4
  Summary: AI-powered research, planning, and task management CLI tool
5
5
  Project-URL: Homepage, https://shotgun.sh/
6
6
  Project-URL: Repository, https://github.com/shotgun-sh/shotgun
@@ -30,14 +30,16 @@ Requires-Dist: jinja2>=3.1.0
30
30
  Requires-Dist: logfire>=2.0.0
31
31
  Requires-Dist: openai>=1.0.0
32
32
  Requires-Dist: packaging>=23.0
33
+ Requires-Dist: pathspec>=0.12.0
33
34
  Requires-Dist: posthog>=3.0.0
35
+ Requires-Dist: psutil>=5.9.0
34
36
  Requires-Dist: pydantic-ai>=1.26.0
35
37
  Requires-Dist: pydantic-settings>=2.0.0
38
+ Requires-Dist: pymupdf>=1.26.7
36
39
  Requires-Dist: pyperclip>=1.10.0
37
- Requires-Dist: real-ladybug>=0.12.0
40
+ Requires-Dist: real-ladybug==0.14.0
38
41
  Requires-Dist: rich>=13.0.0
39
42
  Requires-Dist: sentencepiece>=0.2.0
40
- Requires-Dist: sentry-sdk[pure-eval]>=2.0.0
41
43
  Requires-Dist: tenacity>=8.0.0
42
44
  Requires-Dist: textual-dev>=1.7.0
43
45
  Requires-Dist: textual-serve>=0.1.0
@@ -51,11 +53,6 @@ Requires-Dist: tree-sitter-typescript>=0.23.0
51
53
  Requires-Dist: tree-sitter>=0.21.0
52
54
  Requires-Dist: typer>=0.12.0
53
55
  Requires-Dist: watchdog>=4.0.0
54
- Provides-Extra: dev
55
- Requires-Dist: commitizen>=3.13.0; extra == 'dev'
56
- Requires-Dist: lefthook>=1.12.0; extra == 'dev'
57
- Requires-Dist: mypy>=1.11.0; extra == 'dev'
58
- Requires-Dist: ruff>=0.6.0; extra == 'dev'
59
56
  Description-Content-Type: text/markdown
60
57
 
61
58
  <div align="center">
@@ -97,10 +94,6 @@ Description-Content-Type: text/markdown
97
94
 
98
95
  It includes research on existing patterns, implementation plans that respect your architecture, and task breakdowns ready to export as **AGENTS.md** files. Each spec is complete enough that your AI agent can work longer and further without losing context or creating conflicts.
99
96
 
100
- <p align="center">
101
- <img src="https://github.com/user-attachments/assets/9c7ca014-1ed3-4935-b310-9147b275fdc7" alt="Shotgun Demo" />
102
- </p>
103
-
104
97
  </td>
105
98
  </tr>
106
99
  </table>
@@ -141,12 +134,52 @@ curl -LsSf https://astral.sh/uv/install.sh | sh
141
134
  <td>
142
135
 
143
136
  ```powershell
144
- powershell -c "irm https://astral.sh/uv/install.ps1 | iex"
137
+ powershell -c "irm https://astral.sh/uv/install.ps1 | iex"
145
138
  ```
146
139
  </td>
147
140
  </tr>
148
141
  </table>
149
142
 
143
+ <details>
144
+ <summary><strong>Windows Installation</strong></summary>
145
+
146
+ ```powershell
147
+ # Set execution policy (one-time)
148
+ Set-ExecutionPolicy RemoteSigned -Scope CurrentUser -Force
149
+
150
+ # Install uv
151
+ powershell -c "irm https://astral.sh/uv/install.ps1 | iex"
152
+
153
+ # Add to PATH (or restart terminal)
154
+ $env:Path = "C:\Users\$env:USERNAME\.local\bin;$env:Path"
155
+
156
+ # Run Shotgun (ephemeral)
157
+ uvx --python 3.12 shotgun-sh@latest
158
+
159
+ # Or install permanently
160
+ uv tool install --python 3.12 shotgun-sh
161
+ ```
162
+
163
+ | Supported | Not Supported |
164
+ |-----------|---------------|
165
+ | Windows x64 (regular PCs) | 32-bit Python |
166
+ | Python 3.11-3.13 | Python 3.14+ (no wheels yet) |
167
+
168
+ **Important:** Run in **PowerShell**, not Command Prompt or VS Developer shells.
169
+
170
+ #### Optional: Enable Code Indexing
171
+
172
+ Code indexing requires the Visual C++ Redistributable. Run this in PowerShell (as Administrator):
173
+
174
+ ```powershell
175
+ # Download and install Visual C++ Redistributable
176
+ Import-Module BitsTransfer
177
+ Start-BitsTransfer -Source "https://aka.ms/vs/17/release/vc_redist.x64.exe" -Destination "$env:TEMP\vc_redist.x64.exe"
178
+ Start-Process -FilePath "$env:TEMP\vc_redist.x64.exe" -ArgumentList "/install", "/quiet", "/norestart" -Wait
179
+ ```
180
+
181
+ </details>
182
+
150
183
  _πŸ’‘ Restart your terminal after installation_
151
184
 
152
185
  ### 2. Run Shotgun
@@ -218,17 +251,25 @@ _Click the image above to watch the full demo on YouTube_
218
251
 
219
252
  # 🎯 Usage
220
253
 
221
- Shotgun's Terminal UI guides you through **5 specialized modes** β€” from research to export. Each mode has a dedicated AI agent optimized for that phase.
222
-
223
254
  ### Launch Shotgun in your project directory:
224
255
 
225
256
  | Already Installed | First Time / Try It Out |
226
257
  |-------------------|------------------------|
227
258
  | `shotgun` | `uvx shotgun-sh@latest` |
228
259
 
229
- _The TUI opens automatically. **Press `Shift+Tab` to switch modes** or `Ctrl+P` for the command palette._
260
+ Shotgun's Terminal UI runs a Router that orchestrates your work using two execution modes: **Planning** and **Drafting**.
261
+
262
+ ### Planning vs Drafting
263
+
264
+ | Mode | How It Works | When to Use It |
265
+ |------|--------------|---------------|
266
+ | **Planning** (default) | Shotgun proposes an execution plan, shows each step, and asks for confirmation before running agents that change files. You get checkpoints, can refine the plan, and can confirm or skip cascaded updates when one change affects other docs. | When you want control, visibility, and the ability to refine the plan before execution. |
267
+ | **Drafting** | Shotgun runs the full plan in one go, without intermediate confirmations. Progress is still tracked internally, but you won’t be prompted at each step. | When you’re confident in the plan and want fast, end-to-end execution. |
268
+
269
+ _The TUI opens automatically. **Press `Shift+Tab` to switch between Planning & Drafting** or `Ctrl+P` for the command palette._
230
270
 
231
- ### The 5-Phase Workflow
271
+ ### How the Router Works Internally
272
+ Under the hood, the Router relies on specialized sub-agents. You don’t select or manage them manually.
232
273
 
233
274
  <table>
234
275
  <tr>
@@ -244,22 +285,10 @@ _The TUI opens automatically. **Press `Shift+Tab` to switch modes** or `Ctrl+P`
244
285
  </tr>
245
286
  </table>
246
287
 
247
- _Each phase builds on the previous one, creating a complete specification ready for AI coding agents._
248
-
249
- ### Mode Reference
250
-
251
- | Mode | What It Does | Example Prompt | Output |
252
- |:-----|:-------------|:---------------|:-------|
253
- | **πŸ”¬&nbsp;Research** | Searches codebase + web, identifies patterns | `How do we handle authentication in this codebase?` | `research.md` |
254
- | **πŸ“&nbsp;Specify** | Creates technical specs aware of architecture | `Add OAuth2 authentication with refresh token support` | `specification.md` |
255
- | **πŸ“‹&nbsp;Plan** | Generates implementation roadmap | `Create an implementation plan for the payment system` | `plan.md` |
256
- | **βœ…&nbsp;Tasks** | Breaks plans into actionable items | `Break down the user dashboard plan into tasks` | `tasks.md` |
257
- | **πŸ“€&nbsp;Export** | Formats for AI coding agents | `Export everything to AGENTS.md` | `AGENTS.md` |
288
+ > Planning and Drafting are the only execution modes you control; everything else is handled by the Router.
258
289
 
259
290
  _**Mode switching:** `Shift+Tab` cycles through modes_
260
291
 
261
- _**Visual status:** See current mode and progress at bottom_
262
-
263
292
  ### ⌨️ Keyboard Shortcuts
264
293
 
265
294
  | Shortcut | Action |
@@ -277,7 +306,7 @@ _**Visual status:** See current mode and progress at bottom_
277
306
  | βœ… `Research how we handle auth` | ❌ Jump straight to building |
278
307
  | βœ… `Shotgun please ask me questions first` | ❌ Assume Shotgun knows your needs |
279
308
  | βœ… `I'm working on payments, need refunds` | ❌ `Add refunds` (no context) |
280
- | βœ… Follow Research β†’ Specify β†’ Plan β†’ Tasks | ❌ Skip phases |
309
+ | βœ… Start in Planning mode, let Shotgun propose and refine a plan with you, then run it | ❌ Blast everything in one go without reviewing the plan first (unless you intentionally switch to Drafting mode) |
281
310
 
282
311
  **Result:** Your AI coding agent gets complete contextβ€”what exists, why, and what to build.
283
312
 
@@ -285,6 +314,30 @@ _**Visual status:** See current mode and progress at bottom_
285
314
 
286
315
  ---
287
316
 
317
+ # 🀝 Share Specs with Your Team
318
+
319
+ Sharing specs to a workspace is available on **paid Shotgun plans**.
320
+
321
+ Shotgun lets you share specs externally by publishing them to a **workspace**. This creates a versioned, shareable snapshot your team can access outside the repo.
322
+
323
+ ### How to Share a Spec
324
+
325
+ 1. Hit `Ctrl+P` β†’ select _Share specs to workspace_
326
+ 2. Choose one option:
327
+ - **Create new spec** β€” publish a fresh spec from your current `.shotgun/` files
328
+ - **Add new version** β€” publish an updated version of an existing spec
329
+ 3. Wait for upload to complete. When finished, you can:
330
+ - **Open in Browser** β€” view the shared spec in the workspace
331
+ - **Copy URL** β€” share the link with your team
332
+ - **Done** β€” return to Shotgun
333
+ <img width="516" height="181" alt="image" src="https://github.com/user-attachments/assets/6dd9412c-345e-4dab-a40a-ad5f1c994d34" />
334
+
335
+
336
+ Your local `.shotgun/*.md` files remain unchanged.
337
+ The workspace contains a **shareable, versioned snapshot** of the spec.
338
+
339
+ ---
340
+
288
341
  # ✨ Features
289
342
 
290
343
  ### What Makes Shotgun Different
@@ -329,7 +382,7 @@ Single-agent or one-size-fits-all prompts.
329
382
  <tr>
330
383
  <td><strong>Structured Workflow</strong></td>
331
384
  <td>
332
- 5-phase journey with checkpoints: Research β†’ Spec β†’ Plan β†’ Tasks β†’ Export
385
+ Router-driven flow with Planning and Drafting modes; internally it runs Research β†’ Spec β†’ Plan β†’ Tasks β†’ Export with checkpoints in Planning mode.
333
386
  </td>
334
387
  <td>
335
388
  No structure. Just "prompt and hope."
@@ -376,7 +429,7 @@ We had to implement payments. Cursor, Claude Code, and Copilot all suggested bui
376
429
 
377
430
  **Q: Does Shotgun collect any stats or data?**
378
431
 
379
- A: We only gather minimal, anonymous events (e.g., install, server start, tool call). We don't collect the content itselfβ€”only that an event occurred. We use Sentry for error reporting to improve stability.
432
+ A: We only gather minimal, anonymous events (e.g., install, server start, tool call). We don't collect the content itselfβ€”only that an event occurred. We use PostHog for analytics and error reporting to improve stability.
380
433
 
381
434
  **Q: Does my code leave my computer when indexing?**
382
435
 
@@ -433,7 +486,7 @@ Shotgun is open-source and we welcome contributions. Whether you're fixing bugs,
433
486
 
434
487
  ## πŸš€ Ready to Stop AI Agents from Derailing?
435
488
 
436
- **Research β†’ Specify β†’ Plan β†’ Tasks β†’ Export** β€” Five phases that give AI agents the full picture.
489
+ **Planning β†’ Drafting** β€” Two execution modes that give AI agents the full picture, backed by internal phases for Research β†’ Specify β†’ Plan β†’ Tasks β†’ Export.
437
490
 
438
491
  ```bash
439
492
  uvx shotgun-sh@latest