get-shit-pretty 0.6.2 → 0.7.0

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 (161) hide show
  1. package/README.md +7 -12
  2. package/bin/install.js +125 -84
  3. package/gsp/agents/gsp-accessibility-auditor.md +4 -4
  4. package/gsp/agents/gsp-ascii-artist.md +2 -2
  5. package/gsp/agents/gsp-brand-auditor.md +3 -3
  6. package/gsp/agents/gsp-brand-engineer.md +131 -0
  7. package/gsp/agents/gsp-brand-strategist.md +3 -3
  8. package/gsp/agents/gsp-brand-syncer.md +8 -7
  9. package/gsp/agents/gsp-builder.md +49 -6
  10. package/gsp/agents/gsp-campaign-director.md +3 -4
  11. package/gsp/agents/gsp-creative-director.md +80 -0
  12. package/gsp/agents/gsp-critic.md +100 -18
  13. package/gsp/agents/gsp-designer.md +52 -5
  14. package/gsp/agents/gsp-project-researcher.md +4 -4
  15. package/gsp/agents/gsp-researcher.md +5 -5
  16. package/gsp/agents/gsp-reviewer.md +3 -3
  17. package/gsp/agents/gsp-scoper.md +3 -3
  18. package/gsp/hooks/hooks.json +5 -5
  19. package/gsp/skills/get-shit-pretty/SKILL.md +10 -9
  20. package/gsp/skills/gsp-accessibility/SKILL.md +12 -12
  21. package/gsp/skills/gsp-accessibility-audit/SKILL.md +8 -9
  22. package/gsp/skills/gsp-add-reference/SKILL.md +6 -1
  23. package/gsp/skills/gsp-art/SKILL.md +6 -1
  24. package/gsp/skills/gsp-brand-audit/SKILL.md +5 -5
  25. package/gsp/skills/gsp-brand-guidelines/SKILL.md +233 -0
  26. package/gsp/skills/gsp-brand-guidelines/token-mapping.md +329 -0
  27. package/gsp/skills/gsp-brand-identity/SKILL.md +29 -20
  28. package/gsp/skills/gsp-brand-refine/SKILL.md +30 -23
  29. package/gsp/skills/gsp-brand-research/SKILL.md +4 -4
  30. package/gsp/{references → skills/gsp-brand-research}/design-trends.md +4 -4
  31. package/gsp/skills/gsp-brand-strategy/SKILL.md +7 -7
  32. package/gsp/skills/gsp-brand-sync/SKILL.md +10 -10
  33. package/gsp/skills/gsp-brand-sync/chunk-format.md +79 -0
  34. package/gsp/skills/gsp-color/SKILL.md +73 -0
  35. package/gsp/skills/gsp-color/chunk-format.md +79 -0
  36. package/gsp/skills/{gsp-palette/SKILL.md → gsp-color/domains/palette.md} +31 -101
  37. package/gsp/skills/gsp-color/domains/system.md +123 -0
  38. package/gsp/skills/gsp-design-system/SKILL.md +9 -4
  39. package/gsp/skills/gsp-doctor/SKILL.md +25 -18
  40. package/gsp/skills/gsp-help/SKILL.md +30 -29
  41. package/gsp/skills/gsp-icons/SKILL.md +108 -0
  42. package/gsp/skills/gsp-icons/chunk-format.md +79 -0
  43. package/gsp/skills/gsp-launch/SKILL.md +3 -4
  44. package/gsp/skills/gsp-logo/SKILL.md +173 -0
  45. package/gsp/skills/gsp-logo/chunk-format.md +79 -0
  46. package/gsp/skills/gsp-phase-transition/SKILL.md +124 -0
  47. package/gsp/skills/gsp-pretty/SKILL.md +2 -2
  48. package/gsp/skills/gsp-progress/SKILL.md +20 -20
  49. package/gsp/skills/gsp-project-brief/SKILL.md +8 -9
  50. package/gsp/skills/gsp-project-build/SKILL.md +30 -25
  51. package/gsp/skills/gsp-project-critique/SKILL.md +17 -18
  52. package/gsp/{references → skills/gsp-project-critique}/visual-taste.md +1 -1
  53. package/gsp/skills/gsp-project-design/SKILL.md +18 -18
  54. package/gsp/skills/gsp-project-research/SKILL.md +6 -7
  55. package/gsp/skills/gsp-project-review/SKILL.md +8 -10
  56. package/gsp/skills/gsp-scaffold/SKILL.md +3 -3
  57. package/gsp/skills/gsp-start/SKILL.md +15 -15
  58. package/gsp/{references → skills/gsp-start}/questioning.md +1 -1
  59. package/gsp/skills/gsp-style/SKILL.md +43 -45
  60. package/gsp/skills/gsp-style/chunk-format.md +79 -0
  61. package/gsp/skills/gsp-style/style-preset-schema.md +124 -0
  62. package/gsp/skills/gsp-style/styles/INDEX.yml +1 -1
  63. package/gsp/skills/gsp-style/styles/academia.yml +80 -0
  64. package/gsp/skills/gsp-style/styles/art-deco.yml +81 -0
  65. package/gsp/skills/gsp-style/styles/bauhaus.yml +78 -0
  66. package/gsp/skills/gsp-style/styles/bold-typography.yml +73 -0
  67. package/gsp/skills/gsp-style/styles/botanical.yml +78 -0
  68. package/gsp/skills/gsp-style/styles/claymorphism.yml +84 -0
  69. package/gsp/skills/gsp-style/styles/cyberpunk.yml +87 -0
  70. package/gsp/skills/gsp-style/styles/enterprise.yml +81 -0
  71. package/gsp/skills/gsp-style/styles/flat-design.yml +67 -0
  72. package/gsp/skills/gsp-style/styles/fluent.yml +82 -0
  73. package/gsp/skills/gsp-style/styles/glassmorphism.yml +83 -0
  74. package/gsp/skills/gsp-style/styles/humanist-literary.yml +74 -0
  75. package/gsp/skills/gsp-style/styles/industrial.yml +82 -0
  76. package/gsp/skills/gsp-style/styles/kinetic.yml +94 -0
  77. package/gsp/skills/gsp-style/styles/liquid-glass.yml +91 -0
  78. package/gsp/skills/gsp-style/styles/luxury.yml +83 -0
  79. package/gsp/skills/gsp-style/styles/material.yml +83 -0
  80. package/gsp/skills/gsp-style/styles/maximalism.yml +92 -0
  81. package/gsp/skills/gsp-style/styles/minimal-dark.yml +75 -0
  82. package/gsp/skills/gsp-style/styles/modern-dark.yml +88 -0
  83. package/gsp/skills/gsp-style/styles/monochrome.yml +68 -0
  84. package/gsp/skills/gsp-style/styles/neubrutalism.yml +83 -0
  85. package/gsp/skills/gsp-style/styles/neumorphism.yml +77 -0
  86. package/gsp/skills/gsp-style/styles/newsprint.yml +81 -0
  87. package/gsp/skills/gsp-style/styles/organic.yml +77 -0
  88. package/gsp/skills/gsp-style/styles/playful-geometric.yml +90 -0
  89. package/gsp/skills/gsp-style/styles/professional.yml +67 -0
  90. package/gsp/skills/gsp-style/styles/retro.yml +85 -0
  91. package/gsp/skills/gsp-style/styles/saas.yml +83 -0
  92. package/gsp/skills/gsp-style/styles/sketch.yml +86 -0
  93. package/gsp/skills/gsp-style/styles/swiss-minimalist.yml +69 -0
  94. package/gsp/skills/gsp-style/styles/terminal.yml +83 -0
  95. package/gsp/skills/gsp-style/styles/vaporwave.yml +84 -0
  96. package/gsp/skills/gsp-style/styles/web3.yml +82 -0
  97. package/gsp/skills/gsp-typography/SKILL.md +70 -0
  98. package/gsp/skills/gsp-typography/chunk-format.md +79 -0
  99. package/gsp/skills/gsp-typography/domains/pairing.md +109 -0
  100. package/gsp/skills/gsp-typography/domains/scale.md +227 -0
  101. package/gsp/skills/gsp-typography/domains/system.md +108 -0
  102. package/gsp/skills/gsp-update/SKILL.md +1 -2
  103. package/gsp/skills/gsp-visuals/SKILL.md +82 -0
  104. package/gsp/skills/gsp-visuals/chunk-format.md +79 -0
  105. package/gsp/skills/gsp-visuals/domains/3d.md +127 -0
  106. package/gsp/skills/gsp-visuals/domains/imagery.md +145 -0
  107. package/gsp/skills/gsp-visuals/domains/textures.md +138 -0
  108. package/gsp/skills/gsp-visuals/domains/video.md +107 -0
  109. package/gsp/templates/branding/config.json +1 -1
  110. package/gsp/templates/branding/roadmap.md +9 -9
  111. package/gsp/templates/exports-index.md +8 -8
  112. package/gsp/templates/phases/brief.md +1 -1
  113. package/gsp/templates/phases/build.md +1 -1
  114. package/gsp/templates/phases/critique.md +1 -1
  115. package/gsp/templates/phases/design.md +2 -2
  116. package/gsp/templates/phases/discover.md +1 -1
  117. package/gsp/templates/phases/identity.md +1 -1
  118. package/gsp/templates/phases/launch.md +1 -1
  119. package/gsp/templates/phases/patterns.md +60 -71
  120. package/gsp/templates/phases/research.md +1 -1
  121. package/gsp/templates/phases/review.md +1 -1
  122. package/gsp/templates/phases/strategy.md +1 -1
  123. package/gsp/templates/phases/style.md +158 -0
  124. package/gsp/templates/projects/config.json +1 -1
  125. package/gsp/templates/projects/roadmap.md +7 -7
  126. package/gsp/templates/projects/state.md +1 -1
  127. package/package.json +1 -2
  128. package/.claude-plugin/plugin.json +0 -24
  129. package/gsp/agents/gsp-identity-designer.md +0 -74
  130. package/gsp/agents/gsp-pattern-architect.md +0 -189
  131. package/gsp/prompts/01-design-system-architect.md +0 -19
  132. package/gsp/prompts/02-brand-identity-creator.md +0 -16
  133. package/gsp/prompts/03-ui-ux-pattern-master.md +0 -21
  134. package/gsp/prompts/04-marketing-asset-factory.md +0 -14
  135. package/gsp/prompts/05-implementation-spec-expert.md +0 -15
  136. package/gsp/prompts/06-design-critique-partner.md +0 -14
  137. package/gsp/prompts/07-design-trend-synthesizer.md +0 -3
  138. package/gsp/prompts/08-accessibility-auditor.md +0 -23
  139. package/gsp/prompts/09-design-to-code-translator.md +0 -49
  140. package/gsp/prompts/10-project-scoper.md +0 -17
  141. package/gsp/prompts/11-deliverable-reviewer.md +0 -18
  142. package/gsp/prompts/12-project-researcher.md +0 -18
  143. package/gsp/references/phase-transitions.md +0 -132
  144. package/gsp/references/style-preset-schema.md +0 -63
  145. package/gsp/skills/gsp-brand-patterns/SKILL.md +0 -240
  146. package/gsp/skills/gsp-typescale/SKILL.md +0 -234
  147. /package/gsp/{references → skills/gsp-accessibility-audit}/wcag-checklist.md +0 -0
  148. /package/gsp/{references → skills/gsp-art}/terminal-art.md +0 -0
  149. /package/gsp/{references → skills/gsp-brand-audit}/chunk-format.md +0 -0
  150. /package/gsp/{references → skills/gsp-brand-guidelines}/design-tokens.md +0 -0
  151. /package/gsp/{references → skills/gsp-brand-strategy}/brand-archetypes.md +0 -0
  152. /package/gsp/{references → skills/gsp-brand-strategy}/brand-prism.md +0 -0
  153. /package/gsp/{references → skills/gsp-brand-strategy}/positioning-frameworks.md +0 -0
  154. /package/gsp/{references → skills/gsp-brand-strategy}/voice-tone.md +0 -0
  155. /package/gsp/{references → skills/gsp-color/references}/color-composition.md +0 -0
  156. /package/gsp/{references → skills/gsp-project-build}/visual-effects.md +0 -0
  157. /package/gsp/{references → skills/gsp-project-critique}/anti-patterns.md +0 -0
  158. /package/gsp/{references → skills/gsp-project-critique}/nielsen-heuristics.md +0 -0
  159. /package/gsp/{references → skills/gsp-project-design}/apple-hig-patterns.md +0 -0
  160. /package/gsp/{references → skills/gsp-project-design}/block-patterns.md +0 -0
  161. /package/gsp/{references → skills/gsp-typography/references}/typography-scales.md +0 -0
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,22 +1197,34 @@ 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;
1215
1205
  forceSymlink(path.join('..', '..', 'gsp', 'skills', dir.name), path.join(skillsDest, dir.name));
1216
1206
  skillCount++;
1217
1207
  }
1208
+ // ── Dev skill symlinks (local only — not shipped in npm package) ──
1209
+ const devSkillsSrc = path.join(cwd, 'dev', 'skills');
1210
+ let devSkillCount = 0;
1211
+ try {
1212
+ if (fs.existsSync(devSkillsSrc)) {
1213
+ for (const dir of fs.readdirSync(devSkillsSrc, { withFileTypes: true })) {
1214
+ if (!dir.isDirectory()) continue;
1215
+ forceSymlink(path.join('..', '..', 'dev', 'skills', dir.name), path.join(skillsDest, dir.name));
1216
+ devSkillCount++;
1217
+ }
1218
+ }
1219
+ } catch {
1220
+ console.log(` ${c.secondary}! Could not read dev/skills/ — skipping dev skills${c.reset}`);
1221
+ }
1222
+
1218
1223
  if (skillCount > 0) {
1219
- console.log(` ${c.success}✓${c.reset} Symlinked ${skillCount} skills`);
1224
+ const msg = devSkillCount > 0
1225
+ ? `Symlinked ${skillCount} skills + ${devSkillCount} dev`
1226
+ : `Symlinked ${skillCount} skills`;
1227
+ console.log(` ${c.success}✓${c.reset} ${msg}`);
1220
1228
  } else { failures.push('skills'); }
1221
1229
 
1222
1230
  // Clean up legacy commands/gsp dir (may be broken symlink)
@@ -1227,19 +1235,25 @@ function installLocalSymlinks(targetDir, src) {
1227
1235
  console.log(` ${c.success}✓${c.reset} Removed legacy commands/gsp`);
1228
1236
  } catch {}
1229
1237
 
1230
- // ── Bundle symlinks (prompts, templates, references → runtime root) ──
1231
- // Clean up legacy get-shit-pretty/ bundle dir
1238
+ // ── Bundle symlinks (templates → runtime root) ──
1239
+ // Clean up legacy dirs
1232
1240
  const legacyBundleDest = path.join(targetDir, 'get-shit-pretty');
1233
1241
  if (fs.existsSync(legacyBundleDest)) {
1234
1242
  fs.rmSync(legacyBundleDest, { recursive: true });
1235
1243
  console.log(` ${c.success}✓${c.reset} Removed legacy get-shit-pretty/ bundle`);
1236
1244
  }
1245
+ for (const legacyDir of ['prompts', 'references']) {
1246
+ const legacyPath = path.join(targetDir, legacyDir);
1247
+ try {
1248
+ fs.lstatSync(legacyPath);
1249
+ fs.rmSync(legacyPath, { recursive: true });
1250
+ console.log(` ${c.success}✓${c.reset} Removed legacy ${legacyDir}/`);
1251
+ } catch {}
1252
+ }
1237
1253
 
1238
- for (const dir of ['prompts', 'templates', 'references']) {
1239
- if (fs.existsSync(path.join(gspRoot, dir))) {
1240
- forceSymlink(path.join('..', 'gsp', dir), path.join(targetDir, dir));
1241
- console.log(` ${c.success}✓${c.reset} Symlinked ${dir}/`);
1242
- }
1254
+ if (fs.existsSync(path.join(gspRoot, 'templates'))) {
1255
+ forceSymlink(path.join('..', 'gsp', 'templates'), path.join(targetDir, 'templates'));
1256
+ console.log(` ${c.success}✓${c.reset} Symlinked templates/`);
1243
1257
  }
1244
1258
 
1245
1259
  // Write VERSION from package.json (local dev uses repo root VERSION via symlinks)
@@ -1267,6 +1281,16 @@ function installLocalSymlinks(targetDir, src) {
1267
1281
  process.exit(1);
1268
1282
  }
1269
1283
 
1284
+ // Warn if GSP skills also exist globally (may cause duplicates)
1285
+ const globalSkillsDir = path.join(getGlobalDir('claude', null), 'skills');
1286
+ if (fs.existsSync(globalSkillsDir)) {
1287
+ const dupes = fs.readdirSync(globalSkillsDir).filter(e => e.startsWith('gsp-'));
1288
+ if (dupes.length > 0) {
1289
+ console.log(` ${yellow}!${reset} Found ${dupes.length} GSP skills in ${globalSkillsDir.replace(os.homedir(), '~')} — may cause duplicates`);
1290
+ console.log(` ${c.dim}To remove: node bin/install.js --claude --global --uninstall${c.reset}`);
1291
+ }
1292
+ }
1293
+
1270
1294
  return true;
1271
1295
  }
1272
1296
 
@@ -1417,23 +1441,25 @@ function install(isGlobal, runtime = 'claude') {
1417
1441
  }
1418
1442
  }
1419
1443
 
1420
- // ── Bundle: prompts, templates, references → runtime root ──
1421
- // Clean up legacy get-shit-pretty/ bundle dir from previous installs
1444
+ // ── Bundle: templates, references → runtime root ──
1445
+ // Clean up legacy dirs from previous installs
1422
1446
  const legacyBundle = path.join(targetDir, 'get-shit-pretty');
1423
1447
  if (fs.existsSync(legacyBundle)) {
1424
1448
  fs.rmSync(legacyBundle, { recursive: true });
1425
1449
  console.log(` ${c.success}✓${c.reset} Removed legacy get-shit-pretty/ bundle`);
1426
1450
  }
1451
+ const legacyPromptsDir = path.join(targetDir, 'prompts');
1452
+ if (fs.existsSync(legacyPromptsDir)) {
1453
+ fs.rmSync(legacyPromptsDir, { recursive: true });
1454
+ console.log(` ${c.success}✓${c.reset} Removed legacy prompts/`);
1455
+ }
1427
1456
 
1428
- const bundleDirs = ['prompts', 'templates', 'references'];
1429
- for (const dir of bundleDirs) {
1430
- const dirSrc = path.join(gspRoot, dir);
1431
- if (fs.existsSync(dirSrc)) {
1432
- copyWithPathReplacement(dirSrc, path.join(targetDir, dir), pathPrefix, runtime);
1433
- if (verifyInstalled(path.join(targetDir, dir), dir)) {
1434
- console.log(` ${c.success}✓${c.reset} Installed ${dir}/`);
1435
- } else { failures.push(dir); }
1436
- }
1457
+ const templatesSrc = path.join(gspRoot, 'templates');
1458
+ if (fs.existsSync(templatesSrc)) {
1459
+ copyWithPathReplacement(templatesSrc, path.join(targetDir, 'templates'), pathPrefix, runtime);
1460
+ if (verifyInstalled(path.join(targetDir, 'templates'), 'templates')) {
1461
+ console.log(` ${c.success}✓${c.reset} Installed templates/`);
1462
+ } else { failures.push('templates'); }
1437
1463
  }
1438
1464
 
1439
1465
  // Write VERSION file
@@ -1467,6 +1493,21 @@ function install(isGlobal, runtime = 'claude') {
1467
1493
  process.exit(1);
1468
1494
  }
1469
1495
 
1496
+ // Warn if GSP skills exist in the other location (may cause duplicates)
1497
+ if (runtime === 'claude') {
1498
+ const otherDir = isGlobal
1499
+ ? path.join(process.cwd(), '.claude', 'skills')
1500
+ : path.join(getGlobalDir('claude', null), 'skills');
1501
+ if (fs.existsSync(otherDir)) {
1502
+ const dupes = fs.readdirSync(otherDir).filter(e => e.startsWith('gsp-'));
1503
+ if (dupes.length > 0) {
1504
+ const label = otherDir.replace(os.homedir(), '~');
1505
+ console.log(` ${yellow}!${reset} Found ${dupes.length} GSP skills in ${label} — may cause duplicates`);
1506
+ console.log(` ${c.dim}To remove: node bin/install.js --claude ${isGlobal ? '--local' : '--global'} --uninstall${c.reset}`);
1507
+ }
1508
+ }
1509
+ }
1510
+
1470
1511
  // ── Settings (Claude Code & Gemini only) ──
1471
1512
  const settingsPath = path.join(targetDir, 'settings.json');
1472
1513
  const settings = readSettings(settingsPath);
@@ -1545,7 +1586,7 @@ function uninstall(isGlobal, runtime = 'claude') {
1545
1586
  }
1546
1587
  }
1547
1588
  } else {
1548
- // All other runtimes: remove gsp- skill dirs
1589
+ // All other runtimes (including Claude): remove gsp- skill dirs
1549
1590
  const skillsDir = path.join(targetDir, 'skills');
1550
1591
  if (fs.existsSync(skillsDir)) {
1551
1592
  let skillCount = 0;
@@ -1593,7 +1634,7 @@ function uninstall(isGlobal, runtime = 'claude') {
1593
1634
  }
1594
1635
 
1595
1636
  // Remove flattened bundle dirs
1596
- for (const dir of ['prompts', 'templates', 'references']) {
1637
+ for (const dir of ['prompts', 'templates', 'references']) { // prompts included for legacy cleanup
1597
1638
  const bundlePath = path.join(targetDir, dir);
1598
1639
  if (fs.existsSync(bundlePath)) {
1599
1640
  fs.rmSync(bundlePath, { recursive: true });
@@ -1726,8 +1767,8 @@ function finishInstall(settingsPath, settings, statuslineCommand, shouldInstallS
1726
1767
  }
1727
1768
 
1728
1769
  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';
1770
+ const helpCmd = isCodex ? '$gsp-help' : '/gsp-help';
1771
+ const newCmd = isCodex ? '$gsp-start' : '/gsp-start';
1731
1772
 
1732
1773
  // Show onboarding once (not per-runtime)
1733
1774
  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
@@ -58,7 +58,7 @@ Write your audit as chunks to the output directory (path provided by the skill t
58
58
 
59
59
  ### Chunk files
60
60
 
61
- Write each chunk following the format in `references/chunk-format.md`:
61
+ Write each chunk following the standard chunk format:
62
62
 
63
63
  1. **`accessibility-audit.md`** (~100-150 lines) — Perceivable, Operable, Understandable, Robust checklists (pass/fail per criterion with notes), Mobile accessibility, Cognitive accessibility, summary (total pass/fail/not-applicable counts, overall conformance level), accessibility statement draft
64
64
  2. **`accessibility-fixes.md`** (~50-100 lines) — Violations table (issue, severity Critical/Major/Minor, WCAG criterion, remediation steps). Only Critical and Major severity items.
@@ -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
@@ -19,7 +19,7 @@ You are a creative who happens to work in a grid of fixed-width cells. Every pie
19
19
  </role>
20
20
 
21
21
  <reference>
22
- @references/terminal-art.md
22
+ @skills/gsp-art/terminal-art.md
23
23
  </reference>
24
24
 
25
25
  <methodology>
@@ -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>
@@ -38,7 +38,7 @@ Assess existing brand identities — coherence, market fit, equity, evolution op
38
38
  <output>
39
39
  Write 5 chunks + INDEX.md to the audit directory (path provided by the skill that spawned you).
40
40
 
41
- Each chunk follows `references/chunk-format.md`.
41
+ Each chunk follows the standard chunk format.
42
42
 
43
43
  1. **`brand-inventory.md`** — structured inventory of all current assets (logo, colors with hex, typefaces, voice samples, messaging, positioning)
44
44
  2. **`coherence-assessment.md`** — strategy coherence (1-5), strategy↔visual alignment (1-5), key disconnects