claude-skill-lord 1.5.0 → 1.5.1

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.
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "$schema": "https://anthropic.com/claude-code/marketplace.schema.json",
3
- "name": "skilllord",
3
+ "name": "claude-skill-lord",
4
4
  "owner": {
5
5
  "name": "Dong Anh",
6
6
  "email": "donganhvu20@gmail.com"
7
7
  },
8
8
  "plugins": [
9
9
  {
10
- "name": "skilllord",
10
+ "name": "claude-skill-lord",
11
11
  "source": "./",
12
- "description": "Curated best-of-both Claude Code plugin — 22 agents, 55 tiered skills, 40+ commands, intelligent skill routing",
13
- "version": "1.0.0",
12
+ "description": "Curated Claude Code plugin — 22 agents, 61 skills, 40+ commands with intelligent skill routing and UI/UX design intelligence",
13
+ "version": "1.5.1",
14
14
  "category": "workflow",
15
15
  "tags": ["agents", "skills", "commands", "hooks", "skill-routing", "quality-gate", "tdd", "code-review"],
16
16
  "strict": false
@@ -1,12 +1,13 @@
1
1
  {
2
- "name": "skilllord",
3
- "version": "1.4.0",
4
- "description": "Curated best-of-both Claude Code plugin — 22 agents, 61 tiered skills, 40+ commands with intelligent skill routing, quality gates, and comprehensive UI/UX design intelligence",
2
+ "name": "claude-skill-lord",
3
+ "version": "1.5.1",
4
+ "description": "Curated Claude Code plugin — 22 agents, 61 skills, 40+ commands with intelligent skill routing and UI/UX design intelligence",
5
5
  "author": {
6
- "name": "SkillLord Contributors"
6
+ "name": "Dong Anh",
7
+ "email": "donganhvu20@gmail.com"
7
8
  },
8
- "homepage": "https://github.com/skilllord/skilllord",
9
- "repository": "https://github.com/skilllord/skilllord",
9
+ "homepage": "https://github.com/donganhvuphp/Claude-Skills-Lord",
10
+ "repository": "https://github.com/donganhvuphp/Claude-Skills-Lord",
10
11
  "license": "MIT",
11
12
  "keywords": [
12
13
  "claude-code",
package/README.md CHANGED
@@ -41,16 +41,17 @@ That's it. `csl init` copies skills, agents, and commands into `.claude/` and ge
41
41
 
42
42
  ```bash
43
43
  csl init # interactive setup (asks profile + target)
44
- csl init full # install everything (61 skills)
45
- csl init core # lightweight setup (16 skills)
44
+ csl init full # install everything (61 skills + canvas fonts)
46
45
  csl init --dry-run # preview without copying
47
46
  csl init --fresh # clean reinstall
47
+ csl upgrade full # upgrade to full profile (additive, no overwrites)
48
48
  csl update # update CLI to latest version
49
49
  csl migrate # update project files after csl update
50
50
  csl migrate --dry-run # preview what would change
51
+ csl diff # compare project files with source package
51
52
  csl uninstall # remove from current project
52
53
  csl doctor # check health + available updates
53
- csl list # show all components
54
+ csl list # show all components with install status
54
55
  ```
55
56
 
56
57
  ### Alternative: per-project install
@@ -74,9 +75,8 @@ node scripts/sl.js init full --target /path/to/your/project
74
75
 
75
76
  | Profile | Skills | Agents | Best For |
76
77
  |---------|--------|--------|----------|
77
- | `core` | 16 (Tier 1) | 7 core | Small projects, quick setup |
78
- | `developer` | 44 (Tier 1+2) | 22 all | Full development workflow |
79
- | `full` | 61 (all tiers) | 22 all | Multi-language, enterprise |
78
+ | `developer` | 44 (Tier 1+2) | 22 all | Recommended for all projects (default) |
79
+ | `full` | 61 (all tiers) | 22 all + canvas fonts | Multi-language, design, enterprise |
80
80
 
81
81
  ---
82
82
 
@@ -1,42 +1,24 @@
1
1
  {
2
- "version": 1,
2
+ "version": 2,
3
3
  "modules": [
4
4
  {
5
- "id": "agents-core",
5
+ "id": "agents",
6
6
  "kind": "agents",
7
- "description": "Core agents — planner, code-reviewer, debugger, tdd-guide, scout",
8
- "paths": ["agents/planner.md", "agents/code-reviewer.md", "agents/debugger.md", "agents/tdd-guide.md", "agents/scout.md", "agents/git-manager.md", "agents/docs-manager.md"],
7
+ "description": "All 22 agents — planner, code-reviewer, debugger, architect, security, scout, and more",
8
+ "paths": ["agents/"],
9
9
  "defaultInstall": true,
10
- "cost": "light",
11
- "stability": "stable"
12
- },
13
- {
14
- "id": "agents-extended",
15
- "kind": "agents",
16
- "description": "Extended agents — architect, security, e2e, refactor, loop, router, gate",
17
- "paths": ["agents/architect.md", "agents/security-reviewer.md", "agents/e2e-runner.md", "agents/refactor-cleaner.md", "agents/loop-operator.md", "agents/skill-router.md", "agents/quality-gate.md", "agents/chief-of-staff.md", "agents/harness-optimizer.md", "agents/build-error-resolver.md", "agents/project-manager.md", "agents/ui-ux-designer.md", "agents/database-admin.md", "agents/brainstormer.md", "agents/copywriter.md"],
18
- "defaultInstall": false,
19
10
  "cost": "medium",
20
11
  "stability": "stable"
21
12
  },
22
13
  {
23
- "id": "commands-core",
14
+ "id": "commands",
24
15
  "kind": "commands",
25
- "description": "Core commands — plan, code, test, fix, debug, review, cook",
16
+ "description": "All commands — plan, code, test, fix, cook, design, bootstrap, and more",
26
17
  "paths": ["commands/"],
27
18
  "defaultInstall": true,
28
19
  "cost": "light",
29
20
  "stability": "stable"
30
21
  },
31
- {
32
- "id": "commands-extended",
33
- "kind": "commands",
34
- "description": "Extended commands — design, bootstrap, evolve, learn, tdd, e2e",
35
- "paths": ["commands/"],
36
- "defaultInstall": false,
37
- "cost": "light",
38
- "stability": "stable"
39
- },
40
22
  {
41
23
  "id": "skills-tier-1",
42
24
  "kind": "skills",
@@ -1,17 +1,4 @@
1
1
  {
2
- "version": 1,
3
- "profiles": {
4
- "core": {
5
- "description": "Essential development skills — debugging, testing, code review, security",
6
- "modules": ["agents-core", "commands-core", "skills-tier-1", "hooks-essential", "workflows"]
7
- },
8
- "developer": {
9
- "description": "Full development toolkit — core + frameworks, patterns, CI/CD",
10
- "modules": ["agents-core", "agents-extended", "commands-core", "commands-extended", "skills-tier-1", "skills-tier-2", "hooks-essential", "workflows"]
11
- },
12
- "full": {
13
- "description": "Complete SkillLord — all skills, all agents, all commands",
14
- "modules": ["agents-core", "agents-extended", "commands-core", "commands-extended", "skills-tier-1", "skills-tier-2", "skills-tier-3", "canvas-fonts", "hooks-essential", "workflows"]
15
- }
16
- }
2
+ "version": 3,
3
+ "modules": ["agents", "commands", "skills-tier-1", "skills-tier-2", "skills-tier-3", "canvas-fonts", "hooks-essential", "workflows"]
17
4
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-skill-lord",
3
- "version": "1.5.0",
3
+ "version": "1.5.1",
4
4
  "description": "Curated best-of-both Claude Code plugin — 22 agents, 61 tiered skills, 40+ commands with intelligent skill routing and UI/UX design intelligence",
5
5
  "author": {
6
6
  "name": "Dong Anh",
@@ -1,17 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  /**
4
- * SkillLord Installer Profile-aware selective installation
4
+ * Claude Skill Lord Installer
5
5
  *
6
- * Usage:
7
- * skilllord-install [profile] [--target <path>] [--dry-run]
8
- *
9
- * Profiles: core, developer, full (default: developer)
10
- *
11
- * Examples:
12
- * skilllord-install core
13
- * skilllord-install full --target ./my-project
14
- * skilllord-install developer --dry-run
6
+ * Usage: csl init [--target <path>] [--dry-run] [--no-fonts]
15
7
  */
16
8
 
17
9
  const fs = require('fs');
@@ -20,34 +12,29 @@ const path = require('path');
20
12
  // Parse CLI args
21
13
  const args = process.argv.slice(2);
22
14
  const flags = {};
23
- let profile = 'developer';
24
15
 
25
16
  for (let i = 0; i < args.length; i++) {
26
17
  if (args[i] === '--target' && args[i + 1]) {
27
18
  flags.target = args[++i];
28
19
  } else if (args[i] === '--dry-run') {
29
20
  flags.dryRun = true;
21
+ } else if (args[i] === '--no-fonts') {
22
+ flags.noFonts = true;
30
23
  } else if (args[i] === '--help' || args[i] === '-h') {
31
24
  flags.help = true;
32
- } else if (!args[i].startsWith('-')) {
33
- profile = args[i];
34
25
  }
35
26
  }
36
27
 
37
28
  if (flags.help) {
38
29
  console.log(`
39
- Claude Skill Lord Installer — Profile-aware selective installation
30
+ Claude Skill Lord Installer
40
31
 
41
- Usage: csl init [profile] [options]
42
-
43
- Profiles:
44
- core 16 tier-1 skills, 7 agents (lightweight)
45
- developer 44 skills (tier-1+2), 22 agents (recommended)
46
- full 61 skills (all tiers), 22 agents (everything)
32
+ Usage: csl init [options]
47
33
 
48
34
  Options:
49
35
  --target <path> Target project directory (default: current directory)
50
36
  --dry-run Show what would be installed without copying
37
+ --no-fonts Skip canvas font files (~7MB)
51
38
  --help, -h Show this help
52
39
  `);
53
40
  process.exit(0);
@@ -58,39 +45,33 @@ const skillLordRoot = path.resolve(__dirname, '..');
58
45
  const targetDir = path.resolve(flags.target || process.cwd());
59
46
  const targetClaudeDir = path.join(targetDir, '.claude');
60
47
 
61
- // Load manifests
62
- const profilesPath = path.join(skillLordRoot, 'manifests', 'install-profiles.json');
48
+ // Load manifest
49
+ const { collectModuleFiles, buildPluginJson } = require('./lib/profile-utils');
50
+ const manifestPath = path.join(skillLordRoot, 'manifests', 'install-profiles.json');
63
51
  const modulesPath = path.join(skillLordRoot, 'manifests', 'install-modules.json');
64
52
 
65
- if (!fs.existsSync(profilesPath) || !fs.existsSync(modulesPath)) {
53
+ if (!fs.existsSync(manifestPath) || !fs.existsSync(modulesPath)) {
66
54
  console.error('Error: Manifest files not found. Ensure SkillLord is properly installed.');
67
55
  process.exit(1);
68
56
  }
69
57
 
70
- const profiles = JSON.parse(fs.readFileSync(profilesPath, 'utf8'));
58
+ const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
71
59
  const modules = JSON.parse(fs.readFileSync(modulesPath, 'utf8'));
72
60
 
73
- const selectedProfile = profiles.profiles[profile];
74
- if (!selectedProfile) {
75
- console.error(`Error: Unknown profile "${profile}".`);
76
- console.error(`Available profiles: ${Object.keys(profiles.profiles).join(', ')}`);
77
- process.exit(1);
61
+ let moduleIds = manifest.modules;
62
+ if (flags.noFonts) {
63
+ moduleIds = moduleIds.filter(id => id !== 'canvas-fonts');
78
64
  }
79
65
 
66
+ const selectedModules = modules.modules.filter(m => moduleIds.includes(m.id));
67
+
80
68
  const pkg = require(path.join(skillLordRoot, 'package.json'));
81
- console.log(`\n Claude Skill Lord Installer v${pkg.version}`);
69
+ console.log(`\n Claude Skill Lord v${pkg.version}`);
82
70
  console.log(` ${'='.repeat(38)}\n`);
83
- console.log(` Profile: ${profile}`);
84
- console.log(` Desc: ${selectedProfile.description}`);
85
71
  console.log(` Target: ${targetDir}`);
72
+ if (flags.noFonts) console.log(` Fonts: skipped (--no-fonts)`);
86
73
  console.log(` Dry run: ${flags.dryRun ? 'yes' : 'no'}\n`);
87
74
 
88
- // Resolve modules for selected profile
89
- const { collectModuleFiles } = require('./lib/profile-utils');
90
- const selectedModules = modules.modules.filter(
91
- (m) => selectedProfile.modules.includes(m.id)
92
- );
93
-
94
75
  // Collect all files to copy
95
76
  for (const mod of selectedModules) {
96
77
  console.log(` [${mod.cost}] ${mod.id}: ${mod.description}`);
@@ -116,12 +97,10 @@ for (const f of filesToCopy) {
116
97
  const destPath = path.join(targetClaudeDir, f.rel);
117
98
  const destDir = path.dirname(destPath);
118
99
 
119
- // Create directory if needed
120
100
  if (!fs.existsSync(destDir)) {
121
101
  fs.mkdirSync(destDir, { recursive: true });
122
102
  }
123
103
 
124
- // Copy file (don't overwrite existing)
125
104
  if (fs.existsSync(destPath)) {
126
105
  skipped++;
127
106
  } else {
@@ -130,15 +109,13 @@ for (const f of filesToCopy) {
130
109
  }
131
110
  }
132
111
 
133
- // Generate plugin.json for the target project (always regenerate to match current profile)
134
- const { buildPluginJson } = require('./lib/profile-utils');
112
+ // Generate plugin.json
135
113
  const pluginJsonPath = path.join(targetClaudeDir, 'plugin.json');
136
- const pluginJson = buildPluginJson(profile, filesToCopy, pkg.version);
114
+ const pluginJson = buildPluginJson('full', filesToCopy, pkg.version);
137
115
  fs.writeFileSync(pluginJsonPath, JSON.stringify(pluginJson, null, 2));
138
116
  console.log(`\n Generated: .claude/plugin.json`);
139
117
 
140
118
  console.log(`\n Installation complete!`);
141
119
  console.log(` Copied: ${copied} files`);
142
- console.log(` Skipped: ${skipped} files (already exist)`);
120
+ if (skipped > 0) console.log(` Skipped: ${skipped} files (already exist)`);
143
121
  console.log(`\n Run "claude" in your project to start using Claude Skill Lord.\n`);
144
-
@@ -1,6 +1,6 @@
1
1
  /**
2
- * Shared utilities for profile detection and plugin.json generation.
3
- * Used by: install.js, sl.js (migrate, upgrade, doctor, list, diff)
2
+ * Shared utilities for installation and plugin.json generation.
3
+ * Used by: install.js, sl.js (migrate, doctor, list, diff)
4
4
  */
5
5
 
6
6
  const fs = require('fs');
@@ -9,19 +9,9 @@ const path = require('path');
9
9
  const rootDir = path.resolve(__dirname, '..', '..');
10
10
 
11
11
  function loadManifests() {
12
- const profiles = JSON.parse(fs.readFileSync(path.join(rootDir, 'manifests', 'install-profiles.json'), 'utf8'));
12
+ const manifest = JSON.parse(fs.readFileSync(path.join(rootDir, 'manifests', 'install-profiles.json'), 'utf8'));
13
13
  const modules = JSON.parse(fs.readFileSync(path.join(rootDir, 'manifests', 'install-modules.json'), 'utf8'));
14
- return { profiles, modules };
15
- }
16
-
17
- function detectInstalledProfile(claudeDir) {
18
- const skillsDir = path.join(claudeDir, 'skills');
19
- if (!fs.existsSync(skillsDir)) return null;
20
- const dirs = fs.readdirSync(skillsDir, { withFileTypes: true })
21
- .filter(e => e.isDirectory()).map(e => e.name);
22
- if (dirs.includes('tier-3')) return 'full';
23
- if (dirs.includes('tier-2')) return 'developer';
24
- return 'core';
14
+ return { manifest, modules };
25
15
  }
26
16
 
27
17
  function buildPluginJson(profile, filesToCopy, version) {
@@ -40,8 +30,7 @@ function buildPluginJson(profile, filesToCopy, version) {
40
30
  return {
41
31
  name: 'claude-skill-lord',
42
32
  version,
43
- profile,
44
- description: `Claude Skill Lord (${profile} profile)`,
33
+ description: `Claude Skill Lord v${version}`,
45
34
  agents: agentFiles,
46
35
  commands: ['./commands/'],
47
36
  skills: [...skillDirs],
@@ -94,4 +83,4 @@ function collectModuleFiles(selectedModules) {
94
83
  return filesToCopy;
95
84
  }
96
85
 
97
- module.exports = { loadManifests, detectInstalledProfile, buildPluginJson, readPluginJson, collectFiles, collectModuleFiles };
86
+ module.exports = { loadManifests, buildPluginJson, readPluginJson, collectFiles, collectModuleFiles };
package/scripts/sl.js CHANGED
@@ -45,40 +45,14 @@ const commands = {
45
45
  console.log(`Claude Skill Lord v${getInstalledVersion()}`);
46
46
  },
47
47
 
48
- init: async () => {
49
- let profile = subArgs.find(a => !a.startsWith('-')) || null;
48
+ init: () => {
50
49
  const hasTarget = subArgs.includes('--target');
51
50
  const dryRun = subArgs.includes('--dry-run');
52
51
  const fresh = subArgs.includes('--fresh');
52
+ const noFonts = subArgs.includes('--no-fonts');
53
53
 
54
- // Interactive mode if no profile specified and not in CI
55
- if (!profile && !process.env.CI) {
56
- console.log(`\n Claude Skill Lord — Project Setup\n`);
57
- console.log(' Profiles:');
58
- console.log(' 1) core — 16 skills, 7 agents (lightweight)');
59
- console.log(' 2) developer — 44 skills, 22 agents (recommended)');
60
- console.log(' 3) full — 61 skills, 22 agents (everything)\n');
61
-
62
- const choice = await ask(' Choose profile [1/2/3] (default: 2): ');
63
- profile = { '1': 'core', '2': 'developer', '3': 'full' }[choice] || 'developer';
64
-
65
- const confirmTarget = await ask(` Target directory [.]: `);
66
- const target = confirmTarget || '.';
67
-
68
- const confirm = await ask(`\n Install "${profile}" profile to "${path.resolve(target)}"? [Y/n]: `);
69
- if (confirm.toLowerCase() === 'n') {
70
- console.log(' Cancelled.\n');
71
- return;
72
- }
73
-
74
- process.argv = ['node', 'install.js', profile, '--target', target];
75
- if (dryRun) process.argv.push('--dry-run');
76
- if (fresh) process.argv.push('--fresh');
77
- } else {
78
- profile = profile || 'developer';
79
- const initArgs = hasTarget ? subArgs : [...subArgs, '--target', '.'];
80
- process.argv = ['node', 'install.js', ...initArgs];
81
- }
54
+ const initArgs = hasTarget ? subArgs : [...subArgs, '--target', '.'];
55
+ process.argv = ['node', 'install.js', ...initArgs];
82
56
 
83
57
  // Handle --fresh: remove existing .claude/ before install
84
58
  if (fresh) {
@@ -91,44 +65,17 @@ const commands = {
91
65
  }
92
66
  }
93
67
 
94
- // B2 + B7: Check existing installation for upgrade/downgrade/same-profile warnings
68
+ // Check existing installation
95
69
  if (!fresh && !dryRun) {
96
- const { detectInstalledProfile, readPluginJson } = require('./lib/profile-utils');
70
+ const { readPluginJson } = require('./lib/profile-utils');
97
71
  const targetIdx = process.argv.indexOf('--target');
98
72
  const targetPath = targetIdx >= 0 ? path.resolve(process.argv[targetIdx + 1]) : path.resolve('.');
99
- const existingClaudeDir = path.join(targetPath, '.claude');
100
- const existingPlugin = readPluginJson(existingClaudeDir);
73
+ const existingPlugin = readPluginJson(path.join(targetPath, '.claude'));
101
74
 
102
75
  if (existingPlugin) {
103
- const existingProfile = existingPlugin.profile || detectInstalledProfile(existingClaudeDir);
104
-
105
- if (existingProfile === profile) {
106
- // B7: Same profile re-init
107
- console.log(`\n Already installed: ${profile} profile (v${existingPlugin.version})`);
108
- console.log(` Use "csl init ${profile} --fresh" to reinstall from scratch.\n`);
109
- return;
110
- }
111
-
112
- const profileOrder = { core: 1, developer: 2, full: 3 };
113
- const isDowngrade = profileOrder[profile] < profileOrder[existingProfile];
114
-
115
- if (isDowngrade && !process.env.CI) {
116
- // B2: Downgrade warning
117
- const agentCount = existingPlugin.agents ? existingPlugin.agents.length : '?';
118
- console.log(`\n WARNING: Downgrade detected`);
119
- console.log(` Current: ${existingProfile} (${agentCount} agents)`);
120
- console.log(` Target: ${profile}`);
121
- console.log(` Extra agents/skills will become unreferenced.\n`);
122
-
123
- const confirm = await ask(` Continue with downgrade? [y/N]: `);
124
- if (confirm.toLowerCase() !== 'y') {
125
- console.log(' Cancelled.\n');
126
- return;
127
- }
128
- } else if (!isDowngrade) {
129
- // Upgrade info
130
- console.log(`\n Upgrading: ${existingProfile} -> ${profile}`);
131
- }
76
+ console.log(`\n Already installed (v${existingPlugin.version})`);
77
+ console.log(` Use "csl init --fresh" to reinstall from scratch.\n`);
78
+ return;
132
79
  }
133
80
  }
134
81
 
@@ -193,23 +140,10 @@ const commands = {
193
140
  console.log(` Installed version: ${currentVersion}`);
194
141
  console.log(` New version: ${newVersion}`);
195
142
 
196
- // Collect files from source
197
- const profiles = JSON.parse(fs.readFileSync(path.join(rootDir, 'manifests', 'install-profiles.json'), 'utf8'));
198
- const modules = JSON.parse(fs.readFileSync(path.join(rootDir, 'manifests', 'install-modules.json'), 'utf8'));
199
-
200
- // Detect which profile is installed based on skill directories
201
- const installedSkillDirs = fs.existsSync(path.join(claudeDir, 'skills'))
202
- ? fs.readdirSync(path.join(claudeDir, 'skills'), { withFileTypes: true })
203
- .filter(e => e.isDirectory()).map(e => e.name)
204
- : [];
205
- const hasTier3 = installedSkillDirs.includes('tier-3');
206
- const hasTier2 = installedSkillDirs.includes('tier-2');
207
- const detectedProfile = hasTier3 ? 'full' : hasTier2 ? 'developer' : 'core';
208
-
209
- console.log(` Detected profile: ${detectedProfile}`);
210
-
211
- const selectedProfile = profiles.profiles[detectedProfile];
212
- const selectedModules = modules.modules.filter(m => selectedProfile.modules.includes(m.id));
143
+ // Collect files from source (all modules)
144
+ const { loadManifests } = require('./lib/profile-utils');
145
+ const { manifest, modules } = loadManifests();
146
+ const selectedModules = modules.modules.filter(m => manifest.modules.includes(m.id));
213
147
 
214
148
  // Collect all source files
215
149
  const sourceFiles = collectModuleFiles(selectedModules);
@@ -245,7 +179,7 @@ const commands = {
245
179
  // Rebuild plugin.json with correct agents/skills for detected profile
246
180
  const { buildPluginJson } = require('./lib/profile-utils');
247
181
  if (!dryRun) {
248
- const rebuilt = buildPluginJson(detectedProfile, sourceFiles, newVersion);
182
+ const rebuilt = buildPluginJson('full', sourceFiles, newVersion);
249
183
  fs.writeFileSync(pluginPath, JSON.stringify(rebuilt, null, 2));
250
184
  console.log(` Rebuilt plugin.json (${rebuilt.agents.length} agents, ${rebuilt.skills.length} skill dirs)`);
251
185
  }
@@ -282,73 +216,8 @@ const commands = {
282
216
  console.log(' Claude Skill Lord has been uninstalled from this project.\n');
283
217
  },
284
218
 
285
- upgrade: async () => {
286
- const { detectInstalledProfile, buildPluginJson, loadManifests } = require('./lib/profile-utils');
287
- const targetProfile = subArgs.find(a => !a.startsWith('-')) || null;
288
- const targetDir = path.resolve(subArgs.includes('--target')
289
- ? subArgs[subArgs.indexOf('--target') + 1] : '.');
290
- const claudeDir = path.join(targetDir, '.claude');
291
- const dryRun = subArgs.includes('--dry-run');
292
-
293
- if (!fs.existsSync(claudeDir)) {
294
- console.log(`\n No .claude/ found. Run "csl init" first.\n`);
295
- process.exit(1);
296
- }
297
-
298
- const currentProfile = detectInstalledProfile(claudeDir);
299
- if (!currentProfile) {
300
- console.log(`\n Could not detect current profile. Run "csl init" first.\n`);
301
- return;
302
- }
303
- const newProfile = targetProfile || currentProfile;
304
- const profileOrder = { core: 1, developer: 2, full: 3 };
305
-
306
- if (!profileOrder[newProfile]) {
307
- console.log(`\n Unknown profile "${newProfile}". Available: core, developer, full\n`);
308
- return;
309
- }
310
-
311
- if (profileOrder[newProfile] < profileOrder[currentProfile]) {
312
- console.log(`\n Cannot downgrade with upgrade. Use "csl init ${newProfile} --fresh" instead.\n`);
313
- return;
314
- }
315
-
316
- console.log(`\n Claude Skill Lord — Upgrade\n`);
317
- console.log(` Current: ${currentProfile}`);
318
- console.log(` Target: ${newProfile}`);
319
-
320
- const { profiles, modules } = loadManifests();
321
- const selectedProfile = profiles.profiles[newProfile];
322
- const selectedModules = modules.modules.filter(m => selectedProfile.modules.includes(m.id));
323
-
324
- const filesToCopy = collectModuleFiles(selectedModules);
325
-
326
- let added = 0;
327
- for (const f of filesToCopy) {
328
- const destPath = path.join(claudeDir, f.rel);
329
- if (!fs.existsSync(destPath)) {
330
- if (dryRun) { console.log(` + ${f.rel}`); }
331
- else {
332
- const destDir = path.dirname(destPath);
333
- if (!fs.existsSync(destDir)) fs.mkdirSync(destDir, { recursive: true });
334
- fs.copyFileSync(f.src, destPath);
335
- }
336
- added++;
337
- }
338
- }
339
-
340
- if (!dryRun) {
341
- const pkg = require(path.join(rootDir, 'package.json'));
342
- const pluginJson = buildPluginJson(newProfile, filesToCopy, pkg.version);
343
- fs.writeFileSync(path.join(claudeDir, 'plugin.json'), JSON.stringify(pluginJson, null, 2));
344
- }
345
-
346
- console.log(`\n ${dryRun ? '[DRY RUN] ' : ''}Added ${added} new files`);
347
- console.log(` Profile: ${currentProfile} -> ${newProfile}\n`);
348
- },
349
-
350
219
  diff: () => {
351
- const { detectInstalledProfile, loadManifests } = require('./lib/profile-utils');
220
+ const { loadManifests } = require('./lib/profile-utils');
352
221
  const targetDir = path.resolve(subArgs.includes('--target')
353
222
  ? subArgs[subArgs.indexOf('--target') + 1] : '.');
354
223
  const claudeDir = path.join(targetDir, '.claude');
@@ -358,12 +227,10 @@ const commands = {
358
227
  process.exit(1);
359
228
  }
360
229
 
361
- const profile = detectInstalledProfile(claudeDir);
362
- console.log(`\n Claude Skill Lord — Diff (${profile} profile)\n`);
230
+ console.log(`\n Claude Skill Lord — Diff\n`);
363
231
 
364
- const { profiles, modules } = loadManifests();
365
- const selectedProfile = profiles.profiles[profile];
366
- const selectedModules = modules.modules.filter(m => selectedProfile.modules.includes(m.id));
232
+ const { manifest, modules } = loadManifests();
233
+ const selectedModules = modules.modules.filter(m => manifest.modules.includes(m.id));
367
234
 
368
235
  const sourceFiles = collectModuleFiles(selectedModules);
369
236
 
@@ -402,44 +269,20 @@ const commands = {
402
269
  },
403
270
 
404
271
  list: () => {
405
- const { readPluginJson, detectInstalledProfile } = require('./lib/profile-utils');
406
272
  const manifest = JSON.parse(
407
273
  fs.readFileSync(path.join(rootDir, 'skills', 'manifest.json'), 'utf8')
408
274
  );
409
275
  const agents = fs.readdirSync(path.join(rootDir, 'agents')).filter(f => f.endsWith('.md'));
410
276
 
411
- // Detect installed state from project
412
- const projectClaudeDir = path.join(process.cwd(), '.claude');
413
- const projectPlugin = readPluginJson(projectClaudeDir);
414
- const installedAgents = projectPlugin
415
- ? new Set((projectPlugin.agents || []).map(a => a.replace('./', '').replace('.md', '')))
416
- : null;
417
- const installedSkillDirs = projectPlugin
418
- ? new Set((projectPlugin.skills || []).map(s => s.replace('./', '').replace(/\/$/, '')))
419
- : null;
420
-
421
- const tag = (name, set) => set ? (set.has(name) ? ' [installed]' : ' [available]') : '';
422
-
423
277
  console.log(`\n Claude Skill Lord Components\n`);
424
278
 
425
- if (projectPlugin) {
426
- const profile = projectPlugin.profile || detectInstalledProfile(projectClaudeDir) || '?';
427
- console.log(` Project profile: ${profile} (v${projectPlugin.version || '?'})\n`);
428
- }
429
-
430
279
  console.log(` Agents: ${agents.length}`);
431
- agents.forEach(a => {
432
- const name = a.replace('.md', '');
433
- console.log(` - ${name}${tag(`agents/${name}`, installedAgents)}`);
434
- });
280
+ agents.forEach(a => console.log(` - ${a.replace('.md', '')}`));
435
281
 
436
282
  console.log(`\n Skills: ${manifest.skills.length}`);
437
283
  [1, 2, 3].forEach(tier => {
438
284
  const skills = manifest.skills.filter(s => s.tier === tier);
439
- const tierDir = `skills/tier-${tier}`;
440
- const tierInstalled = installedSkillDirs ? installedSkillDirs.has(tierDir) : null;
441
- const tierTag = tierInstalled === null ? '' : tierInstalled ? ' [installed]' : ' [available]';
442
- console.log(`\n Tier ${tier}${tierTag} (${skills.length}):`);
285
+ console.log(`\n Tier ${tier} (${skills.length}):`);
443
286
  skills.forEach(s => console.log(` - ${s.name}: ${s.description}`));
444
287
  });
445
288
 
@@ -557,42 +400,15 @@ const commands = {
557
400
  if (missing.length) throw new Error(`missing: ${missing.join(', ')}`);
558
401
  });
559
402
 
560
- // B5: Profile consistency checks
561
- info('Profile consistency', () => {
403
+ // Consistency: check declared skill dirs exist on disk
404
+ info('Skills intact', () => {
562
405
  const pPath = path.join(projectClaudeDir, 'plugin.json');
563
406
  if (!fs.existsSync(pPath)) throw new Error('no plugin.json');
564
407
  const p = JSON.parse(fs.readFileSync(pPath, 'utf8'));
565
-
566
- const declaredAgents = (p.agents || []).map(a => a.replace('./', ''));
567
- const agentsDir = path.join(projectClaudeDir, 'agents');
568
- const diskAgents = fs.existsSync(agentsDir)
569
- ? fs.readdirSync(agentsDir).filter(f => f.endsWith('.md'))
570
- : [];
571
- const orphaned = diskAgents.filter(f => !declaredAgents.includes(`agents/${f}`));
572
-
573
408
  const declaredSkillDirs = (p.skills || []).map(s => s.replace('./', '').replace(/\/$/, ''));
574
- const missingSkillDirs = declaredSkillDirs.filter(d => !fs.existsSync(path.join(projectClaudeDir, d)));
575
-
576
- if (missingSkillDirs.length > 0) {
577
- throw new Error(`${missingSkillDirs.length} declared skill dirs missing: ${missingSkillDirs.join(', ')}`);
578
- }
579
-
580
- const details = [];
581
- if (orphaned.length > 0) details.push(`${orphaned.length} orphaned agent files`);
582
- if (p.profile) details.push(`profile: ${p.profile}`);
583
- if (details.length) console.log(` (${details.join(', ')})`);
584
- });
585
-
586
- info('Profile metadata', () => {
587
- const pPath = path.join(projectClaudeDir, 'plugin.json');
588
- const p = JSON.parse(fs.readFileSync(pPath, 'utf8'));
589
- if (!p.profile) {
590
- throw new Error('no profile field in plugin.json. Run "csl migrate" to fix.');
591
- }
592
- const { detectInstalledProfile } = require('./lib/profile-utils');
593
- const detected = detectInstalledProfile(projectClaudeDir);
594
- if (detected && detected !== p.profile) {
595
- throw new Error(`plugin.json says "${p.profile}" but disk shows "${detected}". Run "csl migrate" to fix.`);
409
+ const missing = declaredSkillDirs.filter(d => !fs.existsSync(path.join(projectClaudeDir, d)));
410
+ if (missing.length > 0) {
411
+ throw new Error(`${missing.length} skill dirs missing: ${missing.join(', ')}`);
596
412
  }
597
413
  });
598
414
  }
@@ -617,10 +433,9 @@ const commands = {
617
433
  Usage: csl <command> [options]
618
434
 
619
435
  Commands:
620
- init [profile] Set up in current project (interactive if no profile given)
621
- upgrade [profile] Upgrade to a higher profile (additive, no overwrites)
436
+ init Install in current project (22 agents, 61 skills, all commands)
622
437
  update Update CLI to latest version
623
- migrate Update installed files to match current CLI version
438
+ migrate Update project files after csl update
624
439
  diff Compare project files with source package
625
440
  uninstall Remove Claude Skill Lord from a project
626
441
  list List all agents, skills, and commands
@@ -632,35 +447,23 @@ const commands = {
632
447
  --target <path> Target directory (default: current directory)
633
448
  --dry-run Preview without copying
634
449
  --fresh Clean reinstall (remove existing .claude/ first)
450
+ --no-fonts Skip canvas font files (~7MB)
635
451
 
636
- Upgrade Options:
637
- --target <path> Target directory (default: current directory)
638
- --dry-run Preview what would be added
639
-
640
- Migrate Options:
641
- --target <path> Target directory (default: current directory)
642
- --dry-run Preview changes without applying
643
-
644
- Diff Options:
452
+ Migrate/Diff Options:
645
453
  --target <path> Target directory (default: current directory)
454
+ --dry-run Preview changes without applying (migrate only)
646
455
 
647
456
  Uninstall Options:
648
457
  --target <path> Target directory (default: current directory)
649
458
  --force, -f Skip confirmation prompt
650
459
 
651
- Profiles:
652
- core 16 skills, 7 agents — lightweight
653
- developer 44 skills, 22 agents — recommended
654
- full 61 skills, 22 agents — everything
655
-
656
460
  Examples:
657
- csl init # Interactive setup
658
- csl init full # Install everything, no questions
659
- csl init core --dry-run # Preview core profile
660
- csl upgrade full # Upgrade to full profile (additive)
461
+ csl init # Install everything
462
+ csl init --no-fonts # Skip canvas fonts (~7MB lighter)
463
+ csl init --dry-run # Preview without copying
464
+ csl init --fresh # Clean reinstall
661
465
  csl update # Update to latest version
662
466
  csl migrate # Update project files after csl update
663
- csl migrate --dry-run # Preview what would change
664
467
  csl diff # Show modified/missing/extra files
665
468
  csl uninstall # Remove from current project
666
469
  csl doctor # Check health + updates