-
Notifications
You must be signed in to change notification settings - Fork 6k
Expand file tree
/
Copy pathinstall.ps1
More file actions
279 lines (248 loc) · 10.8 KB
/
Copy pathinstall.ps1
File metadata and controls
279 lines (248 loc) · 10.8 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
<#
.SYNOPSIS
Understand-Anything installer for Windows (PowerShell).
.DESCRIPTION
Clones the repo and creates skill symlinks/junctions for the chosen platform.
.EXAMPLE
./install.ps1 # prompt for platform
./install.ps1 codex # install for codex
./install.ps1 -Update # pull latest changes
./install.ps1 -Uninstall codex # remove links for codex
#>
param(
[Parameter(Position = 0)]
[string]$Platform,
[switch]$Update,
[string]$Uninstall,
[switch]$Help
)
$ErrorActionPreference = 'Stop'
$RepoUrl = if ($env:UA_REPO_URL) { $env:UA_REPO_URL } else { 'https://github.com/Egonex-AI/Understand-Anything.git' }
$RepoDir = if ($env:UA_DIR) { $env:UA_DIR } else { Join-Path $HOME '.understand-anything\repo' }
$PluginLink = Join-Path $HOME '.understand-anything-plugin'
# Platform table — Target = skills directory; Style = "per-skill" | "folder"
$Platforms = [ordered]@{
gemini = @{ Target = (Join-Path $HOME '.agents\skills'); Style = 'per-skill' }
codex = @{ Target = (Join-Path $HOME '.agents\skills'); Style = 'per-skill' }
opencode = @{ Target = (Join-Path $HOME '.agents\skills'); Style = 'per-skill' }
pi = @{ Target = (Join-Path $HOME '.agents\skills'); Style = 'per-skill' }
openclaw = @{ Target = (Join-Path $HOME '.openclaw\skills'); Style = 'folder' }
antigravity = @{ Target = (Join-Path $HOME '.gemini\antigravity\skills'); Style = 'folder' }
vscode = @{ Target = (Join-Path $HOME '.copilot\skills'); Style = 'per-skill' }
hermes = @{ Target = (Join-Path $HOME '.hermes\skills'); Style = 'folder' }
cline = @{ Target = (Join-Path $HOME '.cline\skills'); Style = 'folder' }
kimi = @{ Target = (Join-Path $HOME '.kimi\skills'); Style = 'folder' }
trae = @{ Target = (Join-Path $HOME '.trae\skills'); Style = 'per-skill' }
nanobot = @{ Target = (Join-Path $HOME '.nanobot\workspace\skills'); Style = 'per-skill' }
kiro = @{ Target = (Join-Path $HOME '.kiro\skills'); Style = 'per-skill' }
}
function Show-Usage {
@"
Understand-Anything installer (Windows)
Usage:
install.ps1 [<platform>] Install for <platform> (or prompt if omitted)
install.ps1 -Update Pull latest changes
install.ps1 -Uninstall <platform> Remove links for <platform>
install.ps1 -Help
Supported platforms:
$($Platforms.Keys -join ', ')
Environment:
UA_REPO_URL Override clone URL
UA_DIR Override clone destination (default: %USERPROFILE%\.understand-anything\repo)
"@
}
function Resolve-Platform([string]$Id) {
if (-not $Platforms.Contains($Id)) {
Write-Error "Unknown platform: $Id. Supported: $($Platforms.Keys -join ', ')"
}
return $Platforms[$Id]
}
function Prompt-Platform {
$ids = @($Platforms.Keys)
Write-Host 'Which platform are you installing for?'
for ($i = 0; $i -lt $ids.Count; $i++) {
Write-Host (" {0}) {1}" -f ($i + 1), $ids[$i])
}
$choice = Read-Host ("Choose [1-{0}]" -f $ids.Count)
$n = 0
if (-not [int]::TryParse($choice, [ref]$n) -or $n -lt 1 -or $n -gt $ids.Count) {
Write-Error "Invalid choice: $choice"
}
return $ids[$n - 1]
}
function Get-SkillsRoot { Join-Path $RepoDir 'understand-anything-plugin\skills' }
function Clone-Or-Update {
if (Test-Path (Join-Path $RepoDir '.git')) {
Write-Host "→ Updating existing checkout at $RepoDir"
git -C $RepoDir pull --ff-only
} else {
Write-Host "→ Cloning $RepoUrl → $RepoDir"
$parent = Split-Path -Parent $RepoDir
if (-not (Test-Path $parent)) { New-Item -ItemType Directory -Path $parent | Out-Null }
git clone $RepoUrl $RepoDir
}
}
function Get-SkillNames {
$root = Get-SkillsRoot
if (-not (Test-Path $root)) { Write-Error "Skills directory not found: $root" }
Get-ChildItem -Path $root -Directory | Select-Object -ExpandProperty Name
}
function Test-IsReparse([string]$Path) {
if (-not (Test-Path $Path)) { return $false }
$item = Get-Item -LiteralPath $Path -Force
return ($item.LinkType -eq 'Junction' -or $item.LinkType -eq 'SymbolicLink')
}
function Remove-Reparse([string]$Path) {
# Removes a junction/symlink without touching its target. Refuses to touch
# real files or directories so an existing user folder at the same path is
# never destroyed.
if (-not (Test-Path $Path)) { return $false }
$item = Get-Item -LiteralPath $Path -Force
if ($item.LinkType -eq 'Junction' -or $item.LinkType -eq 'SymbolicLink') {
$item.Delete()
return $true
}
Write-Warning "Refusing to delete $Path — it is a real file/directory, not a junction/symlink we created. Remove it manually if you intended to."
return $false
}
function New-Junction([string]$LinkPath, [string]$TargetPath) {
if (Test-Path $LinkPath) {
if (Test-IsReparse $LinkPath) {
(Get-Item -LiteralPath $LinkPath -Force).Delete()
} else {
Write-Error "Refusing to overwrite $LinkPath — it is a real file/directory, not a junction. Move or remove it first."
}
}
New-Item -ItemType Junction -Path $LinkPath -Target $TargetPath | Out-Null
}
function Link-Skills([string]$Target, [string]$Style) {
$root = Get-SkillsRoot
if (-not (Test-Path $Target)) { New-Item -ItemType Directory -Path $Target | Out-Null }
switch ($Style) {
'per-skill' {
foreach ($skill in Get-SkillNames) {
$link = Join-Path $Target $skill
$src = Join-Path $root $skill
New-Junction $link $src
Write-Host " ✓ $link → $src"
}
}
'folder' {
$link = Join-Path $Target 'understand-anything'
New-Junction $link $root
Write-Host " ✓ $link → $root"
}
default { Write-Error "Unknown style: $Style" }
}
}
function Unlink-Skills([string]$Target, [string]$Style) {
if (-not (Test-Path $Target)) { return }
switch ($Style) {
'per-skill' {
$skillsRoot = Get-SkillsRoot
if (Test-Path $skillsRoot) {
foreach ($skill in Get-SkillNames) {
Remove-Reparse (Join-Path $Target $skill) | Out-Null
}
} else {
# Checkout is gone — scan the target dir for stale links pointing
# into our plugin tree so we can still clean up.
Get-ChildItem -LiteralPath $Target -Force | ForEach-Object {
if ($_.LinkType -eq 'Junction' -or $_.LinkType -eq 'SymbolicLink') {
if ($_.Target -match 'understand-anything-plugin[\\/]+skills[\\/]+') {
Remove-Reparse $_.FullName | Out-Null
}
}
}
}
}
'folder' {
Remove-Reparse (Join-Path $Target 'understand-anything') | Out-Null
}
}
}
function Link-Plugin-Root {
if (Test-Path $PluginLink) {
Write-Host " • $PluginLink already exists, leaving as-is"
} else {
$src = Join-Path $RepoDir 'understand-anything-plugin'
New-Item -ItemType Junction -Path $PluginLink -Target $src | Out-Null
Write-Host " ✓ $PluginLink → $src"
}
}
function ConvertTo-FileUri([string]$Path) {
# Produce a forward-slashed file URI (Windows: file:///C:/path/...).
return 'file:///' + ($Path -replace '\\', '/')
}
function Cmd-Install([string]$Id) {
$cfg = Resolve-Platform $Id
Clone-Or-Update
Write-Host "→ Linking skills for $Id ($($cfg.Style) → $($cfg.Target))"
Link-Skills $cfg.Target $cfg.Style
Write-Host '→ Linking universal plugin root'
Link-Plugin-Root
if ($Id -eq 'kiro') {
Write-Host '→ Creating Kiro agent configuration'
$agentsDir = Join-Path $HOME '.kiro\agents'
if (-not (Test-Path $agentsDir)) { New-Item -ItemType Directory -Path $agentsDir | Out-Null }
$pluginRoot = Join-Path $RepoDir 'understand-anything-plugin'
# Build the "resources" list dynamically from the agent definitions in
# the repo so it never drifts as agents are added or removed.
$resources = @(
Get-ChildItem -Path (Join-Path $pluginRoot 'agents') -Filter '*.md' -File |
Sort-Object Name |
ForEach-Object { ConvertTo-FileUri $_.FullName }
)
$agent = [ordered]@{
name = 'understand'
description = 'Analyze codebase into interactive knowledge graph — Understand Anything'
prompt = ConvertTo-FileUri (Join-Path $pluginRoot 'skills\understand\SKILL.md')
tools = @('read', 'write', 'shell', 'grep', 'glob', 'code', 'subagent')
resources = $resources
}
$agentJson = Join-Path $agentsDir 'understand.json'
# WriteAllText emits UTF-8 without a BOM on every PowerShell version.
[System.IO.File]::WriteAllText($agentJson, ($agent | ConvertTo-Json -Depth 5))
Write-Host " ✓ $agentJson"
}
Write-Host "`n✓ Installed Understand-Anything for $Id"
Write-Host ' Restart your CLI or IDE to pick up the skills.'
if ($Id -eq 'vscode') {
Write-Host "`n Tip: VS Code can also auto-discover the plugin by opening this repo"
Write-Host ' directly (it reads .copilot-plugin/plugin.json), no symlinks needed.'
}
if ($Id -eq 'kiro') {
Write-Host "`n Usage: kiro-cli chat --agent understand `"Analyze this project`""
}
}
function Cmd-Uninstall([string]$Id) {
$cfg = Resolve-Platform $Id
Write-Host "→ Removing skill links for $Id"
Unlink-Skills $cfg.Target $cfg.Style
if ($Id -eq 'kiro') {
$agentJson = Join-Path $HOME '.kiro\agents\understand.json'
if (Test-Path $agentJson) {
Remove-Item -LiteralPath $agentJson -Force
Write-Host " ✓ removed $agentJson"
}
}
if (Remove-Reparse $PluginLink) {
Write-Host " ✓ removed $PluginLink"
}
if (Test-Path $RepoDir) {
Write-Host "`nThe checkout at $RepoDir was kept (other platforms may still use it)."
Write-Host "To remove it: Remove-Item -Recurse -Force '$RepoDir'"
}
}
function Cmd-Update {
if (-not (Test-Path (Join-Path $RepoDir '.git'))) {
Write-Error "No installation found at $RepoDir. Run install first."
}
git -C $RepoDir pull --ff-only
Write-Host '✓ Updated.'
}
if ($Help) { Show-Usage; return }
if ($Update) { Cmd-Update; return }
if ($Uninstall) { Cmd-Uninstall $Uninstall; return }
if (-not $Platform) { $Platform = Prompt-Platform }
Cmd-Install $Platform