-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinstall.sh
More file actions
executable file
·457 lines (397 loc) · 15.9 KB
/
Copy pathinstall.sh
File metadata and controls
executable file
·457 lines (397 loc) · 15.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
#!/bin/bash
# tech-lead-stack installer
SOURCE_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
if [[ "${1:-}" != "--link" ]]; then
echo "Usage: ./install.sh --link [--ide auto|cursor|continue|none] [target_path]"
exit 1
fi
shift
IDE_MODE="auto"
TARGET_DIR=""
while [[ $# -gt 0 ]]; do
case "$1" in
--ide)
if [[ -z "${2:-}" ]]; then
echo "Error: --ide requires a value (auto, cursor, continue, or none)."
exit 1
fi
IDE_MODE="$2"
shift 2
;;
*)
TARGET_DIR=$(realpath "$1")
shift
;;
esac
done
[[ -z "$TARGET_DIR" ]] && TARGET_DIR=$(realpath ".")
case "$IDE_MODE" in
auto|cursor|continue|none) ;;
*)
echo "Error: --ide must be auto, cursor, continue, or none (got: $IDE_MODE)"
exit 1
;;
esac
should_install_cursor_skills() {
case "$IDE_MODE" in
cursor) return 0 ;;
none) return 1 ;;
auto)
if [[ -n "${CURSOR_TRACE_ID:-}" ]] || [[ -n "${CURSOR_AGENT:-}" ]]; then
return 0
fi
return 1
;;
esac
}
should_install_continue() {
case "$IDE_MODE" in
continue) return 0 ;;
none) return 1 ;;
auto)
if [[ -d "$HOME/.continue" ]] || [[ -d "$TARGET_DIR/.continue" ]] || [[ -n "${VSCODE_IPC_HOOK_CLI:-}" ]]; then
return 0
fi
return 1
;;
esac
}
setup_cursor_skills() {
local manifest="$SOURCE_DIR/.ai/cursor-skills.manifest"
if [[ ! -f "$manifest" ]]; then
echo "⚠️ Cursor skills manifest not found at $manifest — skipping."
return
fi
mkdir -p "$HOME/.cursor/skills"
echo "🎯 Installing Cursor skills under $HOME/.cursor/skills (symlinks to this repo)..."
local line dir rel src dest_dir count=0
while IFS= read -r line || [[ -n "$line" ]]; do
[[ -z "${line//[[:space:]]/}" ]] && continue
[[ "$line" =~ ^[[:space:]]*# ]] && continue
dir=$(echo "$line" | cut -d'|' -f1 | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
rel=$(echo "$line" | cut -d'|' -f2 | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
[[ -z "$dir" || -z "$rel" ]] && continue
src="$SOURCE_DIR/$rel"
if [[ ! -f "$src" ]]; then
echo " ⚠️ Missing source for Cursor skill '$dir': $src"
continue
fi
dest_dir="$HOME/.cursor/skills/$dir"
mkdir -p "$dest_dir"
ln -sfn "$src" "$dest_dir/SKILL.md"
echo " ✅ $dir → $rel"
count=$((count + 1))
done < "$manifest"
echo " 📌 Linked $count skill(s). Re-run install if you move the tech-lead-stack repo."
}
setup_cursor_mcp_environment() {
local mcp_file="$HOME/.cursor/mcp.json"
if ! command -v jq &> /dev/null; then
echo " ⚠️ jq not found — skipping Cursor MCP JSON merge."
return
fi
mkdir -p "$(dirname "$mcp_file")"
if [[ -f "$mcp_file" ]] && grep -q "tech-lead-stack" "$mcp_file" 2>/dev/null; then
echo " - Cursor MCP already references tech-lead-stack."
return
fi
if [[ -f "$mcp_file" ]]; then
jq --arg cmd "npm" \
--arg prefix "$SOURCE_DIR" \
'.mcpServers = (.mcpServers // {}) | .mcpServers["tech-lead-stack"] = {"command": $cmd, "args": ["--prefix", $prefix, "--silent", "run", "mcp:start"]}' \
"$mcp_file" > /tmp/mcp_cursor_tls.json && mv /tmp/mcp_cursor_tls.json "$mcp_file"
else
jq -n --arg cmd "npm" \
--arg prefix "$SOURCE_DIR" \
'{mcpServers: {"tech-lead-stack": {"command": $cmd, "args": ["--prefix", $prefix, "--silent", "run", "mcp:start"]}}}' \
> "$mcp_file"
fi
echo " ✅ Added tech-lead-stack MCP server for Cursor: $mcp_file"
}
setup_continue() {
local config_file="$HOME/.continue/config.yaml"
mkdir -p "$(dirname "$config_file")"
if [[ ! -f "$config_file" ]]; then
echo "models: []" > "$config_file"
fi
echo " - Merging tech-lead-stack into Continue config..."
# 1. Safely merge mcpServers to avoid duplicate root keys
if grep -q "tech-lead-stack:" "$config_file" 2>/dev/null; then
echo " - tech-lead-stack MCP server already present in Continue config."
else
# Use awk to inject into existing mcpServers key, or append if missing
SOURCE_DIR="$SOURCE_DIR" awk '
BEGIN { mcp_done=0; }
/^mcpServers:/ {
print $0
print " tech-lead-stack:"
print " command: npm"
print " args:"
print " - --prefix"
print " - \"" ENVIRON["SOURCE_DIR"] "\""
print " - --silent"
print " - run"
print " - mcp:start"
mcp_done=1
next
}
{ print }
END {
if (mcp_done == 0) {
print "mcpServers:"
print " tech-lead-stack:"
print " command: npm"
print " args:"
print " - --prefix"
print " - \"" ENVIRON["SOURCE_DIR"] "\""
print " - --silent"
print " - run"
print " - mcp:start"
}
}
' "$config_file" > /tmp/continue_config.yaml && mv /tmp/continue_config.yaml "$config_file"
echo " ✅ Added tech-lead-stack MCP server to Continue config."
fi
# 2. Symlink workflows into ~/.continue/prompts/
# Continue v2.0.0 reliably reads .prompt files here, allowing single-source execution.
local prompts_dir="$HOME/.continue/prompts"
mkdir -p "$prompts_dir"
echo " - Symlinking workflows to $prompts_dir..."
local count=0
for wf in "$SOURCE_DIR/.agents/workflows/"*.md; do
if [[ -f "$wf" ]]; then
local wf_name
wf_name=$(basename "$wf" .md)
local dest_file="$prompts_dir/$wf_name.prompt"
ln -sfn "$wf" "$dest_file"
count=$((count + 1))
fi
done
echo " ✅ Linked $count Continue prompts. Re-run install if you move the tech-lead-stack repo."
echo " ✅ Configured Continue globally."
}
echo "🚀 Initializing Tech-Lead Stack..."
echo " IDE mode: $IDE_MODE"
# 0. Smart Package Manager & Project Health Check
detect_manager() {
if [[ -f "$TARGET_DIR/pnpm-lock.yaml" ]]; then echo "pnpm"
elif [[ -f "$TARGET_DIR/yarn.lock" ]]; then echo "yarn"
elif [[ -f "$TARGET_DIR/bun.lockb" ]]; then echo "bun"
else echo "npm"
fi
}
PKG_MANAGER=$(detect_manager)
echo "📦 Detected project manager: $PKG_MANAGER"
if [[ -f "$TARGET_DIR/package.json" ]]; then
echo "🔍 Reviewing project health..."
if ! node -e "try { require('$TARGET_DIR/package.json') } catch(e) { process.exit(1) }" &> /dev/null; then
echo "⚠️ Warning: $TARGET_DIR/package.json appeared to be invalid."
echo " Proceeding with caution, but you might want to check it for syntax errors or invalid names."
fi
fi
# Ensure stack's own dependencies are installed using the preferred manager
echo "🛠️ Ensuring Stack dependencies are installed with $PKG_MANAGER..."
(cd "$SOURCE_DIR" && "$PKG_MANAGER" install --quiet)
# 1. Symlinks (Robust & Non-Recursive)
mkdir -p "$TARGET_DIR/.github"
# helper for safe symlinking
safe_ln() {
local src="$1"
local dest="$2"
# Don't symlink if source and target are identical
if [[ "$(realpath "$src")" == "$(realpath "$dest" 2>/dev/null)" ]]; then
echo " - Skipping identical path: $dest"
return
fi
ln -nfs "$src" "$dest"
}
echo "🔗 Linking components..."
safe_ln "$SOURCE_DIR/.ai" "$TARGET_DIR/.ai"
safe_ln "$SOURCE_DIR/.agents" "$TARGET_DIR/.agents"
# Root-level AGENTS.md so Jules, Cursor, Copilot etc. read it automatically.
# Guard: never overwrite a real file — only create/refresh our own symlink.
if [[ -e "$TARGET_DIR/AGENTS.md" && ! -L "$TARGET_DIR/AGENTS.md" ]]; then
echo " - AGENTS.md already exists as a real file — leaving it alone."
else
safe_ln "$SOURCE_DIR/.ai/agents.md" "$TARGET_DIR/AGENTS.md"
echo " ✅ Linked root AGENTS.md"
fi
cp "$SOURCE_DIR/templates/PULL_REQUEST_TEMPLATE.md" "$TARGET_DIR/.github/PULL_REQUEST_TEMPLATE.md"
if [[ ! -d "$TARGET_DIR/.github/workflows" ]]; then
mkdir -p "$TARGET_DIR/.github/workflows"
fi
if [[ ! -f "$TARGET_DIR/.github/workflows/design-review-trigger.yml" ]]; then
cp "$SOURCE_DIR/docs/github-action-example.yml" "$TARGET_DIR/.github/workflows/design-review-trigger.yml"
echo " ✅ Added GitHub Action for Design Review triggers"
else
echo " - GitHub Action design-review-trigger.yml already exists"
fi
# 2. Python Setup
echo "🐍 Ensuring Python dependencies are met..."
python3 -m pip install -r "$SOURCE_DIR/requirements.txt" --quiet
# 3. GitHub CLI Setup
echo "🛠️ Ensuring GitHub CLI (gh) is installed..."
if ! command -v gh &> /dev/null; then
echo " - GitHub CLI not found. Attempting to install via Homebrew..."
if command -v brew &> /dev/null; then
brew install gh
else
echo "❌ Homebrew is required to auto-install gh on macOS. Please install gh manually: https://cli.github.com"
fi
else
echo " - GitHub CLI is already installed."
fi
echo "🔐 Checking GitHub CLI authentication status..."
if ! gh auth status &> /dev/null; then
echo " ⚠️ Not authenticated with GitHub CLI."
echo " 👉 Please open a NEW terminal window and run: gh auth login"
echo " ⏳ Waiting for successful authentication to continue..."
while ! gh auth status &> /dev/null; do
sleep 5
echo -n "."
done
echo ""
echo " ✅ Successfully authenticated with GitHub!"
else
echo " - Already authenticated with GitHub."
fi
# 4. RTK Setup & Immediate Pre-Flight Check
if ! command -v rtk &> /dev/null; then
echo "🛠️ Installing RTK via curl..."
curl -fsSL https://raw.githubusercontent.com/rtk-ai/rtk/refs/heads/master/install.sh | sh
fi
if command -v rtk &> /dev/null; then
echo "🤖 Initializing RTK..."
(cd "$TARGET_DIR" && rtk init)
echo "📡 Running Mission Control Pre-Flight..."
(cd "$TARGET_DIR" && bash "$SOURCE_DIR/scripts/rtk-run.sh" run mission-control)
else
echo "❌ RTK setup failed. Please install it manually: https://rtk-ai.app"
fi
# 4b. Antigravity Knowledge Items Bootstrap
echo "📚 Bootstrapping Antigravity Knowledge Items directory..."
mkdir -p "$HOME/.gemini/antigravity/knowledge"
echo " ✅ Knowledge Items directory initialized: $HOME/.gemini/antigravity/knowledge"
# 4c. Reflexion Loop (✨ Special Feature) — key check
# The Reflexion Loop is the one non-agent-agnostic skill: it calls Gemini AND
# Claude directly. No new deps to install (it reuses @ai-sdk/* already in
# package.json and is exposed automatically via the MCP server). We only verify
# the keys so the feature is ready to use, and never block install if absent.
echo "✨ Checking Reflexion Loop (special feature) prerequisites..."
# Load the stack's .env if present so we can read keys.
[ -f "$SOURCE_DIR/.env" ] && set -a && . "$SOURCE_DIR/.env" && set +a
if [[ -n "${GEMINI_API_KEY:-}" && -n "${ANTHROPIC_API_KEY:-}" ]]; then
echo " ✅ GEMINI_API_KEY + ANTHROPIC_API_KEY found — '/reflexion-loop' is ready."
else
echo " ℹ️ Reflexion Loop needs GEMINI_API_KEY and ANTHROPIC_API_KEY in your .env."
echo " Add them (see .env.example) to enable 'rtk run reflexion-loop' and the website page."
fi
# 5. Generic MCP Configuration (Claude Desktop, etc.)
setup_mcp_environment() {
# Check common configuration paths for various agents/IDEs
local config_paths=(
"$HOME/Library/Application Support/Claude/claude_desktop_config.json"
"$HOME/.config/Claude/claude_desktop_config.json"
)
for config_file in "${config_paths[@]}"; do
if [[ -f "$config_file" ]]; then
echo "⚙️ Detected Agent configuration at: $config_file"
# Check if server already exists
if ! grep -q "tech-lead-stack" "$config_file"; then
echo " ✨ Adding tech-lead-stack to Agent tools..."
if command -v jq &> /dev/null; then
local tmp_config="/tmp/mcp_config_tmp.json"
# Use --prefix instead of cwd for universal compatibility
jq --arg name "tech-lead-stack" \
--arg cmd "npm" \
--arg prefix "$SOURCE_DIR" \
'.mcpServers[$name] = {"command": $cmd, "args": ["--prefix", $prefix, "--silent", "run", "mcp:start"]}' \
"$config_file" > "$tmp_config" && mv "$tmp_config" "$config_file"
echo " ✅ Successfully configured!"
else
echo " ⚠️ jq not found. Skipping automated JSON update to avoid corruption."
fi
else
echo " - Configuration already present."
fi
fi
done
}
setup_mcp_environment
# 5b. Cursor: global skills (no files under TARGET_DIR) + MCP
if should_install_cursor_skills; then
echo ""
echo "🖱️ Cursor detected or --ide cursor: configuring global skills and MCP..."
setup_cursor_skills
setup_cursor_mcp_environment
elif [[ "$IDE_MODE" == "auto" ]]; then
echo ""
echo "💡 Skipping global Cursor skills (IDE mode auto; not in Cursor terminal). Use --ide cursor to install ~/.cursor/skills links."
fi
# 5c. Continue: global config (+ MCP and Prompts)
if should_install_continue; then
echo ""
echo "🔄 Continue detected or --ide continue: configuring global Continue config..."
setup_continue
elif [[ "$IDE_MODE" == "auto" ]]; then
echo ""
echo "💡 Skipping global Continue config (IDE mode auto; not in VS Code/Continue). Use --ide continue to install to ~/.continue/config.yaml."
fi
echo "✨ Initialization complete."
echo ""
# 6. Native Alias Automation
ALIAS_CMD="alias rtk='$SOURCE_DIR/scripts/rtk-run.sh'"
ALIAS_ADDED=false
add_alias_to_rc() {
local rc_file="$1"
if [[ -f "$rc_file" ]]; then
# Check if this exact alias command is already in the file
if ! grep -Fxq "$ALIAS_CMD" "$rc_file"; then
echo "" >> "$rc_file"
echo "# Tech-Lead Stack local RTK alias for $(pwd)" >> "$rc_file"
echo "$ALIAS_CMD" >> "$rc_file"
echo " ✅ Added native 'rtk' alias to: $rc_file"
ALIAS_ADDED=true
else
echo " - Alias already exists in: $rc_file"
ALIAS_ADDED=true
fi
fi
}
echo "⚙️ Configuring native shell commands..."
add_alias_to_rc "$HOME/.zshrc"
add_alias_to_rc "$HOME/.bashrc"
echo ""
echo "----------------------------------------------------------------"
echo "🚨 IMPORTANT: AGENT TELEMETRY CONFIGURATION 🚨"
echo "----------------------------------------------------------------"
echo "To track skill usage, add this to your Agent's MCP settings:"
echo ""
echo "{"
echo " \"mcpServers\": {"
echo " \"tech-lead-stack\": {"
echo " \"command\": \"npm\","
echo " \"args\": ["
echo " \"--prefix\","
echo " \"$SOURCE_DIR\","
echo " \"--silent\","
echo " \"run\","
echo " \"mcp:start\""
echo " ]"
echo " }"
echo " }"
echo "}"
echo ""
echo "🔧 FIXED: \"Property cwd is not allowed\""
echo "We now use the --prefix flag inside the args list, which is"
echo "supported by all MCP clients including Antigravity."
echo ""
echo "Cursor users: install also merges this into ~/.cursor/mcp.json when --ide cursor or auto-detect runs."
echo "----------------------------------------------------------------"
echo ""
if [ "$ALIAS_ADDED" = true ]; then
echo "💡 Tip: Restart your terminal or run \`source ~/.zshrc\` (or .bashrc) to use 'rtk run <tool>' natively!"
else
echo "💡 Tip: We couldn't find your .zshrc or .bashrc. To use 'rtk run <tool>' natively, manually run:"
echo " $ALIAS_CMD"
fi