@ramarivera/coding-buddy 0.4.0-alpha.9 → 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 +7 -3
  3. package/LICENSE +1 -1
  4. package/README.md +88 -37
  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 +130 -33
  22. package/cli/buddy-shell.ts +1 -1
  23. package/{adapters/claude/install → cli}/disable.ts +19 -32
  24. package/cli/doctor.ts +231 -0
  25. package/{adapters/claude/install → cli}/hunt.ts +7 -9
  26. package/cli/index.ts +30 -26
  27. package/{adapters/claude/install → cli}/install.ts +65 -83
  28. package/{adapters/claude/install → cli}/pick.ts +111 -50
  29. package/{adapters/claude/install → cli}/settings.ts +2 -2
  30. package/{adapters/claude/install → cli}/show.ts +4 -4
  31. package/{adapters/claude/install → cli}/test-statusline.sh +2 -2
  32. package/{adapters/claude/install → cli}/test-statusline.ts +21 -11
  33. package/cli/tui.tsx +106 -17
  34. package/{adapters/claude/install → cli}/uninstall.ts +40 -47
  35. package/cli/upgrade.ts +2 -2
  36. package/cli/validate-species.ts +209 -0
  37. package/cli/verify.ts +3 -3
  38. package/core/achievements.ts +12 -20
  39. package/core/art-data.ts +26 -0
  40. package/core/command-service.ts +99 -97
  41. package/core/engine.ts +83 -1
  42. package/core/ports.ts +10 -0
  43. package/core/reactions.ts +533 -95
  44. package/core/slot-slug.ts +22 -0
  45. package/{adapters/claude/hooks → hooks}/buddy-comment.sh +19 -1
  46. package/hooks/file-type-react.sh +401 -0
  47. package/hooks/hooks.json +52 -0
  48. package/hooks/mood-react.sh +208 -0
  49. package/{adapters/claude/hooks → hooks}/name-react.sh +1 -1
  50. package/hooks/react.sh +1368 -0
  51. package/hooks/suggest.sh +55 -0
  52. package/package.json +70 -31
  53. package/scripts/gen-emoji-widths.ts +34 -0
  54. package/scripts/paths.sh +17 -1
  55. package/scripts/postinstall.cjs +42 -0
  56. package/scripts/snapshot-statusline.sh +54 -0
  57. package/server/achievements.ts +1419 -15
  58. package/server/art.ts +450 -1
  59. package/server/award-xp.ts +48 -0
  60. package/server/check-suggestions.ts +102 -0
  61. package/server/consolidate.ts +33 -0
  62. package/{adapters/claude/server → server}/index.ts +556 -95
  63. package/server/mcp-launcher.sh +16 -6
  64. package/server/memory.ts +404 -0
  65. package/server/mood.ts +254 -0
  66. package/server/path.ts +70 -18
  67. package/server/shift-mood.ts +43 -0
  68. package/server/state.ts +540 -3
  69. package/server/suggestions.ts +335 -0
  70. package/server/theme.ts +53 -0
  71. package/server/xp.ts +435 -0
  72. package/{adapters/claude/skills → skills}/buddy/SKILL.md +36 -7
  73. package/statusline/buddy-status.sh +397 -0
  74. package/statusline/combined-status.sh +134 -0
  75. package/statusline/emoji-widths.data +4 -0
  76. package/adapters/claude/hooks/hooks.json +0 -35
  77. package/adapters/claude/hooks/react.sh +0 -207
  78. package/adapters/claude/install/doctor.ts +0 -172
  79. package/adapters/claude/rendering/art.ts +0 -264
  80. package/adapters/claude/server/instructions.ts +0 -24
  81. package/adapters/claude/server/path.ts +0 -12
  82. package/adapters/claude/server/resources.ts +0 -38
  83. package/adapters/claude/statusline/buddy-status.sh +0 -408
  84. package/adapters/claude/storage/achievements.ts +0 -253
  85. package/adapters/claude/storage/identity.ts +0 -13
  86. package/adapters/claude/storage/paths.ts +0 -33
  87. package/adapters/claude/storage/settings.ts +0 -91
  88. package/adapters/claude/storage/state.ts +0 -365
  89. package/adapters/pi/README.md +0 -83
  90. package/adapters/pi/tools.ts +0 -6
  91. package/server/engine.ts +0 -1
  92. package/server/reactions.ts +0 -1
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env bash
2
+ # coding-buddy Stop hook — proactive suggestion detection
3
+ # Detects coding patterns and offers suggestions when relevant.
4
+ #
5
+ # Combined with buddy-comment.sh to avoid running two separate Stop hooks.
6
+
7
+ # shellcheck source=../scripts/paths.sh
8
+ source "$(dirname "${BASH_SOURCE[0]}")/../scripts/paths.sh"
9
+
10
+ STATE_DIR="$BUDDY_STATE_DIR"
11
+ CONFIG_FILE="$STATE_DIR/config.json"
12
+ LAST_SUGGESTION_FILE="$STATE_DIR/.last_suggestion"
13
+ SUGGESTIONS_FILE="$STATE_DIR/suggestions.json"
14
+
15
+ [ -f "$CONFIG_FILE" ] || exit 0
16
+
17
+ # Check if suggestions are enabled (default: true)
18
+ SUGGESTIONS_ENABLED="true"
19
+ if [ -f "$CONFIG_FILE" ]; then
20
+ _enabled=$(jq -r '.suggestionsEnabled // true' "$CONFIG_FILE" 2>/dev/null)
21
+ [ "$_enabled" = "false" ] && exit 0
22
+ fi
23
+
24
+ # Check cooldown (default: 180s = 3 min)
25
+ SUGGESTION_COOLDOWN=180
26
+ if [ -f "$CONFIG_FILE" ]; then
27
+ _cd=$(jq -r '.suggestionCooldown // 180' "$CONFIG_FILE" 2>/dev/null || echo 180)
28
+ [[ "$_cd" =~ ^[0-9]+$ ]] && SUGGESTION_COOLDOWN=$_cd
29
+ fi
30
+
31
+ if [ -f "$LAST_SUGGESTION_FILE" ]; then
32
+ LAST=$(cat "$LAST_SUGGESTION_FILE" 2>/dev/null)
33
+ NOW=$(date +%s)
34
+ DIFF=$(( NOW - ${LAST:-0} ))
35
+ [ "$DIFF" -lt "$SUGGESTION_COOLDOWN" ] && exit 0
36
+ fi
37
+
38
+ INPUT=$(cat)
39
+
40
+ # Extract messages
41
+ ASSISTANT_MSG=$(echo "$INPUT" | jq -r '.last_assistant_message // ""' 2>/dev/null)
42
+ [ -z "$ASSISTANT_MSG" ] && exit 0
43
+
44
+ # Record turn and check patterns
45
+ PLUGIN_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
46
+
47
+ # Check for patterns via the suggestions script
48
+ if [ -x "$(command -v bun)" ]; then
49
+ # Run the suggestion check (async, non-blocking)
50
+ bun run "$PLUGIN_ROOT/server/check-suggestions.ts" \
51
+ "$(echo "$ASSISTANT_MSG" | jq -Rs .)" \
52
+ >/dev/null 2>&1 &
53
+ fi
54
+
55
+ exit 0
package/package.json CHANGED
@@ -1,66 +1,77 @@
1
1
  {
2
2
  "name": "@ramarivera/coding-buddy",
3
- "version": "0.4.0-alpha.9",
4
- "description": "Persistent coding companion for Claude Code and pi",
3
+ "version": "0.6.0",
4
+ "description": "Persistent coding companion for Claude Code, Pi, and Oh My Pi",
5
5
  "type": "module",
6
+ "omp": {
7
+ "extensions": [
8
+ "./adapters/omp/index.ts"
9
+ ]
10
+ },
11
+ "pi": {
12
+ "extensions": [
13
+ "./adapters/pi/index.ts"
14
+ ]
15
+ },
6
16
  "bin": {
7
- "coding-buddy": "./cli/index.ts"
17
+ "coding-buddy": "cli/index.ts"
8
18
  },
9
19
  "scripts": {
10
- "server": "bun run adapters/claude/server/index.ts",
11
- "pick": "bun run adapters/claude/install/pick.ts",
12
- "hunt": "bun run adapters/claude/install/hunt.ts",
13
- "install-buddy": "bun run adapters/claude/install/install.ts",
14
- "show": "bun run adapters/claude/install/show.ts",
15
- "doctor": "bun run adapters/claude/install/doctor.ts",
16
- "test-statusline": "bun run adapters/claude/install/test-statusline.ts",
17
- "backup": "bun run adapters/claude/install/backup.ts",
18
- "settings": "bun run adapters/claude/install/settings.ts",
19
- "disable": "bun run adapters/claude/install/disable.ts",
20
- "enable": "bun run adapters/claude/install/install.ts",
20
+ "postinstall": "node scripts/postinstall.cjs",
21
+ "server": "bun run server/index.ts",
22
+ "pick": "bun run cli/pick.ts",
23
+ "hunt": "bun run cli/hunt.ts",
24
+ "install-buddy": "bun run cli/install.ts",
25
+ "show": "bun run cli/show.ts",
26
+ "doctor": "bun run cli/doctor.ts",
27
+ "test-statusline": "bun run cli/test-statusline.ts",
28
+ "backup": "bun run cli/backup.ts",
29
+ "settings": "bun run cli/settings.ts",
30
+ "disable": "bun run cli/disable.ts",
31
+ "enable": "bun run cli/install.ts",
21
32
  "upgrade": "bun run cli/upgrade.ts",
22
- "uninstall": "bun run adapters/claude/install/uninstall.ts",
33
+ "uninstall": "bun run cli/uninstall.ts",
23
34
  "help": "bun run cli/index.ts help",
24
35
  "buddy-shell": "npx tsx cli/buddy-shell.ts",
25
36
  "tui": "bun run cli/tui.tsx",
26
37
  "test": "bun test",
27
- "typecheck": "tsc --noEmit"
38
+ "typecheck": "tsc --noEmit",
39
+ "gen:emoji-widths": "bun run scripts/gen-emoji-widths.ts"
28
40
  },
29
41
  "files": [
30
42
  "core/",
31
43
  "adapters/",
44
+ "server/",
32
45
  "cli/",
46
+ "skills/",
47
+ "hooks/",
48
+ "statusline/",
33
49
  "scripts/",
34
- "server/",
50
+ ".claude-plugin/",
35
51
  "!**/*.test.ts"
36
52
  ],
37
53
  "keywords": [
54
+ "coding-buddy",
38
55
  "claude-code",
56
+ "pi",
57
+ "oh-my-pi",
58
+ "omp",
39
59
  "buddy",
40
60
  "companion",
41
61
  "mcp",
42
62
  "terminal-pet",
43
63
  "tamagotchi",
44
- "pi-package"
64
+ "pi-package",
65
+ "omp-extension"
45
66
  ],
46
67
  "repository": {
47
68
  "type": "git",
48
- "url": "git+https://github.com/ramarivera/claude-buddy.git"
69
+ "url": "git+https://github.com/1270011/claude-buddy.git"
49
70
  },
50
- "homepage": "https://github.com/ramarivera/claude-buddy#readme",
71
+ "homepage": "https://github.com/1270011/claude-buddy#readme",
51
72
  "license": "MIT",
52
- "publishConfig": {
53
- "access": "public",
54
- "registry": "https://registry.npmjs.org/"
55
- },
56
- "pi": {
57
- "extensions": [
58
- "./adapters/pi/index.ts"
59
- ]
60
- },
61
73
  "dependencies": {
62
74
  "@homebridge/node-pty-prebuilt-multiarch": "^0.13.1",
63
- "@mariozechner/pi-coding-agent": "0.66.1",
64
75
  "@modelcontextprotocol/sdk": "^1.12.1",
65
76
  "@xterm/addon-serialize": "^0.14.0",
66
77
  "@xterm/headless": "^6.0.0",
@@ -69,6 +80,11 @@
69
80
  "react": "^19.2.5"
70
81
  },
71
82
  "devDependencies": {
83
+ "@mariozechner/pi-coding-agent": "0.66.1",
84
+ "@oh-my-pi/pi-agent-core": "17.0.9",
85
+ "@oh-my-pi/pi-ai": "17.0.9",
86
+ "@oh-my-pi/pi-coding-agent": "17.0.9",
87
+ "@oh-my-pi/pi-catalog": "17.0.9",
72
88
  "@types/react": "^19.2.14",
73
89
  "bun-types": "^1.3.11",
74
90
  "tsx": "^4.21.0",
@@ -76,5 +92,28 @@
76
92
  },
77
93
  "trustedDependencies": [
78
94
  "@homebridge/node-pty-prebuilt-multiarch"
79
- ]
95
+ ],
96
+ "publishConfig": {
97
+ "access": "public"
98
+ },
99
+ "peerDependencies": {
100
+ "@mariozechner/pi-coding-agent": "0.66.1",
101
+ "@oh-my-pi/pi-agent-core": "17.0.9",
102
+ "@oh-my-pi/pi-ai": "17.0.9",
103
+ "@oh-my-pi/pi-coding-agent": "17.0.9"
104
+ },
105
+ "peerDependenciesMeta": {
106
+ "@mariozechner/pi-coding-agent": {
107
+ "optional": true
108
+ },
109
+ "@oh-my-pi/pi-agent-core": {
110
+ "optional": true
111
+ },
112
+ "@oh-my-pi/pi-ai": {
113
+ "optional": true
114
+ },
115
+ "@oh-my-pi/pi-coding-agent": {
116
+ "optional": true
117
+ }
118
+ }
80
119
  }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Generate statusline/emoji-widths.data from Unicode's Emoji_Presentation
3
+ * property. The bash statusline renderer loads this file because awk has no
4
+ * Unicode property escapes; server/art.ts uses the same regex directly.
5
+ *
6
+ * Regenerate: bun run gen:emoji-widths
7
+ *
8
+ * The emitted list holds decimal codepoints in U+2600-U+27BF that default to
9
+ * emoji rendering (2 cols). Everything outside that range is handled by
10
+ * simple range checks in the bash/TS code, so we only need to export the
11
+ * ambiguous Miscellaneous Symbols + Dingbats block.
12
+ */
13
+
14
+ import { writeFileSync } from "fs";
15
+ import { join } from "path";
16
+
17
+ const OUT = join(import.meta.dir, "..", "statusline", "emoji-widths.data");
18
+
19
+ const EMOJI_PRES_RE = /\p{Emoji_Presentation}/u;
20
+ const codepoints: number[] = [];
21
+ for (let cp = 0x2600; cp <= 0x27BF; cp++) {
22
+ if (EMOJI_PRES_RE.test(String.fromCodePoint(cp))) codepoints.push(cp);
23
+ }
24
+
25
+ const content = [
26
+ "# Auto-generated by scripts/gen-emoji-widths.ts — do not edit by hand.",
27
+ "# Decimal codepoints in U+2600-U+27BF with Unicode Emoji_Presentation=Yes.",
28
+ "# Regenerate with: bun run gen:emoji-widths",
29
+ codepoints.join(" "),
30
+ "",
31
+ ].join("\n");
32
+
33
+ writeFileSync(OUT, content);
34
+ console.log(`Wrote ${codepoints.length} codepoints to ${OUT}`);
package/scripts/paths.sh CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env bash
2
- # Path resolvers for claude-buddy shell scripts.
2
+ # Path resolvers for coding-buddy shell scripts.
3
3
  #
4
4
  # Must stay in sync with server/path.ts. Source this file early:
5
5
  # source "$(dirname "$0")/../scripts/paths.sh"
@@ -38,3 +38,19 @@ else
38
38
  fi
39
39
 
40
40
  export CLAUDE_CFG_DIR CLAUDE_SETTINGS_FILE CLAUDE_USER_CONFIG BUDDY_STATE_DIR
41
+
42
+ # Windows: Chocolatey installs a PowerShell shim for jq that doesn't work in
43
+ # Git Bash. If jq is not found on PATH, check the real Chocolatey binary path
44
+ # and common Windows locations, then prepend to PATH so all scripts find it.
45
+ if ! command -v jq >/dev/null 2>&1; then
46
+ for _jq_candidate in \
47
+ "/c/ProgramData/chocolatey/lib/jq/tools/jq.exe" \
48
+ "/c/tools/jq/jq.exe" \
49
+ "$HOME/bin/jq.exe" \
50
+ "/usr/local/bin/jq.exe"; do
51
+ if [ -x "$_jq_candidate" ]; then
52
+ export PATH="$(dirname "$_jq_candidate"):$PATH"
53
+ break
54
+ fi
55
+ done
56
+ fi
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Post-install check: warn if bun is unavailable.
4
+ * Installation must succeed for Node-only Pi/OMP consumers; Claude-only commands
5
+ * will diagnose bun at runtime.
6
+ */
7
+
8
+ const { spawn } = require("child_process");
9
+
10
+ function checkBun() {
11
+ return new Promise((resolve) => {
12
+ const proc = spawn("bun", ["--version"], { stdio: "pipe" });
13
+ let output = "";
14
+ proc.stdout.on("data", (data) => {
15
+ output += data.toString();
16
+ });
17
+ proc.on("close", (code) => {
18
+ if (code === 0) {
19
+ console.log(`✓ bun ${output.trim()} detected`);
20
+ resolve(true);
21
+ } else {
22
+ console.warn(
23
+ "Bun is required only for Claude-only commands; install it from https://bun.sh or run `npm install -g bun`."
24
+ );
25
+ resolve(false);
26
+ }
27
+ });
28
+ proc.on("error", () => {
29
+ console.warn(
30
+ "Bun is required only for Claude-only commands; install it from https://bun.sh or run `npm install -g bun`."
31
+ );
32
+ resolve(false);
33
+ });
34
+ });
35
+ }
36
+
37
+ checkBun().then((ok) => {
38
+ if (!ok) {
39
+ console.warn("Install completed, but bun is required to run Claude-only commands.");
40
+ }
41
+ process.exit(0);
42
+ });
@@ -0,0 +1,54 @@
1
+ #!/usr/bin/env bash
2
+ # Render the statusline for every species at every frame index. Used for
3
+ # visual review after changes to art pipeline (server render + bash cycler).
4
+ #
5
+ # Usage:
6
+ # ./scripts/snapshot-statusline.sh # print to stdout
7
+ # ./scripts/snapshot-statusline.sh out/fixtures # write one file per case
8
+ #
9
+ # Uses a temp BUDDY_STATE_DIR so it never touches the user's real state.
10
+ set -euo pipefail
11
+
12
+ ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
13
+ OUT_DIR="${1:-}"
14
+
15
+ TMP_STATE=$(mktemp -d)
16
+ trap 'rm -rf "$TMP_STATE"' EXIT
17
+ export CLAUDE_CONFIG_DIR="$TMP_STATE"
18
+ mkdir -p "$TMP_STATE/buddy-state"
19
+
20
+ SPECIES_LIST=(duck goose blob cat dragon octopus owl penguin turtle snail
21
+ ghost axolotl capybara cactus robot rabbit mushroom chonk)
22
+ HATS=(none crown propeller wizard)
23
+ # Ticks hit all 4 distinct frames: 0→F0, 4→F1, 8→blink, 11→F2.
24
+ TICKS=(0 4 8 11)
25
+
26
+ for species in "${SPECIES_LIST[@]}"; do
27
+ for hat in "${HATS[@]}"; do
28
+ # Generate status.json with pre-rendered frames via a small bun script.
29
+ bun -e "
30
+ import { writeStatusState } from '${ROOT}/server/state.ts';
31
+ writeStatusState({
32
+ bones: {
33
+ species: '${species}', eye: '\\u00b0', hat: '${hat}',
34
+ rarity: 'common', shiny: false,
35
+ stats: { DEBUGGING: 50, PATIENCE: 50, CHAOS: 50, WISDOM: 50, SNARK: 50 },
36
+ peak: 'DEBUGGING', dump: 'PATIENCE',
37
+ },
38
+ name: 'Test', personality: '', hatchedAt: 0, userId: 'x',
39
+ });
40
+ " > /dev/null
41
+
42
+ for tick in "${TICKS[@]}"; do
43
+ label="${species} hat=${hat} tick=${tick}"
44
+ body=$(BUDDY_FAKE_NOW="$tick" COLUMNS=80 \
45
+ "$ROOT/statusline/buddy-status.sh" < /dev/null)
46
+ if [ -n "$OUT_DIR" ]; then
47
+ mkdir -p "$OUT_DIR"
48
+ printf '%s\n' "$body" > "$OUT_DIR/${species}_${hat}_t${tick}.out"
49
+ else
50
+ printf '=== %s ===\n%s\n\n' "$label" "$body"
51
+ fi
52
+ done
53
+ done
54
+ done