get-shit-pretty 0.6.2 → 0.6.3

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.
Files changed (121) hide show
  1. package/README.md +7 -12
  2. package/bin/install.js +96 -71
  3. package/gsp/agents/gsp-accessibility-auditor.md +3 -3
  4. package/gsp/agents/gsp-ascii-artist.md +1 -1
  5. package/gsp/agents/gsp-brand-auditor.md +2 -2
  6. package/gsp/agents/gsp-brand-engineer.md +131 -0
  7. package/gsp/agents/gsp-brand-strategist.md +2 -2
  8. package/gsp/agents/gsp-brand-syncer.md +8 -7
  9. package/gsp/agents/gsp-builder.md +48 -5
  10. package/gsp/agents/gsp-campaign-director.md +2 -3
  11. package/gsp/agents/gsp-creative-director.md +80 -0
  12. package/gsp/agents/gsp-critic.md +99 -17
  13. package/gsp/agents/gsp-designer.md +51 -4
  14. package/gsp/agents/gsp-project-researcher.md +3 -3
  15. package/gsp/agents/gsp-researcher.md +4 -4
  16. package/gsp/agents/gsp-reviewer.md +2 -2
  17. package/gsp/agents/gsp-scoper.md +2 -2
  18. package/gsp/hooks/hooks.json +5 -5
  19. package/gsp/references/design-trends.md +4 -4
  20. package/gsp/references/phase-transitions.md +12 -12
  21. package/gsp/references/questioning.md +1 -1
  22. package/gsp/references/token-mapping.md +329 -0
  23. package/gsp/skills/gsp-3d/SKILL.md +112 -0
  24. package/gsp/skills/gsp-accessibility/SKILL.md +11 -11
  25. package/gsp/skills/gsp-accessibility-audit/SKILL.md +6 -7
  26. package/gsp/skills/gsp-add-reference/SKILL.md +1 -1
  27. package/gsp/skills/gsp-art/SKILL.md +1 -1
  28. package/gsp/skills/gsp-brand-audit/SKILL.md +3 -3
  29. package/gsp/skills/gsp-brand-guidelines/SKILL.md +233 -0
  30. package/gsp/skills/gsp-brand-identity/SKILL.md +27 -18
  31. package/gsp/skills/gsp-brand-refine/SKILL.md +29 -22
  32. package/gsp/skills/gsp-brand-research/SKILL.md +2 -2
  33. package/gsp/skills/gsp-brand-strategy/SKILL.md +3 -3
  34. package/gsp/skills/gsp-brand-sync/SKILL.md +7 -7
  35. package/gsp/skills/gsp-color/SKILL.md +105 -0
  36. package/gsp/skills/gsp-design-system/SKILL.md +4 -4
  37. package/gsp/skills/gsp-doctor/SKILL.md +25 -18
  38. package/gsp/skills/gsp-help/SKILL.md +28 -28
  39. package/gsp/skills/gsp-icons/SKILL.md +108 -0
  40. package/gsp/skills/gsp-images/SKILL.md +197 -0
  41. package/gsp/skills/gsp-launch/SKILL.md +2 -3
  42. package/gsp/skills/gsp-logo/SKILL.md +173 -0
  43. package/gsp/skills/gsp-palette/SKILL.md +13 -13
  44. package/gsp/skills/gsp-pretty/SKILL.md +2 -2
  45. package/gsp/skills/gsp-progress/SKILL.md +20 -20
  46. package/gsp/skills/gsp-project-brief/SKILL.md +7 -8
  47. package/gsp/skills/gsp-project-build/SKILL.md +21 -21
  48. package/gsp/skills/gsp-project-critique/SKILL.md +13 -14
  49. package/gsp/skills/gsp-project-design/SKILL.md +17 -17
  50. package/gsp/skills/gsp-project-research/SKILL.md +5 -6
  51. package/gsp/skills/gsp-project-review/SKILL.md +7 -9
  52. package/gsp/skills/gsp-scaffold/SKILL.md +3 -3
  53. package/gsp/skills/gsp-start/SKILL.md +14 -14
  54. package/gsp/skills/gsp-style/SKILL.md +41 -43
  55. package/gsp/skills/gsp-style/styles/INDEX.yml +1 -1
  56. package/gsp/skills/gsp-style/styles/academia.yml +80 -0
  57. package/gsp/skills/gsp-style/styles/art-deco.yml +81 -0
  58. package/gsp/skills/gsp-style/styles/bauhaus.yml +78 -0
  59. package/gsp/skills/gsp-style/styles/bold-typography.yml +73 -0
  60. package/gsp/skills/gsp-style/styles/botanical.yml +78 -0
  61. package/gsp/skills/gsp-style/styles/claymorphism.yml +84 -0
  62. package/gsp/skills/gsp-style/styles/cyberpunk.yml +87 -0
  63. package/gsp/skills/gsp-style/styles/enterprise.yml +81 -0
  64. package/gsp/skills/gsp-style/styles/flat-design.yml +67 -0
  65. package/gsp/skills/gsp-style/styles/fluent.yml +82 -0
  66. package/gsp/skills/gsp-style/styles/glassmorphism.yml +83 -0
  67. package/gsp/skills/gsp-style/styles/humanist-literary.yml +74 -0
  68. package/gsp/skills/gsp-style/styles/industrial.yml +82 -0
  69. package/gsp/skills/gsp-style/styles/kinetic.yml +94 -0
  70. package/gsp/skills/gsp-style/styles/liquid-glass.yml +91 -0
  71. package/gsp/skills/gsp-style/styles/luxury.yml +83 -0
  72. package/gsp/skills/gsp-style/styles/material.yml +83 -0
  73. package/gsp/skills/gsp-style/styles/maximalism.yml +92 -0
  74. package/gsp/skills/gsp-style/styles/minimal-dark.yml +75 -0
  75. package/gsp/skills/gsp-style/styles/modern-dark.yml +88 -0
  76. package/gsp/skills/gsp-style/styles/monochrome.yml +68 -0
  77. package/gsp/skills/gsp-style/styles/neubrutalism.yml +83 -0
  78. package/gsp/skills/gsp-style/styles/neumorphism.yml +77 -0
  79. package/gsp/skills/gsp-style/styles/newsprint.yml +81 -0
  80. package/gsp/skills/gsp-style/styles/organic.yml +77 -0
  81. package/gsp/skills/gsp-style/styles/playful-geometric.yml +90 -0
  82. package/gsp/skills/gsp-style/styles/professional.yml +67 -0
  83. package/gsp/skills/gsp-style/styles/retro.yml +85 -0
  84. package/gsp/skills/gsp-style/styles/saas.yml +83 -0
  85. package/gsp/skills/gsp-style/styles/sketch.yml +86 -0
  86. package/gsp/skills/gsp-style/styles/swiss-minimalist.yml +69 -0
  87. package/gsp/skills/gsp-style/styles/terminal.yml +83 -0
  88. package/gsp/skills/gsp-style/styles/vaporwave.yml +84 -0
  89. package/gsp/skills/gsp-style/styles/web3.yml +82 -0
  90. package/gsp/skills/gsp-textures/SKILL.md +132 -0
  91. package/gsp/skills/gsp-typescale/SKILL.md +11 -11
  92. package/gsp/skills/gsp-typography/SKILL.md +108 -0
  93. package/gsp/skills/gsp-update/SKILL.md +1 -2
  94. package/gsp/skills/gsp-video/SKILL.md +101 -0
  95. package/gsp/templates/branding/config.json +1 -1
  96. package/gsp/templates/branding/roadmap.md +9 -9
  97. package/gsp/templates/exports-index.md +8 -8
  98. package/gsp/templates/phases/build.md +1 -1
  99. package/gsp/templates/phases/design.md +1 -1
  100. package/gsp/templates/phases/patterns.md +60 -71
  101. package/gsp/templates/phases/style.md +158 -0
  102. package/gsp/templates/projects/config.json +1 -1
  103. package/gsp/templates/projects/roadmap.md +7 -7
  104. package/gsp/templates/projects/state.md +1 -1
  105. package/package.json +1 -2
  106. package/.claude-plugin/plugin.json +0 -24
  107. package/gsp/agents/gsp-identity-designer.md +0 -74
  108. package/gsp/agents/gsp-pattern-architect.md +0 -189
  109. package/gsp/prompts/01-design-system-architect.md +0 -19
  110. package/gsp/prompts/02-brand-identity-creator.md +0 -16
  111. package/gsp/prompts/03-ui-ux-pattern-master.md +0 -21
  112. package/gsp/prompts/04-marketing-asset-factory.md +0 -14
  113. package/gsp/prompts/05-implementation-spec-expert.md +0 -15
  114. package/gsp/prompts/06-design-critique-partner.md +0 -14
  115. package/gsp/prompts/07-design-trend-synthesizer.md +0 -3
  116. package/gsp/prompts/08-accessibility-auditor.md +0 -23
  117. package/gsp/prompts/09-design-to-code-translator.md +0 -49
  118. package/gsp/prompts/10-project-scoper.md +0 -17
  119. package/gsp/prompts/11-deliverable-reviewer.md +0 -18
  120. package/gsp/prompts/12-project-researcher.md +0 -18
  121. package/gsp/skills/gsp-brand-patterns/SKILL.md +0 -240
package/README.md CHANGED
@@ -258,7 +258,7 @@ GSP works across all major AI coding tools. The installer converts Claude Code's
258
258
  | Gemini CLI | `~/.gemini/` | `~/.gemini/skills/` | `~/.gemini/agents/` |
259
259
  | Codex CLI | `~/.codex/` | `~/.agents/skills/` | — |
260
260
 
261
- > **Codex note:** Skills are discovered at `~/.agents/skills/`, not `~/.codex/skills/`. Config and bundle files (prompts, templates, references) stay at `~/.codex/get-shit-pretty/`. Codex does not support agent `.md` files.
261
+ > **Codex note:** Skills are discovered at `~/.agents/skills/`, not `~/.codex/skills/`. Config and bundle files (templates, references) stay at `~/.codex/get-shit-pretty/`. Codex does not support agent `.md` files.
262
262
 
263
263
  ---
264
264
 
@@ -308,14 +308,14 @@ npx get-shit-pretty --codex --global --uninstall
308
308
  </details>
309
309
 
310
310
  <details>
311
- <summary><strong>Use as Claude Code plugin</strong></summary>
311
+ <summary><strong>Local development</strong></summary>
312
312
 
313
313
  ```bash
314
- # From a project directory:
315
- claude --plugin-dir /path/to/get-shit-pretty
314
+ # From the repo root:
315
+ node bin/install.js --claude --local
316
316
  ```
317
317
 
318
- Uses the `.claude-plugin/plugin.json` manifest. Skills, agents, and hooks load directly from source no install step needed.
318
+ Symlinks skills and agents to `.claude/` edits to `gsp/` are reflected immediately.
319
319
 
320
320
  </details>
321
321
 
@@ -325,15 +325,13 @@ Uses the `.claude-plugin/plugin.json` manifest. Skills, agents, and hooks load d
325
325
 
326
326
  ```
327
327
  get-shit-pretty/
328
- ├── .claude-plugin/ Plugin manifest (plugin.json)
329
328
  ├── bin/
330
329
  │ └── install.js Multi-runtime installer
331
330
  ├── scripts/ Hook scripts and utilities
332
331
  ├── gsp/ Source of truth for all content
333
332
  │ ├── agents/ 15 subagents (gsp-*.md)
334
- │ ├── skills/ 30 skills (*/SKILL.md)
335
- │ ├── hooks/ Plugin-level hooks (hooks.json)
336
- │ ├── prompts/ 12 agent system prompts
333
+ │ ├── skills/ 38 skills (*/SKILL.md)
334
+ │ ├── hooks/ Hooks (hooks.json)
337
335
  │ ├── templates/ Config, state, brief, roadmap templates
338
336
  │ └── references/ Shared reference material
339
337
  ├── dev/ Internal dev tools (not installed)
@@ -356,9 +354,6 @@ Edit source under `gsp/` — never edit inside `.claude/` or other runtime dirs
356
354
  # Install locally with symlinks
357
355
  node bin/install.js --claude --local
358
356
 
359
- # Test as a plugin
360
- claude --plugin-dir .
361
-
362
357
  # Run the integrity test suite
363
358
  bash dev/scripts/audit-tests.sh
364
359
  ```
package/bin/install.js CHANGED
@@ -167,7 +167,7 @@ function center(text, width) {
167
167
  }
168
168
 
169
169
  const columns = process.stdout.columns || 80;
170
- const rampText = `${c.accent}░▒▓█${c.reset} ${c.bold} GET SHIT PRETTY ${c.reset} ${c.accent}█▓▒░${c.reset}`;
170
+ const rampText = `${c.accent}░▒▓█${c.reset} ${c.bold} GET SHIT PRETTY ${c.reset} ${c.dim}v${pkg.version}${c.reset} ${c.accent}█▓▒░${c.reset}`;
171
171
  const boxWidth = 48;
172
172
  const innerWidth = boxWidth - 2; // inside the border chars
173
173
  const showSparkles = columns >= 44;
@@ -197,7 +197,7 @@ const banner = '\n' +
197
197
  (showSparkles ? sparkle('dense') + '\n' : '') +
198
198
  bottomBorder + '\n' +
199
199
  '\n' +
200
- ` ${c.bold}${c.accent}/gsp:${c.reset} ${c.tertiary}◇◇${c.reset} ${c.dim}v${pkg.version}${c.reset}\n` +
200
+ ` ${c.bold}${c.accent}/gsp${c.reset} ${c.tertiary}◇◇${c.reset}\n` +
201
201
  ` ${c.dim}${tagline}${c.reset}\n`;
202
202
 
203
203
  console.log(banner);
@@ -395,7 +395,7 @@ function applyOpencodeBodyReplacements(content) {
395
395
  converted = converted.replace(/\bSlashCommand\b/g, 'skill');
396
396
  converted = converted.replace(/\bSkill\b(?=\s+tool\b)/g, 'skill');
397
397
  converted = converted.replace(/\bTodoWrite\b/g, 'todowrite');
398
- converted = converted.replace(/\/gsp:/g, '/gsp-');
398
+ converted = converted.replace(/\/gsp:/g, '/gsp-'); // legacy: source may still have /gsp: in older versions
399
399
  converted = converted.replace(/~\/\.claude\b/g, '~/.config/opencode');
400
400
  converted = converted.replace(/subagent_type="general-purpose"/g, 'subagent_type="general"');
401
401
  // Convert Claude agent spawning to OpenCode subagent delegation
@@ -806,7 +806,8 @@ function convertClaudeSkillToGemini(content, skillName) {
806
806
  */
807
807
  function applyCodexBodyReplacements(content) {
808
808
  let converted = content;
809
- converted = converted.replace(/\/gsp:/g, '$gsp-');
809
+ converted = converted.replace(/\/gsp:/g, '$gsp-'); // legacy: source may still have /gsp: in older versions
810
+ converted = converted.replace(/\/gsp-/g, '$gsp-');
810
811
  converted = converted.replace(/~\/\.claude\b/g, '~/.codex');
811
812
  converted = converted.replace(/\bAskUserQuestion\b/g, 'ask the user');
812
813
  converted = converted.replace(/\bSlashCommand\b/g, 'skill');
@@ -892,15 +893,7 @@ function convertClaudeSkillToCodex(content, skillName) {
892
893
  function copyOpencodeSkills(srcDir, destDir, pathPrefix) {
893
894
  if (!fs.existsSync(srcDir)) return 0;
894
895
  fs.mkdirSync(destDir, { recursive: true });
895
-
896
- // Clean old gsp- skill dirs
897
- if (fs.existsSync(destDir)) {
898
- for (const entry of fs.readdirSync(destDir, { withFileTypes: true })) {
899
- if (entry.isDirectory() && entry.name.startsWith('gsp-')) {
900
- fs.rmSync(path.join(destDir, entry.name), { recursive: true });
901
- }
902
- }
903
- }
896
+ cleanStaleGspDirs(destDir);
904
897
 
905
898
  let count = 0;
906
899
  const skillDirs = fs.readdirSync(srcDir, { withFileTypes: true });
@@ -910,18 +903,15 @@ function copyOpencodeSkills(srcDir, destDir, pathPrefix) {
910
903
  const skillMd = path.join(srcDir, dir.name, 'SKILL.md');
911
904
  if (!fs.existsSync(skillMd)) continue;
912
905
 
913
- // OpenCode skill names: lowercase, hyphens, no consecutive hyphens, 1-64 chars
914
- // Prefix with gsp- so they don't collide, unless already prefixed
915
- const skillName = dir.name.startsWith('gsp-') ? dir.name : `gsp-${dir.name}`;
916
- const skillDest = path.join(destDir, skillName);
906
+ const skillDest = path.join(destDir, dir.name);
917
907
  fs.mkdirSync(skillDest, { recursive: true });
918
908
 
919
909
  let content = fs.readFileSync(skillMd, 'utf8');
920
910
  content = content.replace(/~\/\.claude\//g, pathPrefix);
921
911
  content = content.replace(/\.\/\.claude\//g, './.opencode/');
922
- content = convertClaudeSkillToOpencode(content, skillName);
912
+ content = convertClaudeSkillToOpencode(content, dir.name);
923
913
  fs.writeFileSync(path.join(skillDest, 'SKILL.md'), content);
924
- copySiblingFiles(path.join(srcDir, dir.name), skillDest, pathPrefix);
914
+ copySiblingFiles(path.join(srcDir, dir.name), skillDest);
925
915
  count++;
926
916
  }
927
917
 
@@ -930,13 +920,14 @@ function copyOpencodeSkills(srcDir, destDir, pathPrefix) {
930
920
 
931
921
  /**
932
922
  * Copy skills/ source to Codex skill structure.
933
- * skills/<name>/SKILL.md → .agents/skills/gsp-<name>/SKILL.md
923
+ * skills/gsp-<name>/SKILL.md → .agents/skills/gsp-<name>/SKILL.md
934
924
  *
935
925
  * Codex expects: .agents/skills/<name>/SKILL.md with YAML frontmatter (name + description).
936
926
  */
937
927
  function copyCodexSkillsFromSource(srcDir, destDir, pathPrefix) {
938
928
  if (!fs.existsSync(srcDir)) return 0;
939
929
  fs.mkdirSync(destDir, { recursive: true });
930
+ cleanStaleGspDirs(destDir);
940
931
 
941
932
  let count = 0;
942
933
  const skillDirs = fs.readdirSync(srcDir, { withFileTypes: true });
@@ -945,15 +936,14 @@ function copyCodexSkillsFromSource(srcDir, destDir, pathPrefix) {
945
936
  const skillMd = path.join(srcDir, dir.name, 'SKILL.md');
946
937
  if (!fs.existsSync(skillMd)) continue;
947
938
 
948
- const skillName = dir.name.startsWith('gsp-') ? dir.name : `gsp-${dir.name}`;
949
- const skillDest = path.join(destDir, skillName);
939
+ const skillDest = path.join(destDir, dir.name);
950
940
  fs.mkdirSync(skillDest, { recursive: true });
951
941
 
952
942
  let content = fs.readFileSync(skillMd, 'utf8');
953
943
  content = content.replace(/~\/\.claude\//g, pathPrefix);
954
- content = convertClaudeSkillToCodex(content, skillName);
944
+ content = convertClaudeSkillToCodex(content, dir.name);
955
945
  fs.writeFileSync(path.join(skillDest, 'SKILL.md'), content);
956
- copySiblingFiles(path.join(srcDir, dir.name), skillDest, pathPrefix);
946
+ copySiblingFiles(path.join(srcDir, dir.name), skillDest);
957
947
  count++;
958
948
  }
959
949
  return count;
@@ -961,22 +951,14 @@ function copyCodexSkillsFromSource(srcDir, destDir, pathPrefix) {
961
951
 
962
952
  /**
963
953
  * Copy skills/ source to Gemini skill structure.
964
- * skills/<name>/SKILL.md → .gemini/skills/gsp-<name>/SKILL.md
954
+ * skills/gsp-<name>/SKILL.md → .gemini/skills/gsp-<name>/SKILL.md
965
955
  *
966
956
  * Gemini expects: .gemini/skills/<name>/SKILL.md with YAML frontmatter (name + description).
967
957
  */
968
958
  function copyGeminiSkills(srcDir, destDir, pathPrefix) {
969
959
  if (!fs.existsSync(srcDir)) return 0;
970
960
  fs.mkdirSync(destDir, { recursive: true });
971
-
972
- // Clean old gsp- skill dirs
973
- if (fs.existsSync(destDir)) {
974
- for (const entry of fs.readdirSync(destDir, { withFileTypes: true })) {
975
- if (entry.isDirectory() && entry.name.startsWith('gsp-')) {
976
- fs.rmSync(path.join(destDir, entry.name), { recursive: true });
977
- }
978
- }
979
- }
961
+ cleanStaleGspDirs(destDir);
980
962
 
981
963
  let count = 0;
982
964
  const skillDirs = fs.readdirSync(srcDir, { withFileTypes: true });
@@ -985,16 +967,15 @@ function copyGeminiSkills(srcDir, destDir, pathPrefix) {
985
967
  const skillMd = path.join(srcDir, dir.name, 'SKILL.md');
986
968
  if (!fs.existsSync(skillMd)) continue;
987
969
 
988
- const skillName = dir.name.startsWith('gsp-') ? dir.name : `gsp-${dir.name}`;
989
- const skillDest = path.join(destDir, skillName);
970
+ const skillDest = path.join(destDir, dir.name);
990
971
  fs.mkdirSync(skillDest, { recursive: true });
991
972
 
992
973
  let content = fs.readFileSync(skillMd, 'utf8');
993
974
  content = content.replace(/~\/\.claude\//g, pathPrefix);
994
975
  content = content.replace(/\.\/\.claude\//g, './.gemini/');
995
- content = convertClaudeSkillToGemini(content, skillName);
976
+ content = convertClaudeSkillToGemini(content, dir.name);
996
977
  fs.writeFileSync(path.join(skillDest, 'SKILL.md'), content);
997
- copySiblingFiles(path.join(srcDir, dir.name), skillDest, pathPrefix);
978
+ copySiblingFiles(path.join(srcDir, dir.name), skillDest);
998
979
  count++;
999
980
  }
1000
981
  return count;
@@ -1036,49 +1017,64 @@ function copyAgents(srcDir, destDir, pathPrefix, runtime, { clean = false } = {}
1036
1017
  }
1037
1018
 
1038
1019
  /**
1039
- * Copy Claude Code skills (global install path no body conversion, only path replacement).
1040
- * Returns skill count.
1020
+ * Remove stale GSP skill dirs/symlinks (gsp-* and get-shit-pretty) from a target directory.
1021
+ * Handles broken symlinks via lstat fallback.
1041
1022
  */
1023
+ function cleanStaleGspDirs(dir) {
1024
+ let count = 0;
1025
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
1026
+ const name = entry.name;
1027
+ if (!name.startsWith('gsp-') && name !== 'get-shit-pretty') continue;
1028
+ const entryPath = path.join(dir, name);
1029
+ try {
1030
+ // withFileTypes doesn't resolve broken symlinks — use lstat for those
1031
+ if (entry.isSymbolicLink()) { fs.unlinkSync(entryPath); count++; }
1032
+ else if (entry.isDirectory()) { fs.rmSync(entryPath, { recursive: true }); count++; }
1033
+ else {
1034
+ // broken symlink: withFileTypes returns isFile=false, isDir=false, isSymlink=false
1035
+ const s = fs.lstatSync(entryPath);
1036
+ if (s.isSymbolicLink()) { fs.unlinkSync(entryPath); count++; }
1037
+ }
1038
+ } catch {}
1039
+ }
1040
+ return count;
1041
+ }
1042
+
1042
1043
  /**
1043
1044
  * Recursively copy sibling files in a skill directory (everything except SKILL.md).
1044
- * All sibling files are copied verbatim — no path replacement applied.
1045
1045
  */
1046
- function copySiblingFiles(srcDir, destDir, pathPrefix) {
1046
+ function copySiblingFiles(srcDir, destDir) {
1047
1047
  for (const entry of fs.readdirSync(srcDir, { withFileTypes: true })) {
1048
- if (entry.name === 'SKILL.md') continue; // already handled by caller
1048
+ if (entry.name === 'SKILL.md') continue;
1049
1049
  const srcPath = path.join(srcDir, entry.name);
1050
1050
  const destPath = path.join(destDir, entry.name);
1051
1051
  if (entry.isDirectory()) {
1052
1052
  fs.mkdirSync(destPath, { recursive: true });
1053
- copySiblingFiles(srcPath, destPath, pathPrefix);
1053
+ copySiblingFiles(srcPath, destPath);
1054
1054
  } else {
1055
1055
  fs.copyFileSync(srcPath, destPath);
1056
1056
  }
1057
1057
  }
1058
1058
  }
1059
1059
 
1060
+ /**
1061
+ * Copy Claude Code skills (global install — no body conversion, only path replacement).
1062
+ */
1060
1063
  function copyClaudeSkills(srcDir, destDir, pathPrefix) {
1061
1064
  fs.mkdirSync(destDir, { recursive: true });
1062
-
1063
- // Clean old gsp- skill dirs
1064
- for (const entry of fs.readdirSync(destDir, { withFileTypes: true })) {
1065
- if (entry.isDirectory() && (entry.name.startsWith('gsp-') || entry.name === 'get-shit-pretty')) {
1066
- fs.rmSync(path.join(destDir, entry.name), { recursive: true });
1067
- }
1068
- }
1065
+ cleanStaleGspDirs(destDir);
1069
1066
 
1070
1067
  let skillCount = 0;
1071
1068
  for (const dir of fs.readdirSync(srcDir, { withFileTypes: true })) {
1072
1069
  if (!dir.isDirectory()) continue;
1073
1070
  const skillMd = path.join(srcDir, dir.name, 'SKILL.md');
1074
1071
  if (!fs.existsSync(skillMd)) continue;
1075
- const skillName = dir.name.startsWith('gsp-') ? dir.name : `gsp-${dir.name}`;
1076
- const destSkillDir = path.join(destDir, skillName);
1072
+ const destSkillDir = path.join(destDir, dir.name);
1077
1073
  fs.mkdirSync(destSkillDir, { recursive: true });
1078
1074
  let content = fs.readFileSync(skillMd, 'utf8');
1079
1075
  content = content.replace(/~\/\.claude\//g, pathPrefix);
1080
1076
  fs.writeFileSync(path.join(destSkillDir, 'SKILL.md'), content);
1081
- copySiblingFiles(path.join(srcDir, dir.name), destSkillDir, pathPrefix);
1077
+ copySiblingFiles(path.join(srcDir, dir.name), destSkillDir);
1082
1078
  skillCount++;
1083
1079
  }
1084
1080
  return skillCount;
@@ -1201,14 +1197,8 @@ function installLocalSymlinks(targetDir, src) {
1201
1197
  const skillsDest = path.join(targetDir, 'skills');
1202
1198
  fs.mkdirSync(skillsDest, { recursive: true });
1203
1199
 
1204
- // Clean old GSP skill dirs
1205
- for (const entry of fs.readdirSync(skillsDest, { withFileTypes: true })) {
1206
- if (entry.isDirectory() && (entry.name.startsWith('gsp-') || entry.name === 'get-shit-pretty')) {
1207
- fs.rmSync(path.join(skillsDest, entry.name), { recursive: true });
1208
- }
1209
- }
1210
-
1211
1200
  const skillsSrc = path.join(gspRoot, 'skills');
1201
+ cleanStaleGspDirs(skillsDest);
1212
1202
  let skillCount = 0;
1213
1203
  for (const dir of fs.readdirSync(skillsSrc, { withFileTypes: true })) {
1214
1204
  if (!dir.isDirectory()) continue;
@@ -1227,15 +1217,20 @@ function installLocalSymlinks(targetDir, src) {
1227
1217
  console.log(` ${c.success}✓${c.reset} Removed legacy commands/gsp`);
1228
1218
  } catch {}
1229
1219
 
1230
- // ── Bundle symlinks (prompts, templates, references → runtime root) ──
1231
- // Clean up legacy get-shit-pretty/ bundle dir
1220
+ // ── Bundle symlinks (templates, references → runtime root) ──
1221
+ // Clean up legacy dirs
1232
1222
  const legacyBundleDest = path.join(targetDir, 'get-shit-pretty');
1233
1223
  if (fs.existsSync(legacyBundleDest)) {
1234
1224
  fs.rmSync(legacyBundleDest, { recursive: true });
1235
1225
  console.log(` ${c.success}✓${c.reset} Removed legacy get-shit-pretty/ bundle`);
1236
1226
  }
1227
+ const legacyPrompts = path.join(targetDir, 'prompts');
1228
+ if (fs.existsSync(legacyPrompts)) {
1229
+ fs.rmSync(legacyPrompts, { recursive: true });
1230
+ console.log(` ${c.success}✓${c.reset} Removed legacy prompts/`);
1231
+ }
1237
1232
 
1238
- for (const dir of ['prompts', 'templates', 'references']) {
1233
+ for (const dir of ['templates', 'references']) {
1239
1234
  if (fs.existsSync(path.join(gspRoot, dir))) {
1240
1235
  forceSymlink(path.join('..', 'gsp', dir), path.join(targetDir, dir));
1241
1236
  console.log(` ${c.success}✓${c.reset} Symlinked ${dir}/`);
@@ -1267,6 +1262,16 @@ function installLocalSymlinks(targetDir, src) {
1267
1262
  process.exit(1);
1268
1263
  }
1269
1264
 
1265
+ // Warn if GSP skills also exist globally (may cause duplicates)
1266
+ const globalSkillsDir = path.join(getGlobalDir('claude', null), 'skills');
1267
+ if (fs.existsSync(globalSkillsDir)) {
1268
+ const dupes = fs.readdirSync(globalSkillsDir).filter(e => e.startsWith('gsp-'));
1269
+ if (dupes.length > 0) {
1270
+ console.log(` ${yellow}!${reset} Found ${dupes.length} GSP skills in ${globalSkillsDir.replace(os.homedir(), '~')} — may cause duplicates`);
1271
+ console.log(` ${c.dim}To remove: node bin/install.js --claude --global --uninstall${c.reset}`);
1272
+ }
1273
+ }
1274
+
1270
1275
  return true;
1271
1276
  }
1272
1277
 
@@ -1417,15 +1422,20 @@ function install(isGlobal, runtime = 'claude') {
1417
1422
  }
1418
1423
  }
1419
1424
 
1420
- // ── Bundle: prompts, templates, references → runtime root ──
1421
- // Clean up legacy get-shit-pretty/ bundle dir from previous installs
1425
+ // ── Bundle: templates, references → runtime root ──
1426
+ // Clean up legacy dirs from previous installs
1422
1427
  const legacyBundle = path.join(targetDir, 'get-shit-pretty');
1423
1428
  if (fs.existsSync(legacyBundle)) {
1424
1429
  fs.rmSync(legacyBundle, { recursive: true });
1425
1430
  console.log(` ${c.success}✓${c.reset} Removed legacy get-shit-pretty/ bundle`);
1426
1431
  }
1432
+ const legacyPromptsDir = path.join(targetDir, 'prompts');
1433
+ if (fs.existsSync(legacyPromptsDir)) {
1434
+ fs.rmSync(legacyPromptsDir, { recursive: true });
1435
+ console.log(` ${c.success}✓${c.reset} Removed legacy prompts/`);
1436
+ }
1427
1437
 
1428
- const bundleDirs = ['prompts', 'templates', 'references'];
1438
+ const bundleDirs = ['templates', 'references'];
1429
1439
  for (const dir of bundleDirs) {
1430
1440
  const dirSrc = path.join(gspRoot, dir);
1431
1441
  if (fs.existsSync(dirSrc)) {
@@ -1467,6 +1477,21 @@ function install(isGlobal, runtime = 'claude') {
1467
1477
  process.exit(1);
1468
1478
  }
1469
1479
 
1480
+ // Warn if GSP skills exist in the other location (may cause duplicates)
1481
+ if (runtime === 'claude') {
1482
+ const otherDir = isGlobal
1483
+ ? path.join(process.cwd(), '.claude', 'skills')
1484
+ : path.join(getGlobalDir('claude', null), 'skills');
1485
+ if (fs.existsSync(otherDir)) {
1486
+ const dupes = fs.readdirSync(otherDir).filter(e => e.startsWith('gsp-'));
1487
+ if (dupes.length > 0) {
1488
+ const label = otherDir.replace(os.homedir(), '~');
1489
+ console.log(` ${yellow}!${reset} Found ${dupes.length} GSP skills in ${label} — may cause duplicates`);
1490
+ console.log(` ${c.dim}To remove: node bin/install.js --claude ${isGlobal ? '--local' : '--global'} --uninstall${c.reset}`);
1491
+ }
1492
+ }
1493
+ }
1494
+
1470
1495
  // ── Settings (Claude Code & Gemini only) ──
1471
1496
  const settingsPath = path.join(targetDir, 'settings.json');
1472
1497
  const settings = readSettings(settingsPath);
@@ -1545,7 +1570,7 @@ function uninstall(isGlobal, runtime = 'claude') {
1545
1570
  }
1546
1571
  }
1547
1572
  } else {
1548
- // All other runtimes: remove gsp- skill dirs
1573
+ // All other runtimes (including Claude): remove gsp- skill dirs
1549
1574
  const skillsDir = path.join(targetDir, 'skills');
1550
1575
  if (fs.existsSync(skillsDir)) {
1551
1576
  let skillCount = 0;
@@ -1593,7 +1618,7 @@ function uninstall(isGlobal, runtime = 'claude') {
1593
1618
  }
1594
1619
 
1595
1620
  // Remove flattened bundle dirs
1596
- for (const dir of ['prompts', 'templates', 'references']) {
1621
+ for (const dir of ['prompts', 'templates', 'references']) { // prompts included for legacy cleanup
1597
1622
  const bundlePath = path.join(targetDir, dir);
1598
1623
  if (fs.existsSync(bundlePath)) {
1599
1624
  fs.rmSync(bundlePath, { recursive: true });
@@ -1726,8 +1751,8 @@ function finishInstall(settingsPath, settings, statuslineCommand, shouldInstallS
1726
1751
  }
1727
1752
 
1728
1753
  const runtimeLabel = getRuntimeLabel(runtime);
1729
- const helpCmd = isOpencode ? '/gsp-help' : isCodex ? '$gsp-help' : '/gsp:help';
1730
- const newCmd = isOpencode ? '/gsp-start' : isCodex ? '$gsp-start' : '/gsp:start';
1754
+ const helpCmd = isCodex ? '$gsp-help' : '/gsp-help';
1755
+ const newCmd = isCodex ? '$gsp-start' : '/gsp-start';
1731
1756
 
1732
1757
  // Show onboarding once (not per-runtime)
1733
1758
  if (!onboardingShown && !hasQuiet) {
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: gsp-accessibility-auditor
3
- description: Audits designs and code for WCAG 2.2 AA/AAA compliance. Spawned by /gsp:accessibility or /gsp:project-critique.
3
+ description: Audits designs and code for WCAG 2.2 AA/AAA compliance. Spawned by /gsp-accessibility or /gsp-project-critique.
4
4
  tools: Read, Write, Grep, Glob
5
5
  disallowedTools: Edit, Bash
6
6
  maxTurns: 40
@@ -10,7 +10,7 @@ color: cyan
10
10
  ---
11
11
 
12
12
  <role>
13
- You are a GSP accessibility auditor spawned by `/gsp:accessibility` or `/gsp:project-critique`.
13
+ You are a GSP accessibility auditor spawned by `/gsp-accessibility` or `/gsp-project-critique`.
14
14
 
15
15
  Act as Apple Accessibility Specialist. Your job is to audit designs or code against WCAG 2.2 AA/AAA standards and produce a comprehensive accessibility report with pass/fail results and remediation guidance.
16
16
 
@@ -39,7 +39,7 @@ Accessibility is a core quality requirement.
39
39
 
40
40
  ## Code Audit Mode
41
41
 
42
- When spawned by `/gsp:accessibility --code`, audit the actual codebase:
42
+ When spawned by `/gsp-accessibility --code`, audit the actual codebase:
43
43
 
44
44
  1. **Grep for missing ARIA** — interactive elements without `role`, `aria-label`, `aria-labelledby`, `aria-describedby`
45
45
  2. **Alt text** — `<img>` tags without `alt`, icons without `aria-hidden` or labels
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: gsp-ascii-artist
3
- description: Easter egg agent that creates ASCII art for the terminal. Spawned by /gsp:art.
3
+ description: Easter egg agent that creates ASCII art for the terminal. Spawned by /gsp-art.
4
4
  tools: Read, Bash
5
5
  disallowedTools: Edit, Write, Grep, Glob
6
6
  model: haiku
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: gsp-brand-auditor
3
- description: Audits existing brand identities for evolution. Spawned by /gsp:brand-audit.
3
+ description: Audits existing brand identities for evolution. Spawned by /gsp-brand-audit.
4
4
  tools: Read, Write, Bash, Grep, Glob, WebSearch, WebFetch
5
5
  disallowedTools: Edit
6
6
  maxTurns: 40
@@ -9,7 +9,7 @@ color: magenta
9
9
  ---
10
10
 
11
11
  <role>
12
- You are a GSP brand auditor spawned by `/gsp:brand-audit`.
12
+ You are a GSP brand auditor spawned by `/gsp-brand-audit`.
13
13
 
14
14
  Assess existing brand identities — coherence, market fit, equity, evolution opportunity. Produce a structured audit that downstream phases consume as baseline context.
15
15
  </role>
@@ -0,0 +1,131 @@
1
+ ---
2
+ name: gsp-brand-engineer
3
+ description: Operationalizes brand identity for projects — assembles .yml, STYLE.md, token mapping, component specs, guidelines. Spawned by /gsp-brand-guidelines.
4
+ tools: Read, Write, Edit, Bash, Grep, Glob
5
+ maxTurns: 60
6
+ permissionMode: acceptEdits
7
+ color: magenta
8
+ ---
9
+
10
+ <role>
11
+ You are a GSP brand engineer spawned by `/gsp-brand-guidelines`.
12
+
13
+ Act as a Design Systems Engineer. Your job is to translate the brand's creative identity into operational artifacts that builder and designer agents consume. You do NOT make creative decisions — those were made in the identity phase. You operationalize them.
14
+
15
+ The identity phase produced: logo directions, color system (with OKLCH palettes), typography (with math scale), imagery style. You read those and produce: the `.yml` preset, STYLE.md, component token mapping, and guidelines.
16
+ </role>
17
+
18
+ <inputs>
19
+ - Identity chunks: color-system.md, typography.md, logo-directions.md, imagery-style.md (all enriched by domain skills)
20
+ - Identity palettes.json (OKLCH scales)
21
+ - BRIEF.md
22
+ - Strategy chunks: voice-and-tone.md, archetype.md, positioning.md
23
+ - system_strategy and tech_stack from config.json
24
+ - `.design/system/STACK.md`, `COMPONENTS.md`, `TOKENS.md` (if exist)
25
+ - style_base from config.json + preset `.yml` (if set) — the starting scaffold
26
+ - style_base preset `.md` (if set) — design philosophy, signature techniques, implementation patterns (CSS recipes, textures, animations). Source content for STYLE.md's Philosophy, Bold Bets, and Implementation sections.
27
+ - Output path
28
+ </inputs>
29
+
30
+ <methodology>
31
+ ## What you produce (operational, not creative)
32
+
33
+ 1. **Assemble `{brand-name}.yml`** — the single source of truth. Take identity decisions and structure them into the preset format:
34
+ - `tokens:` — extract color hex values from color-system.md, font families from typography.md, spacing/shape/elevation from the style_base preset or sensible defaults
35
+ - `intensity:` — derive from brand archetype + strategy (e.g., a "rebel" archetype → higher variance; a "sage" → lower)
36
+ - `patterns:` — 7 component composition rules derived from the brand's aesthetic (how cards, buttons, inputs SHOULD look given these colors/type/constraints)
37
+ - `constraints:` — never/always rules that protect the brand (derived from identity anti-patterns + style_base constraints)
38
+ - `effects:` — interaction vocabulary coherent with the brand energy
39
+ - `dark_mode:` — from color-system.md dark mode mapping
40
+
41
+ 2. **Render `STYLE.md`** — follows `templates/phases/style.md` format. Source each section:
42
+ - **Intensity** — from the assembled `.yml` `intensity:` block
43
+ - **Philosophy** — synthesize from brand strategy (archetype, positioning, voice) + preset `.md` companion's Design Philosophy section (if provided). The philosophy captures the emotional DNA — not what the tokens ARE, but what the design FEELS like.
44
+ - **Patterns** — from the assembled `.yml` `patterns:` block, rendered as tables per component
45
+ - **Constraints** — from the assembled `.yml` `constraints:` block, rendered as never/always bullet lists
46
+ - **Effects** — from the assembled `.yml` `effects:` block, rendered as interaction vocabulary + state tables
47
+ - **Bold Bets** — the 3-5 most distinctive visual techniques from the identity phase's boldest choices + preset `.md` companion's signature techniques. Each must be specific enough for a builder to implement.
48
+ - **Implementation** — extract from preset `.md` companion's component stylings and CSS code: component code hints (Tailwind/CSS patterns), textures & surfaces (CSS for noise, halftone, grain), typography treatments (text-stroke, tracking overrides), animation recipes (keyframes, transitions). Skip sections that don't apply to this brand.
49
+
50
+ 3. **Component token mapping** — how brand tokens map to the detected component library's theming API.
51
+
52
+ 4. **Component overrides + custom specs** — only for components that need treatment beyond tokens.
53
+
54
+ 5. **`guidelines.html`** — self-contained visual brand guide. This is the primary artifact users see. Single HTML file with embedded CSS, no external dependencies. Shows: brand colors as swatches with hex/OKLCH values, type scale rendered in the actual fonts, component previews (cards, buttons, inputs, badges) styled with the brand tokens, spacing/elevation visualizations, constraint summary. Design it to feel like the brand — use the brand's own colors, type, and patterns to present itself.
55
+
56
+ ## Inheritance from style_base
57
+
58
+ If `style_base` contains one preset, start from its values and customize. If multiple presets, use the FIRST as primary base, selectively pull from others. Last-wins for conflicts.
59
+
60
+ If a preset constraint conflicts with brand identity, remove it and document why as a `.yml` comment.
61
+
62
+ If no `style_base` was set, build the full `.yml` from scratch using identity outputs.
63
+
64
+ ## System Strategy
65
+
66
+ Read `system_strategy` from brand config:
67
+
68
+ **GENERATE** — Full system from scratch. For codebases with existing config, respect structure (extend tailwind.config, not replace).
69
+
70
+ **EXTEND** — Evolve existing system: audit tokens against brand identity (keep what works, adjust what doesn't, fill gaps). Classify existing components: KEEP / RESTYLE / OVERRIDE / REPLACE. Output delta tokens. Preserve existing naming conventions.
71
+
72
+ **REFACTOR** — Redesign from ground up informed by existing: understand current system, design complete new system, produce migration mapping, flag breaking changes.
73
+
74
+ ## Component Strategy
75
+
76
+ Leverage existing UI libraries — don't rewrite from scratch.
77
+
78
+ **Tier 1: Token mapping** (always) — `components/token-mapping.md`. Maps brand tokens to library's theming API. Copy-paste-ready. See `references/token-mapping.md` for the CSS generation spec.
79
+
80
+ **Tier 2: Override specs** (selective) — one file per component needing treatment beyond tokens. Why it's overridden, code hints.
81
+
82
+ **Tier 3: Custom component specs** (selective) — full specs only for brand-distinctive components with no library equivalent.
83
+
84
+ Tier 2 + 3 combined: 5-12 components max.
85
+
86
+ ## Quality Standards
87
+ - Token mapping must target the actual library's theming API
88
+ - Every value in `.yml` must trace to an identity chunk
89
+ - STYLE.md must be renderable from `.yml` alone (no external dependencies)
90
+ - Component specs need: states, anatomy, usage rules, accessibility, code hints
91
+ </methodology>
92
+
93
+ <output>
94
+ Write operational artifacts to the brand's guidelines directory (path provided by the skill that spawned you):
95
+
96
+ ### Core files
97
+
98
+ - **`{brand-name}.yml`** — Single source of truth. Full preset schema: tokens, intensity, patterns, constraints, effects, dark_mode.
99
+ - **`STYLE.md`** — Agent-readable contract rendered from `.yml` + philosophy + bold bets. Follows `templates/phases/style.md`.
100
+ - **`guidelines.html`** — Self-contained visual brand guide. Single HTML file with embedded CSS — no external deps. Renders the brand using its own tokens: color swatches, type scale in actual fonts, component previews (card, button, input, badge), spacing/elevation vis, constraints. This is what the user sees.
101
+
102
+ ### Components
103
+
104
+ Write to `components/`:
105
+
106
+ 1. **`token-mapping.md`** (always) — brand tokens → library theming API. Reference values from `{brand-name}.yml`.
107
+ 2. **Override specs** (selective) — one per component needing more than tokens.
108
+ 3. **Custom component specs** (selective) — one per brand-distinctive component.
109
+
110
+ ### `INDEX.md`
111
+
112
+ ```markdown
113
+ # Guidelines
114
+ > Phase: guidelines | Brand: {name} | Generated: {DATE}
115
+
116
+ ## Core
117
+
118
+ | File | Description |
119
+ |------|-------------|
120
+ | [{brand-name}.yml](./{brand-name}.yml) | Style preset — single source of truth |
121
+ | [STYLE.md](./STYLE.md) | Agent contract (rendered from .yml) |
122
+ | [guidelines.html](./guidelines.html) | Visual brand guide (open in browser) |
123
+
124
+ ## Components
125
+
126
+ | File | Type | Description |
127
+ |------|------|-------------|
128
+ | [token-mapping.md](./components/token-mapping.md) | mapping | Brand tokens → {library} theming API |
129
+ | ... | ... | ... |
130
+ ```
131
+ </output>
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: gsp-brand-strategist
3
- description: Develops brand strategy, voice, and messaging. Spawned by /gsp:brand-strategy.
3
+ description: Develops brand strategy, voice, and messaging. Spawned by /gsp-brand-strategy.
4
4
  tools: Read, Write, Bash, Grep, Glob, WebSearch, WebFetch
5
5
  disallowedTools: Edit
6
6
  maxTurns: 40
@@ -9,7 +9,7 @@ color: magenta
9
9
  ---
10
10
 
11
11
  <role>
12
- You are a GSP brand strategist spawned by `/gsp:brand-strategy`.
12
+ You are a GSP brand strategist spawned by `/gsp-brand-strategy`.
13
13
 
14
14
  Act as Head of Strategy at a top branding agency. Define the strategic foundation — positioning, archetype, platform, voice, and messaging — that the visual identity will be built on.
15
15