sdtk-kit 0.3.3 → 0.3.4
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/README.md +36 -2
- package/assets/manifest/toolkit-bundle.manifest.json +18 -8
- package/assets/manifest/toolkit-bundle.sha256.txt +4 -2
- package/assets/toolkit/toolkit/install.ps1 +31 -7
- package/assets/toolkit/toolkit/scripts/install-claude-skills.ps1 +129 -0
- package/assets/toolkit/toolkit/scripts/install-codex-skills.ps1 +8 -0
- package/assets/toolkit/toolkit/scripts/uninstall-claude-skills.ps1 +139 -0
- package/package.json +1 -1
- package/src/commands/help.js +30 -4
- package/src/commands/init.js +25 -1
- package/src/commands/runtime.js +217 -0
- package/src/index.js +4 -1
- package/src/lib/scope.js +68 -0
package/README.md
CHANGED
|
@@ -36,7 +36,9 @@ sdtk generate --feature-key USER_PROFILE --feature-name "User Profile"
|
|
|
36
36
|
Initialize SDTK workspace in the current or specified project directory.
|
|
37
37
|
|
|
38
38
|
```bash
|
|
39
|
-
sdtk init --runtime <codex|claude> [--project-path <path>] [--force] [--skip-
|
|
39
|
+
sdtk init --runtime <codex|claude> [--project-path <path>] [--force] [--runtime-scope <project|user>] [--skip-runtime-assets]
|
|
40
|
+
|
|
41
|
+
# Deprecated: --skip-skills (use --skip-runtime-assets instead)
|
|
40
42
|
```
|
|
41
43
|
|
|
42
44
|
Creates:
|
|
@@ -44,7 +46,9 @@ Creates:
|
|
|
44
46
|
- `sdtk.config.json` -- project configuration
|
|
45
47
|
- `sdtk.config.profiles.example.json` -- stack profile examples
|
|
46
48
|
- `CODEX.md` or `CLAUDE.md` -- runtime adapter
|
|
47
|
-
- for `--runtime claude`,
|
|
49
|
+
- for `--runtime claude`, skill files are installed into `.claude/skills/` (project scope, default) or `~/.claude/skills/` (user scope) unless `--skip-runtime-assets` is used
|
|
50
|
+
- for `--runtime codex`, skill files are installed into `$CODEX_HOME/skills/` or `~/.codex/skills/` (user scope only) unless `--skip-runtime-assets` is used
|
|
51
|
+
- `--skip-skills` is deprecated; use `--skip-runtime-assets` instead
|
|
48
52
|
|
|
49
53
|
### `sdtk auth`
|
|
50
54
|
|
|
@@ -83,6 +87,36 @@ sdtk generate --feature-key <UPPER_SNAKE_CASE> --feature-name "<text>" [--projec
|
|
|
83
87
|
|
|
84
88
|
Output files include: project initiation, BA spec, flow-action spec, PRD, backlog, architecture design, database spec, API specs (OpenAPI + endpoints + design detail + flow list), UI design layout, implementation plan, test cases, and QA release report.
|
|
85
89
|
|
|
90
|
+
### `sdtk runtime`
|
|
91
|
+
|
|
92
|
+
Manage runtime skill assets independently of `sdtk init`.
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
sdtk runtime install --runtime <codex|claude> [--scope <project|user>]
|
|
96
|
+
sdtk runtime uninstall --runtime <codex|claude> [--scope <project|user>]
|
|
97
|
+
sdtk runtime status --runtime <codex|claude>
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Scope defaults:
|
|
101
|
+
- `claude`: `project` (installs to `.claude/skills/`); `user` installs to `~/.claude/skills/`
|
|
102
|
+
- `codex`: `user` only (installs to `$CODEX_HOME/skills/` or `~/.codex/skills/`); project scope is not supported (Gate C0)
|
|
103
|
+
|
|
104
|
+
Examples:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
# Install Claude skills at project scope (default)
|
|
108
|
+
sdtk runtime install --runtime claude
|
|
109
|
+
|
|
110
|
+
# Install Claude skills at user scope
|
|
111
|
+
sdtk runtime install --runtime claude --scope user
|
|
112
|
+
|
|
113
|
+
# Check installed runtime assets
|
|
114
|
+
sdtk runtime status --runtime claude
|
|
115
|
+
|
|
116
|
+
# Remove runtime assets
|
|
117
|
+
sdtk runtime uninstall --runtime claude --scope project
|
|
118
|
+
```
|
|
119
|
+
|
|
86
120
|
### `sdtk --help` / `sdtk --version`
|
|
87
121
|
|
|
88
122
|
```bash
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"buildTimestamp": "2026-03-
|
|
2
|
+
"buildTimestamp": "2026-03-07T02:40:24Z",
|
|
3
3
|
"files": [
|
|
4
4
|
{
|
|
5
5
|
"path": "toolkit/AGENTS.md",
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
},
|
|
9
9
|
{
|
|
10
10
|
"path": "toolkit/install.ps1",
|
|
11
|
-
"sha256": "
|
|
12
|
-
"size":
|
|
11
|
+
"sha256": "e717a2791fb597d7a21f57f4c4790dbc545e954f0af3ca0c47f160f78c8a2474",
|
|
12
|
+
"size": 9777
|
|
13
13
|
},
|
|
14
14
|
{
|
|
15
15
|
"path": "toolkit/runtimes/claude/CLAUDE_TEMPLATE.md",
|
|
@@ -26,10 +26,20 @@
|
|
|
26
26
|
"sha256": "5c1f5442fd3c26b8bf62db4b25e9f1c4207258c7fe52f12ed533968f77dfbf65",
|
|
27
27
|
"size": 10557
|
|
28
28
|
},
|
|
29
|
+
{
|
|
30
|
+
"path": "toolkit/scripts/install-claude-skills.ps1",
|
|
31
|
+
"sha256": "8c66c27262ad4abc3c42bbcbe3a97752a5f29956ac93397133e6780354911549",
|
|
32
|
+
"size": 4315
|
|
33
|
+
},
|
|
29
34
|
{
|
|
30
35
|
"path": "toolkit/scripts/install-codex-skills.ps1",
|
|
31
|
-
"sha256": "
|
|
32
|
-
"size":
|
|
36
|
+
"sha256": "ca64e0c2a0f13137bc6b780a57442de46a3e0551778bbcbadd4eb779c21cb203",
|
|
37
|
+
"size": 9427
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"path": "toolkit/scripts/uninstall-claude-skills.ps1",
|
|
41
|
+
"sha256": "809ffc1f96528ac1cd453214cd1c2d231ca0753f0d3c19b4a20f11835a64a152",
|
|
42
|
+
"size": 4482
|
|
33
43
|
},
|
|
34
44
|
{
|
|
35
45
|
"path": "toolkit/scripts/uninstall-codex-skills.ps1",
|
|
@@ -397,7 +407,7 @@
|
|
|
397
407
|
"size": 3255
|
|
398
408
|
}
|
|
399
409
|
],
|
|
400
|
-
"sourceCommit": "
|
|
401
|
-
"version": "0.3.
|
|
402
|
-
"fileCount":
|
|
410
|
+
"sourceCommit": "965d6ad1f80a42b8b49c4296ec7a96ffef2655e3",
|
|
411
|
+
"version": "0.3.4",
|
|
412
|
+
"fileCount": 81
|
|
403
413
|
}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
868430474b46e4e8d27ed26b780a794936e84cf4f0278f2cc3d061f54877f498 toolkit/AGENTS.md
|
|
2
|
-
|
|
2
|
+
e717a2791fb597d7a21f57f4c4790dbc545e954f0af3ca0c47f160f78c8a2474 toolkit/install.ps1
|
|
3
3
|
0f3e0bfe1b5165250f0da4da5790a9e6220023752713088a0076eb7f17fd6397 toolkit/runtimes/claude/CLAUDE_TEMPLATE.md
|
|
4
4
|
4154c15c71f44d2f2caf07fb41722fa65d4f9ec7e78f798ee084effd12345c62 toolkit/runtimes/codex/CODEX_TEMPLATE.md
|
|
5
5
|
5c1f5442fd3c26b8bf62db4b25e9f1c4207258c7fe52f12ed533968f77dfbf65 toolkit/scripts/init-feature.ps1
|
|
6
|
-
|
|
6
|
+
8c66c27262ad4abc3c42bbcbe3a97752a5f29956ac93397133e6780354911549 toolkit/scripts/install-claude-skills.ps1
|
|
7
|
+
ca64e0c2a0f13137bc6b780a57442de46a3e0551778bbcbadd4eb779c21cb203 toolkit/scripts/install-codex-skills.ps1
|
|
8
|
+
809ffc1f96528ac1cd453214cd1c2d231ca0753f0d3c19b4a20f11835a64a152 toolkit/scripts/uninstall-claude-skills.ps1
|
|
7
9
|
e0d462bd6dcdb17cc003d459063ff341bd2e4f60b245cda9b7e9b9e94b3cf01f toolkit/scripts/uninstall-codex-skills.ps1
|
|
8
10
|
de2921da9ce504487d9c7d97bf862b65d0ba00b9f1593a4fbfadf41ac36adb49 toolkit/sdtk.config.json
|
|
9
11
|
21b1b0212f85c76dc6a89ae5936b39c4c1df7837a333f7a3db337f3039babb7b toolkit/sdtk.config.profiles.example.json
|
|
@@ -2,9 +2,12 @@ param(
|
|
|
2
2
|
[string]$ProjectPath,
|
|
3
3
|
[switch]$Force,
|
|
4
4
|
[switch]$SkipSkills,
|
|
5
|
+
[switch]$SkipRuntimeAssets,
|
|
5
6
|
[switch]$Quiet,
|
|
6
7
|
[ValidateSet('codex', 'claude')]
|
|
7
|
-
[string]$Runtime = 'codex'
|
|
8
|
+
[string]$Runtime = 'codex',
|
|
9
|
+
[ValidateSet('project', 'user', '')]
|
|
10
|
+
[string]$Scope = ''
|
|
8
11
|
)
|
|
9
12
|
|
|
10
13
|
$ErrorActionPreference = 'Stop'
|
|
@@ -181,6 +184,15 @@ if (-not $ProjectPath) {
|
|
|
181
184
|
}
|
|
182
185
|
$projectRoot = Resolve-Path -LiteralPath $ProjectPath
|
|
183
186
|
|
|
187
|
+
# Merge SkipRuntimeAssets and legacy SkipSkills
|
|
188
|
+
if ($SkipRuntimeAssets) { $SkipSkills = $true }
|
|
189
|
+
|
|
190
|
+
# Default scope: project for Claude, user for Codex
|
|
191
|
+
if (-not $Scope -or $Scope -eq '') {
|
|
192
|
+
if ($Runtime -eq 'claude') { $Scope = 'project' }
|
|
193
|
+
else { $Scope = 'user' }
|
|
194
|
+
}
|
|
195
|
+
|
|
184
196
|
if (-not $Quiet) {
|
|
185
197
|
Write-Host "SDTK toolkit : $toolkitRoot"
|
|
186
198
|
Write-Host "Project root : $projectRoot"
|
|
@@ -217,17 +229,29 @@ if (($Runtime -eq 'codex') -and (-not $SkipSkills)) {
|
|
|
217
229
|
}
|
|
218
230
|
|
|
219
231
|
Write-Host ""
|
|
220
|
-
Write-Host "Installing Codex skills
|
|
232
|
+
Write-Host "Installing Codex skills (scope: $Scope)..."
|
|
221
233
|
if ($Force) {
|
|
222
|
-
& $skillInstaller -Force | Out-Host
|
|
234
|
+
& $skillInstaller -Scope $Scope -Force | Out-Host
|
|
223
235
|
} else {
|
|
224
|
-
& $skillInstaller | Out-Host
|
|
236
|
+
& $skillInstaller -Scope $Scope | Out-Host
|
|
225
237
|
}
|
|
226
238
|
}
|
|
227
239
|
elseif (($Runtime -eq 'claude') -and (-not $SkipSkills)) {
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
240
|
+
$skillInstaller = Join-Path $toolkitRoot 'scripts/install-claude-skills.ps1'
|
|
241
|
+
if (-not (Test-Path -LiteralPath $skillInstaller)) {
|
|
242
|
+
# Fallback to inline Install-ClaudeSkills for backward compatibility
|
|
243
|
+
Write-Host ""
|
|
244
|
+
Write-Host "Installing Claude Code skills..."
|
|
245
|
+
Install-ClaudeSkills -ToolkitRoot $toolkitRoot -ProjectRoot $projectRoot -Overwrite ([bool]$Force)
|
|
246
|
+
} else {
|
|
247
|
+
Write-Host ""
|
|
248
|
+
Write-Host "Installing Claude Code skills (scope: $Scope)..."
|
|
249
|
+
if ($Force) {
|
|
250
|
+
& $skillInstaller -Scope $Scope -ProjectPath $projectRoot.ToString() -Force | Out-Host
|
|
251
|
+
} else {
|
|
252
|
+
& $skillInstaller -Scope $Scope -ProjectPath $projectRoot.ToString() | Out-Host
|
|
253
|
+
}
|
|
254
|
+
}
|
|
231
255
|
}
|
|
232
256
|
|
|
233
257
|
if (-not $Quiet) {
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
param(
|
|
2
|
+
[string]$ProjectPath,
|
|
3
|
+
[ValidateSet('project', 'user')]
|
|
4
|
+
[string]$Scope = 'project',
|
|
5
|
+
[switch]$Force
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
$ErrorActionPreference = 'Stop'
|
|
9
|
+
Set-StrictMode -Version Latest
|
|
10
|
+
|
|
11
|
+
function Copy-File {
|
|
12
|
+
param(
|
|
13
|
+
[Parameter(Mandatory = $true)][string]$SourcePath,
|
|
14
|
+
[Parameter(Mandatory = $true)][string]$DestinationPath,
|
|
15
|
+
[Parameter(Mandatory = $true)][bool]$Overwrite
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
if (-not (Test-Path -LiteralPath $SourcePath)) {
|
|
19
|
+
throw "Missing source: $SourcePath"
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (Test-Path -LiteralPath $DestinationPath) {
|
|
23
|
+
if (-not $Overwrite) {
|
|
24
|
+
Write-Warning "Already exists (skipping). Use -Force to overwrite: $DestinationPath"
|
|
25
|
+
return
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
$parent = Split-Path -Parent $DestinationPath
|
|
30
|
+
if ($parent -and -not (Test-Path -LiteralPath $parent)) {
|
|
31
|
+
New-Item -ItemType Directory -Force -Path $parent | Out-Null
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
Copy-Item -LiteralPath $SourcePath -Destination $DestinationPath -Force
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
$toolkitRoot = Resolve-Path (Join-Path $PSScriptRoot '..')
|
|
38
|
+
|
|
39
|
+
# Resolve destination based on scope
|
|
40
|
+
if ($Scope -eq 'user') {
|
|
41
|
+
$skillsDest = Join-Path $HOME '.claude/skills'
|
|
42
|
+
Write-Host "Scope: user (installing to $skillsDest)"
|
|
43
|
+
} else {
|
|
44
|
+
if (-not $ProjectPath) {
|
|
45
|
+
$ProjectPath = (Resolve-Path (Join-Path $toolkitRoot '..')).Path
|
|
46
|
+
}
|
|
47
|
+
$projectRoot = Resolve-Path -LiteralPath $ProjectPath
|
|
48
|
+
$skillsDest = Join-Path $projectRoot '.claude/skills'
|
|
49
|
+
Write-Host "Scope: project (installing to $skillsDest)"
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
$skillsSource = Join-Path $toolkitRoot 'skills-claude'
|
|
53
|
+
if (-not (Test-Path -LiteralPath $skillsSource)) {
|
|
54
|
+
throw "Claude skills source not found: $skillsSource"
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
$skillCount = 0
|
|
58
|
+
foreach ($skillDir in (Get-ChildItem -Path $skillsSource -Directory)) {
|
|
59
|
+
$srcFile = Join-Path $skillDir.FullName 'SKILL.md'
|
|
60
|
+
if (-not (Test-Path -LiteralPath $srcFile)) { continue }
|
|
61
|
+
|
|
62
|
+
$destFile = Join-Path $skillsDest "$($skillDir.Name)/SKILL.md"
|
|
63
|
+
Copy-File -SourcePath $srcFile -DestinationPath $destFile -Overwrite ([bool]$Force)
|
|
64
|
+
$skillCount++
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
# Install reference files
|
|
68
|
+
$refDest = Join-Path $skillsDest 'references'
|
|
69
|
+
if (-not (Test-Path -LiteralPath $refDest)) {
|
|
70
|
+
New-Item -ItemType Directory -Force -Path $refDest | Out-Null
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
$refCount = 0
|
|
74
|
+
$missingRefs = @()
|
|
75
|
+
|
|
76
|
+
# 6 files from toolkit/templates/docs/
|
|
77
|
+
$templateRefs = @(
|
|
78
|
+
@{ Src = 'templates/docs/api/YAML_CREATION_RULES.md' },
|
|
79
|
+
@{ Src = 'templates/docs/api/API_DESIGN_FLOWCHART_CREATION_RULES.md' },
|
|
80
|
+
@{ Src = 'templates/docs/api/FLOWCHART_CREATION_RULES.md' },
|
|
81
|
+
@{ Src = 'templates/docs/api/API_DESIGN_CREATION_RULES.md' },
|
|
82
|
+
@{ Src = 'templates/docs/specs/FLOW_ACTION_SPEC_CREATION_RULES.md' },
|
|
83
|
+
@{ Src = 'templates/docs/qa/TEST_CASE_CREATION_RULES.md' }
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
foreach ($ref in $templateRefs) {
|
|
87
|
+
$srcPath = Join-Path $toolkitRoot $ref.Src
|
|
88
|
+
$fileName = Split-Path -Leaf $srcPath
|
|
89
|
+
$destPath = Join-Path $refDest $fileName
|
|
90
|
+
if (Test-Path -LiteralPath $srcPath) {
|
|
91
|
+
Copy-File -SourcePath $srcPath -DestinationPath $destPath -Overwrite ([bool]$Force)
|
|
92
|
+
$refCount++
|
|
93
|
+
} else {
|
|
94
|
+
$missingRefs += $srcPath
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
# 3 files from toolkit/skills/sdtk-screen-design-spec/references/
|
|
99
|
+
$screenRefs = @('numbering-rules.md', 'figma-mcp.md', 'excel-image-export.md')
|
|
100
|
+
foreach ($fileName in $screenRefs) {
|
|
101
|
+
$srcPath = Join-Path $toolkitRoot "skills/sdtk-screen-design-spec/references/$fileName"
|
|
102
|
+
$destPath = Join-Path $refDest $fileName
|
|
103
|
+
if (Test-Path -LiteralPath $srcPath) {
|
|
104
|
+
Copy-File -SourcePath $srcPath -DestinationPath $destPath -Overwrite ([bool]$Force)
|
|
105
|
+
$refCount++
|
|
106
|
+
} else {
|
|
107
|
+
$missingRefs += $srcPath
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
# Fail-fast: abort if any reference files are missing
|
|
112
|
+
if ($missingRefs.Count -gt 0) {
|
|
113
|
+
$list = ($missingRefs | ForEach-Object { " - $_" }) -join "`n"
|
|
114
|
+
throw "Claude install failed. Missing reference files:`n$list"
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
# Strict count assertions
|
|
118
|
+
$expectedSkills = 13
|
|
119
|
+
$expectedRefs = 9
|
|
120
|
+
if ($skillCount -ne $expectedSkills) {
|
|
121
|
+
throw "Claude install failed. Expected $expectedSkills skills but installed $skillCount."
|
|
122
|
+
}
|
|
123
|
+
if ($refCount -ne $expectedRefs) {
|
|
124
|
+
throw "Claude install failed. Expected $expectedRefs reference files but installed $refCount."
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
Write-Host " Skills installed: $skillCount"
|
|
128
|
+
Write-Host " Reference files : $refCount"
|
|
129
|
+
Write-Host " Destination : $skillsDest"
|
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
param(
|
|
2
|
+
[ValidateSet('project', 'user')]
|
|
3
|
+
[string]$Scope = 'user',
|
|
2
4
|
[switch]$Force
|
|
3
5
|
)
|
|
4
6
|
|
|
7
|
+
# Gate C0: Codex does not support project-local skills
|
|
8
|
+
if ($Scope -eq 'project') {
|
|
9
|
+
Write-Error "Codex does not support project-local skills. Use --scope user instead."
|
|
10
|
+
exit 1
|
|
11
|
+
}
|
|
12
|
+
|
|
5
13
|
$ErrorActionPreference = 'Stop'
|
|
6
14
|
Set-StrictMode -Version Latest
|
|
7
15
|
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
param(
|
|
2
|
+
[string]$ProjectPath,
|
|
3
|
+
[ValidateSet('project', 'user')]
|
|
4
|
+
[string]$Scope = 'project',
|
|
5
|
+
[string]$SkillName,
|
|
6
|
+
[switch]$All,
|
|
7
|
+
[switch]$BackupExisting,
|
|
8
|
+
[string]$BackupPath
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
$ErrorActionPreference = 'Stop'
|
|
12
|
+
Set-StrictMode -Version Latest
|
|
13
|
+
|
|
14
|
+
function Backup-Directory {
|
|
15
|
+
param(
|
|
16
|
+
[Parameter(Mandatory = $true)][string]$SourcePath,
|
|
17
|
+
[Parameter(Mandatory = $true)][string]$BackupRoot,
|
|
18
|
+
[Parameter(Mandatory = $true)][string]$Name
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
if (-not (Test-Path -LiteralPath $SourcePath)) {
|
|
22
|
+
return $null
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
New-Item -ItemType Directory -Force -Path $BackupRoot | Out-Null
|
|
26
|
+
$dest = Join-Path $BackupRoot $Name
|
|
27
|
+
if (Test-Path -LiteralPath $dest) {
|
|
28
|
+
Remove-Item -LiteralPath $dest -Recurse -Force
|
|
29
|
+
}
|
|
30
|
+
Copy-Item -LiteralPath $SourcePath -Destination $dest -Recurse -Force
|
|
31
|
+
return $dest
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if ($All -and $SkillName) {
|
|
35
|
+
throw "Use either -All or -SkillName, not both."
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
$toolkitRoot = Resolve-Path (Join-Path $PSScriptRoot '..')
|
|
39
|
+
$skillsSrc = Join-Path $toolkitRoot 'skills-claude'
|
|
40
|
+
if (-not (Test-Path -LiteralPath $skillsSrc)) {
|
|
41
|
+
throw "Missing toolkit Claude skills source directory: $skillsSrc"
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
$managedSkillNames = Get-ChildItem -LiteralPath $skillsSrc -Directory | Select-Object -ExpandProperty Name
|
|
45
|
+
if (-not $managedSkillNames -or $managedSkillNames.Count -eq 0) {
|
|
46
|
+
throw "No managed Claude skills found in: $skillsSrc"
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
$targetNames = @()
|
|
50
|
+
if ($SkillName) {
|
|
51
|
+
if ($managedSkillNames -notcontains $SkillName) {
|
|
52
|
+
throw "Skill '$SkillName' is not in managed Claude skills list. Known skills: $($managedSkillNames -join ', ')"
|
|
53
|
+
}
|
|
54
|
+
$targetNames = @($SkillName)
|
|
55
|
+
} elseif ($All) {
|
|
56
|
+
$targetNames = @($managedSkillNames)
|
|
57
|
+
} else {
|
|
58
|
+
$targetNames = @($managedSkillNames)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
# Resolve destination based on scope
|
|
62
|
+
if ($Scope -eq 'user') {
|
|
63
|
+
$skillsDest = Join-Path $HOME '.claude/skills'
|
|
64
|
+
} else {
|
|
65
|
+
if (-not $ProjectPath) {
|
|
66
|
+
$ProjectPath = (Resolve-Path (Join-Path $toolkitRoot '..')).Path
|
|
67
|
+
}
|
|
68
|
+
$projectRoot = Resolve-Path -LiteralPath $ProjectPath
|
|
69
|
+
$skillsDest = Join-Path $projectRoot '.claude/skills'
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (-not (Test-Path -LiteralPath $skillsDest)) {
|
|
73
|
+
Write-Host "Claude skills directory not found: $skillsDest"
|
|
74
|
+
exit 0
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
$backupRootResolved = $null
|
|
78
|
+
if ($BackupExisting) {
|
|
79
|
+
if (-not $BackupPath -or $BackupPath.Trim().Length -eq 0) {
|
|
80
|
+
$timestamp = Get-Date -Format 'yyyyMMdd-HHmmss'
|
|
81
|
+
$parentDir = if ($Scope -eq 'user') { Join-Path $HOME '.claude' } else { $projectRoot }
|
|
82
|
+
$BackupPath = Join-Path $parentDir (Join-Path 'skills-backups' ("uninstall-" + $timestamp))
|
|
83
|
+
}
|
|
84
|
+
New-Item -ItemType Directory -Force -Path $BackupPath | Out-Null
|
|
85
|
+
$backupRootResolved = (Resolve-Path -LiteralPath $BackupPath).Path
|
|
86
|
+
Write-Host "Backup mode enabled: $backupRootResolved"
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
$removed = New-Object System.Collections.Generic.List[string]
|
|
90
|
+
$missing = New-Object System.Collections.Generic.List[string]
|
|
91
|
+
|
|
92
|
+
foreach ($name in $targetNames) {
|
|
93
|
+
$dest = Join-Path $skillsDest $name
|
|
94
|
+
if (-not (Test-Path -LiteralPath $dest)) {
|
|
95
|
+
$missing.Add($name) | Out-Null
|
|
96
|
+
Write-Warning "Skill not installed, skipping: $name"
|
|
97
|
+
continue
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if ($BackupExisting) {
|
|
101
|
+
$backupDest = Backup-Directory -SourcePath $dest -BackupRoot $backupRootResolved -Name $name
|
|
102
|
+
if ($backupDest) {
|
|
103
|
+
Write-Host "Backed up: $name -> $backupDest"
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
Remove-Item -LiteralPath $dest -Recurse -Force
|
|
108
|
+
$removed.Add($name) | Out-Null
|
|
109
|
+
Write-Host "Uninstalled: $name"
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
# Also remove references directory if uninstalling all
|
|
113
|
+
if ($All -or (-not $SkillName)) {
|
|
114
|
+
$refDir = Join-Path $skillsDest 'references'
|
|
115
|
+
if (Test-Path -LiteralPath $refDir) {
|
|
116
|
+
if ($BackupExisting) {
|
|
117
|
+
Backup-Directory -SourcePath $refDir -BackupRoot $backupRootResolved -Name 'references' | Out-Null
|
|
118
|
+
Write-Host "Backed up: references -> $backupRootResolved/references"
|
|
119
|
+
}
|
|
120
|
+
Remove-Item -LiteralPath $refDir -Recurse -Force
|
|
121
|
+
Write-Host "Removed references directory."
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
Write-Host ""
|
|
126
|
+
Write-Host "Uninstall summary:"
|
|
127
|
+
Write-Host "- Scope: $Scope"
|
|
128
|
+
Write-Host "- Destination: $skillsDest"
|
|
129
|
+
Write-Host "- Removed: $($removed.Count)"
|
|
130
|
+
if ($removed.Count -gt 0) {
|
|
131
|
+
$removed | ForEach-Object { Write-Host " - $_" }
|
|
132
|
+
}
|
|
133
|
+
Write-Host "- Missing/Skipped: $($missing.Count)"
|
|
134
|
+
if ($missing.Count -gt 0) {
|
|
135
|
+
$missing | ForEach-Object { Write-Host " - $_" }
|
|
136
|
+
}
|
|
137
|
+
if ($backupRootResolved) {
|
|
138
|
+
Write-Host "- Backup directory: $backupRootResolved"
|
|
139
|
+
}
|
package/package.json
CHANGED
package/src/commands/help.js
CHANGED
|
@@ -9,15 +9,36 @@ function cmdHelp() {
|
|
|
9
9
|
"",
|
|
10
10
|
"Commands:",
|
|
11
11
|
" init Initialize SDTK workspace (runtime adapter + config)",
|
|
12
|
+
" runtime Manage runtime asset installation (install, uninstall, status)",
|
|
12
13
|
" auth Manage GitHub authentication and entitlement",
|
|
13
14
|
" generate Scaffold feature documentation from templates (17 files)",
|
|
14
15
|
"",
|
|
15
16
|
"Init options:",
|
|
16
|
-
" --runtime <codex|claude>
|
|
17
|
+
" --runtime <codex|claude> Runtime adapter (default: codex)",
|
|
18
|
+
" --runtime-scope <project|user> Install scope (default: project for claude, user for codex)",
|
|
19
|
+
" --project-path <path> Target project directory (default: cwd)",
|
|
20
|
+
" --force Overwrite existing files",
|
|
21
|
+
" --skip-runtime-assets Skip runtime asset installation",
|
|
22
|
+
" --skip-skills (deprecated, use --skip-runtime-assets)",
|
|
23
|
+
" --verbose Show detailed PowerShell script output",
|
|
24
|
+
"",
|
|
25
|
+
"Runtime subcommands:",
|
|
26
|
+
" sdtk runtime install --runtime <codex|claude> [--scope <project|user>]",
|
|
27
|
+
" sdtk runtime uninstall --runtime <codex|claude> [--scope <project|user>] [--all]",
|
|
28
|
+
" sdtk runtime status --runtime <codex|claude>",
|
|
29
|
+
"",
|
|
30
|
+
"Runtime options:",
|
|
31
|
+
" --runtime <codex|claude> Target runtime (required)",
|
|
32
|
+
" --scope <project|user> Install scope (default: project for claude, user for codex)",
|
|
17
33
|
" --project-path <path> Target project directory (default: cwd)",
|
|
18
|
-
" --force Overwrite existing
|
|
19
|
-
" --
|
|
20
|
-
" --verbose Show detailed
|
|
34
|
+
" --force Overwrite existing skills",
|
|
35
|
+
" --all Uninstall all managed skills",
|
|
36
|
+
" --verbose Show detailed script output",
|
|
37
|
+
"",
|
|
38
|
+
"Scope behavior:",
|
|
39
|
+
" project Skills are installed inside the repo (Claude only: .claude/skills/)",
|
|
40
|
+
" user Skills are installed in the runtime home (~/.claude/skills/ or ~/.codex/skills/)",
|
|
41
|
+
" Note: Codex supports user scope only. Project scope is not available for Codex.",
|
|
21
42
|
"",
|
|
22
43
|
"Auth options:",
|
|
23
44
|
" --token <value> Store GitHub PAT",
|
|
@@ -60,6 +81,11 @@ function cmdHelp() {
|
|
|
60
81
|
" sdtk auth --verify",
|
|
61
82
|
' sdtk generate --feature-key USER_PROFILE --feature-name "User Profile"',
|
|
62
83
|
" sdtk generate --feature-key ORDER_MGMT --feature-name \"Order Management\" --validate-only",
|
|
84
|
+
" sdtk init --runtime claude --runtime-scope user",
|
|
85
|
+
" sdtk runtime install --runtime claude --scope project",
|
|
86
|
+
" sdtk runtime install --runtime codex --scope user",
|
|
87
|
+
" sdtk runtime status --runtime claude",
|
|
88
|
+
" sdtk runtime uninstall --runtime claude --scope project --all",
|
|
63
89
|
"",
|
|
64
90
|
" # Override entitlement repo (bash/zsh):",
|
|
65
91
|
" export SDTK_ENTITLEMENT_REPO=owner/repo",
|
package/src/commands/init.js
CHANGED
|
@@ -5,12 +5,15 @@ const { parseFlags, validateChoice } = require("../lib/args");
|
|
|
5
5
|
const { verify, resolvePayloadFile } = require("../lib/toolkit-payload");
|
|
6
6
|
const { runScript } = require("../lib/powershell");
|
|
7
7
|
const { ValidationError } = require("../lib/errors");
|
|
8
|
+
const { VALID_SCOPES, defaultScope, isProjectScopeSupported } = require("../lib/scope");
|
|
8
9
|
|
|
9
10
|
const FLAG_DEFS = {
|
|
10
11
|
runtime: { type: "string" },
|
|
11
12
|
"project-path": { type: "string" },
|
|
13
|
+
"runtime-scope": { type: "string" },
|
|
12
14
|
force: { type: "boolean" },
|
|
13
15
|
"skip-skills": { type: "boolean" },
|
|
16
|
+
"skip-runtime-assets": { type: "boolean" },
|
|
14
17
|
verbose: { type: "boolean" },
|
|
15
18
|
};
|
|
16
19
|
|
|
@@ -23,6 +26,25 @@ async function cmdInit(args) {
|
|
|
23
26
|
const runtime = flags.runtime || "codex";
|
|
24
27
|
validateChoice(runtime, VALID_RUNTIMES, "runtime");
|
|
25
28
|
|
|
29
|
+
// Resolve scope
|
|
30
|
+
const scope = flags["runtime-scope"] || defaultScope(runtime);
|
|
31
|
+
validateChoice(scope, VALID_SCOPES, "runtime-scope");
|
|
32
|
+
|
|
33
|
+
// Gate C0: Codex does not support project-local skills
|
|
34
|
+
if (scope === "project" && !isProjectScopeSupported(runtime)) {
|
|
35
|
+
throw new ValidationError(
|
|
36
|
+
"Codex does not support project-local skills. Use --runtime-scope user instead."
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Handle deprecated --skip-skills
|
|
41
|
+
const skipAssets = flags["skip-runtime-assets"] || flags["skip-skills"];
|
|
42
|
+
if (flags["skip-skills"] && !flags["skip-runtime-assets"]) {
|
|
43
|
+
console.warn(
|
|
44
|
+
"Warning: --skip-skills is deprecated. Use --skip-runtime-assets instead."
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
26
48
|
// Resolve project path
|
|
27
49
|
const projectPath = flags["project-path"]
|
|
28
50
|
? path.resolve(flags["project-path"])
|
|
@@ -38,13 +60,15 @@ async function cmdInit(args) {
|
|
|
38
60
|
const params = {
|
|
39
61
|
ProjectPath: projectPath,
|
|
40
62
|
Runtime: runtime,
|
|
63
|
+
Scope: scope,
|
|
41
64
|
};
|
|
42
65
|
if (flags.force) params.Force = true;
|
|
43
|
-
if (
|
|
66
|
+
if (skipAssets) params.SkipRuntimeAssets = true;
|
|
44
67
|
if (!flags.verbose) params.Quiet = true;
|
|
45
68
|
|
|
46
69
|
console.log(`Initializing SDTK workspace...`);
|
|
47
70
|
console.log(` Runtime: ${runtime}`);
|
|
71
|
+
console.log(` Scope: ${scope}`);
|
|
48
72
|
console.log(` Project: ${projectPath}`);
|
|
49
73
|
console.log("");
|
|
50
74
|
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const path = require("path");
|
|
4
|
+
const fs = require("fs");
|
|
5
|
+
const { parseFlags, requireFlag, validateChoice } = require("../lib/args");
|
|
6
|
+
const { verify, resolvePayloadFile } = require("../lib/toolkit-payload");
|
|
7
|
+
const { runScript } = require("../lib/powershell");
|
|
8
|
+
const { ValidationError } = require("../lib/errors");
|
|
9
|
+
const {
|
|
10
|
+
VALID_SCOPES,
|
|
11
|
+
defaultScope,
|
|
12
|
+
isProjectScopeSupported,
|
|
13
|
+
resolveSkillsDir,
|
|
14
|
+
managedSkillNames,
|
|
15
|
+
} = require("../lib/scope");
|
|
16
|
+
|
|
17
|
+
const FLAG_DEFS = {
|
|
18
|
+
runtime: { type: "string" },
|
|
19
|
+
scope: { type: "string" },
|
|
20
|
+
"project-path": { type: "string" },
|
|
21
|
+
force: { type: "boolean" },
|
|
22
|
+
all: { type: "boolean" },
|
|
23
|
+
verbose: { type: "boolean" },
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const VALID_RUNTIMES = ["codex", "claude"];
|
|
27
|
+
const SUBCOMMANDS = ["install", "uninstall", "status"];
|
|
28
|
+
|
|
29
|
+
function validateScopeForRuntime(runtime, scope) {
|
|
30
|
+
if (scope === "project" && !isProjectScopeSupported(runtime)) {
|
|
31
|
+
throw new ValidationError(
|
|
32
|
+
`Codex does not support project-local skills. Use --scope user instead.`
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async function cmdRuntimeInstall(flags) {
|
|
38
|
+
const runtime = requireFlag(flags, "runtime", "runtime");
|
|
39
|
+
validateChoice(runtime, VALID_RUNTIMES, "runtime");
|
|
40
|
+
|
|
41
|
+
const scope = flags.scope || defaultScope(runtime);
|
|
42
|
+
validateChoice(scope, VALID_SCOPES, "scope");
|
|
43
|
+
validateScopeForRuntime(runtime, scope);
|
|
44
|
+
|
|
45
|
+
const projectPath = flags["project-path"]
|
|
46
|
+
? path.resolve(flags["project-path"])
|
|
47
|
+
: process.cwd();
|
|
48
|
+
|
|
49
|
+
verify();
|
|
50
|
+
|
|
51
|
+
const scriptName =
|
|
52
|
+
runtime === "claude"
|
|
53
|
+
? "toolkit/scripts/install-claude-skills.ps1"
|
|
54
|
+
: "toolkit/scripts/install-codex-skills.ps1";
|
|
55
|
+
const script = resolvePayloadFile(scriptName);
|
|
56
|
+
|
|
57
|
+
const params = { Scope: scope };
|
|
58
|
+
if (runtime === "claude") {
|
|
59
|
+
params.ProjectPath = projectPath;
|
|
60
|
+
}
|
|
61
|
+
if (flags.force) params.Force = true;
|
|
62
|
+
|
|
63
|
+
console.log(`Installing ${runtime} runtime assets...`);
|
|
64
|
+
console.log(` Runtime: ${runtime}`);
|
|
65
|
+
console.log(` Scope: ${scope}`);
|
|
66
|
+
if (scope === "project") {
|
|
67
|
+
console.log(` Project: ${projectPath}`);
|
|
68
|
+
}
|
|
69
|
+
console.log("");
|
|
70
|
+
|
|
71
|
+
const result = await runScript(script, params, {
|
|
72
|
+
silent: !flags.verbose,
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
if (result.exitCode !== 0) {
|
|
76
|
+
if (result.stderr) console.error(result.stderr);
|
|
77
|
+
throw new ValidationError(
|
|
78
|
+
`Runtime install failed (exit code ${result.exitCode}).`
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
console.log("");
|
|
83
|
+
console.log(`${runtime} runtime assets installed successfully.`);
|
|
84
|
+
return 0;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
async function cmdRuntimeUninstall(flags) {
|
|
88
|
+
const runtime = requireFlag(flags, "runtime", "runtime");
|
|
89
|
+
validateChoice(runtime, VALID_RUNTIMES, "runtime");
|
|
90
|
+
|
|
91
|
+
const scope = flags.scope || defaultScope(runtime);
|
|
92
|
+
validateChoice(scope, VALID_SCOPES, "scope");
|
|
93
|
+
validateScopeForRuntime(runtime, scope);
|
|
94
|
+
|
|
95
|
+
const projectPath = flags["project-path"]
|
|
96
|
+
? path.resolve(flags["project-path"])
|
|
97
|
+
: process.cwd();
|
|
98
|
+
|
|
99
|
+
verify();
|
|
100
|
+
|
|
101
|
+
const scriptName =
|
|
102
|
+
runtime === "claude"
|
|
103
|
+
? "toolkit/scripts/uninstall-claude-skills.ps1"
|
|
104
|
+
: "toolkit/scripts/uninstall-codex-skills.ps1";
|
|
105
|
+
const script = resolvePayloadFile(scriptName);
|
|
106
|
+
|
|
107
|
+
const params = {};
|
|
108
|
+
if (runtime === "claude") {
|
|
109
|
+
params.Scope = scope;
|
|
110
|
+
params.ProjectPath = projectPath;
|
|
111
|
+
}
|
|
112
|
+
if (flags.all) params.All = true;
|
|
113
|
+
|
|
114
|
+
console.log(`Uninstalling ${runtime} runtime assets...`);
|
|
115
|
+
console.log(` Runtime: ${runtime}`);
|
|
116
|
+
console.log(` Scope: ${scope}`);
|
|
117
|
+
console.log("");
|
|
118
|
+
|
|
119
|
+
const result = await runScript(script, params, {
|
|
120
|
+
silent: !flags.verbose,
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
if (result.exitCode !== 0) {
|
|
124
|
+
if (result.stderr) console.error(result.stderr);
|
|
125
|
+
throw new ValidationError(
|
|
126
|
+
`Runtime uninstall failed (exit code ${result.exitCode}).`
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
console.log("");
|
|
131
|
+
console.log(`${runtime} runtime assets uninstalled successfully.`);
|
|
132
|
+
return 0;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function cmdRuntimeStatus(flags) {
|
|
136
|
+
const runtime = requireFlag(flags, "runtime", "runtime");
|
|
137
|
+
validateChoice(runtime, VALID_RUNTIMES, "runtime");
|
|
138
|
+
|
|
139
|
+
const projectPath = flags["project-path"]
|
|
140
|
+
? path.resolve(flags["project-path"])
|
|
141
|
+
: process.cwd();
|
|
142
|
+
|
|
143
|
+
console.log(`Runtime: ${runtime}`);
|
|
144
|
+
console.log("");
|
|
145
|
+
|
|
146
|
+
// Check both scopes
|
|
147
|
+
const scopes = runtime === "claude" ? ["project", "user"] : ["user"];
|
|
148
|
+
|
|
149
|
+
for (const scope of scopes) {
|
|
150
|
+
const skillsDir = resolveSkillsDir(runtime, scope, projectPath);
|
|
151
|
+
const exists = fs.existsSync(skillsDir);
|
|
152
|
+
let skillCount = 0;
|
|
153
|
+
|
|
154
|
+
const managed = managedSkillNames(runtime);
|
|
155
|
+
let installedNames = [];
|
|
156
|
+
|
|
157
|
+
if (exists) {
|
|
158
|
+
try {
|
|
159
|
+
const entries = fs.readdirSync(skillsDir, { withFileTypes: true });
|
|
160
|
+
installedNames = entries
|
|
161
|
+
.filter((e) => e.isDirectory() && managed.includes(e.name))
|
|
162
|
+
.map((e) => e.name);
|
|
163
|
+
skillCount = installedNames.length;
|
|
164
|
+
} catch {
|
|
165
|
+
// Directory not readable
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const allInstalled = skillCount === managed.length;
|
|
170
|
+
|
|
171
|
+
console.log(` Scope: ${scope}`);
|
|
172
|
+
console.log(` Path: ${skillsDir}`);
|
|
173
|
+
const statusLabel = !exists
|
|
174
|
+
? "not installed"
|
|
175
|
+
: allInstalled
|
|
176
|
+
? `installed (${skillCount}/${managed.length} SDTK skills)`
|
|
177
|
+
: `partial (${skillCount}/${managed.length} SDTK skills)`;
|
|
178
|
+
console.log(` Status: ${statusLabel}`);
|
|
179
|
+
if (exists && skillCount < managed.length) {
|
|
180
|
+
const missing = managed.filter((n) => !installedNames.includes(n));
|
|
181
|
+
console.log(` Missing: ${missing.join(", ")}`);
|
|
182
|
+
}
|
|
183
|
+
console.log("");
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return 0;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
async function cmdRuntime(args) {
|
|
190
|
+
const { flags, positional } = parseFlags(args, FLAG_DEFS);
|
|
191
|
+
|
|
192
|
+
const subcommand = positional[0];
|
|
193
|
+
if (!subcommand) {
|
|
194
|
+
throw new ValidationError(
|
|
195
|
+
`Missing subcommand. Usage: sdtk runtime <${SUBCOMMANDS.join("|")}> [options]`
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if (!SUBCOMMANDS.includes(subcommand)) {
|
|
200
|
+
throw new ValidationError(
|
|
201
|
+
`Unknown subcommand: "${subcommand}". Must be one of: ${SUBCOMMANDS.join(", ")}`
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
switch (subcommand) {
|
|
206
|
+
case "install":
|
|
207
|
+
return cmdRuntimeInstall(flags);
|
|
208
|
+
case "uninstall":
|
|
209
|
+
return cmdRuntimeUninstall(flags);
|
|
210
|
+
case "status":
|
|
211
|
+
return cmdRuntimeStatus(flags);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
module.exports = {
|
|
216
|
+
cmdRuntime,
|
|
217
|
+
};
|
package/src/index.js
CHANGED
|
@@ -4,6 +4,7 @@ const { cmdHelp } = require("./commands/help");
|
|
|
4
4
|
const { cmdInit } = require("./commands/init");
|
|
5
5
|
const { cmdAuth } = require("./commands/auth");
|
|
6
6
|
const { cmdGenerate } = require("./commands/generate");
|
|
7
|
+
const { cmdRuntime } = require("./commands/runtime");
|
|
7
8
|
const { ValidationError, CliError } = require("./lib/errors");
|
|
8
9
|
|
|
9
10
|
function getVersion() {
|
|
@@ -25,7 +26,7 @@ function parseCommand(argv) {
|
|
|
25
26
|
return { command: first, args: rest };
|
|
26
27
|
}
|
|
27
28
|
|
|
28
|
-
const COMMANDS = new Set(["help", "version", "init", "auth", "generate"]);
|
|
29
|
+
const COMMANDS = new Set(["help", "version", "init", "auth", "generate", "runtime"]);
|
|
29
30
|
|
|
30
31
|
async function run(argv) {
|
|
31
32
|
const { command, args } = parseCommand(argv);
|
|
@@ -48,6 +49,8 @@ async function run(argv) {
|
|
|
48
49
|
return cmdAuth(args);
|
|
49
50
|
case "generate":
|
|
50
51
|
return cmdGenerate(args);
|
|
52
|
+
case "runtime":
|
|
53
|
+
return cmdRuntime(args);
|
|
51
54
|
}
|
|
52
55
|
}
|
|
53
56
|
|
package/src/lib/scope.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const path = require("path");
|
|
4
|
+
const os = require("os");
|
|
5
|
+
|
|
6
|
+
const VALID_SCOPES = ["project", "user"];
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Returns the default scope for a given runtime.
|
|
10
|
+
* Claude defaults to project-local, Codex defaults to user/global.
|
|
11
|
+
*/
|
|
12
|
+
function defaultScope(runtime) {
|
|
13
|
+
return runtime === "claude" ? "project" : "user";
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Returns true if the given runtime supports project-local scope.
|
|
18
|
+
* Gate C0: Codex does not support project-local skills.
|
|
19
|
+
*/
|
|
20
|
+
function isProjectScopeSupported(runtime) {
|
|
21
|
+
return runtime === "claude";
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Resolves the skills directory for a given runtime, scope, and project path.
|
|
26
|
+
*/
|
|
27
|
+
function resolveSkillsDir(runtime, scope, projectPath) {
|
|
28
|
+
if (runtime === "claude") {
|
|
29
|
+
if (scope === "user") {
|
|
30
|
+
return path.join(os.homedir(), ".claude", "skills");
|
|
31
|
+
}
|
|
32
|
+
return path.join(projectPath || process.cwd(), ".claude", "skills");
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Codex: always user/global scope
|
|
36
|
+
const codexHome = process.env.CODEX_HOME || path.join(os.homedir(), ".codex");
|
|
37
|
+
return path.join(codexHome, "skills");
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* SDTK-managed skill directory names per runtime.
|
|
42
|
+
* Used by runtime status to distinguish SDTK skills from unrelated user skills.
|
|
43
|
+
*/
|
|
44
|
+
const MANAGED_CODEX_SKILLS = [
|
|
45
|
+
"sdtk-api-design-spec", "sdtk-api-doc", "sdtk-arch", "sdtk-ba",
|
|
46
|
+
"sdtk-design-layout", "sdtk-dev", "sdtk-dev-backend", "sdtk-dev-frontend",
|
|
47
|
+
"sdtk-orchestrator", "sdtk-pm", "sdtk-qa", "sdtk-screen-design-spec",
|
|
48
|
+
"sdtk-test-case-spec",
|
|
49
|
+
];
|
|
50
|
+
|
|
51
|
+
const MANAGED_CLAUDE_SKILLS = [
|
|
52
|
+
"api-design-spec", "api-doc", "arch", "ba",
|
|
53
|
+
"design-layout", "dev", "dev-backend", "dev-frontend",
|
|
54
|
+
"orchestrator", "pm", "qa", "screen-design-spec",
|
|
55
|
+
"test-case-spec",
|
|
56
|
+
];
|
|
57
|
+
|
|
58
|
+
function managedSkillNames(runtime) {
|
|
59
|
+
return runtime === "claude" ? MANAGED_CLAUDE_SKILLS : MANAGED_CODEX_SKILLS;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
module.exports = {
|
|
63
|
+
VALID_SCOPES,
|
|
64
|
+
defaultScope,
|
|
65
|
+
isProjectScopeSupported,
|
|
66
|
+
resolveSkillsDir,
|
|
67
|
+
managedSkillNames,
|
|
68
|
+
};
|