@uniswap/ai-toolkit-nx-claude 0.5.23 → 0.5.24-next.1

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.
@@ -35,7 +35,7 @@ Language-agnostic slash command definitions for Claude Code. Each markdown file
35
35
  - `work-through-pr-comments.md` - Methodically work through PR comments
36
36
  - `generate-commit-message.md` - Generate structured commit messages
37
37
  - `split-stack.md` - Split Graphite PR stacks
38
- - `git-worktree-orchestrator.md` - Create and manage git worktrees with spec-workflow and Linear integration
38
+ - `git-worktree-orchestrator.md` - Create and manage git worktrees with spec-workflow, Graphite, setup scripts, and Linear integration
39
39
 
40
40
  ### Documentation
41
41
 
@@ -118,6 +118,7 @@ Commands that manage larger processes:
118
118
  - `/implement-spec` - Spec task implementation
119
119
  - `/execute-plan` - Plan execution
120
120
  - `/work-through-pr-comments` - Comment resolution workflow
121
+ - `/git-worktree-orchestrator` - Worktree creation with Graphite, setup scripts, and Linear automation
121
122
 
122
123
  ## Development
123
124
 
@@ -1,13 +1,15 @@
1
1
  ---
2
2
  name: git-worktree-orchestrator
3
- description: Create and manage a git worktree based on the current directory and a branch name, with optional spec-workflow setup and Linear task automation.
4
- argument-hint: <branch-name> [linear-task-id]
3
+ description: Create and manage a git worktree based on the current directory and a branch name, with optional spec-workflow setup, Graphite integration, and Linear task automation.
4
+ argument-hint: <branch-name> [--graphite [--trunk <branch>]] [--setup <script-or-command>] [linear-task-id]
5
5
  ---
6
6
 
7
7
  # Git Worktree Orchestrator
8
8
 
9
9
  Create and manage a git worktree based on the current directory and a branch name. After creating the worktree, it copies the .spec-workflow directory, adds the spec-workflow MCP, and can optionally commit/push, open a PR, and clean up the worktree. It also copies other files from the root git worktree into the newly created worktree.
10
10
 
11
+ Supports Graphite integration to track the new branch on top of a trunk branch, and can run a setup script immediately after creating the worktree.
12
+
11
13
  Optionally accepts a Linear task ID to automatically spawn a new Claude Code instance that will complete the task autonomously.
12
14
 
13
15
  ## Usage
@@ -16,13 +18,28 @@ Optionally accepts a Linear task ID to automatically spawn a new Claude Code ins
16
18
  # Create worktree for a new branch
17
19
  /git-worktree-orchestrator add-new-color
18
20
 
19
- # Create worktree and attach a Linear task for autonomous completion
20
- /git-worktree-orchestrator feature/auth-system DEV-1234
21
+ # Create worktree with Graphite tracking (will prompt for trunk branch)
22
+ /git-worktree-orchestrator feature/new-ui --graphite
23
+
24
+ # Create worktree with Graphite tracking on specific trunk
25
+ /git-worktree-orchestrator feature/new-ui --graphite --trunk main
26
+
27
+ # Create worktree and run a setup script
28
+ /git-worktree-orchestrator feature/setup-test --setup "./scripts/setup-dev.sh"
29
+
30
+ # Create worktree and run an inline setup command
31
+ /git-worktree-orchestrator feature/npm-setup --setup "npm install && npm run build"
32
+
33
+ # Full example with all options
34
+ /git-worktree-orchestrator feature/auth-system --graphite --trunk main --setup "npm ci" DEV-1234
21
35
  ```
22
36
 
23
37
  ## Arguments
24
38
 
25
39
  - **branch** (required): Branch name to create/use for the worktree
40
+ - **--graphite, -g** (optional): Enable Graphite integration to track the branch
41
+ - **--trunk <branch>** (optional): Trunk branch name for Graphite tracking (defaults to prompting user, or 'main' if not specified)
42
+ - **--setup <script-or-command>** (optional): Setup script file path or inline command to run after creating the worktree
26
43
  - **linear_task_id** (optional): Linear task ID (e.g., DEV-1234) to complete autonomously in the new worktree
27
44
 
28
45
  ## Prerequisites
@@ -30,6 +47,7 @@ Optionally accepts a Linear task ID to automatically spawn a new Claude Code ins
30
47
  - git (2.5+ for worktree support)
31
48
  - claude CLI (for MCP registration and spawning new instances)
32
49
  - gh (optional, for PR creation)
50
+ - gt (optional, for Graphite integration)
33
51
 
34
52
  ## Workflow Steps
35
53
 
@@ -64,7 +82,36 @@ Registers the spec-workflow MCP with Claude for the new worktree directory:
64
82
  claude mcp add spec-workflow "npx @uniswap/spec-workflow-mcp@latest" "$NEW_DIR"
65
83
  ```
66
84
 
67
- ### Step 6: Optional Operations
85
+ ### Step 6: Graphite Integration (Optional)
86
+
87
+ If Graphite is enabled (via `--graphite` flag or user prompt):
88
+
89
+ 1. Prompts for trunk branch if not provided via `--trunk`
90
+ 2. Runs `gt track` in the new worktree to track the branch on top of the trunk branch
91
+
92
+ ```bash
93
+ gt track --trunk "$TRUNK_BRANCH"
94
+ ```
95
+
96
+ ### Step 7: Setup Script Execution (Optional)
97
+
98
+ If a setup script is provided (via `--setup` flag or user prompt):
99
+
100
+ 1. Detects whether the input is a file path or inline command
101
+ 2. If file: validates existence and executes it
102
+ 3. If inline command: executes directly in the worktree directory
103
+
104
+ ```bash
105
+ # File execution
106
+ if [[ -f "$SETUP_SCRIPT" ]]; then
107
+ bash "$SETUP_SCRIPT"
108
+ else
109
+ # Inline command execution
110
+ eval "$SETUP_SCRIPT"
111
+ fi
112
+ ```
113
+
114
+ ### Step 8: Optional Operations
68
115
 
69
116
  Interactive prompts for:
70
117
 
@@ -73,7 +120,7 @@ Interactive prompts for:
73
120
  - **Create PR**: Create a pull request via `gh` or provide URL for manual creation
74
121
  - **Cleanup**: Remove the worktree after work is complete
75
122
 
76
- ### Step 7: Linear Task Automation
123
+ ### Step 9: Linear Task Automation
77
124
 
78
125
  If a Linear task ID is provided, optionally spawns a new Claude Code instance to:
79
126
 
@@ -91,13 +138,68 @@ If a Linear task ID is provided, optionally spawns a new Claude Code instance to
91
138
  #!/usr/bin/env bash
92
139
  set -euo pipefail
93
140
 
94
- # Accept arguments from positional or env-provided variables (depending on Claude Code runtime)
95
- BRANCH="${1:-${branch:-}}"
96
- LINEAR_TASK_ID="${2:-${linear_task_id:-}}"
141
+ # Initialize variables
142
+ BRANCH=""
143
+ LINEAR_TASK_ID=""
144
+ USE_GRAPHITE=""
145
+ TRUNK_BRANCH=""
146
+ SETUP_SCRIPT=""
147
+
148
+ # Parse arguments
149
+ while [[ $# -gt 0 ]]; do
150
+ case "$1" in
151
+ --graphite|-g)
152
+ USE_GRAPHITE="true"
153
+ shift
154
+ ;;
155
+ --trunk)
156
+ if [[ -n "${2:-}" && ! "$2" =~ ^- ]]; then
157
+ TRUNK_BRANCH="$2"
158
+ shift 2
159
+ else
160
+ echo "Error: --trunk requires a branch name argument"
161
+ exit 1
162
+ fi
163
+ ;;
164
+ --setup)
165
+ if [[ -n "${2:-}" && ! "$2" =~ ^- ]]; then
166
+ SETUP_SCRIPT="$2"
167
+ shift 2
168
+ else
169
+ echo "Error: --setup requires a script path or command argument"
170
+ exit 1
171
+ fi
172
+ ;;
173
+ -*)
174
+ echo "Error: Unknown option: $1"
175
+ echo "Usage: <command> <branch-name> [--graphite| -g] [--trunk <branch>] [--setup <script-or-command>] [linear-task-id]"
176
+ exit 1
177
+ ;;
178
+ *)
179
+ # Positional arguments: first is branch, second is linear_task_id
180
+ if [[ -z "$BRANCH" ]]; then
181
+ BRANCH="$1"
182
+ elif [[ -z "$LINEAR_TASK_ID" ]]; then
183
+ LINEAR_TASK_ID="$1"
184
+ else
185
+ echo "Error: Unexpected argument: $1"
186
+ exit 1
187
+ fi
188
+ shift
189
+ ;;
190
+ esac
191
+ done
192
+
193
+ # Also check for env-provided variables as fallback
194
+ BRANCH="${BRANCH:-${branch:-}}"
195
+ LINEAR_TASK_ID="${LINEAR_TASK_ID:-${linear_task_id:-}}"
196
+ USE_GRAPHITE="${USE_GRAPHITE:-${use_graphite:-}}"
197
+ TRUNK_BRANCH="${TRUNK_BRANCH:-${trunk_branch:-}}"
198
+ SETUP_SCRIPT="${SETUP_SCRIPT:-${setup_script:-}}"
97
199
 
98
200
  if [[ -z "${BRANCH:-}" ]]; then
99
201
  echo "Error: branch name is required."
100
- echo "Usage: <command> <branch-name> [linear-task-id]"
202
+ echo "Usage: <command> <branch-name> [--graphite | -g] [--trunk <branch>] [--setup <script-or-command>] [linear-task-id]"
101
203
  exit 1
102
204
  fi
103
205
 
@@ -205,6 +307,98 @@ else
205
307
  echo " claude mcp add spec-workflow npx @uniswap/spec-workflow-mcp@latest \"$NEW_DIR\""
206
308
  fi
207
309
 
310
+ # Prompt for Graphite usage if not specified
311
+ if [[ -z "${USE_GRAPHITE:-}" ]]; then
312
+ echo ""
313
+ read -r -p "Use Graphite to track this branch? (y/N): " GRAPHITE_RESP || true
314
+ if [[ "$GRAPHITE_RESP" =~ ^[Yy]$ ]]; then
315
+ USE_GRAPHITE="true"
316
+ fi
317
+ fi
318
+
319
+ # Graphite integration
320
+ if [[ "${USE_GRAPHITE:-}" == "true" ]]; then
321
+ echo ""
322
+ echo "============================================"
323
+ echo "Graphite Integration"
324
+ echo "============================================"
325
+
326
+ if ! command -v gt >/dev/null 2>&1; then
327
+ echo "Warning: 'gt' (Graphite CLI) not found. Skipping Graphite setup."
328
+ echo "Install it from: https://graphite.dev/docs/installing-the-cli"
329
+ else
330
+ # Prompt for trunk branch if not provided
331
+ if [[ -z "${TRUNK_BRANCH:-}" ]]; then
332
+ DEFAULT_TRUNK="$(git -C "$NEW_DIR" remote show origin 2>/dev/null | sed -n 's/.*HEAD branch: //p')" || DEFAULT_TRUNK=""
333
+ DEFAULT_TRUNK="${DEFAULT_TRUNK:-main}"
334
+ read -r -p "Enter trunk branch name [$DEFAULT_TRUNK]: " TRUNK_INPUT || true
335
+ TRUNK_BRANCH="${TRUNK_INPUT:-$DEFAULT_TRUNK}"
336
+ fi
337
+
338
+ echo "Tracking branch '$BRANCH' on top of trunk '$TRUNK_BRANCH'..."
339
+ if ! gt -C "$NEW_DIR" track --trunk "$TRUNK_BRANCH"; then
340
+ echo "Warning: Failed to track branch with Graphite. You can run this manually:"
341
+ echo " cd \"$NEW_DIR\" && gt track --trunk \"$TRUNK_BRANCH\""
342
+ else
343
+ echo "Successfully tracked branch with Graphite."
344
+ fi
345
+ fi
346
+ fi
347
+
348
+ # Prompt for setup script if not provided
349
+ if [[ -z "${SETUP_SCRIPT:-}" ]]; then
350
+ echo ""
351
+ read -r -p "Run a setup script/command in the new worktree? (y/N): " SETUP_RESP || true
352
+ if [[ "$SETUP_RESP" =~ ^[Yy]$ ]]; then
353
+ read -r -p "Enter script path or inline command: " SETUP_SCRIPT || true
354
+ fi
355
+ fi
356
+
357
+ # Execute setup script if provided
358
+ if [[ -n "${SETUP_SCRIPT:-}" ]]; then
359
+ echo ""
360
+ echo "============================================"
361
+ echo "Running Setup Script"
362
+ echo "============================================"
363
+ echo "Executing: $SETUP_SCRIPT"
364
+ echo ""
365
+
366
+ # Change to the new worktree directory for script execution
367
+ pushd "$NEW_DIR" >/dev/null
368
+
369
+ # Check if it's a file path (absolute or relative to original directory)
370
+ SCRIPT_PATH=""
371
+ if [[ -f "$SETUP_SCRIPT" ]]; then
372
+ SCRIPT_PATH="$SETUP_SCRIPT"
373
+ elif [[ -f "$CWD/$SETUP_SCRIPT" ]]; then
374
+ SCRIPT_PATH="$CWD/$SETUP_SCRIPT"
375
+ elif [[ -f "$REPO_ROOT/$SETUP_SCRIPT" ]]; then
376
+ SCRIPT_PATH="$REPO_ROOT/$SETUP_SCRIPT"
377
+ fi
378
+
379
+ if [[ -n "$SCRIPT_PATH" ]]; then
380
+ echo "Running script file: $SCRIPT_PATH"
381
+ if [[ -x "$SCRIPT_PATH" ]]; then
382
+ "$SCRIPT_PATH"
383
+ else
384
+ bash "$SCRIPT_PATH"
385
+ fi
386
+ else
387
+ # Treat as inline command
388
+ echo "Running inline command..."
389
+ eval "$SETUP_SCRIPT"
390
+ fi
391
+
392
+ SETUP_EXIT_CODE=$?
393
+ popd >/dev/null
394
+
395
+ if [[ $SETUP_EXIT_CODE -eq 0 ]]; then
396
+ echo "Setup script completed successfully."
397
+ else
398
+ echo "Warning: Setup script exited with code $SETUP_EXIT_CODE"
399
+ fi
400
+ fi
401
+
208
402
  # Prompt for Linear task ID if not provided
209
403
  if [[ -z "${LINEAR_TASK_ID:-}" ]]; then
210
404
  echo ""
@@ -361,7 +555,8 @@ The command creates worktrees in a sibling directory pattern:
361
555
  - **Spec Workflow**: Symlinks `.spec-workflow` from the main repo to enable spec-workflow MCP functionality
362
556
  - **Claude Settings**: Copies local Claude settings to maintain consistent behavior
363
557
  - **Linear Integration**: Supports autonomous task completion when provided with a Linear task ID
364
- - **Graphite Compatible**: Works alongside Graphite for PR stack management
558
+ - **Graphite Integration**: Built-in support for `gt track` to manage branch stacks; tracks new branches on specified trunk
559
+ - **Setup Scripts**: Runs custom setup scripts or commands (e.g., `npm install`, `./scripts/setup.sh`) after worktree creation
365
560
 
366
561
  ## Merging Work Back
367
562
 
@@ -407,4 +602,46 @@ claude mcp add spec-workflow "npx @uniswap/spec-workflow-mcp@latest" "/path/to/w
407
602
 
408
603
  **Solution:** Install Claude Code from <https://claude.ai/download>
409
604
 
605
+ ### "gt (Graphite CLI) not found"
606
+
607
+ **Solution:** Install the Graphite CLI:
608
+
609
+ ```bash
610
+ npm install -g @withgraphite/graphite-cli
611
+ ```
612
+
613
+ Or follow the installation guide at <https://graphite.dev/docs/installing-the-cli>
614
+
615
+ ### "Failed to track branch with Graphite"
616
+
617
+ **Solution:** Ensure you're in a Graphite-enabled repository and the trunk branch exists:
618
+
619
+ ```bash
620
+ cd /path/to/worktree
621
+ gt init # If not already initialized
622
+ gt track --trunk main
623
+ ```
624
+
625
+ ### "Setup script failed"
626
+
627
+ **Solution:** Check that your script:
628
+
629
+ 1. Exists at the specified path (relative to CWD or repo root)
630
+ 2. Has proper execute permissions (`chmod +x script.sh`)
631
+ 3. Returns exit code 0 on success
632
+
633
+ You can test the script manually:
634
+
635
+ ```bash
636
+ cd /path/to/worktree
637
+ ./your-script.sh # or: bash your-script.sh
638
+ ```
639
+
640
+ ### "Setup command not found"
641
+
642
+ **Solution:** Inline commands are executed with `eval` in the worktree directory. Ensure:
643
+
644
+ 1. The command is available in your PATH
645
+ 2. You're using proper shell syntax for chained commands (`&&` for sequential, `;` for independent)
646
+
410
647
  Arguments: $ARGUMENTS
@@ -23,14 +23,19 @@ npx nx generate @uniswap/ai-toolkit-nx-claude:addons \
23
23
 
24
24
  ### Installation Control
25
25
 
26
- - `installMode` - Installation mode:
26
+ - `selectionMode` - Selection mode for which addons to install:
27
27
  - `all` - Install all available addons
28
28
  - `specific` - Choose specific addons to install
29
- - `addon` - Specific addon to install (when `installMode=specific`)
29
+ - `addons` - Specific addons to install (when `selectionMode=specific`)
30
+ - `installationType` - Installation location for MCP servers:
31
+ - `global` - Install to `~/.claude` (available in all projects)
32
+ - `local` - Install to `./.claude` (project-specific configuration)
30
33
 
31
34
  ### Integration Options
32
35
 
33
- - `installMode` (hidden) - Set to "default" or "custom" when called from init generator to prevent duplicate prompts
36
+ - `installMode` (hidden) - Set to "default" or "custom" when called from init generator to control prompting behavior:
37
+ - When `installMode === 'default'`: Skips all prompts, uses `installationType` from parent or defaults to 'global'
38
+ - When undefined (standalone execution): Shows full interactive prompts including `installationType` selection
34
39
 
35
40
  ## Available Addons
36
41
 
@@ -95,10 +100,10 @@ Registered in `addon-registry.ts`:
95
100
 
96
101
  ## Generator Flow
97
102
 
98
- 1. **Mode Selection** (if not from init):
103
+ 1. **Mode Selection** (if running standalone):
99
104
 
100
- - All addons
101
- - Specific addon
105
+ - Selection mode: All addons vs Specific addons
106
+ - Installation location: Global (`~/.claude`) vs Local (`./.claude`)
102
107
 
103
108
  2. **Addon Selection** (if specific mode):
104
109
 
@@ -110,7 +115,9 @@ Registered in `addon-registry.ts`:
110
115
 
111
116
  - For each selected addon:
112
117
  - Run addon's setup function
113
- - Update Claude configuration
118
+ - Install MCP server using `claude mcp add` with appropriate scope:
119
+ - `--scope user` for global installation
120
+ - `--scope project` for local installation
114
121
  - Create necessary files/directories
115
122
  - Install dependencies if needed
116
123
 
@@ -190,21 +197,35 @@ npx nx generate @uniswap/ai-toolkit-nx-claude:addons \
190
197
 
191
198
  ## Integration with Init Generator
192
199
 
193
- The addons generator supports the `installMode` pattern:
200
+ The addons generator supports the `installMode` pattern for programmatic invocation:
194
201
 
195
202
  ```typescript
196
203
  // From init generator
197
204
  await addonsGenerator(tree, {
198
- installMode: normalizedOptions.installMode, // 'default' or 'custom'
199
- addon: 'spec-mcp-workflow', // Pre-selected addon
205
+ installMode: 'default', // or 'custom'
206
+ selectionMode: 'all', // or 'specific'
207
+ installationType: normalizedOptions.installationType, // 'global' or 'local'
208
+ force: false,
209
+ skipVerification: false,
210
+ dashboardMode: 'always',
211
+ port: 0,
200
212
  });
201
213
  ```
202
214
 
203
- When `installMode === 'default'`:
215
+ **Behavior by installMode**:
204
216
 
205
- - Skips installation mode prompt
206
- - Uses provided addon selection
207
- - No user interaction required
217
+ - `installMode === 'default'`:
218
+
219
+ - Skips all interactive prompts
220
+ - Uses `installationType` from init generator (or defaults to 'global')
221
+ - Uses provided `selectionMode` and other options
222
+ - No user interaction required
223
+
224
+ - `installMode` undefined (standalone execution):
225
+ - Shows `selectionMode` prompt (all vs specific)
226
+ - Shows `installationType` prompt (global vs local)
227
+ - Shows addon selection for 'specific' mode
228
+ - Full interactive experience
208
229
 
209
230
  ## Configuration Updates
210
231
 
@@ -127,9 +127,7 @@ async function validateAddonRequirements(addonId) {
127
127
  if (addon.requirements?.node) {
128
128
  const nodeVersion = process.version;
129
129
  if (!nodeVersion.match(/v1[89]\.\d+\.\d+/) && !nodeVersion.match(/v2\d+\.\d+\.\d+/)) {
130
- errors.push(
131
- `Node.js ${addon.requirements.node} required, found ${nodeVersion}`
132
- );
130
+ errors.push(`Node.js ${addon.requirements.node} required, found ${nodeVersion}`);
133
131
  }
134
132
  }
135
133
  if (addon.requirements?.commands) {
@@ -211,7 +209,7 @@ var init_addon_registry = __esm({
211
209
  mcp: {
212
210
  serverName: "slack",
213
211
  command: "npx",
214
- args: ["-y", "@zencoderai/slack-mcp-server", "--transport", "stdio"],
212
+ args: ["-y", "-p", "@zencoderai/slack-mcp-server", "slack-mcp"],
215
213
  env: {
216
214
  SLACK_BOT_TOKEN: "PROMPT_TO_INSERT_SLACK_BOT_TOKEN",
217
215
  SLACK_TEAM_ID: "TKZBCKUJJ"
@@ -233,13 +231,13 @@ var init_addon_registry = __esm({
233
231
  {
234
232
  id: "linear-mcp",
235
233
  name: "Linear MCP",
236
- description: "MCP server for Linear issue tracking (SSE)",
234
+ description: "MCP server for Linear issue tracking (HTTP)",
237
235
  type: "mcp-server",
238
236
  packageName: "linear",
239
237
  mcp: {
240
238
  serverName: "linear",
241
- command: "npx",
242
- args: ["-y", "mcp-remote", "https://mcp.linear.app/sse"]
239
+ transport: "http",
240
+ url: "https://mcp.linear.app/mcp"
243
241
  }
244
242
  },
245
243
  {
@@ -429,7 +427,25 @@ var require_schema = __commonJS({
429
427
  type: "string",
430
428
  description: "Installation mode from parent generator (default or custom)",
431
429
  enum: ["default", "custom"],
432
- hidden: true
430
+ hidden: true,
431
+ "x-skip-prompt": true
432
+ },
433
+ installationType: {
434
+ type: "string",
435
+ description: "Installation location for MCP servers",
436
+ enum: ["global", "local"],
437
+ "prompt-message": "\u{1F4CD} Where should MCP servers be installed?",
438
+ "prompt-type": "list",
439
+ "prompt-items": [
440
+ {
441
+ value: "global",
442
+ label: "Global (~/.claude) - Available in all projects"
443
+ },
444
+ {
445
+ value: "local",
446
+ label: "Local (./.claude) - Project-specific configuration"
447
+ }
448
+ ]
433
449
  }
434
450
  },
435
451
  required: []
@@ -838,7 +854,7 @@ init_addon_registry();
838
854
  var import_child_process = require("child_process");
839
855
  init_addon_registry();
840
856
  async function installMcpServer(options) {
841
- const { addon, additionalArgs = [], dryRun = false } = options;
857
+ const { addon, additionalArgs = [], dryRun = false, installationType = "global" } = options;
842
858
  try {
843
859
  (0, import_child_process.execSync)("claude --version", { stdio: "ignore" });
844
860
  } catch {
@@ -849,7 +865,8 @@ async function installMcpServer(options) {
849
865
  };
850
866
  }
851
867
  const serverName = addon.mcp?.serverName;
852
- let command = `claude mcp add ${serverName} --scope user`;
868
+ const scope = installationType === "local" ? "project" : "user";
869
+ let command = `claude mcp add ${serverName} --scope ${scope}`;
853
870
  if (addon.mcp?.env && Object.keys(addon.mcp.env).length > 0) {
854
871
  for (const [key, value] of Object.entries(addon.mcp.env)) {
855
872
  command += ` --env ${key}=${value}`;
@@ -892,10 +909,8 @@ async function installMcpServer(options) {
892
909
  while (attempts < maxAttempts) {
893
910
  attempts++;
894
911
  try {
895
- console.log(
896
- `
897
- \u{1F527} Installing MCP server (attempt ${attempts}/${maxAttempts})...`
898
- );
912
+ console.log(`
913
+ \u{1F527} Installing MCP server (attempt ${attempts}/${maxAttempts})...`);
899
914
  const output = (0, import_child_process.execSync)(command, {
900
915
  encoding: "utf-8",
901
916
  stdio: "pipe"
@@ -1260,6 +1275,7 @@ async function generator(tree, schema) {
1260
1275
  port: schema.port || 0,
1261
1276
  dry: schema.dry || false,
1262
1277
  installMode: "default",
1278
+ installationType: schema.installationType || "global",
1263
1279
  dryRun: isDryRun
1264
1280
  };
1265
1281
  } else {
@@ -1297,10 +1313,8 @@ async function installSelectedAddons(tree, options) {
1297
1313
  const results = [];
1298
1314
  for (let i = 0; i < selectedAddons.length; i++) {
1299
1315
  const addon = selectedAddons[i];
1300
- console.log(
1301
- `
1302
- [${i + 1}/${selectedAddons.length}] Installing: ${addon.name}`
1303
- );
1316
+ console.log(`
1317
+ [${i + 1}/${selectedAddons.length}] Installing: ${addon.name}`);
1304
1318
  console.log(` ${addon.description}`);
1305
1319
  try {
1306
1320
  if (!options.force && !options.dryRun) {
@@ -1341,23 +1355,17 @@ async function installSelectedAddons(tree, options) {
1341
1355
  });
1342
1356
  options.projectPath = projectPath;
1343
1357
  if (options.dryRun) {
1344
- console.log(
1345
- `
1346
- \u{1F4C1} [DRY-RUN] Would set up project configuration at: ${projectPath}`
1347
- );
1358
+ console.log(`
1359
+ \u{1F4C1} [DRY-RUN] Would set up project configuration at: ${projectPath}`);
1348
1360
  }
1349
1361
  await installProjectSetup(addon, options);
1350
1362
  } else if (options.dryRun) {
1351
- console.log(
1352
- "\n\u{1F4C1} [DRY-RUN] Skipping project configuration (user chose not to set up)"
1353
- );
1363
+ console.log("\n\u{1F4C1} [DRY-RUN] Skipping project configuration (user chose not to set up)");
1354
1364
  }
1355
1365
  }
1356
1366
  results.push({ addon, success: true });
1357
1367
  } catch (error) {
1358
- console.error(
1359
- ` \u274C Failed: ${error instanceof Error ? error.message : String(error)}`
1360
- );
1368
+ console.error(` \u274C Failed: ${error instanceof Error ? error.message : String(error)}`);
1361
1369
  results.push({
1362
1370
  addon,
1363
1371
  success: false,
@@ -1374,9 +1382,7 @@ async function installSelectedAddons(tree, options) {
1374
1382
  if (failed.length > 0) {
1375
1383
  console.log(`
1376
1384
  \u274C Failed to install: ${failed.length}`);
1377
- failed.forEach(
1378
- (r) => console.log(` \u2022 ${r.addon.name} - ${r.error || "Unknown error"}`)
1379
- );
1385
+ failed.forEach((r) => console.log(` \u2022 ${r.addon.name} - ${r.error || "Unknown error"}`));
1380
1386
  }
1381
1387
  if (options.dryRun) {
1382
1388
  console.log("\n\u2728 Dry-run complete! No changes were made.\n");
@@ -1422,9 +1428,7 @@ async function installAllAddons(tree, options) {
1422
1428
  await installMcpAddon(addon, options);
1423
1429
  results.push({ addon, success: true });
1424
1430
  } catch (error) {
1425
- console.error(
1426
- ` \u274C Failed: ${error instanceof Error ? error.message : String(error)}`
1427
- );
1431
+ console.error(` \u274C Failed: ${error instanceof Error ? error.message : String(error)}`);
1428
1432
  results.push({
1429
1433
  addon,
1430
1434
  success: false,
@@ -1441,9 +1445,7 @@ async function installAllAddons(tree, options) {
1441
1445
  if (failed.length > 0) {
1442
1446
  console.log(`
1443
1447
  \u274C Failed to install: ${failed.length}`);
1444
- failed.forEach(
1445
- (r) => console.log(` \u2022 ${r.addon.name} - ${r.error || "Unknown error"}`)
1446
- );
1448
+ failed.forEach((r) => console.log(` \u2022 ${r.addon.name} - ${r.error || "Unknown error"}`));
1447
1449
  }
1448
1450
  if (options.dryRun) {
1449
1451
  console.log("\n\u2728 Dry-run complete! No changes were made.\n");
@@ -1482,7 +1484,8 @@ async function installMcpAddon(addon, options) {
1482
1484
  const installResult = await installMcpServer({
1483
1485
  addon,
1484
1486
  additionalArgs,
1485
- dryRun: options.dryRun
1487
+ dryRun: options.dryRun,
1488
+ installationType: options.installationType || "global"
1486
1489
  });
1487
1490
  if (!installResult.success) {
1488
1491
  throw new Error(installResult.error || installResult.message);
@@ -1524,9 +1527,7 @@ function showGeneralMcpInstructions(installedAddons) {
1524
1527
  const hasSlack = installedAddons.some((addon) => addon.id === "slack-mcp");
1525
1528
  const hasGithub = installedAddons.some((addon) => addon.id === "github-mcp");
1526
1529
  const hasPulumi = installedAddons.some((addon) => addon.id === "pulumi-mcp");
1527
- const hasAws = installedAddons.some(
1528
- (addon) => addon.id === "aws-log-analyzer-mcp"
1529
- );
1530
+ const hasAws = installedAddons.some((addon) => addon.id === "aws-log-analyzer-mcp");
1530
1531
  if (hasSlack || hasGithub || hasAws || hasPulumi) {
1531
1532
  console.log("\u{1F4CB} Specific Authentication Instructions:\n");
1532
1533
  if (hasSlack) {
@@ -1542,18 +1543,12 @@ function showGeneralMcpInstructions(installedAddons) {
1542
1543
  console.log("\u{1F510} GitHub MCP:");
1543
1544
  console.log(" You can obtain your GitHub Personal Access Token using:");
1544
1545
  console.log(" $ gh auth token");
1545
- console.log(
1546
- " (Requires GitHub CLI to be installed and authenticated)\n"
1547
- );
1546
+ console.log(" (Requires GitHub CLI to be installed and authenticated)\n");
1548
1547
  }
1549
1548
  if (hasAws) {
1550
1549
  console.log("\u{1F510} AWS Log Analyzer MCP:");
1551
- console.log(
1552
- " Requires AWS credentials with CloudWatchLogsReadOnlyAccess"
1553
- );
1554
- console.log(
1555
- " \u{1F4D6} Documentation: https://github.com/awslabs/Log-Analyzer-with-MCP\n"
1556
- );
1550
+ console.log(" Requires AWS credentials with CloudWatchLogsReadOnlyAccess");
1551
+ console.log(" \u{1F4D6} Documentation: https://github.com/awslabs/Log-Analyzer-with-MCP\n");
1557
1552
  }
1558
1553
  if (hasPulumi) {
1559
1554
  console.log("\u{1F510} Pulumi MCP:");
@@ -1563,9 +1558,7 @@ function showGeneralMcpInstructions(installedAddons) {
1563
1558
  console.log(
1564
1559
  " \u{1F4D6} Documentation: https://www.pulumi.com/docs/iac/guides/ai-integration/mcp-server/"
1565
1560
  );
1566
- console.log(
1567
- " Create your PAT at: https://app.pulumi.com/account/tokens\n"
1568
- );
1561
+ console.log(" Create your PAT at: https://app.pulumi.com/account/tokens\n");
1569
1562
  }
1570
1563
  }
1571
1564
  }