@woopsy/ai-agent-skills 1.0.0

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.
package/install.ps1 ADDED
@@ -0,0 +1,463 @@
1
+ <#
2
+ .SYNOPSIS
3
+ Auto-installs AI Agent Skills to all detected agent platforms.
4
+
5
+ .DESCRIPTION
6
+ Detects your Obsidian vault (connect or scaffold), detects installed AI agents,
7
+ and installs secondary-brain + obsidian skills to each one.
8
+
9
+ .PARAMETER VaultPath
10
+ Explicit path to your Obsidian vault (skips auto-detection).
11
+
12
+ .PARAMETER SkipAgentDetect
13
+ Skip agent detection and just configure the vault.
14
+
15
+ .PARAMETER DryRun
16
+ Show what would be done without actually writing files.
17
+
18
+ .EXAMPLE
19
+ .\install.ps1
20
+ .\install.ps1 -VaultPath "C:\Users\me\Documents\Obsidian Vault"
21
+ .\install.ps1 -DryRun
22
+ #>
23
+
24
+ param(
25
+ [string]$VaultPath,
26
+ [switch]$SkipAgentDetect,
27
+ [switch]$DryRun
28
+ )
29
+
30
+ $ErrorActionPreference = "Stop"
31
+ $RepoRoot = Split-Path -Parent $PSCommandPath
32
+
33
+ function Write-Step { Write-Host "`n=== $args[0] ===" -ForegroundColor Cyan }
34
+ function Write-OK { Write-Host " $args[0]" -ForegroundColor Green }
35
+ function Write-Warn { Write-Host " $args[0]" -ForegroundColor Yellow }
36
+ function Write-Fail { Write-Host " $args[0]" -ForegroundColor Red }
37
+ function Write-Info { Write-Host " $args[0]" -ForegroundColor Gray }
38
+
39
+ # --- Detect environment ---
40
+ function Test-IsWSL {
41
+ try {
42
+ $model = (Get-CimInstance Win32_ComputerSystem).Model
43
+ return $model -match "WSL" -or $env:WSLENV
44
+ } catch {
45
+ return $false
46
+ }
47
+ }
48
+
49
+ # --- Detect or scaffold vault ---
50
+ function Find-OrCreateVault {
51
+ param([string]$ExplicitPath)
52
+
53
+ if ($ExplicitPath) {
54
+ $vault = Resolve-Path $ExplicitPath -ErrorAction SilentlyContinue
55
+ if (-not $vault) { throw "Specified vault path not found: $ExplicitPath" }
56
+ return $vault.Path
57
+ }
58
+
59
+ $obsidianConfig = "$env:APPDATA\Obsidian\obsidian.json"
60
+ if (Test-Path $obsidianConfig) {
61
+ try {
62
+ $config = Get-Content $obsidianConfig -Raw | ConvertFrom-Json
63
+ if ($config.vaults) {
64
+ foreach ($entry in $config.vaults.PSObject.Properties) {
65
+ $vp = $entry.Value.path
66
+ if (Test-Path (Join-Path $vp "SecondaryBrain\GLOBAL-PROJECT-MEMORY.md")) {
67
+ Write-OK "SecondaryBrain vault found at: $vp"
68
+ return $vp
69
+ }
70
+ }
71
+ foreach ($entry in $config.vaults.PSObject.Properties) {
72
+ $vp = $entry.Value.path
73
+ if (Test-Path $vp) {
74
+ Write-Warn "No SecondaryBrain in '$vp' - will scaffold"
75
+ return $vp
76
+ }
77
+ }
78
+ }
79
+ } catch {
80
+ Write-Warn "Could not parse Obsidian config: $_"
81
+ }
82
+ }
83
+
84
+ $commonPaths = @(
85
+ "$env:USERPROFILE\Documents\Obsidian Vault",
86
+ "$env:USERPROFILE\Obsidian",
87
+ "$env:USERPROFILE\Documents\Obsidian",
88
+ "$env:USERPROFILE\Documents\Vault"
89
+ )
90
+ foreach ($cp in $commonPaths) {
91
+ if (Test-Path (Join-Path $cp "SecondaryBrain\GLOBAL-PROJECT-MEMORY.md")) {
92
+ Write-OK "SecondaryBrain vault found at: $cp"
93
+ return $cp
94
+ }
95
+ }
96
+
97
+ Write-Warn "No Obsidian vault detected."
98
+ $default = "$env:USERPROFILE\Documents\Obsidian Vault"
99
+ Write-Host " Default location: $default"
100
+ $ans = Read-Host " Use this path? [Y/n]"
101
+ if ($ans -eq "n" -or $ans -eq "no") {
102
+ $custom = Read-Host " Enter vault path"
103
+ if (-not $custom) { throw "Vault path required" }
104
+ $default = $custom
105
+ }
106
+
107
+ return $default
108
+ }
109
+
110
+ function Scaffold-Vault {
111
+ param([string]$VaultRoot)
112
+
113
+ $sbDir = Join-Path $VaultRoot "SecondaryBrain"
114
+ $sysDir = Join-Path $sbDir "_System"
115
+ $mpDir = Join-Path $sbDir "_ManualPrompting"
116
+
117
+ if (Test-Path $sbDir) {
118
+ Write-OK "SecondaryBrain directory already exists"
119
+ return
120
+ }
121
+
122
+ if ($DryRun) {
123
+ Write-Info "[DRY-RUN] Would create: $sbDir"
124
+ return
125
+ }
126
+
127
+ New-Item -ItemType Directory -Path $sbDir -Force | Out-Null
128
+ New-Item -ItemType Directory -Path $sysDir -Force | Out-Null
129
+ New-Item -ItemType Directory -Path $mpDir -Force | Out-Null
130
+
131
+ $globalLines = @(
132
+ "# GLOBAL PROJECT MEMORY",
133
+ "",
134
+ "Global source of truth and index for the SecondaryBrain.",
135
+ "",
136
+ "## Project clusters",
137
+ "",
138
+ "*(Add your projects here)*",
139
+ "",
140
+ "## Evolution timeline",
141
+ "",
142
+ "*(Track changes here)*",
143
+ "",
144
+ "## Deprecated Nodes",
145
+ "",
146
+ "*(Archived nodes go here)*"
147
+ )
148
+ Set-Content -Path (Join-Path $sbDir "GLOBAL-PROJECT-MEMORY.md") -Value ($globalLines -join "`r`n")
149
+
150
+ $refLines = @(
151
+ '# Reference Architecture Protocol - "Deep Mode"',
152
+ "",
153
+ "The full-ceremony ruleset for the SecondaryBrain.",
154
+ "Apply these rules when explicitly working in **deep mode**.",
155
+ "",
156
+ "See skills/secondary-brain/reference/deep-mode.md in the skill repository."
157
+ )
158
+ Set-Content -Path (Join-Path $sysDir "reference-architecture-protocol.md") -Value ($refLines -join "`r`n")
159
+
160
+ Write-OK "SecondaryBrain vault scaffolded at: $sbDir"
161
+ }
162
+
163
+ # --- Detect AI agents ---
164
+ function Find-InstalledAgents {
165
+ $agents = @{}
166
+
167
+ $checks = @(
168
+ @{ Name = "claude-code"; Path = "$env:USERPROFILE\.claude\settings.json"; Type = "claude" }
169
+ @{ Name = "opencode"; Path = "$env:USERPROFILE\.config\opencode\opencode.jsonc"; Type = "opencode" }
170
+ @{ Name = "cursor"; Path = "$env:USERPROFILE\.cursor\"; Type = "cursor" }
171
+ @{ Name = "codex"; Path = "$env:USERPROFILE\.codex\"; Type = "codex" }
172
+ @{ Name = "gemini"; Path = "$env:USERPROFILE\.gemini\"; Type = "gemini" }
173
+ @{ Name = "antigravity"; Path = "$env:LOCALAPPDATA\antigravity\"; Type = "antigravity" }
174
+ @{ Name = "copilot"; Path = "$env:LOCALAPPDATA\GitHub\copilot\"; Type = "copilot" }
175
+ )
176
+
177
+ foreach ($c in $checks) {
178
+ if (Test-Path $c.Path) {
179
+ $agents[$c.Name] = $c.Type
180
+ Write-OK "$($c.Name) detected"
181
+ }
182
+ }
183
+
184
+ return $agents
185
+ }
186
+
187
+ # --- Install skills to an agent ---
188
+ function Install-ToAgent {
189
+ param(
190
+ [string]$AgentName,
191
+ [string]$AgentType,
192
+ [string]$VaultRoot
193
+ )
194
+
195
+ $skillContent = Get-Content (Join-Path $RepoRoot "skills\secondary-brain\SKILL.md") -Raw
196
+ $resolved = $skillContent -replace '\{\{VAULT_PATH\}\}', $VaultRoot
197
+
198
+ if ($DryRun) {
199
+ Write-Info "[DRY-RUN] Would install secondary-brain to $AgentName ($AgentType)"
200
+ return
201
+ }
202
+
203
+ switch ($AgentType) {
204
+ "claude" {
205
+ $targets = @(
206
+ "$env:USERPROFILE\.skills-manager\skills\secondary-brain"
207
+ "$env:USERPROFILE\.claude\skills\secondary-brain"
208
+ )
209
+ foreach ($t in $targets) {
210
+ New-Item -ItemType Directory -Path $t -Force | Out-Null
211
+ Set-Content -Path (Join-Path $t "SKILL.md") -Value $resolved
212
+ if (Test-Path "$RepoRoot\skills\secondary-brain\reference") {
213
+ Copy-Item "$RepoRoot\skills\secondary-brain\reference\*" "$t\reference\" -Recurse -Force
214
+ }
215
+ if (Test-Path "$RepoRoot\skills\secondary-brain\templates") {
216
+ Copy-Item "$RepoRoot\skills\secondary-brain\templates\*" "$t\templates\" -Recurse -Force
217
+ }
218
+ }
219
+ Write-OK "Installed secondary-brain to Claude Code"
220
+
221
+ $settingsPath = "$env:USERPROFILE\.claude\settings.json"
222
+ if (Test-Path $settingsPath) {
223
+ try {
224
+ $settings = Get-Content $settingsPath -Raw | ConvertFrom-Json
225
+ if (-not $settings.enabledPlugins) {
226
+ $settings | Add-Member -NotePropertyName "enabledPlugins" -NotePropertyValue @{}
227
+ }
228
+ $settings.enabledPlugins | Add-Member -NotePropertyName "secondary-brain@local" -NotePropertyValue $true -Force
229
+ $settings | ConvertTo-Json -Depth 10 | Set-Content $settingsPath -Force
230
+ Write-OK "Registered secondary-brain in Claude Code settings"
231
+ } catch {
232
+ Write-Warn "Could not update Claude Code settings: $_"
233
+ }
234
+ }
235
+ }
236
+ "opencode" {
237
+ $target = "$env:USERPROFILE\.config\opencode\skills\secondary-brain"
238
+ New-Item -ItemType Directory -Path $target -Force | Out-Null
239
+ New-Item -ItemType Directory -Path "$target\reference" -Force | Out-Null
240
+ New-Item -ItemType Directory -Path "$target\templates" -Force | Out-Null
241
+ Set-Content -Path (Join-Path $target "SKILL.md") -Value $resolved
242
+ if (Test-Path "$RepoRoot\skills\secondary-brain\reference") {
243
+ Copy-Item "$RepoRoot\skills\secondary-brain\reference\*" "$target\reference\" -Force
244
+ }
245
+ if (Test-Path "$RepoRoot\skills\secondary-brain\templates") {
246
+ Copy-Item "$RepoRoot\skills\secondary-brain\templates\*" "$target\templates\" -Force
247
+ }
248
+ Write-OK "Installed secondary-brain to opencode"
249
+ }
250
+ "cursor" {
251
+ $targetDir = "$env:USERPROFILE\.cursor\rules"
252
+ New-Item -ItemType Directory -Path $targetDir -Force | Out-Null
253
+ $mdcLines = @(
254
+ "---"
255
+ 'description: "SecondaryBrain - persistent project memory via Obsidian vault"'
256
+ 'globs: "**/*"'
257
+ "---"
258
+ ""
259
+ $resolved
260
+ )
261
+ Set-Content -Path (Join-Path $targetDir "secondary-brain.mdc") -Value ($mdcLines -join "`r`n")
262
+ Write-OK "Installed secondary-brain to Cursor"
263
+ }
264
+ "codex" {
265
+ $target = "$env:USERPROFILE\.codex\skills\secondary-brain"
266
+ New-Item -ItemType Directory -Path $target -Force | Out-Null
267
+ New-Item -ItemType Directory -Path "$target\reference" -Force | Out-Null
268
+ New-Item -ItemType Directory -Path "$target\templates" -Force | Out-Null
269
+ Set-Content -Path (Join-Path $target "SKILL.md") -Value $resolved
270
+ if (Test-Path "$RepoRoot\skills\secondary-brain\reference") {
271
+ Copy-Item "$RepoRoot\skills\secondary-brain\reference\*" "$target\reference\" -Force
272
+ }
273
+ if (Test-Path "$RepoRoot\skills\secondary-brain\templates") {
274
+ Copy-Item "$RepoRoot\skills\secondary-brain\templates\*" "$target\templates\" -Force
275
+ }
276
+ Write-OK "Installed secondary-brain to Codex"
277
+ }
278
+ "gemini" {
279
+ $targetDir = "$env:USERPROFILE\.gemini\instructions"
280
+ New-Item -ItemType Directory -Path $targetDir -Force | Out-Null
281
+ Set-Content -Path (Join-Path $targetDir "secondary-brain.md") -Value $resolved
282
+ Write-OK "Installed secondary-brain to Gemini Code Assist"
283
+ }
284
+ "antigravity" {
285
+ $target = "$env:LOCALAPPDATA\antigravity\skills\secondary-brain"
286
+ New-Item -ItemType Directory -Path $target -Force | Out-Null
287
+ Set-Content -Path (Join-Path $target "SKILL.md") -Value $resolved
288
+ Write-OK "Installed secondary-brain to Antigravity"
289
+ }
290
+ "copilot" {
291
+ $target = "$env:USERPROFILE\.github\copilot-instructions.md"
292
+ $existing = ""
293
+ if (Test-Path $target) { $existing = Get-Content $target -Raw }
294
+ $copilotLines = @(
295
+ ""
296
+ "## SecondaryBrain Protocol"
297
+ ""
298
+ "Before any task, read GLOBAL-PROJECT-MEMORY.md and the relevant project cluster."
299
+ "After changes, update project nodes and GLOBAL-PROJECT-MEMORY.md."
300
+ "Reuse patterns from Ai - skills/ when possible."
301
+ )
302
+ $copilotSection = $copilotLines -join "`r`n"
303
+ if ($existing -notmatch "SecondaryBrain") {
304
+ Add-Content $target -Value $copilotSection
305
+ Write-OK "Appended SecondaryBrain instructions to GitHub Copilot"
306
+ } else {
307
+ Write-Info "GitHub Copilot already has SecondaryBrain instructions"
308
+ }
309
+ }
310
+ }
311
+ }
312
+
313
+ # --- Copy dependency skills to an agent ---
314
+ function Install-DependencySkills {
315
+ param([string]$AgentName, [string]$AgentType)
316
+
317
+ $deps = @(
318
+ @{ Name = "obsidian-skills"; Src = "skills\obsidian"; Label = "Obsidian" }
319
+ @{ Name = "graphify"; Src = "skills\graphify"; Label = "Graphify" }
320
+ )
321
+
322
+ foreach ($dep in $deps) {
323
+ $srcDir = Join-Path $RepoRoot $dep.Src
324
+ if (-not (Test-Path $srcDir)) {
325
+ continue
326
+ }
327
+ if ($DryRun) {
328
+ Write-Info "[DRY-RUN] Would install $($dep.Label) skills to $AgentName"
329
+ continue
330
+ }
331
+ switch ($AgentType) {
332
+ "claude" {
333
+ $target = "$env:USERPROFILE\.skills-manager\skills"
334
+ Copy-Item "$srcDir\*" "$target\" -Recurse -Force
335
+ }
336
+ "opencode" {
337
+ $target = "$env:USERPROFILE\.config\opencode\skills"
338
+ Copy-Item "$srcDir\*" "$target\" -Recurse -Force
339
+ }
340
+ "codex" {
341
+ $target = "$env:USERPROFILE\.codex\skills"
342
+ Copy-Item "$srcDir\*" "$target\" -Recurse -Force
343
+ }
344
+ }
345
+ }
346
+ }
347
+
348
+ # --- Download dependencies ---
349
+ function Download-Dependencies {
350
+ if ($DryRun) {
351
+ Write-Info "[DRY-RUN] Would download obsidian-skills and graphify"
352
+ return
353
+ }
354
+
355
+ $deps = @(
356
+ @{ Name = "obsidian-skills"; Repo = "https://github.com/kepano/obsidian-skills.git"; Target = "skills\obsidian" }
357
+ @{ Name = "graphify"; Repo = "https://github.com/Graphify-Labs/graphify.git"; Target = "skills\graphify" }
358
+ )
359
+
360
+ foreach ($dep in $deps) {
361
+ $targetPath = Join-Path $RepoRoot $dep.Target
362
+ if (Test-Path (Join-Path $targetPath "SKILL.md")) {
363
+ Write-OK "$($dep.Name) already downloaded"
364
+ continue
365
+ }
366
+ if (Test-Path $targetPath) {
367
+ Remove-Item $targetPath -Recurse -Force -ErrorAction SilentlyContinue
368
+ }
369
+ Write-Info "Downloading $($dep.Name)..."
370
+ try {
371
+ git clone --depth 1 $dep.Repo $targetPath 2>&1 | Out-Null
372
+ Write-OK "$($dep.Name) downloaded"
373
+ } catch {
374
+ Write-Warn "Failed to download $($dep.Name): $_"
375
+ Write-Info " Manually: git clone --depth 1 $($dep.Repo) $($dep.Target)"
376
+ }
377
+ }
378
+ }
379
+
380
+ # --- Write brain-config.json ---
381
+ function Write-Config {
382
+ param([string]$VaultRoot, [hashtable]$Agents)
383
+
384
+ $config = @{
385
+ vaultPath = $VaultRoot
386
+ installedAgents = @($Agents.Keys)
387
+ environment = if (Test-IsWSL) { "wsl" } else { "windows" }
388
+ installedAt = (Get-Date -Format "o")
389
+ }
390
+
391
+ $configPath = Join-Path $RepoRoot "skills\secondary-brain\brain-config.json"
392
+ if ($DryRun) {
393
+ Write-Info "[DRY-RUN] Would write config to: $configPath"
394
+ return
395
+ }
396
+ $config | ConvertTo-Json | Set-Content $configPath -Force
397
+ Write-OK "Config saved: brain-config.json"
398
+ }
399
+
400
+ # ==================== MAIN ====================
401
+ Write-Host "============================================" -ForegroundColor Cyan
402
+ Write-Host " AI Agent Skills - Auto Installer" -ForegroundColor Cyan
403
+ Write-Host "============================================" -ForegroundColor Cyan
404
+
405
+ # Phase 1: Vault
406
+ Write-Step "Phase 1: Vault Detection"
407
+ $vaultRoot = Find-OrCreateVault -ExplicitPath $VaultPath
408
+ Write-Host " Vault: $vaultRoot" -ForegroundColor White
409
+
410
+ if (-not (Test-Path (Join-Path $vaultRoot "SecondaryBrain\GLOBAL-PROJECT-MEMORY.md"))) {
411
+ Write-Step "Phase 1b: Scaffolding SecondaryBrain"
412
+ Scaffold-Vault -VaultRoot $vaultRoot
413
+ } else {
414
+ Write-OK "SecondaryBrain already initialized"
415
+ }
416
+
417
+ # Phase 2: Download dependencies
418
+ Write-Step "Phase 2: Downloading Dependencies"
419
+ Download-Dependencies
420
+
421
+ # Phase 3: Agent detection
422
+ if (-not $SkipAgentDetect) {
423
+ Write-Step "Phase 2: Agent Detection"
424
+ $agents = Find-InstalledAgents
425
+
426
+ if ($agents.Count -eq 0) {
427
+ Write-Warn "No supported AI agents detected."
428
+ Write-Info "Expected locations:"
429
+ Write-Info " Claude Code: USERPROFILE\.claude\"
430
+ Write-Info " opencode: USERPROFILE\.config\opencode\"
431
+ Write-Info " Cursor: USERPROFILE\.cursor\"
432
+ Write-Info " Codex: USERPROFILE\.codex\"
433
+ } else {
434
+ Write-OK "$($agents.Count) agent(s) detected"
435
+ }
436
+
437
+ Write-Step "Phase 4: Installing Skills"
438
+ foreach ($agent in $agents.GetEnumerator()) {
439
+ Write-Host " --- $($agent.Name) ---" -ForegroundColor Yellow
440
+ Install-ToAgent -AgentName $agent.Name -AgentType $agent.Value -VaultRoot $vaultRoot
441
+ Install-DependencySkills -AgentName $agent.Name -AgentType $agent.Value
442
+ }
443
+ } else {
444
+ Write-Info "Agent detection skipped (--SkipAgentDetect)"
445
+ }
446
+
447
+ Write-Step "Phase 5: Saving Configuration"
448
+ Write-Config -VaultRoot $vaultRoot -Agents $agents
449
+
450
+ Write-Host "`n============================================" -ForegroundColor Cyan
451
+ if ($DryRun) {
452
+ Write-Host " DRY RUN COMPLETE - No files written" -ForegroundColor Yellow
453
+ } else {
454
+ Write-Host " INSTALL COMPLETE" -ForegroundColor Green
455
+ }
456
+ Write-Host "============================================" -ForegroundColor Cyan
457
+ Write-Host ""
458
+ Write-Host "Next steps:"
459
+ Write-Host " 1. Open your AI agent and try: secondary-brain:status"
460
+ Write-Host " 2. Or use: secondary-brain:handoff to generate a project handoff"
461
+ if ($agents.Count -gt 0) {
462
+ Write-Host " 3. Restart your AI agents to load the new skills"
463
+ }
package/install.sh ADDED
@@ -0,0 +1,224 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # AI Agent Skills — WSL/Linux Installer
5
+ # Detects vault + agents and installs skills.
6
+ # Falls back to install.ps1 via PowerShell if on Windows.
7
+
8
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
9
+
10
+ echo "============================================"
11
+ echo " AI Agent Skills — Installer"
12
+ echo "============================================"
13
+
14
+ # Detect environment
15
+ IS_WSL=false
16
+ if grep -qi microsoft /proc/version 2>/dev/null; then
17
+ IS_WSL=true
18
+ echo " Environment: WSL"
19
+ else
20
+ echo " Environment: Linux"
21
+ fi
22
+
23
+ # On WSL, prefer the PowerShell installer if available
24
+ if $IS_WSL && command -v powershell.exe &>/dev/null; then
25
+ echo ""
26
+ echo "→ WSL detected with PowerShell available."
27
+ echo " The Windows installer can detect Windows-side agents."
28
+
29
+ WIN_SCRIPT=$(wslpath -m "$SCRIPT_DIR/install.ps1" 2>/dev/null || echo "$SCRIPT_DIR/install.ps1")
30
+ exec powershell.exe -ExecutionPolicy Bypass -File "$WIN_SCRIPT" "$@"
31
+ fi
32
+
33
+ # --- Vault detection (Linux) ---
34
+ echo ""
35
+ echo "=== Phase 1: Vault Detection ==="
36
+
37
+ VAULT_PATH=""
38
+ for arg in "$@"; do
39
+ case "$arg" in
40
+ --vault-path=*) VAULT_PATH="${arg#*=}" ;;
41
+ --vault-path*) VAULT_PATH="$2"; shift ;;
42
+ esac
43
+ done
44
+
45
+ if [ -z "$VAULT_PATH" ]; then
46
+ # Check common locations
47
+ for dir in "$HOME/Documents/Obsidian Vault" "$HOME/Obsidian" "$HOME/Documents/Vault"; do
48
+ if [ -f "$dir/SecondaryBrain/GLOBAL-PROJECT-MEMORY.md" ]; then
49
+ VAULT_PATH="$dir"
50
+ echo " ✓ SecondaryBrain vault found at: $dir"
51
+ break
52
+ fi
53
+ done
54
+ fi
55
+
56
+ if [ -z "$VAULT_PATH" ]; then
57
+ echo " ⚠️ No vault detected."
58
+ read -rp " Enter Obsidian vault path (or leave empty to skip): " input
59
+ if [ -n "$input" ]; then
60
+ VAULT_PATH="$input"
61
+ else
62
+ echo " Skipping vault setup."
63
+ fi
64
+ fi
65
+
66
+ # --- Agent detection (Linux) ---
67
+ echo ""
68
+ echo "=== Phase 2: Agent Detection ==="
69
+
70
+ detect_agent() {
71
+ local name="$1"
72
+ local path="$2"
73
+ if [ -e "$path" ]; then
74
+ echo " ✓ $name detected"
75
+ return 0
76
+ fi
77
+ return 1
78
+ }
79
+
80
+ AGENTS=""
81
+ detect_agent "Claude Code" "$HOME/.claude/settings.json" && AGENTS="$AGENTS claude"
82
+ detect_agent "opencode" "$HOME/.config/opencode/opencode.jsonc" && AGENTS="$AGENTS opencode"
83
+ detect_agent "Cursor" "$HOME/.cursor" && AGENTS="$AGENTS cursor"
84
+ detect_agent "Codex" "$HOME/.codex" && AGENTS="$AGENTS codex"
85
+
86
+ if [ -z "$AGENTS" ]; then
87
+ echo " ⚠️ No supported AI agents detected."
88
+ echo " Install manually — see reference/platform-adapters.md"
89
+ fi
90
+
91
+ # --- Download dependencies ---
92
+ echo ""
93
+ echo "=== Phase 3: Download Dependencies ==="
94
+
95
+ download_dep() {
96
+ local name="$1"
97
+ local repo="$2"
98
+ local target="$3"
99
+ if [ -f "$target/SKILL.md" ]; then
100
+ echo " ✓ $name already downloaded"
101
+ return
102
+ fi
103
+ echo " Downloading $name..."
104
+ if git clone --depth 1 "$repo" "$target" 2>/dev/null; then
105
+ echo " ✓ $name downloaded"
106
+ else
107
+ echo " ⚠️ Failed to download $name"
108
+ echo " Manually: git clone --depth 1 $repo $target"
109
+ fi
110
+ }
111
+
112
+ download_dep "obsidian-skills" "https://github.com/kepano/obsidian-skills.git" "$SCRIPT_DIR/skills/obsidian"
113
+ download_dep "graphify" "https://github.com/Graphify-Labs/graphify.git" "$SCRIPT_DIR/skills/graphify"
114
+
115
+ # --- Install ---
116
+ if [ -n "$VAULT_PATH" ] || [ -n "$AGENTS" ]; then
117
+ echo ""
118
+ echo "=== Phase 4: Install ==="
119
+
120
+ SKILL_SRC="$SCRIPT_DIR/skills/secondary-brain"
121
+
122
+ install_dep_skills() {
123
+ local agent_type="$1"
124
+ local target_base="$2"
125
+ for dep_dir in "$SCRIPT_DIR/skills/obsidian" "$SCRIPT_DIR/skills/graphify"; do
126
+ if [ -d "$dep_dir" ]; then
127
+ cp -r "$dep_dir"/* "$target_base/" 2>/dev/null || true
128
+ fi
129
+ done
130
+ }
131
+
132
+ for agent in $AGENTS; do
133
+ case "$agent" in
134
+ claude)
135
+ TARGET="$HOME/.claude/skills/secondary-brain"
136
+ mkdir -p "$TARGET/reference" "$TARGET/templates"
137
+ sed "s|{{VAULT_PATH}}|$VAULT_PATH|g" "$SKILL_SRC/SKILL.md" > "$TARGET/SKILL.md"
138
+ cp "$SKILL_SRC/reference/"* "$TARGET/reference/" 2>/dev/null || true
139
+ cp "$SKILL_SRC/templates/"* "$TARGET/templates/" 2>/dev/null || true
140
+ echo " ✓ Installed secondary-brain to Claude Code"
141
+
142
+ install_dep_skills "claude" "$HOME/.claude/skills"
143
+
144
+ # Symlink for skills-manager
145
+ mkdir -p "$HOME/.skills-manager/skills/secondary-brain"
146
+ ln -sf "$TARGET/SKILL.md" "$HOME/.skills-manager/skills/secondary-brain/SKILL.md" 2>/dev/null || true
147
+ install_dep_skills "claude" "$HOME/.skills-manager/skills"
148
+ ;;
149
+ opencode)
150
+ TARGET="$HOME/.config/opencode/skills/secondary-brain"
151
+ mkdir -p "$TARGET/reference" "$TARGET/templates"
152
+ sed "s|{{VAULT_PATH}}|$VAULT_PATH|g" "$SKILL_SRC/SKILL.md" > "$TARGET/SKILL.md"
153
+ cp "$SKILL_SRC/reference/"* "$TARGET/reference/" 2>/dev/null || true
154
+ cp "$SKILL_SRC/templates/"* "$TARGET/templates/" 2>/dev/null || true
155
+ echo " ✓ Installed secondary-brain to opencode"
156
+ install_dep_skills "opencode" "$HOME/.config/opencode/skills"
157
+ ;;
158
+ cursor)
159
+ TARGET="$HOME/.cursor/rules"
160
+ mkdir -p "$TARGET"
161
+ CONTENT=$(sed "s|{{VAULT_PATH}}|$VAULT_PATH|g" "$SKILL_SRC/SKILL.md")
162
+ cat > "$TARGET/secondary-brain.mdc" << EOF
163
+ ---
164
+ description: "SecondaryBrain — persistent project memory via Obsidian vault"
165
+ globs: "**/*"
166
+ ---
167
+
168
+ $CONTENT
169
+ EOF
170
+ echo " ✓ Installed secondary-brain to Cursor"
171
+ for dep_dir in "$SCRIPT_DIR/skills/obsidian" "$SCRIPT_DIR/skills/graphify"; do
172
+ if [ -d "$dep_dir" ]; then
173
+ for skill_subdir in "$dep_dir"/skills/*/; do
174
+ sname=$(basename "$skill_subdir")
175
+ if [ -f "$skill_subdir/SKILL.md" ]; then
176
+ cat > "$TARGET/${sname}.mdc" << EOF
177
+ ---
178
+ description: "Skill: $sname"
179
+ globs: "**/*"
180
+ ---
181
+
182
+ $(cat "$skill_subdir/SKILL.md")
183
+ EOF
184
+ fi
185
+ done
186
+ fi
187
+ done
188
+ ;;
189
+ codex)
190
+ TARGET="$HOME/.codex/skills/secondary-brain"
191
+ mkdir -p "$TARGET/reference" "$TARGET/templates"
192
+ sed "s|{{VAULT_PATH}}|$VAULT_PATH|g" "$SKILL_SRC/SKILL.md" > "$TARGET/SKILL.md"
193
+ cp "$SKILL_SRC/reference/"* "$TARGET/reference/" 2>/dev/null || true
194
+ cp "$SKILL_SRC/templates/"* "$TARGET/templates/" 2>/dev/null || true
195
+ echo " ✓ Installed secondary-brain to Codex"
196
+ install_dep_skills "codex" "$HOME/.codex/skills"
197
+ ;;
198
+ esac
199
+ done
200
+ fi
201
+
202
+ # --- Save config ---
203
+ if [ -n "$VAULT_PATH" ]; then
204
+ cat > "$SKILL_SRC/brain-config.json" << EOF
205
+ {
206
+ "vaultPath": "$VAULT_PATH",
207
+ "installedAgents": "$AGENTS",
208
+ "environment": "$(uname -s)",
209
+ "installedAt": "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
210
+ }
211
+ EOF
212
+ echo ""
213
+ echo " ✓ Config saved"
214
+ fi
215
+
216
+ echo ""
217
+ echo "============================================"
218
+ echo " INSTALL COMPLETE"
219
+ echo "============================================"
220
+ echo ""
221
+ echo "Next steps:"
222
+ echo " 1. Restart your AI agents"
223
+ echo " 2. Try: secondary-brain:status"
224
+ echo " 3. Try: secondary-brain:handoff"