@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/.claude-plugin/marketplace.json +14 -0
- package/.claude-plugin/plugin.json +23 -0
- package/README.md +60 -0
- package/SKILL.md +87 -0
- package/bin/ai-agent-skills.js +59 -0
- package/install.ps1 +463 -0
- package/install.sh +224 -0
- package/package.json +41 -0
- package/scripts/install.js +51 -0
- package/scripts/push.js +193 -0
- package/skills/cicd/SKILL.md +134 -0
- package/skills/secondary-brain/SKILL.md +257 -0
- package/skills/secondary-brain/reference/deep-mode.md +90 -0
- package/skills/secondary-brain/reference/mermaid-cheatsheet.md +81 -0
- package/skills/secondary-brain/reference/platform-adapters.md +74 -0
- package/skills/secondary-brain/reference/scoring-guide.md +63 -0
- package/skills/secondary-brain/templates/00-project-node.md +41 -0
- package/skills/secondary-brain/templates/01-feature-node.md +39 -0
- package/skills/secondary-brain/templates/handoff.md +47 -0
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"
|