@ramarivera/coding-buddy 0.4.0-alpha.8 → 0.6.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 (92) hide show
  1. package/{adapters/claude/plugin → .claude-plugin}/marketplace.json +11 -6
  2. package/{adapters/claude/plugin → .claude-plugin}/plugin.json +9 -7
  3. package/LICENSE +1 -1
  4. package/README.md +102 -72
  5. package/adapters/omp/commands.ts +201 -0
  6. package/adapters/omp/context.ts +22 -0
  7. package/adapters/omp/events.ts +551 -0
  8. package/adapters/omp/identity.ts +10 -0
  9. package/adapters/omp/index.ts +39 -0
  10. package/adapters/omp/logger.ts +52 -0
  11. package/adapters/omp/prompt.ts +60 -0
  12. package/adapters/omp/renderers.ts +73 -0
  13. package/adapters/omp/storage.ts +25 -0
  14. package/adapters/omp/ui.ts +85 -0
  15. package/adapters/pi/commands.ts +64 -37
  16. package/adapters/pi/events.ts +147 -72
  17. package/adapters/pi/index.ts +9 -4
  18. package/adapters/pi/storage.ts +14 -285
  19. package/adapters/pi/ui.ts +56 -5
  20. package/adapters/shared/file-storage.ts +526 -0
  21. package/{adapters/claude/install → cli}/backup.ts +59 -44
  22. package/cli/biomes.ts +309 -0
  23. package/cli/buddy-shell.ts +818 -0
  24. package/{adapters/claude/install → cli}/disable.ts +14 -32
  25. package/{adapters/claude/install → cli}/doctor.ts +55 -57
  26. package/{adapters/claude/install → cli}/hunt.ts +7 -9
  27. package/cli/index.ts +36 -25
  28. package/{adapters/claude/install → cli}/install.ts +100 -145
  29. package/{adapters/claude/install → cli}/pick.ts +111 -50
  30. package/{adapters/claude/install → cli}/settings.ts +2 -2
  31. package/{adapters/claude/install → cli}/show.ts +4 -4
  32. package/{adapters/claude/install → cli}/test-statusline.sh +2 -2
  33. package/{adapters/claude/install → cli}/test-statusline.ts +11 -11
  34. package/cli/tui.tsx +2333 -0
  35. package/{adapters/claude/install → cli}/uninstall.ts +23 -38
  36. package/cli/upgrade.ts +213 -0
  37. package/cli/validate-species.ts +209 -0
  38. package/cli/verify.ts +3 -3
  39. package/core/achievements.ts +12 -20
  40. package/core/art-data.ts +26 -0
  41. package/core/command-service.ts +99 -97
  42. package/core/engine.ts +83 -1
  43. package/core/ports.ts +10 -0
  44. package/core/reactions.ts +533 -95
  45. package/core/slot-slug.ts +22 -0
  46. package/{adapters/claude/hooks → hooks}/buddy-comment.sh +23 -2
  47. package/hooks/file-type-react.sh +401 -0
  48. package/hooks/hooks.json +52 -0
  49. package/hooks/mood-react.sh +208 -0
  50. package/{adapters/claude/hooks → hooks}/name-react.sh +5 -2
  51. package/hooks/react.sh +1368 -0
  52. package/hooks/suggest.sh +55 -0
  53. package/package.json +113 -59
  54. package/scripts/gen-emoji-widths.ts +34 -0
  55. package/scripts/paths.sh +56 -0
  56. package/scripts/postinstall.cjs +42 -0
  57. package/scripts/snapshot-statusline.sh +54 -0
  58. package/server/achievements.ts +1419 -0
  59. package/server/art.ts +450 -0
  60. package/server/award-xp.ts +48 -0
  61. package/server/check-suggestions.ts +102 -0
  62. package/server/consolidate.ts +33 -0
  63. package/server/index.ts +1340 -0
  64. package/server/mcp-launcher.sh +26 -0
  65. package/server/memory.ts +404 -0
  66. package/server/mood.ts +254 -0
  67. package/server/path.ts +82 -0
  68. package/server/shift-mood.ts +43 -0
  69. package/{adapters/claude/storage → server}/state.ts +200 -7
  70. package/server/suggestions.ts +335 -0
  71. package/server/theme.ts +53 -0
  72. package/server/xp.ts +435 -0
  73. package/{adapters/claude/skills → skills}/buddy/SKILL.md +48 -4
  74. package/statusline/buddy-status.sh +397 -0
  75. package/statusline/combined-status.sh +134 -0
  76. package/statusline/emoji-widths.data +4 -0
  77. package/adapters/claude/hooks/hooks.json +0 -35
  78. package/adapters/claude/hooks/react.sh +0 -204
  79. package/adapters/claude/popup/buddy-popup.sh +0 -92
  80. package/adapters/claude/popup/buddy-render.sh +0 -540
  81. package/adapters/claude/popup/popup-manager.sh +0 -355
  82. package/adapters/claude/rendering/art.ts +0 -264
  83. package/adapters/claude/server/index.ts +0 -752
  84. package/adapters/claude/server/instructions.ts +0 -24
  85. package/adapters/claude/server/resources.ts +0 -38
  86. package/adapters/claude/statusline/buddy-status.sh +0 -389
  87. package/adapters/claude/storage/achievements.ts +0 -253
  88. package/adapters/claude/storage/identity.ts +0 -13
  89. package/adapters/claude/storage/paths.ts +0 -24
  90. package/adapters/claude/storage/settings.ts +0 -41
  91. package/adapters/pi/README.md +0 -83
  92. package/adapters/pi/tools.ts +0 -6
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env bun
2
2
  /**
3
- * claude-buddy disable — temporarily deactivate buddy without losing data
3
+ * coding-buddy disable — temporarily deactivate buddy without losing data
4
4
  *
5
5
  * Removes: MCP server, status line, hooks
6
6
  * Keeps: companion data, backups, skill files
@@ -9,29 +9,11 @@
9
9
  */
10
10
 
11
11
  import { readFileSync, writeFileSync, existsSync } from "fs";
12
- import { join } from "path";
13
- import { homedir } from "os";
14
- import { getClaudeJsonPath, getClaudeSettingsPath } from "../storage/paths.ts";
15
-
16
- interface HookCommand {
17
- type: "command";
18
- command: string;
19
- }
20
-
21
- interface HookMatcherEntry {
22
- matcher?: string;
23
- hooks?: HookCommand[];
24
- }
25
-
26
- interface ClaudeSettings {
27
- statusLine?: { command?: string };
28
- hooks?: Record<string, HookMatcherEntry[]>;
29
- [key: string]: unknown;
30
- }
31
-
32
- function hasBuddyHook(entry: HookMatcherEntry): boolean {
33
- return (entry.hooks ?? []).some((hook) => hook.command.includes("claude-buddy"));
34
- }
12
+ import {
13
+ buddyStateDir,
14
+ claudeSettingsPath,
15
+ claudeUserConfigPath,
16
+ } from "../server/path.ts";
35
17
 
36
18
  const GREEN = "\x1b[32m";
37
19
  const YELLOW = "\x1b[33m";
@@ -42,11 +24,11 @@ const NC = "\x1b[0m";
42
24
  function ok(msg: string) { console.log(`${GREEN}✓${NC} ${msg}`); }
43
25
  function warn(msg: string) { console.log(`${YELLOW}⚠${NC} ${msg}`); }
44
26
 
45
- const HOME = homedir();
46
- const CLAUDE_JSON = getClaudeJsonPath();
47
- const SETTINGS = getClaudeSettingsPath();
27
+ const CLAUDE_JSON = claudeUserConfigPath();
28
+ const SETTINGS = claudeSettingsPath();
29
+ const STATE_DIR = buddyStateDir();
48
30
 
49
- console.log(`\n${BOLD}Disabling claude-buddy...${NC}\n`);
31
+ console.log(`\n${BOLD}Disabling coding-buddy...${NC}\n`);
50
32
 
51
33
  // 1. Remove MCP server from ~/.claude.json
52
34
  try {
@@ -65,7 +47,7 @@ try {
65
47
 
66
48
  // 2. Remove status line + hooks from settings.json
67
49
  try {
68
- const settings = JSON.parse(readFileSync(SETTINGS, "utf8")) as ClaudeSettings;
50
+ const settings = JSON.parse(readFileSync(SETTINGS, "utf8"));
69
51
  let changed = false;
70
52
 
71
53
  if (settings.statusLine?.command?.includes("buddy")) {
@@ -75,11 +57,11 @@ try {
75
57
  }
76
58
 
77
59
  if (settings.hooks) {
78
- for (const hookType of ["PostToolUse", "Stop", "SessionStart", "SessionEnd"]) {
60
+ for (const hookType of ["PostToolUse", "Stop", "SessionStart", "SessionEnd", "UserPromptSubmit"]) {
79
61
  if (settings.hooks[hookType]) {
80
62
  const before = settings.hooks[hookType].length;
81
63
  settings.hooks[hookType] = settings.hooks[hookType].filter(
82
- (h) => !hasBuddyHook(h),
64
+ (h: any) => !h.hooks?.some((hh: any) => hh.command?.includes("coding-buddy") || hh.command?.includes("claude-buddy")),
83
65
  );
84
66
  if (settings.hooks[hookType].length < before) changed = true;
85
67
  if (settings.hooks[hookType].length === 0) delete settings.hooks[hookType];
@@ -107,7 +89,7 @@ try {
107
89
  console.log(`
108
90
  ${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}
109
91
  ${GREEN} Buddy disabled.${NC}
110
- ${GREEN} Companion data is preserved at ~/.claude-buddy/${NC}
92
+ ${GREEN} Companion data is preserved at ${STATE_DIR}${NC}
111
93
  ${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}
112
94
 
113
95
  ${DIM} Restart Claude Code for changes to take effect.
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env bun
2
2
  /**
3
- * claude-buddy doctor — comprehensive diagnostic report
3
+ * coding-buddy doctor — comprehensive diagnostic report
4
4
  *
5
5
  * Run: bun run doctor
6
6
  *
@@ -10,17 +10,22 @@
10
10
 
11
11
  import { readFileSync, existsSync, statSync } from "fs";
12
12
  import { execSync } from "child_process";
13
- import { join, resolve } from "path";
14
- import { homedir } from "os";
15
- import { getBuddySkillDir, getClaudeConfigDir, getClaudeJsonPath, getClaudeSettingsPath } from "../storage/paths.ts";
16
-
17
- const PROJECT_ROOT = resolve(import.meta.dir, "../../..");
18
- const HOME = homedir();
19
- const CLAUDE_DIR = getClaudeConfigDir();
20
- const CLAUDE_JSON = getClaudeJsonPath();
21
- const SETTINGS = getClaudeSettingsPath();
22
- const SKILL_PATH = join(getBuddySkillDir(), "SKILL.md");
23
- const STATUS_SCRIPT = join(PROJECT_ROOT, "adapters", "claude", "statusline", "buddy-status.sh");
13
+ import { join, resolve, dirname } from "path";
14
+ import {
15
+ buddyStateDir,
16
+ claudeConfigDir,
17
+ claudeSettingsPath,
18
+ claudeSkillDir,
19
+ claudeUserConfigPath,
20
+ } from "../server/path.ts";
21
+
22
+ const PROJECT_ROOT = resolve(dirname(import.meta.dir));
23
+ const CLAUDE_DIR = claudeConfigDir();
24
+ const CLAUDE_JSON = claudeUserConfigPath();
25
+ const STATE_DIR = buddyStateDir();
26
+ const SETTINGS = claudeSettingsPath();
27
+ const SKILL_DIR = claudeSkillDir("buddy");
28
+ const STATUS_SCRIPT = join(PROJECT_ROOT, "statusline", "buddy-status.sh");
24
29
 
25
30
  const RED = "\x1b[31m";
26
31
  const GREEN = "\x1b[32m";
@@ -54,20 +59,16 @@ function tryRead(path: string): string | null {
54
59
  try { return readFileSync(path, "utf8"); } catch { return null; }
55
60
  }
56
61
 
57
- function tryParseJson(text: string | null): unknown {
62
+ function tryParseJson(text: string | null): any | null {
58
63
  if (!text) return null;
59
- try { return JSON.parse(text) as unknown; } catch { return null; }
60
- }
61
-
62
- function isRecord(value: unknown): value is Record<string, unknown> {
63
- return typeof value === "object" && value !== null;
64
+ try { return JSON.parse(text); } catch { return null; }
64
65
  }
65
66
 
66
67
  // ─── Header ─────────────────────────────────────────────────────────────────
67
68
 
68
69
  console.log(`${CYAN}${BOLD}
69
70
  ╔══════════════════════════════════════════════════════════╗
70
- ║ claude-buddy doctor — diagnostic report ║
71
+ ║ coding-buddy doctor — diagnostic report ║
71
72
  ╚══════════════════════════════════════════════════════════╝${NC}`);
72
73
 
73
74
  console.log(`\n${DIM}Copy this entire output into your GitHub issue.${NC}`);
@@ -100,46 +101,43 @@ row("tput cols", tryExec("tput cols 2>/dev/null", "(failed)"));
100
101
  section("Filesystem");
101
102
  const procExists = existsSync("/proc");
102
103
  row("/proc exists", procExists ? `${GREEN}yes${NC} (Linux)` : `${RED}no${NC} (macOS/BSD)`);
103
- row("Claude config dir", CLAUDE_DIR);
104
- row("Claude config dir exists", existsSync(CLAUDE_DIR) ? "yes" : "no");
105
- row("Claude config file", CLAUDE_JSON);
106
- row("Claude config file exists", existsSync(CLAUDE_JSON) ? "yes" : "no");
107
- row("~/.claude-buddy/ exists", existsSync(join(HOME, ".claude-buddy")) ? "yes" : "no");
104
+ row("CLAUDE_CONFIG_DIR", process.env.CLAUDE_CONFIG_DIR ?? "(unset)");
105
+ row(`${CLAUDE_DIR} exists`, existsSync(CLAUDE_DIR) ? "yes" : "no");
106
+ row(`${CLAUDE_JSON} exists`, existsSync(CLAUDE_JSON) ? "yes" : "no");
107
+ row(`${STATE_DIR} exists`, existsSync(STATE_DIR) ? "yes" : "no");
108
108
  row("Project root", PROJECT_ROOT);
109
109
  row("Status script exists", existsSync(STATUS_SCRIPT) ? "yes" : `${RED}no${NC}`);
110
110
 
111
- // ─── claude-buddy state ─────────────────────────────────────────────────────
111
+ // ─── coding-buddy state ─────────────────────────────────────────────────────
112
112
 
113
- section("claude-buddy state");
114
- const menagerie = tryParseJson(tryRead(join(HOME, ".claude-buddy", "menagerie.json")));
115
- const status = tryParseJson(tryRead(join(HOME, ".claude-buddy", "status.json")));
113
+ section("coding-buddy state");
114
+ const menagerie = tryParseJson(tryRead(join(STATE_DIR, "menagerie.json")));
115
+ const status = tryParseJson(tryRead(join(STATE_DIR, "status.json")));
116
116
 
117
- if (isRecord(menagerie)) {
118
- const activeSlot = typeof menagerie.active === "string" ? menagerie.active : "buddy";
119
- const companions = isRecord(menagerie.companions) ? menagerie.companions : {};
120
- const companion = companions[activeSlot];
117
+ if (menagerie) {
118
+ const activeSlot = menagerie.active ?? "buddy";
119
+ const companion = menagerie.companions?.[activeSlot];
121
120
  row("Active slot", activeSlot);
122
- row("Total slots", String(Object.keys(companions).length));
123
- if (isRecord(companion)) {
124
- const bones = isRecord(companion.bones) ? companion.bones : {};
125
- row("Companion name", typeof companion.name === "string" ? companion.name : "(none)");
126
- row("Species", typeof bones.species === "string" ? bones.species : "(none)");
127
- row("Rarity", typeof bones.rarity === "string" ? bones.rarity : "(none)");
128
- row("Hat", typeof bones.hat === "string" ? bones.hat : "(none)");
129
- row("Eye", typeof bones.eye === "string" ? bones.eye : "(none)");
130
- row("Shiny", String(typeof bones.shiny === "boolean" ? bones.shiny : false));
121
+ row("Total slots", String(Object.keys(menagerie.companions ?? {}).length));
122
+ if (companion) {
123
+ row("Companion name", companion.name ?? "(none)");
124
+ row("Species", companion.bones?.species ?? "(none)");
125
+ row("Rarity", companion.bones?.rarity ?? "(none)");
126
+ row("Hat", companion.bones?.hat ?? "(none)");
127
+ row("Eye", companion.bones?.eye ?? "(none)");
128
+ row("Shiny", String(companion.bones?.shiny ?? false));
131
129
  } else {
132
130
  err(`No companion found in active slot "${activeSlot}"`);
133
131
  }
134
132
  } else {
135
- err("No manifest found at ~/.claude-buddy/menagerie.json");
133
+ err(`No manifest found at ${join(STATE_DIR, "menagerie.json")}`);
136
134
  }
137
135
 
138
- if (isRecord(status)) {
139
- row("Status muted", String(typeof status.muted === "boolean" ? status.muted : false));
140
- row("Current reaction", typeof status.reaction === "string" && status.reaction.length > 0 ? status.reaction : "(none)");
136
+ if (status) {
137
+ row("Status muted", String(status.muted ?? false));
138
+ row("Current reaction", status.reaction || "(none)");
141
139
  } else {
142
- warn("No status state at ~/.claude-buddy/status.json");
140
+ warn(`No status state at ${join(STATE_DIR, "status.json")}`);
143
141
  }
144
142
 
145
143
  // ─── settings.json ──────────────────────────────────────────────────────────
@@ -148,35 +146,35 @@ section("Claude Code config");
148
146
  const settings = tryParseJson(tryRead(SETTINGS));
149
147
  const claudeJson = tryParseJson(tryRead(CLAUDE_JSON));
150
148
 
151
- if (isRecord(settings) && "statusLine" in settings && settings.statusLine !== undefined) {
149
+ if (settings?.statusLine) {
152
150
  console.log(` ${DIM}statusLine:${NC}`);
153
151
  console.log(` ${JSON.stringify(settings.statusLine, null, 2).split("\n").join("\n ")}`);
154
152
  } else {
155
- warn("No statusLine in ~/.claude/settings.json");
153
+ warn(`No statusLine in ${SETTINGS}`);
156
154
  }
157
155
 
158
- if (isRecord(settings) && isRecord(settings.hooks)) {
156
+ if (settings?.hooks) {
159
157
  console.log(` ${DIM}hooks:${NC}`);
160
158
  for (const event of Object.keys(settings.hooks)) {
161
- const hookEntries = settings.hooks[event];
162
- const count = Array.isArray(hookEntries) ? hookEntries.length : 0;
159
+ const count = settings.hooks[event]?.length ?? 0;
163
160
  row(` ${event}`, `${count} entr${count === 1 ? "y" : "ies"}`);
164
161
  }
165
162
  } else {
166
163
  warn("No hooks configured");
167
164
  }
168
165
 
169
- if (isRecord(claudeJson) && isRecord(claudeJson.mcpServers) && isRecord(claudeJson.mcpServers["claude-buddy"])) {
170
- ok("MCP server registered in ~/.claude.json");
166
+ if (claudeJson?.mcpServers?.["claude-buddy"]) {
167
+ ok(`MCP server registered in ${CLAUDE_JSON}`);
171
168
  console.log(` ${JSON.stringify(claudeJson.mcpServers["claude-buddy"], null, 2).split("\n").join("\n ")}`);
172
169
  } else {
173
- err("MCP server NOT registered in ~/.claude.json");
170
+ err(`MCP server NOT registered in ${CLAUDE_JSON}`);
174
171
  }
175
172
 
176
- if (existsSync(SKILL_PATH)) {
177
- ok(`Skill installed: ${SKILL_PATH}`);
173
+ const skillPath = join(SKILL_DIR, "SKILL.md");
174
+ if (existsSync(skillPath)) {
175
+ ok(`Skill installed: ${skillPath}`);
178
176
  } else {
179
- err(`Skill missing: ${SKILL_PATH}`);
177
+ err(`Skill missing: ${skillPath}`);
180
178
  }
181
179
 
182
180
  // ─── Live status line test ──────────────────────────────────────────────────
@@ -1,5 +1,5 @@
1
1
  /**
2
- * claude-buddy hunt — brute-force search for a specific buddy
2
+ * coding-buddy hunt — brute-force search for a specific buddy
3
3
  *
4
4
  * Rules:
5
5
  * - Asks for a name before saving
@@ -7,14 +7,12 @@
7
7
  * - Appends to the manifest — never overwrites an existing slot
8
8
  */
9
9
 
10
- import {
11
- searchBuddy, renderBuddy, SPECIES, RARITIES, STAT_NAMES,
12
- type Species, type Rarity, type StatName, type SearchCriteria,
13
- } from "../../../core/engine.ts";
10
+ import { searchBuddy, renderBuddy, SPECIES, RARITIES, STAT_NAMES,
11
+ type Species, type Rarity, type StatName, type SearchCriteria, } from "../core/engine.ts"
14
12
  import {
15
13
  saveCompanionSlot, saveActiveSlot, writeStatusState,
16
14
  slugify, unusedName, listCompanionSlots,
17
- } from "../storage/state.ts";
15
+ } from "../server/state.ts";
18
16
  import { createInterface } from "readline";
19
17
 
20
18
  const CYAN = "\x1b[36m";
@@ -47,7 +45,7 @@ function pickFromList<T extends string>(label: string, items: readonly T[]): Pro
47
45
  async function main() {
48
46
  console.log(`
49
47
  ${CYAN}╔══════════════════════════════════════════════════════════╗${NC}
50
- ${CYAN}║${NC} ${BOLD}claude-buddy hunt${NC} — find your perfect companion ${CYAN}║${NC}
48
+ ${CYAN}║${NC} ${BOLD}coding-buddy hunt${NC} — find your perfect companion ${CYAN}║${NC}
51
49
  ${CYAN}╚══════════════════════════════════════════════════════════╝${NC}
52
50
  `);
53
51
 
@@ -67,8 +65,8 @@ ${CYAN}╚═══════════════════════
67
65
  const statsAns = await ask(`\n Configure stats? [Y/n]: `);
68
66
  if (statsAns.toLowerCase() !== "n") {
69
67
  wantPeak = await pickFromList("Peak stat (highest):", STAT_NAMES);
70
- const dumpOptions = STAT_NAMES.filter((s): s is Exclude<StatName, typeof wantPeak> => s !== wantPeak);
71
- wantDump = await pickFromList("Dump stat (lowest):", dumpOptions);
68
+ const dumpOptions = STAT_NAMES.filter((s) => s !== wantPeak);
69
+ wantDump = await pickFromList("Dump stat (lowest):", dumpOptions as any);
72
70
  console.log(`${GREEN}✓${NC} peak=${wantPeak} dump=${wantDump}`);
73
71
  }
74
72
 
package/cli/index.ts CHANGED
@@ -1,56 +1,62 @@
1
1
  #!/usr/bin/env bun
2
2
  /**
3
- * claude-buddy CLI
3
+ * coding-buddy CLI
4
4
  *
5
5
  * Usage:
6
- * npx claude-buddy Interactive install
7
- * npx claude-buddy install Install MCP + skill + hooks + statusline
8
- * npx claude-buddy show Show current buddy
9
- * npx claude-buddy pick Interactive two-pane buddy picker (saved + search)
10
- * npx claude-buddy hunt Search for a specific buddy (non-interactive)
11
- * npx claude-buddy uninstall Remove all integrations
12
- * npx claude-buddy verify Verify what buddy your ID produces
6
+ * npx -y @ramarivera/coding-buddy Interactive install
7
+ * npx -y @ramarivera/coding-buddy install Install MCP + skill + hooks + statusline
8
+ * npx -y @ramarivera/coding-buddy show Show current buddy
9
+ * npx -y @ramarivera/coding-buddy pick Interactive two-pane buddy picker (saved + search)
10
+ * npx -y @ramarivera/coding-buddy hunt Search for a specific buddy (non-interactive)
11
+ * npx -y @ramarivera/coding-buddy upgrade Pull latest + reinstall
12
+ * npx -y @ramarivera/coding-buddy uninstall Remove all integrations
13
+ * npx -y @ramarivera/coding-buddy verify Verify what buddy your ID produces
13
14
  */
14
15
 
16
+ export {}; // Make this file a module for TypeScript top-level await
17
+
15
18
  const args = process.argv.slice(2);
16
19
  const command = args[0] || "install";
17
20
 
18
21
  switch (command) {
19
22
  case "install":
20
- await import("../adapters/claude/install/install.ts");
23
+ await import("./install.ts");
21
24
  break;
22
25
  case "show":
23
- await import("../adapters/claude/install/show.ts");
26
+ await import("./show.ts");
24
27
  break;
25
28
  case "pick":
26
- await import("../adapters/claude/install/pick.ts");
29
+ await import("./pick.ts");
27
30
  break;
28
31
  case "hunt":
29
- await import("../adapters/claude/install/hunt.ts");
32
+ await import("./hunt.ts");
30
33
  break;
31
34
  case "uninstall":
32
- await import("../adapters/claude/install/uninstall.ts");
35
+ await import("./uninstall.ts");
33
36
  break;
34
37
  case "verify":
35
38
  await import("./verify.ts");
36
39
  break;
37
40
  case "doctor":
38
- await import("../adapters/claude/install/doctor.ts");
41
+ await import("./doctor.ts");
39
42
  break;
40
43
  case "test-statusline":
41
- await import("../adapters/claude/install/test-statusline.ts");
44
+ await import("./test-statusline.ts");
42
45
  break;
43
46
  case "backup":
44
- await import("../adapters/claude/install/backup.ts");
47
+ await import("./backup.ts");
45
48
  break;
46
49
  case "settings":
47
- await import("../adapters/claude/install/settings.ts");
50
+ await import("./settings.ts");
48
51
  break;
49
52
  case "disable":
50
- await import("../adapters/claude/install/disable.ts");
53
+ await import("./disable.ts");
54
+ break;
55
+ case "upgrade":
56
+ await import("./upgrade.ts");
51
57
  break;
52
58
  case "enable":
53
- await import("../adapters/claude/install/install.ts");
59
+ await import("./install.ts");
54
60
  break;
55
61
  case "help":
56
62
  case "--help":
@@ -65,13 +71,14 @@ switch (command) {
65
71
 
66
72
  function showHelp() {
67
73
  console.log(`
68
- claude-buddy — permanent coding companion for Claude Code
74
+ coding-buddy — permanent coding companion for Claude Code, Pi, and Oh My Pi
69
75
 
70
76
  Setup:
71
77
  install-buddy Set up MCP server, skill, hooks, and status line
78
+ upgrade Pull latest version and reinstall integrations
72
79
  enable Same as install-buddy (re-enable after disable)
73
80
  disable Temporarily deactivate buddy (data preserved)
74
- uninstall Remove all claude-buddy integrations
81
+ uninstall Remove all coding-buddy integrations
75
82
 
76
83
  Buddy:
77
84
  show Display your current buddy
@@ -79,6 +86,8 @@ Buddy:
79
86
  hunt Search for a specific buddy (non-interactive)
80
87
  verify Verify what buddy your current ID produces
81
88
 
89
+ upgrade Pull latest version + reinstall (add --check to just check)
90
+
82
91
  Settings:
83
92
  settings Show current settings
84
93
  settings cooldown <n> Set comment cooldown (0-300 seconds)
@@ -87,7 +96,7 @@ Settings:
87
96
  Diagnostics:
88
97
  doctor Run diagnostic report (paste output in bug reports)
89
98
  test-statusline Test status line rendering in Claude Code
90
- backup Snapshot or restore all claude-buddy state
99
+ backup Snapshot or restore all coding-buddy state
91
100
 
92
101
  In Claude Code:
93
102
  /buddy Show companion card with ASCII art + stats
@@ -106,10 +115,12 @@ In Claude Code:
106
115
  /buddy style Show or set bubble style (tmux only)
107
116
  /buddy position Show or set bubble position (tmux only)
108
117
  /buddy rarity Show or hide rarity stars (tmux only)
118
+ /buddy width Set bubble text width in chars (10-60, tmux only)
109
119
 
110
120
  Usage:
111
- bun run <command> e.g. bun run show, bun run doctor
112
- claude-buddy <command> if globally linked (bun link)
113
- bun run help Show this help
121
+ npx -y @ramarivera/coding-buddy <command> Run from the registry without cloning
122
+ bun run <command> e.g. bun run show, bun run doctor (in repo)
123
+ coding-buddy <command> if globally linked (bun link)
124
+ bun run help Show this help
114
125
  `);
115
126
  }