@umang-boss/claudemon 1.4.0 → 1.5.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 (74) hide show
  1. package/bin/claudemon.js +11 -3
  2. package/cli/doctor.ts +52 -2
  3. package/cli/index.ts +26 -8
  4. package/cli/shared.ts +14 -9
  5. package/dist/award-xp.mjs +7395 -0
  6. package/dist/award-xp.mjs.map +7 -0
  7. package/dist/cli.mjs +7497 -0
  8. package/dist/cli.mjs.map +7 -0
  9. package/dist/increment-counter.mjs +6323 -0
  10. package/dist/increment-counter.mjs.map +7 -0
  11. package/dist/server.mjs +10176 -0
  12. package/dist/server.mjs.map +7 -0
  13. package/hooks/post-tool-use.sh +22 -13
  14. package/package.json +6 -4
  15. package/scripts/build.ts +64 -0
  16. package/skills/buddy/SKILL.md +1 -0
  17. package/src/engine/stats.ts +7 -6
  18. package/src/engine/types.ts +1 -0
  19. package/src/engine/version-check.ts +167 -0
  20. package/src/hooks/award-xp.ts +18 -0
  21. package/src/server/index.ts +14 -0
  22. package/src/server/instructions.ts +20 -10
  23. package/src/server/tools/display-helpers.ts +2 -2
  24. package/src/server/tools/settings.ts +51 -10
  25. package/src/server/tools/starter.ts +3 -5
  26. package/src/state/schemas.ts +1 -0
  27. package/src/state/state-manager.ts +67 -11
  28. package/statusline/buddy-status.sh +21 -2
  29. package/dist/cli/doctor.js +0 -280
  30. package/dist/cli/index.js +0 -40
  31. package/dist/cli/install.js +0 -198
  32. package/dist/cli/shared.js +0 -77
  33. package/dist/cli/uninstall.js +0 -120
  34. package/dist/cli/update.js +0 -265
  35. package/dist/src/engine/constants.js +0 -104
  36. package/dist/src/engine/encounter-pool.js +0 -48
  37. package/dist/src/engine/encounters.js +0 -282
  38. package/dist/src/engine/evolution-data.js +0 -454
  39. package/dist/src/engine/evolution.js +0 -238
  40. package/dist/src/engine/mood.js +0 -187
  41. package/dist/src/engine/pokemon-data.js +0 -1751
  42. package/dist/src/engine/reactions.js +0 -834
  43. package/dist/src/engine/starter-pool.js +0 -46
  44. package/dist/src/engine/stats.js +0 -79
  45. package/dist/src/engine/types.js +0 -78
  46. package/dist/src/engine/xp.js +0 -108
  47. package/dist/src/gamification/achievements.js +0 -176
  48. package/dist/src/gamification/legendary-quests.js +0 -233
  49. package/dist/src/gamification/milestones.js +0 -65
  50. package/dist/src/hooks/award-xp.js +0 -164
  51. package/dist/src/hooks/increment-counter.js +0 -20
  52. package/dist/src/server/index.js +0 -75
  53. package/dist/src/server/instructions.js +0 -178
  54. package/dist/src/server/tools/achievements.js +0 -96
  55. package/dist/src/server/tools/catch.js +0 -251
  56. package/dist/src/server/tools/display-helpers.js +0 -27
  57. package/dist/src/server/tools/evolve.js +0 -190
  58. package/dist/src/server/tools/feed.js +0 -120
  59. package/dist/src/server/tools/legendary.js +0 -57
  60. package/dist/src/server/tools/party.js +0 -205
  61. package/dist/src/server/tools/pet.js +0 -99
  62. package/dist/src/server/tools/play.js +0 -310
  63. package/dist/src/server/tools/pokedex.js +0 -234
  64. package/dist/src/server/tools/rename.js +0 -57
  65. package/dist/src/server/tools/settings.js +0 -80
  66. package/dist/src/server/tools/show.js +0 -115
  67. package/dist/src/server/tools/starter.js +0 -186
  68. package/dist/src/server/tools/stats.js +0 -96
  69. package/dist/src/server/tools/train.js +0 -144
  70. package/dist/src/server/tools/visibility.js +0 -52
  71. package/dist/src/sprites/index.js +0 -43
  72. package/dist/src/state/io.js +0 -78
  73. package/dist/src/state/schemas.js +0 -113
  74. package/dist/src/state/state-manager.js +0 -288
package/bin/claudemon.js CHANGED
@@ -12,17 +12,25 @@ import { fileURLToPath } from "node:url";
12
12
  const __dirname = dirname(fileURLToPath(import.meta.url));
13
13
  const args = process.argv.slice(2);
14
14
 
15
- // Try compiled JS first (dist/), then fall back to TS with bun
16
- const distCli = resolve(__dirname, "..", "dist", "cli", "index.js");
15
+ // Try bundled ESM first, then old tsc output, then fall back to TS with bun
16
+ const distCli = resolve(__dirname, "..", "dist", "cli.mjs");
17
+ const distCliLegacy = resolve(__dirname, "..", "dist", "cli", "index.js");
17
18
  const srcCli = resolve(__dirname, "..", "cli", "index.ts");
18
19
 
19
20
  if (existsSync(distCli)) {
20
- // Run compiled JS with node
21
+ // Run bundled ESM with node
21
22
  const result = spawnSync("node", [distCli, ...args], {
22
23
  stdio: "inherit",
23
24
  env: process.env,
24
25
  });
25
26
  process.exit(result.status ?? 1);
27
+ } else if (existsSync(distCliLegacy)) {
28
+ // Run legacy tsc-compiled JS with node
29
+ const result = spawnSync("node", [distCliLegacy, ...args], {
30
+ stdio: "inherit",
31
+ env: process.env,
32
+ });
33
+ process.exit(result.status ?? 1);
26
34
  } else {
27
35
  // Fallback: try bun with source TS
28
36
  const home = process.env.HOME || "";
package/cli/doctor.ts CHANGED
@@ -6,12 +6,13 @@
6
6
  */
7
7
 
8
8
  import { access, stat, unlink, readdir, readFile } from "node:fs/promises";
9
- import { constants as fsConstants } from "node:fs";
9
+ import { constants as fsConstants, existsSync } from "node:fs";
10
10
  import { resolve, dirname } from "node:path";
11
11
  import { fileURLToPath } from "node:url";
12
12
  import { spawnSync } from "node:child_process";
13
13
  import { StateManager } from "../src/state/state-manager.js";
14
14
  import { PlayerStateSchema } from "../src/state/schemas.js";
15
+ import { checkForUpdate, getCurrentVersion } from "../src/engine/version-check.js";
15
16
 
16
17
  import type { ClaudeConfig, ClaudeSettings } from "./shared.js";
17
18
  import {
@@ -32,7 +33,20 @@ const LOCK_MAX_AGE_MS = 5000;
32
33
  const EXPECTED_SPRITE_COUNT = 151;
33
34
  const __filename = fileURLToPath(import.meta.url);
34
35
  const __dirname = dirname(__filename);
35
- const COLORSCRIPT_DIR = resolve(dirname(__dirname), "sprites/colorscripts/small");
36
+ // Sprite dir: check multiple candidate paths (works from source, dist, and npm global)
37
+ function findColorscriptDir(): string | null {
38
+ const candidates = [
39
+ resolve(dirname(__dirname), "sprites", "colorscripts", "small"),
40
+ resolve(dirname(__dirname), "..", "sprites", "colorscripts", "small"),
41
+ resolve(__dirname, "..", "sprites", "colorscripts", "small"),
42
+ resolve(__dirname, "..", "..", "sprites", "colorscripts", "small"),
43
+ ];
44
+ for (const c of candidates) {
45
+ if (existsSync(c)) return c;
46
+ }
47
+ return null;
48
+ }
49
+ const COLORSCRIPT_DIR = findColorscriptDir();
36
50
 
37
51
  // ── Helpers ──────────────────────────────────────────────────
38
52
 
@@ -236,6 +250,9 @@ async function checkStaleLock(): Promise<CheckResult> {
236
250
 
237
251
  async function checkSpriteCount(): Promise<CheckResult> {
238
252
  try {
253
+ if (!COLORSCRIPT_DIR) {
254
+ return { label: "Sprites", passed: false, detail: "colorscripts directory not found" };
255
+ }
239
256
  await access(COLORSCRIPT_DIR, fsConstants.F_OK);
240
257
  const entries = await readdir(COLORSCRIPT_DIR);
241
258
  const spriteFiles = entries.filter((f) => f.endsWith(".txt"));
@@ -294,6 +311,38 @@ async function checkStateValidity(): Promise<CheckResult> {
294
311
  }
295
312
  }
296
313
 
314
+ // ── Check 12: Version ──────────────────────────────────────────
315
+
316
+ async function checkVersion(): Promise<CheckResult> {
317
+ const current = getCurrentVersion();
318
+ if (current === "unknown") {
319
+ return { label: "Version", passed: false, detail: "could not determine current version" };
320
+ }
321
+
322
+ try {
323
+ const result = await checkForUpdate();
324
+ if (!result) {
325
+ return {
326
+ label: "Version",
327
+ passed: true,
328
+ detail: `v${current} (could not reach npm registry)`,
329
+ };
330
+ }
331
+
332
+ if (result.hasUpdate) {
333
+ return {
334
+ label: "Version",
335
+ passed: false,
336
+ detail: `v${current} (v${result.latest} available — run: npm install -g @umang-boss/claudemon)`,
337
+ };
338
+ }
339
+
340
+ return { label: "Version", passed: true, detail: `v${current} (latest)` };
341
+ } catch {
342
+ return { label: "Version", passed: true, detail: `v${current} (check skipped)` };
343
+ }
344
+ }
345
+
297
346
  // ── Main ─────────────────────────────────────────────────────
298
347
 
299
348
  export async function doctor(): Promise<void> {
@@ -303,6 +352,7 @@ export async function doctor(): Promise<void> {
303
352
  console.log("");
304
353
 
305
354
  const checks: CheckResult[] = [
355
+ await checkVersion(),
306
356
  await checkBun(),
307
357
  await checkStateDir(),
308
358
  await checkStateFile(),
package/cli/index.ts CHANGED
@@ -1,19 +1,36 @@
1
1
  #!/usr/bin/env bun
2
2
  /**
3
3
  * Claudemon CLI entry point.
4
- * Routes to install, uninstall, update, or doctor based on first argument.
5
- *
6
- * Usage:
7
- * npx claudemon install
8
- * npx claudemon uninstall
9
- * npx claudemon update
10
- * npx claudemon doctor
4
+ * Routes to install, uninstall, update, doctor, or --version.
11
5
  */
12
6
 
7
+ import { readFileSync } from "node:fs";
8
+ import { resolve, dirname } from "node:path";
9
+ import { fileURLToPath } from "node:url";
10
+
13
11
  export {};
14
12
  const command = process.argv[2];
15
13
 
16
14
  switch (command) {
15
+ case "--version":
16
+ case "-v":
17
+ case "version": {
18
+ const __dirname = dirname(fileURLToPath(import.meta.url));
19
+ const pkgPaths = [
20
+ resolve(__dirname, "..", "package.json"),
21
+ resolve(__dirname, "..", "..", "package.json"),
22
+ ];
23
+ for (const p of pkgPaths) {
24
+ try {
25
+ const pkg = JSON.parse(readFileSync(p, "utf-8")) as { version: string };
26
+ console.log(`claudemon v${pkg.version}`);
27
+ break;
28
+ } catch {
29
+ continue;
30
+ }
31
+ }
32
+ break;
33
+ }
17
34
  case "install":
18
35
  await import("./install.js");
19
36
  break;
@@ -28,13 +45,14 @@ switch (command) {
28
45
  break;
29
46
  default:
30
47
  console.log(`
31
- Claudemon — Pokemon Gen 1 coding companion for Claude Code
48
+ Claudemon — Pokemon coding companion for Claude Code
32
49
 
33
50
  Usage:
34
51
  claudemon install Set up Claudemon (MCP server, hooks, skill, status line)
35
52
  claudemon uninstall Remove Claudemon from Claude Code
36
53
  claudemon update Re-register everything (preserves save data)
37
54
  claudemon doctor Run diagnostics
55
+ claudemon --version Show version
38
56
 
39
57
  After install, start a new Claude Code session and type /buddy
40
58
  `);
package/cli/shared.ts CHANGED
@@ -5,7 +5,8 @@
5
5
 
6
6
  import { resolve, dirname } from "node:path";
7
7
  import { fileURLToPath } from "node:url";
8
- import { existsSync } from "node:fs";
8
+ import { existsSync, constants as fsConstants } from "node:fs";
9
+ import { readFile, writeFile, access as fsAccess } from "node:fs/promises";
9
10
 
10
11
  // ── Config shape interfaces ──────────────────────────────────
11
12
 
@@ -73,11 +74,13 @@ export const STOP_HOOK_SCRIPT = `${PROJECT_DIR}/hooks/stop.sh`;
73
74
  export const USER_PROMPT_HOOK_SCRIPT = `${PROJECT_DIR}/hooks/user-prompt-submit.sh`;
74
75
  export const STATUSLINE_SCRIPT = `${PROJECT_DIR}/statusline/buddy-status.sh`;
75
76
  export const SERVER_ENTRY_TS = `${PROJECT_DIR}/src/server/index.ts`;
76
- export const SERVER_ENTRY_JS = `${PROJECT_DIR}/dist/src/server/index.js`;
77
+ export const SERVER_ENTRY_JS = `${PROJECT_DIR}/dist/server.mjs`;
78
+ /** Legacy tsc output path — kept for backward compatibility */
79
+ export const SERVER_ENTRY_JS_LEGACY = `${PROJECT_DIR}/dist/src/server/index.js`;
77
80
 
78
- /** Find the best runtime and server entry prefers bun (fast), falls back to node (compiled JS) */
81
+ /** Find the best runtime — Bun (fastest) > bundled node > legacy node */
79
82
  export function getRuntime(): { command: string; serverEntry: string } {
80
- // Check for bun (can run .ts directly)
83
+ // Prefer bun (fastest native TS, ~120ms startup)
81
84
  const bunCandidates = [`${HOME}/.bun/bin/bun`, "/usr/local/bin/bun", "/usr/bin/bun"];
82
85
  for (const p of bunCandidates) {
83
86
  if (existsSync(p)) {
@@ -85,11 +88,16 @@ export function getRuntime(): { command: string; serverEntry: string } {
85
88
  }
86
89
  }
87
90
 
88
- // Fall back to node (needs compiled .js from dist/)
91
+ // No bun use bundled ESM with node (~600ms but works everywhere)
89
92
  if (existsSync(SERVER_ENTRY_JS)) {
90
93
  return { command: "node", serverEntry: SERVER_ENTRY_JS };
91
94
  }
92
95
 
96
+ // Fall back to legacy tsc output
97
+ if (existsSync(SERVER_ENTRY_JS_LEGACY)) {
98
+ return { command: "node", serverEntry: SERVER_ENTRY_JS_LEGACY };
99
+ }
100
+
93
101
  // Last resort: assume bun in PATH
94
102
  return { command: "bun", serverEntry: SERVER_ENTRY_TS };
95
103
  }
@@ -109,10 +117,8 @@ export function info(msg: string): void {
109
117
  }
110
118
 
111
119
  export async function readJson<T>(path: string): Promise<T | null> {
112
- const { readFile, access } = await import("node:fs/promises");
113
- const { constants } = await import("node:fs");
114
120
  try {
115
- await access(path, constants.F_OK);
121
+ await fsAccess(path, fsConstants.F_OK);
116
122
  const text = await readFile(path, "utf-8");
117
123
  return JSON.parse(text) as T;
118
124
  } catch {
@@ -121,6 +127,5 @@ export async function readJson<T>(path: string): Promise<T | null> {
121
127
  }
122
128
 
123
129
  export async function writeJson(path: string, data: unknown): Promise<void> {
124
- const { writeFile } = await import("node:fs/promises");
125
130
  await writeFile(path, JSON.stringify(data, null, 2) + "\n", "utf-8");
126
131
  }