@conductor-oss/conductor-skills 1.4.2
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 +20 -0
- package/.claude-plugin/plugin.json +13 -0
- package/LICENSE.txt +176 -0
- package/README.md +352 -0
- package/VERSION +1 -0
- package/bin/conductor-skills.js +135 -0
- package/commands/conductor-optimize.md +18 -0
- package/commands/conductor-scaffold-worker.md +19 -0
- package/commands/conductor-setup.md +15 -0
- package/commands/conductor.md +15 -0
- package/install.ps1 +677 -0
- package/install.sh +855 -0
- package/package.json +50 -0
- package/skills/conductor/SKILL.md +151 -0
- package/skills/conductor/examples/ai-agent-loop.md +119 -0
- package/skills/conductor/examples/ai-agent-mcp.md +129 -0
- package/skills/conductor/examples/create-and-run-workflow.md +50 -0
- package/skills/conductor/examples/do-while-loop.md +72 -0
- package/skills/conductor/examples/fork-join.md +52 -0
- package/skills/conductor/examples/llm-chat.md +61 -0
- package/skills/conductor/examples/llm-rag.md +115 -0
- package/skills/conductor/examples/monitor-and-retry.md +54 -0
- package/skills/conductor/examples/review-workflow.md +67 -0
- package/skills/conductor/examples/signal-wait-task.md +36 -0
- package/skills/conductor/examples/sub-workflow.md +52 -0
- package/skills/conductor/examples/workflows/ai-agent-loop.json +88 -0
- package/skills/conductor/examples/workflows/ai-agent-mcp.json +69 -0
- package/skills/conductor/examples/workflows/child-normalize.json +21 -0
- package/skills/conductor/examples/workflows/do-while-loop.json +35 -0
- package/skills/conductor/examples/workflows/fork-join.json +61 -0
- package/skills/conductor/examples/workflows/llm-chat.json +28 -0
- package/skills/conductor/examples/workflows/llm-rag.json +49 -0
- package/skills/conductor/examples/workflows/parent-pipeline.json +35 -0
- package/skills/conductor/examples/workflows/weather-notification.json +42 -0
- package/skills/conductor/references/api-reference.md +111 -0
- package/skills/conductor/references/cli-index.md +92 -0
- package/skills/conductor/references/fallback-cli.md +36 -0
- package/skills/conductor/references/optimization.md +148 -0
- package/skills/conductor/references/orkes.md +57 -0
- package/skills/conductor/references/schedules.md +81 -0
- package/skills/conductor/references/setup.md +126 -0
- package/skills/conductor/references/troubleshooting.md +35 -0
- package/skills/conductor/references/visualization.md +49 -0
- package/skills/conductor/references/workers.md +227 -0
- package/skills/conductor/references/workflow-definition.md +672 -0
- package/skills/conductor/scripts/conductor_api.py +396 -0
package/install.ps1
ADDED
|
@@ -0,0 +1,677 @@
|
|
|
1
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
2
|
+
# Conductor Skills Installer (PowerShell)
|
|
3
|
+
# Installs Conductor workflow orchestration skills for your AI coding agent.
|
|
4
|
+
# https://github.com/conductor-oss/conductor-skills
|
|
5
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
6
|
+
|
|
7
|
+
param(
|
|
8
|
+
[string]$Agent,
|
|
9
|
+
[string]$ProjectDir = ".",
|
|
10
|
+
[switch]$Global,
|
|
11
|
+
[switch]$All,
|
|
12
|
+
[switch]$Upgrade,
|
|
13
|
+
[switch]$Check,
|
|
14
|
+
[switch]$Force,
|
|
15
|
+
[switch]$Uninstall,
|
|
16
|
+
[switch]$Version
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
$ErrorActionPreference = "Stop"
|
|
20
|
+
|
|
21
|
+
$SCRIPT_VERSION = "1.4.2"
|
|
22
|
+
# Per-file fetches are pinned to this version's tag (see install.sh notes).
|
|
23
|
+
# main is only used for the "is there a newer release?" check.
|
|
24
|
+
$REPO_BASE = "https://raw.githubusercontent.com/conductor-oss/conductor-skills/v$SCRIPT_VERSION"
|
|
25
|
+
$REPO_MAIN = "https://raw.githubusercontent.com/conductor-oss/conductor-skills/main"
|
|
26
|
+
|
|
27
|
+
# When set, skip the network fetch and copy from this directory instead.
|
|
28
|
+
# The npm package sets this so the bundled files are used.
|
|
29
|
+
$LOCAL_DIR = $env:CONDUCTOR_SKILLS_LOCAL_DIR
|
|
30
|
+
|
|
31
|
+
$SKILL_FILES = @(
|
|
32
|
+
"skills/conductor/SKILL.md"
|
|
33
|
+
"skills/conductor/references/setup.md"
|
|
34
|
+
"skills/conductor/references/cli-index.md"
|
|
35
|
+
"skills/conductor/references/fallback-cli.md"
|
|
36
|
+
"skills/conductor/references/workflow-definition.md"
|
|
37
|
+
"skills/conductor/references/workers.md"
|
|
38
|
+
"skills/conductor/references/api-reference.md"
|
|
39
|
+
"skills/conductor/references/visualization.md"
|
|
40
|
+
"skills/conductor/references/schedules.md"
|
|
41
|
+
"skills/conductor/references/orkes.md"
|
|
42
|
+
"skills/conductor/references/optimization.md"
|
|
43
|
+
"skills/conductor/references/troubleshooting.md"
|
|
44
|
+
"skills/conductor/examples/create-and-run-workflow.md"
|
|
45
|
+
"skills/conductor/examples/monitor-and-retry.md"
|
|
46
|
+
"skills/conductor/examples/signal-wait-task.md"
|
|
47
|
+
"skills/conductor/examples/fork-join.md"
|
|
48
|
+
"skills/conductor/examples/do-while-loop.md"
|
|
49
|
+
"skills/conductor/examples/sub-workflow.md"
|
|
50
|
+
"skills/conductor/examples/review-workflow.md"
|
|
51
|
+
"skills/conductor/examples/llm-chat.md"
|
|
52
|
+
"skills/conductor/examples/ai-agent-mcp.md"
|
|
53
|
+
"skills/conductor/examples/ai-agent-loop.md"
|
|
54
|
+
"skills/conductor/examples/llm-rag.md"
|
|
55
|
+
"skills/conductor/examples/workflows/weather-notification.json"
|
|
56
|
+
"skills/conductor/examples/workflows/fork-join.json"
|
|
57
|
+
"skills/conductor/examples/workflows/do-while-loop.json"
|
|
58
|
+
"skills/conductor/examples/workflows/child-normalize.json"
|
|
59
|
+
"skills/conductor/examples/workflows/parent-pipeline.json"
|
|
60
|
+
"skills/conductor/examples/workflows/llm-chat.json"
|
|
61
|
+
"skills/conductor/examples/workflows/ai-agent-mcp.json"
|
|
62
|
+
"skills/conductor/examples/workflows/ai-agent-loop.json"
|
|
63
|
+
"skills/conductor/examples/workflows/llm-rag.json"
|
|
64
|
+
"skills/conductor/scripts/conductor_api.py"
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
$VALID_AGENTS = @("claude","codex","gemini","cursor","windsurf","cline","aider","copilot","amazonq","opencode","roo","amp")
|
|
68
|
+
$GLOBAL_AGENTS = @("claude","codex","gemini","cursor","windsurf","roo","amp","aider","opencode")
|
|
69
|
+
|
|
70
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
71
|
+
# Helpers
|
|
72
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
73
|
+
|
|
74
|
+
function Write-Info { param([string]$Msg) Write-Host "[info] $Msg" -ForegroundColor Blue }
|
|
75
|
+
function Write-Ok { param([string]$Msg) Write-Host "[ok] $Msg" -ForegroundColor Green }
|
|
76
|
+
function Write-Warn { param([string]$Msg) Write-Host "[warn] $Msg" -ForegroundColor Yellow }
|
|
77
|
+
function Write-Err { param([string]$Msg) Write-Host "[error] $Msg" -ForegroundColor Red }
|
|
78
|
+
|
|
79
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
80
|
+
# Agent detection
|
|
81
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
82
|
+
|
|
83
|
+
function Detect-Agents {
|
|
84
|
+
$detected = @()
|
|
85
|
+
$installDir = $env:USERPROFILE
|
|
86
|
+
|
|
87
|
+
if (Get-Command claude -ErrorAction SilentlyContinue) { $detected += "claude" }
|
|
88
|
+
if ((Get-Command codex -ErrorAction SilentlyContinue) -or (Test-Path (Join-Path $installDir ".codex"))) { $detected += "codex" }
|
|
89
|
+
if ((Get-Command gemini -ErrorAction SilentlyContinue) -or (Test-Path (Join-Path $installDir ".gemini"))) { $detected += "gemini" }
|
|
90
|
+
if (Test-Path (Join-Path $installDir ".cursor")) { $detected += "cursor" }
|
|
91
|
+
if (Test-Path (Join-Path $installDir ".codeium")) { $detected += "windsurf" }
|
|
92
|
+
if (Test-Path (Join-Path $installDir ".cline")) { $detected += "cline" }
|
|
93
|
+
if (Get-Command aider -ErrorAction SilentlyContinue) { $detected += "aider" }
|
|
94
|
+
if (Test-Path (Join-Path $installDir ".config\github-copilot")) { $detected += "copilot" }
|
|
95
|
+
if ((Get-Command q -ErrorAction SilentlyContinue) -or (Test-Path (Join-Path $installDir ".amazonq"))) { $detected += "amazonq" }
|
|
96
|
+
if (Get-Command opencode -ErrorAction SilentlyContinue) { $detected += "opencode" }
|
|
97
|
+
if (Test-Path (Join-Path $installDir ".roo")) { $detected += "roo" }
|
|
98
|
+
if ((Get-Command amp -ErrorAction SilentlyContinue) -or (Test-Path (Join-Path $installDir ".config\amp"))) { $detected += "amp" }
|
|
99
|
+
|
|
100
|
+
return $detected
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
104
|
+
# Manifest tracking
|
|
105
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
106
|
+
|
|
107
|
+
$GLOBAL_MANIFEST = Join-Path $env:USERPROFILE ".conductor-skills\manifest.json"
|
|
108
|
+
|
|
109
|
+
function Get-ManifestPath {
|
|
110
|
+
param([bool]$IsGlobal, [string]$ProjDir = ".")
|
|
111
|
+
if ($IsGlobal) { return $GLOBAL_MANIFEST }
|
|
112
|
+
return Join-Path $ProjDir ".conductor-skills\manifest.json"
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function Ensure-Manifest {
|
|
116
|
+
param([string]$ManifestPath)
|
|
117
|
+
$dir = Split-Path -Parent $ManifestPath
|
|
118
|
+
if ($dir -and !(Test-Path $dir)) { New-Item -ItemType Directory -Path $dir -Force | Out-Null }
|
|
119
|
+
if (!(Test-Path $ManifestPath)) {
|
|
120
|
+
'{"schema_version":1,"installations":{}}' | Set-Content -Path $ManifestPath
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function Read-ManifestVersion {
|
|
125
|
+
param([string]$ManifestPath, [string]$AgentName)
|
|
126
|
+
if (!(Test-Path $ManifestPath)) { return "" }
|
|
127
|
+
try {
|
|
128
|
+
$m = Get-Content $ManifestPath -Raw | ConvertFrom-Json
|
|
129
|
+
$entry = $m.installations.PSObject.Properties | Where-Object { $_.Name -eq $AgentName }
|
|
130
|
+
if ($entry) { return $entry.Value.version }
|
|
131
|
+
} catch {}
|
|
132
|
+
return ""
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function Write-ManifestEntry {
|
|
136
|
+
param([string]$ManifestPath, [string]$AgentName, [string]$Ver, [string]$Mode, [string]$TargetPath)
|
|
137
|
+
Ensure-Manifest -ManifestPath $ManifestPath
|
|
138
|
+
$m = Get-Content $ManifestPath -Raw | ConvertFrom-Json
|
|
139
|
+
$now = (Get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ")
|
|
140
|
+
|
|
141
|
+
$existingEntry = $m.installations.PSObject.Properties | Where-Object { $_.Name -eq $AgentName }
|
|
142
|
+
$installedAt = $now
|
|
143
|
+
if ($existingEntry) { $installedAt = $existingEntry.Value.installed_at }
|
|
144
|
+
|
|
145
|
+
$entry = [PSCustomObject]@{
|
|
146
|
+
version = $Ver
|
|
147
|
+
installed_at = $installedAt
|
|
148
|
+
updated_at = $now
|
|
149
|
+
mode = $Mode
|
|
150
|
+
target_path = $TargetPath
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if ($existingEntry) {
|
|
154
|
+
$m.installations.PSObject.Properties.Remove($AgentName)
|
|
155
|
+
}
|
|
156
|
+
$m.installations | Add-Member -NotePropertyName $AgentName -NotePropertyValue $entry
|
|
157
|
+
$m | ConvertTo-Json -Depth 10 | Set-Content -Path $ManifestPath
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function Remove-ManifestEntry {
|
|
161
|
+
param([string]$ManifestPath, [string]$AgentName)
|
|
162
|
+
if (!(Test-Path $ManifestPath)) { return }
|
|
163
|
+
try {
|
|
164
|
+
$m = Get-Content $ManifestPath -Raw | ConvertFrom-Json
|
|
165
|
+
$m.installations.PSObject.Properties.Remove($AgentName)
|
|
166
|
+
$m | ConvertTo-Json -Depth 10 | Set-Content -Path $ManifestPath
|
|
167
|
+
} catch {}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function Get-ManifestAgents {
|
|
171
|
+
param([string]$ManifestPath)
|
|
172
|
+
if (!(Test-Path $ManifestPath)) { return @() }
|
|
173
|
+
try {
|
|
174
|
+
$m = Get-Content $ManifestPath -Raw | ConvertFrom-Json
|
|
175
|
+
return @($m.installations.PSObject.Properties.Name)
|
|
176
|
+
} catch { return @() }
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
180
|
+
# Remote version check
|
|
181
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
182
|
+
|
|
183
|
+
function Fetch-RemoteVersion {
|
|
184
|
+
if ($LOCAL_DIR -and (Test-Path (Join-Path $LOCAL_DIR "VERSION"))) {
|
|
185
|
+
return (Get-Content (Join-Path $LOCAL_DIR "VERSION") -Raw).Trim()
|
|
186
|
+
}
|
|
187
|
+
try {
|
|
188
|
+
$ver = (Invoke-WebRequest -Uri "$REPO_MAIN/VERSION" -UseBasicParsing -ErrorAction Stop).Content.Trim()
|
|
189
|
+
return $ver
|
|
190
|
+
} catch { return "" }
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
194
|
+
# Download & assembly
|
|
195
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
196
|
+
|
|
197
|
+
function Download-Files {
|
|
198
|
+
param([string]$TmpDir)
|
|
199
|
+
|
|
200
|
+
if ($LOCAL_DIR) {
|
|
201
|
+
if (-not (Test-Path -PathType Container $LOCAL_DIR)) {
|
|
202
|
+
Write-Err "CONDUCTOR_SKILLS_LOCAL_DIR=$LOCAL_DIR is not a directory"
|
|
203
|
+
exit 1
|
|
204
|
+
}
|
|
205
|
+
Write-Info "Copying skill files from $LOCAL_DIR..."
|
|
206
|
+
foreach ($file in $SKILL_FILES) {
|
|
207
|
+
$src = Join-Path $LOCAL_DIR $file
|
|
208
|
+
$dest = Join-Path $TmpDir $file
|
|
209
|
+
if (-not (Test-Path $src)) {
|
|
210
|
+
Write-Err "Missing file in local source: $file"
|
|
211
|
+
Remove-Item -Recurse -Force $TmpDir -ErrorAction SilentlyContinue
|
|
212
|
+
exit 1
|
|
213
|
+
}
|
|
214
|
+
$dir = Split-Path -Parent $dest
|
|
215
|
+
if ($dir -and !(Test-Path $dir)) {
|
|
216
|
+
New-Item -ItemType Directory -Path $dir -Force | Out-Null
|
|
217
|
+
}
|
|
218
|
+
Copy-Item $src $dest
|
|
219
|
+
}
|
|
220
|
+
Write-Ok "Copied $($SKILL_FILES.Count) files"
|
|
221
|
+
return
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
Write-Info "Downloading skill files..."
|
|
225
|
+
foreach ($file in $SKILL_FILES) {
|
|
226
|
+
$dir = Split-Path -Parent (Join-Path $TmpDir $file)
|
|
227
|
+
if ($dir -and !(Test-Path $dir)) {
|
|
228
|
+
New-Item -ItemType Directory -Path $dir -Force | Out-Null
|
|
229
|
+
}
|
|
230
|
+
$url = "$REPO_BASE/$file"
|
|
231
|
+
$dest = Join-Path $TmpDir $file
|
|
232
|
+
try {
|
|
233
|
+
Invoke-WebRequest -Uri $url -OutFile $dest -UseBasicParsing -ErrorAction Stop | Out-Null
|
|
234
|
+
} catch {
|
|
235
|
+
Write-Err "Failed to download $file"
|
|
236
|
+
Write-Err "Check your internet connection and try again."
|
|
237
|
+
Remove-Item -Recurse -Force $TmpDir -ErrorAction SilentlyContinue
|
|
238
|
+
exit 1
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
Write-Ok "Downloaded $($SKILL_FILES.Count) files"
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
function Assemble-Content {
|
|
245
|
+
param([string]$TmpDir, [string]$Output)
|
|
246
|
+
|
|
247
|
+
$content = @()
|
|
248
|
+
$content += Get-Content (Join-Path $TmpDir "skills/conductor/SKILL.md") -Raw
|
|
249
|
+
$content += "`n---`n"
|
|
250
|
+
$content += "# References`n"
|
|
251
|
+
foreach ($f in Get-ChildItem (Join-Path $TmpDir "skills/conductor/references") -Filter "*.md") {
|
|
252
|
+
$content += Get-Content $f.FullName -Raw
|
|
253
|
+
$content += "`n---`n"
|
|
254
|
+
}
|
|
255
|
+
$content += "# Examples`n"
|
|
256
|
+
foreach ($f in Get-ChildItem (Join-Path $TmpDir "skills/conductor/examples") -Filter "*.md") {
|
|
257
|
+
$content += Get-Content $f.FullName -Raw
|
|
258
|
+
$content += "`n---`n"
|
|
259
|
+
}
|
|
260
|
+
$content -join "`n" | Set-Content -Path $Output -NoNewline
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
264
|
+
# Safe file writing
|
|
265
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
266
|
+
|
|
267
|
+
function Safe-Write {
|
|
268
|
+
param([string]$Target, [string]$Source, [bool]$ForceWrite)
|
|
269
|
+
|
|
270
|
+
if ((Test-Path $Target) -and !$ForceWrite) {
|
|
271
|
+
Write-Warn "File already exists: $Target"
|
|
272
|
+
$answer = Read-Host " Overwrite? [y/N]"
|
|
273
|
+
if ($answer -notmatch "^[Yy]") {
|
|
274
|
+
Write-Info "Skipped. Use -Force to overwrite."
|
|
275
|
+
return $false
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
$dir = Split-Path -Parent $Target
|
|
280
|
+
if ($dir -and !(Test-Path $dir)) {
|
|
281
|
+
New-Item -ItemType Directory -Path $dir -Force | Out-Null
|
|
282
|
+
}
|
|
283
|
+
Copy-Item -Path $Source -Destination $Target -Force
|
|
284
|
+
Write-Ok "Installed: $Target"
|
|
285
|
+
return $true
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
289
|
+
# Global install paths
|
|
290
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
291
|
+
|
|
292
|
+
function Supports-Global {
|
|
293
|
+
param([string]$AgentName)
|
|
294
|
+
return $GLOBAL_AGENTS -contains $AgentName
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
function Get-GlobalPath {
|
|
298
|
+
param([string]$AgentName)
|
|
299
|
+
$installDir = $env:USERPROFILE
|
|
300
|
+
switch ($AgentName) {
|
|
301
|
+
"claude" { return "__claude__" }
|
|
302
|
+
"codex" { $codexHome = if ($env:CODEX_HOME) { $env:CODEX_HOME } else { Join-Path $installDir ".codex" }; return Join-Path $codexHome "AGENTS.md" }
|
|
303
|
+
"cursor" { return Join-Path $installDir ".cursor\skills\conductor\SKILL.md" }
|
|
304
|
+
"gemini" { return Join-Path $installDir ".gemini\GEMINI.md" }
|
|
305
|
+
"windsurf" { return Join-Path $installDir ".codeium\windsurf\memories\global_rules.md" }
|
|
306
|
+
"roo" { return Join-Path $installDir ".roo\rules\conductor.md" }
|
|
307
|
+
"amp" { return Join-Path $installDir ".config\AGENTS.md" }
|
|
308
|
+
"aider" { return Join-Path $installDir ".aider.conf.yml" }
|
|
309
|
+
"opencode" { return Join-Path $installDir ".config\opencode\skills\conductor\SKILL.md" }
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
function Get-TargetPath {
|
|
314
|
+
param([string]$AgentName, [string]$ProjDir)
|
|
315
|
+
switch ($AgentName) {
|
|
316
|
+
"claude" { return "__claude__" }
|
|
317
|
+
"codex" { return Join-Path $ProjDir "AGENTS.md" }
|
|
318
|
+
"gemini" { return Join-Path $ProjDir "GEMINI.md" }
|
|
319
|
+
"cursor" { return Join-Path $ProjDir ".cursor\rules\conductor.mdc" }
|
|
320
|
+
"windsurf" { return Join-Path $ProjDir ".windsurfrules" }
|
|
321
|
+
"cline" { return Join-Path $ProjDir ".clinerules" }
|
|
322
|
+
"aider" { return Join-Path $ProjDir ".conductor-skills" }
|
|
323
|
+
"copilot" { return Join-Path $ProjDir ".github\copilot-instructions.md" }
|
|
324
|
+
"amazonq" { return Join-Path $ProjDir ".amazonq\rules\conductor.md" }
|
|
325
|
+
"opencode" { return Join-Path $ProjDir "AGENTS.md" }
|
|
326
|
+
"roo" { return Join-Path $ProjDir ".roo\rules\conductor.md" }
|
|
327
|
+
"amp" { return Join-Path $ProjDir ".amp\instructions.md" }
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
332
|
+
# Per-agent install logic
|
|
333
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
334
|
+
|
|
335
|
+
function Install-Claude {
|
|
336
|
+
# Claude Code installs plugins via in-session /plugin commands, not a
|
|
337
|
+
# shell subcommand. Print clear instructions.
|
|
338
|
+
if (!(Get-Command claude -ErrorAction SilentlyContinue)) {
|
|
339
|
+
Write-Warn "'claude' CLI not found, but the Claude install is in-session anyway."
|
|
340
|
+
}
|
|
341
|
+
Write-Info "Conductor Skills is a Claude Code plugin. Run these in your Claude Code session:"
|
|
342
|
+
Write-Host ""
|
|
343
|
+
Write-Host " /plugin marketplace add conductor-oss/conductor-skills"
|
|
344
|
+
Write-Host " /plugin install conductor@conductor-skills"
|
|
345
|
+
Write-Host ""
|
|
346
|
+
Write-Info "Once installed, slash commands like /conductor, /conductor-setup,"
|
|
347
|
+
Write-Info "/conductor-optimize, and /conductor-scaffold-worker become available."
|
|
348
|
+
Write-Ok "Claude Code install instructions printed above."
|
|
349
|
+
return $true
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
function Install-ToFile {
|
|
353
|
+
param([string]$Target, [string]$Assembled, [bool]$ForceWrite, [string]$Prefix = "")
|
|
354
|
+
|
|
355
|
+
if ($Prefix) {
|
|
356
|
+
$tmpFile = [System.IO.Path]::GetTempFileName()
|
|
357
|
+
($Prefix + (Get-Content $Assembled -Raw)) | Set-Content -Path $tmpFile -NoNewline
|
|
358
|
+
Safe-Write -Target $Target -Source $tmpFile -ForceWrite $ForceWrite
|
|
359
|
+
Remove-Item $tmpFile -ErrorAction SilentlyContinue
|
|
360
|
+
} else {
|
|
361
|
+
Safe-Write -Target $Target -Source $Assembled -ForceWrite $ForceWrite
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
function Install-AiderToDir {
|
|
366
|
+
param([string]$SkillDir, [string]$TmpDir, [string]$Config, [string]$ReadPrefix)
|
|
367
|
+
|
|
368
|
+
New-Item -ItemType Directory -Path (Join-Path $SkillDir "references") -Force | Out-Null
|
|
369
|
+
New-Item -ItemType Directory -Path (Join-Path $SkillDir "examples") -Force | Out-Null
|
|
370
|
+
New-Item -ItemType Directory -Path (Join-Path $SkillDir "scripts") -Force | Out-Null
|
|
371
|
+
|
|
372
|
+
Write-Info "Copying skill files to $SkillDir ..."
|
|
373
|
+
Copy-Item (Join-Path $TmpDir "skills/conductor/SKILL.md") $SkillDir -Force
|
|
374
|
+
foreach ($f in Get-ChildItem (Join-Path $TmpDir "skills/conductor/references") -Filter "*.md") {
|
|
375
|
+
Copy-Item $f.FullName (Join-Path $SkillDir "references") -Force
|
|
376
|
+
}
|
|
377
|
+
foreach ($f in Get-ChildItem (Join-Path $TmpDir "skills/conductor/examples") -Filter "*.md") {
|
|
378
|
+
Copy-Item $f.FullName (Join-Path $SkillDir "examples") -Force
|
|
379
|
+
}
|
|
380
|
+
$scriptsDir = Join-Path $TmpDir "skills/conductor/scripts"
|
|
381
|
+
if (Test-Path $scriptsDir) {
|
|
382
|
+
foreach ($f in Get-ChildItem $scriptsDir -Filter "*.py") {
|
|
383
|
+
Copy-Item $f.FullName (Join-Path $SkillDir "scripts") -Force
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
Write-Ok "Files copied to $SkillDir"
|
|
387
|
+
|
|
388
|
+
if ((Test-Path $Config) -and (Select-String -Path $Config -Pattern "conductor-skills" -Quiet)) {
|
|
389
|
+
Write-Info "Aider config already references conductor-skills, skipping."
|
|
390
|
+
} else {
|
|
391
|
+
Write-Info "Adding read entries to $Config ..."
|
|
392
|
+
$entries = @("", "# Conductor Skills", "read:")
|
|
393
|
+
foreach ($file in $SKILL_FILES) {
|
|
394
|
+
$relative = $file -replace "^skills/conductor/", ""
|
|
395
|
+
$entries += " - ${ReadPrefix}${relative}"
|
|
396
|
+
}
|
|
397
|
+
$entries -join "`n" | Add-Content -Path $Config
|
|
398
|
+
Write-Ok "Updated: $Config"
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
function Install-ForAgent {
|
|
403
|
+
param([string]$AgentName, [string]$ProjDir, [bool]$IsGlobal, [bool]$ForceWrite, [string]$TmpDir, [string]$Assembled)
|
|
404
|
+
|
|
405
|
+
if ($AgentName -eq "claude") {
|
|
406
|
+
return Install-Claude
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
if ($IsGlobal) {
|
|
410
|
+
$installDir = $env:USERPROFILE
|
|
411
|
+
if ($AgentName -eq "aider") {
|
|
412
|
+
Install-AiderToDir -SkillDir (Join-Path $installDir ".conductor-skills") -TmpDir $TmpDir -Config (Join-Path $installDir ".aider.conf.yml") -ReadPrefix "$installDir/.conductor-skills/"
|
|
413
|
+
} else {
|
|
414
|
+
$targetPath = Get-GlobalPath -AgentName $AgentName
|
|
415
|
+
Install-ToFile -Target $targetPath -Assembled $Assembled -ForceWrite $ForceWrite
|
|
416
|
+
}
|
|
417
|
+
} else {
|
|
418
|
+
switch ($AgentName) {
|
|
419
|
+
"codex" { Install-ToFile -Target (Join-Path $ProjDir "AGENTS.md") -Assembled $Assembled -ForceWrite $ForceWrite }
|
|
420
|
+
"gemini" { Install-ToFile -Target (Join-Path $ProjDir "GEMINI.md") -Assembled $Assembled -ForceWrite $ForceWrite }
|
|
421
|
+
"cursor" {
|
|
422
|
+
$frontmatter = "---`ndescription: Conductor workflow orchestration - create, run, monitor, and manage workflows`nglobs: `"**/*`"`nalwaysApply: true`n---`n`n"
|
|
423
|
+
Install-ToFile -Target (Join-Path $ProjDir ".cursor\rules\conductor.mdc") -Assembled $Assembled -ForceWrite $ForceWrite -Prefix $frontmatter
|
|
424
|
+
}
|
|
425
|
+
"windsurf" { Install-ToFile -Target (Join-Path $ProjDir ".windsurfrules") -Assembled $Assembled -ForceWrite $ForceWrite }
|
|
426
|
+
"cline" { Install-ToFile -Target (Join-Path $ProjDir ".clinerules") -Assembled $Assembled -ForceWrite $ForceWrite }
|
|
427
|
+
"aider" { Install-AiderToDir -SkillDir (Join-Path $ProjDir ".conductor-skills") -TmpDir $TmpDir -Config (Join-Path $ProjDir ".aider.conf.yml") -ReadPrefix ".conductor-skills/" }
|
|
428
|
+
"copilot" { Install-ToFile -Target (Join-Path $ProjDir ".github\copilot-instructions.md") -Assembled $Assembled -ForceWrite $ForceWrite }
|
|
429
|
+
"amazonq" { Install-ToFile -Target (Join-Path $ProjDir ".amazonq\rules\conductor.md") -Assembled $Assembled -ForceWrite $ForceWrite }
|
|
430
|
+
"opencode" { Install-ToFile -Target (Join-Path $ProjDir "AGENTS.md") -Assembled $Assembled -ForceWrite $ForceWrite }
|
|
431
|
+
"roo" { Install-ToFile -Target (Join-Path $ProjDir ".roo\rules\conductor.md") -Assembled $Assembled -ForceWrite $ForceWrite }
|
|
432
|
+
"amp" { Install-ToFile -Target (Join-Path $ProjDir ".amp\instructions.md") -Assembled $Assembled -ForceWrite $ForceWrite }
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
return $true
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
439
|
+
# Uninstall
|
|
440
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
441
|
+
|
|
442
|
+
function Uninstall-Agent {
|
|
443
|
+
param([string]$AgentName, [string]$ProjDir, [bool]$IsGlobal)
|
|
444
|
+
|
|
445
|
+
if ($AgentName -eq "claude") {
|
|
446
|
+
Write-Info "To remove the Conductor skill from Claude Code, run:"
|
|
447
|
+
Write-Host " /plugin uninstall conductor@conductor-skills (in your Claude Code session)"
|
|
448
|
+
return
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
if ($IsGlobal) {
|
|
452
|
+
if ($AgentName -eq "aider") {
|
|
453
|
+
$skillDir = Join-Path $env:USERPROFILE ".conductor-skills"
|
|
454
|
+
if (Test-Path $skillDir) {
|
|
455
|
+
Remove-Item -Recurse -Force $skillDir
|
|
456
|
+
Write-Ok "Removed: $skillDir"
|
|
457
|
+
Write-Info "Note: You may also want to remove the 'read:' entries from ~/.aider.conf.yml"
|
|
458
|
+
} else {
|
|
459
|
+
Write-Warn "Nothing to uninstall: $skillDir not found"
|
|
460
|
+
}
|
|
461
|
+
return
|
|
462
|
+
}
|
|
463
|
+
$target = Get-GlobalPath -AgentName $AgentName
|
|
464
|
+
} else {
|
|
465
|
+
$target = Get-TargetPath -AgentName $AgentName -ProjDir $ProjDir
|
|
466
|
+
if ($AgentName -eq "aider") {
|
|
467
|
+
if (Test-Path $target) {
|
|
468
|
+
Remove-Item -Recurse -Force $target
|
|
469
|
+
Write-Ok "Removed: $target"
|
|
470
|
+
Write-Info "Note: You may also want to remove the 'read:' entries from .aider.conf.yml"
|
|
471
|
+
} else {
|
|
472
|
+
Write-Warn "Nothing to uninstall: $target not found"
|
|
473
|
+
}
|
|
474
|
+
return
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
if (Test-Path $target) {
|
|
479
|
+
Remove-Item -Force $target
|
|
480
|
+
Write-Ok "Removed: $target"
|
|
481
|
+
} else {
|
|
482
|
+
Write-Warn "Nothing to uninstall: $target not found"
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
487
|
+
# Check mode (dry run)
|
|
488
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
489
|
+
|
|
490
|
+
function Do-Check {
|
|
491
|
+
param([string[]]$Agents)
|
|
492
|
+
|
|
493
|
+
$manifest = Get-ManifestPath -IsGlobal $true
|
|
494
|
+
|
|
495
|
+
Write-Host ""
|
|
496
|
+
Write-Host "Detected agents:" -ForegroundColor White
|
|
497
|
+
if ($Agents.Count -eq 0) {
|
|
498
|
+
Write-Warn "No AI coding agents detected on this system."
|
|
499
|
+
return
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
foreach ($a in $Agents) {
|
|
503
|
+
$installedVer = Read-ManifestVersion -ManifestPath $manifest -AgentName $a
|
|
504
|
+
$globalSupport = if (Supports-Global -AgentName $a) { "yes" } else { "no" }
|
|
505
|
+
|
|
506
|
+
if ($installedVer) {
|
|
507
|
+
if ($installedVer -eq $SCRIPT_VERSION) {
|
|
508
|
+
Write-Host " * $a v$installedVer (up to date)" -ForegroundColor Green
|
|
509
|
+
} else {
|
|
510
|
+
Write-Host " * $a v$installedVer -> v$SCRIPT_VERSION (upgrade available)" -ForegroundColor Yellow
|
|
511
|
+
}
|
|
512
|
+
} else {
|
|
513
|
+
Write-Host " * $a (not installed) global: $globalSupport" -ForegroundColor Blue
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
Write-Host ""
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
520
|
+
# Main
|
|
521
|
+
# ─────────────────────────────────────────────────────────────────────────────
|
|
522
|
+
|
|
523
|
+
if ($Version) {
|
|
524
|
+
Write-Host "v$SCRIPT_VERSION"
|
|
525
|
+
exit 0
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
# Require -Agent or -All
|
|
529
|
+
if (-not $Agent -and -not $All) {
|
|
530
|
+
Write-Err "Missing required -Agent parameter (or use -All)"
|
|
531
|
+
exit 1
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
# Resolve project dir
|
|
535
|
+
$ProjectDir = (Resolve-Path $ProjectDir).Path
|
|
536
|
+
|
|
537
|
+
Write-Host ""
|
|
538
|
+
Write-Host "Conductor Skills Installer v$SCRIPT_VERSION" -ForegroundColor White
|
|
539
|
+
Write-Host ""
|
|
540
|
+
|
|
541
|
+
# Build agent list
|
|
542
|
+
$agentList = @()
|
|
543
|
+
if ($All) {
|
|
544
|
+
$agentList = @(Detect-Agents)
|
|
545
|
+
if ($agentList.Count -eq 0) {
|
|
546
|
+
Write-Warn "No AI coding agents detected on this system."
|
|
547
|
+
Write-Host ""
|
|
548
|
+
Write-Info "Supported agents: claude, codex, gemini, cursor, windsurf, cline,"
|
|
549
|
+
Write-Info " aider, copilot, amazonq, opencode, roo, amp"
|
|
550
|
+
Write-Host ""
|
|
551
|
+
Write-Info "Install one of the above, then re-run this command."
|
|
552
|
+
exit 0
|
|
553
|
+
}
|
|
554
|
+
Write-Info "Detected agents: $($agentList -join ', ')"
|
|
555
|
+
Write-Host ""
|
|
556
|
+
} else {
|
|
557
|
+
$Agent = $Agent.ToLower()
|
|
558
|
+
if ($VALID_AGENTS -notcontains $Agent) {
|
|
559
|
+
Write-Err "Unknown agent: $Agent"
|
|
560
|
+
exit 1
|
|
561
|
+
}
|
|
562
|
+
$agentList = @($Agent)
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
# Check mode
|
|
566
|
+
if ($Check) {
|
|
567
|
+
Do-Check -Agents $agentList
|
|
568
|
+
exit 0
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
# Determine manifest path
|
|
572
|
+
$useGlobalManifest = $Global -or $All
|
|
573
|
+
$manifest = Get-ManifestPath -IsGlobal $useGlobalManifest -ProjDir $ProjectDir
|
|
574
|
+
|
|
575
|
+
# Handle uninstall
|
|
576
|
+
if ($Uninstall) {
|
|
577
|
+
foreach ($a in $agentList) {
|
|
578
|
+
$useGlobal = [bool]$Global
|
|
579
|
+
if ($All -and (Supports-Global -AgentName $a)) { $useGlobal = $true }
|
|
580
|
+
Write-Info "Uninstalling $a ..."
|
|
581
|
+
Uninstall-Agent -AgentName $a -ProjDir $ProjectDir -IsGlobal $useGlobal
|
|
582
|
+
Remove-ManifestEntry -ManifestPath $manifest -AgentName $a
|
|
583
|
+
}
|
|
584
|
+
Write-Host ""
|
|
585
|
+
Write-Ok "Done!"
|
|
586
|
+
exit 0
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
# Check for upgrade
|
|
590
|
+
$targetVersion = $SCRIPT_VERSION
|
|
591
|
+
if ($Upgrade) {
|
|
592
|
+
Write-Info "Checking for updates..."
|
|
593
|
+
$remoteVer = Fetch-RemoteVersion
|
|
594
|
+
if (-not $remoteVer) {
|
|
595
|
+
Write-Warn "Could not check for updates (offline?). Using bundled v$SCRIPT_VERSION."
|
|
596
|
+
} elseif ($remoteVer -ne $SCRIPT_VERSION) {
|
|
597
|
+
Write-Info "Update available: v$SCRIPT_VERSION -> v$remoteVer"
|
|
598
|
+
$targetVersion = $remoteVer
|
|
599
|
+
} else {
|
|
600
|
+
Write-Info "Already at latest version (v$SCRIPT_VERSION)."
|
|
601
|
+
}
|
|
602
|
+
Write-Host ""
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
# Download files to temp dir
|
|
606
|
+
$tmpDir = Join-Path ([System.IO.Path]::GetTempPath()) "conductor-skills-$(Get-Random)"
|
|
607
|
+
New-Item -ItemType Directory -Path $tmpDir -Force | Out-Null
|
|
608
|
+
|
|
609
|
+
try {
|
|
610
|
+
Download-Files -TmpDir $tmpDir
|
|
611
|
+
|
|
612
|
+
$assembled = Join-Path $tmpDir "_assembled.md"
|
|
613
|
+
Assemble-Content -TmpDir $tmpDir -Output $assembled
|
|
614
|
+
$size = (Get-Item $assembled).Length
|
|
615
|
+
Write-Ok "Assembled skill content ($size bytes)"
|
|
616
|
+
|
|
617
|
+
$installedCount = 0
|
|
618
|
+
$skippedCount = 0
|
|
619
|
+
|
|
620
|
+
foreach ($a in $agentList) {
|
|
621
|
+
Write-Host ""
|
|
622
|
+
|
|
623
|
+
# Determine if global for this agent
|
|
624
|
+
$useGlobal = [bool]$Global
|
|
625
|
+
if ($All) {
|
|
626
|
+
if (Supports-Global -AgentName $a) {
|
|
627
|
+
$useGlobal = $true
|
|
628
|
+
} else {
|
|
629
|
+
Write-Info "${a}: skipped (project-only install). Use -ProjectDir <path> to include."
|
|
630
|
+
$skippedCount++
|
|
631
|
+
continue
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
# Validate global support for single-agent mode
|
|
636
|
+
if ($useGlobal -and !(Supports-Global -AgentName $a)) {
|
|
637
|
+
Write-Err "Global install is not supported for $a. Run from your project directory instead."
|
|
638
|
+
continue
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
# Idempotency check
|
|
642
|
+
$installedVer = Read-ManifestVersion -ManifestPath $manifest -AgentName $a
|
|
643
|
+
if ($installedVer -and ($installedVer -eq $targetVersion) -and !$Force -and !$Upgrade) {
|
|
644
|
+
Write-Ok "$a already at v$installedVer, skipping."
|
|
645
|
+
$skippedCount++
|
|
646
|
+
continue
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
if ($installedVer -and ($installedVer -ne $targetVersion)) {
|
|
650
|
+
Write-Info "Upgrading $a from v$installedVer to v$targetVersion ..."
|
|
651
|
+
} else {
|
|
652
|
+
Write-Info "Installing for $a ..."
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
# Perform install
|
|
656
|
+
$result = Install-ForAgent -AgentName $a -ProjDir $ProjectDir -IsGlobal $useGlobal -ForceWrite $Force -TmpDir $tmpDir -Assembled $assembled
|
|
657
|
+
if ($result -ne $false) {
|
|
658
|
+
$targetPath = if ($useGlobal) { Get-GlobalPath -AgentName $a } else { Get-TargetPath -AgentName $a -ProjDir $ProjectDir }
|
|
659
|
+
$mode = if ($useGlobal) { "global" } else { "project" }
|
|
660
|
+
Write-ManifestEntry -ManifestPath $manifest -AgentName $a -Ver $targetVersion -Mode $mode -TargetPath $targetPath
|
|
661
|
+
$installedCount++
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
Write-Host ""
|
|
666
|
+
Write-Host "Done! Installed: $installedCount, Skipped: $skippedCount" -ForegroundColor Green
|
|
667
|
+
Write-Host ""
|
|
668
|
+
Write-Host "Next steps:"
|
|
669
|
+
Write-Host ' Ask your agent to connect to your Conductor server, e.g.:'
|
|
670
|
+
Write-Host ""
|
|
671
|
+
Write-Host ' "Connect to my Conductor server at http://localhost:8080/api"'
|
|
672
|
+
Write-Host ""
|
|
673
|
+
Write-Host " Docs: https://github.com/conductor-oss/conductor-skills" -ForegroundColor Blue
|
|
674
|
+
Write-Host ""
|
|
675
|
+
} finally {
|
|
676
|
+
Remove-Item -Recurse -Force $tmpDir -ErrorAction SilentlyContinue
|
|
677
|
+
}
|