get-shit-pretty 0.1.0 → 0.1.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.
package/bin/install.js CHANGED
@@ -755,14 +755,23 @@ function install(isGlobal, runtime = 'claude') {
755
755
 
756
756
  // ── Statusline (Claude Code only) ──
757
757
  if (runtime === 'claude') {
758
+ const hooksDest = path.join(targetDir, 'hooks');
759
+ fs.mkdirSync(hooksDest, { recursive: true });
760
+
761
+ // Copy GSP statusline
758
762
  const statuslineSrc = path.join(src, 'scripts', 'gsp-statusline.js');
759
763
  if (fs.existsSync(statuslineSrc)) {
760
- const hooksDest = path.join(targetDir, 'hooks');
761
- fs.mkdirSync(hooksDest, { recursive: true });
762
764
  let content = fs.readFileSync(statuslineSrc, 'utf8');
763
765
  content = content.replace(/'\.claude'/g, getConfigDirFromHome(runtime, isGlobal));
764
766
  fs.writeFileSync(path.join(hooksDest, 'gsp-statusline.js'), content);
765
- console.log(` ${green}+${reset} Installed statusline hook`);
767
+ console.log(` ${green}+${reset} Installed GSP statusline`);
768
+ }
769
+
770
+ // Copy dispatcher (routes to GSP or GSD based on project type)
771
+ const dispatcherSrc = path.join(src, 'scripts', 'statusline-dispatcher.js');
772
+ if (fs.existsSync(dispatcherSrc)) {
773
+ fs.copyFileSync(dispatcherSrc, path.join(hooksDest, 'statusline-dispatcher.js'));
774
+ console.log(` ${green}+${reset} Installed statusline dispatcher`);
766
775
  }
767
776
  }
768
777
 
@@ -776,8 +785,8 @@ function install(isGlobal, runtime = 'claude') {
776
785
  const settings = readSettings(settingsPath);
777
786
 
778
787
  const statuslineCommand = isGlobal
779
- ? `node "${targetDir.replace(/\\/g, '/')}/hooks/gsp-statusline.js"`
780
- : `node ${dirName}/hooks/gsp-statusline.js`;
788
+ ? `node "${targetDir.replace(/\\/g, '/')}/hooks/statusline-dispatcher.js"`
789
+ : `node ${dirName}/hooks/statusline-dispatcher.js`;
781
790
 
782
791
  return { settingsPath, settings, statuslineCommand, runtime };
783
792
  }
@@ -866,12 +875,14 @@ function uninstall(isGlobal, runtime = 'claude') {
866
875
  }
867
876
  }
868
877
 
869
- // Remove statusline hook
870
- const statuslineHook = path.join(targetDir, 'hooks', 'gsp-statusline.js');
871
- if (fs.existsSync(statuslineHook)) {
872
- fs.unlinkSync(statuslineHook);
873
- removedCount++;
874
- console.log(` ${green}+${reset} Removed statusline hook`);
878
+ // Remove statusline hooks
879
+ for (const hook of ['gsp-statusline.js', 'statusline-dispatcher.js']) {
880
+ const hookPath = path.join(targetDir, 'hooks', hook);
881
+ if (fs.existsSync(hookPath)) {
882
+ fs.unlinkSync(hookPath);
883
+ removedCount++;
884
+ console.log(` ${green}+${reset} Removed ${hook}`);
885
+ }
875
886
  }
876
887
 
877
888
  // Clean up settings.json (statusline only — no hooks to clean)
@@ -881,7 +892,7 @@ function uninstall(isGlobal, runtime = 'claude') {
881
892
  let modified = false;
882
893
 
883
894
  if (settings.statusLine && settings.statusLine.command &&
884
- settings.statusLine.command.includes('gsp-statusline')) {
895
+ (settings.statusLine.command.includes('gsp-statusline') || settings.statusLine.command.includes('statusline-dispatcher'))) {
885
896
  delete settings.statusLine;
886
897
  modified = true;
887
898
  console.log(` ${green}+${reset} Removed GSP statusline from settings`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "get-shit-pretty",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "A design engineering system for Claude Code, OpenCode, Gemini, and Codex. Research → Brand → System → Design → Spec → Review → Build → Launch.",
5
5
  "bin": {
6
6
  "get-shit-pretty": "bin/install.js"
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env node
2
+ // Statusline Dispatcher — routes to GSP or GSD statusline based on project type
3
+ // Installed by GSP to ~/.claude/hooks/statusline-dispatcher.js
4
+
5
+ const fs = require('fs');
6
+ const path = require('path');
7
+ const { spawn } = require('child_process');
8
+
9
+ // Read stdin first, then decide which statusline to run
10
+ let input = '';
11
+ process.stdin.setEncoding('utf8');
12
+ process.stdin.on('data', chunk => input += chunk);
13
+ process.stdin.on('end', () => {
14
+ try {
15
+ const data = JSON.parse(input);
16
+ const dir = data.workspace?.current_dir || process.cwd();
17
+ const hooksDir = __dirname;
18
+
19
+ // Pick statusline based on project type
20
+ let script;
21
+ if (fs.existsSync(path.join(dir, '.design', 'STATE.md'))) {
22
+ script = path.join(hooksDir, 'gsp-statusline.js');
23
+ } else {
24
+ script = path.join(hooksDir, 'gsd-statusline.js');
25
+ }
26
+
27
+ // Fall back if chosen script doesn't exist
28
+ if (!fs.existsSync(script)) {
29
+ const fallback = script.includes('gsp-') ? 'gsd-statusline.js' : 'gsp-statusline.js';
30
+ script = path.join(hooksDir, fallback);
31
+ if (!fs.existsSync(script)) {
32
+ // Neither exists — output minimal statusline
33
+ const model = data.model?.display_name || 'Claude';
34
+ process.stdout.write(`\x1b[2m${model}\x1b[0m`);
35
+ return;
36
+ }
37
+ }
38
+
39
+ // Pipe the input to the chosen statusline
40
+ const child = spawn(process.execPath, [script], { stdio: ['pipe', 'inherit', 'inherit'] });
41
+ child.stdin.write(input);
42
+ child.stdin.end();
43
+ } catch (e) {
44
+ // Silent fail
45
+ }
46
+ });