@umang-boss/claudemon 1.0.0 → 1.1.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.
- package/bin/claudemon.js +38 -28
- package/cli/doctor.ts +26 -18
- package/cli/install.ts +8 -8
- package/cli/shared.ts +32 -13
- package/cli/uninstall.ts +8 -6
- package/cli/update.ts +13 -14
- package/dist/cli/doctor.js +280 -0
- package/dist/cli/index.js +40 -0
- package/dist/cli/install.js +190 -0
- package/dist/cli/shared.js +72 -0
- package/dist/cli/uninstall.js +120 -0
- package/dist/cli/update.js +257 -0
- package/dist/src/engine/constants.js +98 -0
- package/dist/src/engine/encounter-pool.js +48 -0
- package/dist/src/engine/encounters.js +242 -0
- package/dist/src/engine/evolution-data.js +454 -0
- package/dist/src/engine/evolution.js +238 -0
- package/dist/src/engine/pokemon-data.js +1751 -0
- package/dist/src/engine/reactions.js +834 -0
- package/dist/src/engine/starter-pool.js +46 -0
- package/dist/src/engine/stats.js +79 -0
- package/dist/src/engine/types.js +76 -0
- package/dist/src/engine/xp.js +108 -0
- package/dist/src/gamification/achievements.js +176 -0
- package/dist/src/gamification/legendary-quests.js +233 -0
- package/dist/src/gamification/milestones.js +65 -0
- package/dist/src/hooks/award-xp.js +109 -0
- package/dist/src/hooks/increment-counter.js +20 -0
- package/dist/src/server/index.js +67 -0
- package/dist/src/server/instructions.js +155 -0
- package/dist/src/server/tools/achievements.js +97 -0
- package/dist/src/server/tools/catch.js +250 -0
- package/dist/src/server/tools/display-helpers.js +27 -0
- package/dist/src/server/tools/evolve.js +189 -0
- package/dist/src/server/tools/legendary.js +58 -0
- package/dist/src/server/tools/party.js +206 -0
- package/dist/src/server/tools/pet.js +101 -0
- package/dist/src/server/tools/pokedex.js +235 -0
- package/dist/src/server/tools/rename.js +49 -0
- package/dist/src/server/tools/show.js +111 -0
- package/dist/src/server/tools/starter.js +127 -0
- package/dist/src/server/tools/stats.js +98 -0
- package/dist/src/server/tools/visibility.js +52 -0
- package/dist/src/sprites/index.js +43 -0
- package/dist/src/state/io.js +78 -0
- package/dist/src/state/schemas.js +97 -0
- package/dist/src/state/state-manager.js +272 -0
- package/hooks/post-tool-use.sh +20 -6
- package/package.json +12 -11
- package/src/sprites/index.ts +5 -2
- package/src/state/io.ts +12 -23
- package/src/state/state-manager.ts +12 -3
- package/statusline/buddy-status.sh +14 -4
- package/{tsconfig.json → tsconfig.build.json} +9 -15
package/bin/claudemon.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* Claudemon CLI
|
|
4
|
-
*
|
|
3
|
+
* Claudemon CLI — works with Node.js (no Bun required for users).
|
|
4
|
+
* Routes to install/uninstall/update/doctor.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { spawnSync } from "node:child_process";
|
|
@@ -10,43 +10,53 @@ import { resolve, dirname } from "node:path";
|
|
|
10
10
|
import { fileURLToPath } from "node:url";
|
|
11
11
|
|
|
12
12
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
13
|
-
const cliEntry = resolve(__dirname, "..", "cli", "index.ts");
|
|
14
13
|
const args = process.argv.slice(2);
|
|
15
14
|
|
|
16
|
-
//
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
const candidates = [
|
|
20
|
-
`${home}/.bun/bin/bun`,
|
|
21
|
-
"/usr/local/bin/bun",
|
|
22
|
-
"/usr/bin/bun",
|
|
23
|
-
];
|
|
24
|
-
for (const p of candidates) {
|
|
25
|
-
if (existsSync(p)) return p;
|
|
26
|
-
}
|
|
27
|
-
// Try PATH
|
|
28
|
-
const result = spawnSync("which", ["bun"], { stdio: "pipe" });
|
|
29
|
-
if (result.status === 0) return "bun";
|
|
30
|
-
return null;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const bunPath = findBun();
|
|
15
|
+
// Try compiled JS first (dist/), then fall back to TS with bun
|
|
16
|
+
const distCli = resolve(__dirname, "..", "dist", "cli", "index.js");
|
|
17
|
+
const srcCli = resolve(__dirname, "..", "cli", "index.ts");
|
|
34
18
|
|
|
35
|
-
if (
|
|
36
|
-
|
|
19
|
+
if (existsSync(distCli)) {
|
|
20
|
+
// Run compiled JS with node
|
|
21
|
+
const result = spawnSync("node", [distCli, ...args], {
|
|
37
22
|
stdio: "inherit",
|
|
38
23
|
env: process.env,
|
|
39
24
|
});
|
|
40
25
|
process.exit(result.status ?? 1);
|
|
41
26
|
} else {
|
|
27
|
+
// Fallback: try bun with source TS
|
|
28
|
+
const home = process.env.HOME || "";
|
|
29
|
+
const bunPaths = [`${home}/.bun/bin/bun`, "/usr/local/bin/bun", "/usr/bin/bun"];
|
|
30
|
+
let bunPath = null;
|
|
31
|
+
|
|
32
|
+
for (const p of bunPaths) {
|
|
33
|
+
if (existsSync(p)) {
|
|
34
|
+
bunPath = p;
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (!bunPath) {
|
|
40
|
+
const which = spawnSync("which", ["bun"], { stdio: "pipe" });
|
|
41
|
+
if (which.status === 0) bunPath = "bun";
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (bunPath && existsSync(srcCli)) {
|
|
45
|
+
const result = spawnSync(bunPath, ["run", srcCli, ...args], {
|
|
46
|
+
stdio: "inherit",
|
|
47
|
+
env: process.env,
|
|
48
|
+
});
|
|
49
|
+
process.exit(result.status ?? 1);
|
|
50
|
+
}
|
|
51
|
+
|
|
42
52
|
console.error(`
|
|
43
|
-
|
|
53
|
+
Error: Could not find compiled files (dist/) or Bun runtime.
|
|
44
54
|
|
|
45
|
-
|
|
46
|
-
|
|
55
|
+
If you installed via npm, try reinstalling:
|
|
56
|
+
npm install -g @umang-boss/claudemon
|
|
47
57
|
|
|
48
|
-
|
|
49
|
-
|
|
58
|
+
Or install Bun and run from source:
|
|
59
|
+
curl -fsSL https://bun.sh/install | bash
|
|
50
60
|
`);
|
|
51
61
|
process.exit(1);
|
|
52
62
|
}
|
package/cli/doctor.ts
CHANGED
|
@@ -5,9 +5,11 @@
|
|
|
5
5
|
* Usage: bun run cli/doctor.ts
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import { access, stat, unlink, readdir } from "node:fs/promises";
|
|
8
|
+
import { access, stat, unlink, readdir, readFile } from "node:fs/promises";
|
|
9
9
|
import { constants as fsConstants } from "node:fs";
|
|
10
10
|
import { resolve, dirname } from "node:path";
|
|
11
|
+
import { fileURLToPath } from "node:url";
|
|
12
|
+
import { spawnSync } from "node:child_process";
|
|
11
13
|
import { StateManager } from "../src/state/state-manager.js";
|
|
12
14
|
import { PlayerStateSchema } from "../src/state/schemas.js";
|
|
13
15
|
|
|
@@ -28,7 +30,9 @@ const STATE_FILE = `${STATE_DIR}/state.json`;
|
|
|
28
30
|
const LOCK_FILE = `${STATE_DIR}/state.lock`;
|
|
29
31
|
const LOCK_MAX_AGE_MS = 5000;
|
|
30
32
|
const EXPECTED_SPRITE_COUNT = 151;
|
|
31
|
-
const
|
|
33
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
34
|
+
const __dirname = dirname(__filename);
|
|
35
|
+
const COLORSCRIPT_DIR = resolve(dirname(__dirname), "sprites/colorscripts/small");
|
|
32
36
|
|
|
33
37
|
// ── Helpers ──────────────────────────────────────────────────
|
|
34
38
|
|
|
@@ -47,10 +51,10 @@ function formatCheck(result: CheckResult): string {
|
|
|
47
51
|
|
|
48
52
|
async function checkBun(): Promise<CheckResult> {
|
|
49
53
|
try {
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
return { label: "Bun runtime", passed: true, detail: `v${output
|
|
54
|
+
const result = spawnSync("bun", ["--version"], { stdio: "pipe" });
|
|
55
|
+
if (result.error) throw result.error;
|
|
56
|
+
const output = result.stdout?.toString().trim();
|
|
57
|
+
return { label: "Bun runtime", passed: true, detail: `v${output}` };
|
|
54
58
|
} catch {
|
|
55
59
|
return { label: "Bun runtime", passed: false, detail: "not found" };
|
|
56
60
|
}
|
|
@@ -74,13 +78,14 @@ async function checkStateDir(): Promise<CheckResult> {
|
|
|
74
78
|
// ── Check 3: State File ──────────────────────────────────────
|
|
75
79
|
|
|
76
80
|
async function checkStateFile(): Promise<CheckResult> {
|
|
77
|
-
|
|
78
|
-
|
|
81
|
+
try {
|
|
82
|
+
await access(STATE_FILE, fsConstants.F_OK);
|
|
83
|
+
} catch {
|
|
79
84
|
return { label: "State file", passed: false, detail: "not found (run /buddy starter first)" };
|
|
80
85
|
}
|
|
81
86
|
|
|
82
87
|
try {
|
|
83
|
-
const text = await
|
|
88
|
+
const text = await readFile(STATE_FILE, "utf-8");
|
|
84
89
|
const data = JSON.parse(text) as Record<string, unknown>;
|
|
85
90
|
|
|
86
91
|
// Check for active pokemon
|
|
@@ -150,11 +155,12 @@ async function checkHooks(): Promise<CheckResult> {
|
|
|
150
155
|
// ── Check 6: Skill ───────────────────────────────────────────
|
|
151
156
|
|
|
152
157
|
async function checkSkill(): Promise<CheckResult> {
|
|
153
|
-
|
|
154
|
-
|
|
158
|
+
try {
|
|
159
|
+
await access(SKILL_DEST, fsConstants.F_OK);
|
|
155
160
|
return { label: "Skill", passed: true, detail: "/buddy command installed" };
|
|
161
|
+
} catch {
|
|
162
|
+
return { label: "Skill", passed: false, detail: "~/.claude/skills/buddy/SKILL.md not found" };
|
|
156
163
|
}
|
|
157
|
-
return { label: "Skill", passed: false, detail: "~/.claude/skills/buddy/SKILL.md not found" };
|
|
158
164
|
}
|
|
159
165
|
|
|
160
166
|
// ── Check 7: Hook Script Executable ──────────────────────────
|
|
@@ -164,15 +170,16 @@ async function checkHookScript(): Promise<CheckResult> {
|
|
|
164
170
|
await access(HOOK_SCRIPT, fsConstants.X_OK);
|
|
165
171
|
return { label: "Hook script", passed: true, detail: "executable" };
|
|
166
172
|
} catch {
|
|
167
|
-
|
|
168
|
-
|
|
173
|
+
try {
|
|
174
|
+
await access(HOOK_SCRIPT, fsConstants.F_OK);
|
|
169
175
|
return {
|
|
170
176
|
label: "Hook script",
|
|
171
177
|
passed: false,
|
|
172
178
|
detail: "exists but not executable (run chmod +x)",
|
|
173
179
|
};
|
|
180
|
+
} catch {
|
|
181
|
+
return { label: "Hook script", passed: false, detail: "not found" };
|
|
174
182
|
}
|
|
175
|
-
return { label: "Hook script", passed: false, detail: "not found" };
|
|
176
183
|
}
|
|
177
184
|
}
|
|
178
185
|
|
|
@@ -255,13 +262,14 @@ async function checkSpriteCount(): Promise<CheckResult> {
|
|
|
255
262
|
// ── Check 11: State File Validity (Zod) ─────────────────────
|
|
256
263
|
|
|
257
264
|
async function checkStateValidity(): Promise<CheckResult> {
|
|
258
|
-
|
|
259
|
-
|
|
265
|
+
try {
|
|
266
|
+
await access(STATE_FILE, fsConstants.F_OK);
|
|
267
|
+
} catch {
|
|
260
268
|
return { label: "State validity", passed: true, detail: "no state file yet" };
|
|
261
269
|
}
|
|
262
270
|
|
|
263
271
|
try {
|
|
264
|
-
const text = await
|
|
272
|
+
const text = await readFile(STATE_FILE, "utf-8");
|
|
265
273
|
if (!text.trim()) {
|
|
266
274
|
return { label: "State validity", passed: false, detail: "state file is empty" };
|
|
267
275
|
}
|
package/cli/install.ts
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
import { mkdir, copyFile, chmod, access } from "node:fs/promises";
|
|
9
9
|
import { constants as fsConstants } from "node:fs";
|
|
10
|
+
import { spawnSync } from "node:child_process";
|
|
10
11
|
|
|
11
12
|
import type { ClaudeConfig, ClaudeSettings, HookCommand, HookMatcher } from "./shared.js";
|
|
12
13
|
import {
|
|
@@ -25,8 +26,7 @@ import {
|
|
|
25
26
|
STOP_HOOK_SCRIPT,
|
|
26
27
|
USER_PROMPT_HOOK_SCRIPT,
|
|
27
28
|
STATUSLINE_SCRIPT,
|
|
28
|
-
|
|
29
|
-
getBunPath,
|
|
29
|
+
getRuntime,
|
|
30
30
|
} from "./shared.js";
|
|
31
31
|
|
|
32
32
|
// ── Step 1: Check Prerequisites ──────────────────────────────
|
|
@@ -36,10 +36,10 @@ async function checkPrerequisites(): Promise<boolean> {
|
|
|
36
36
|
|
|
37
37
|
// Check bun (sanity)
|
|
38
38
|
try {
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
ok(`Bun runtime: v${output
|
|
39
|
+
const result = spawnSync("bun", ["--version"], { stdio: "pipe" });
|
|
40
|
+
if (result.error) throw result.error;
|
|
41
|
+
const output = result.stdout?.toString().trim();
|
|
42
|
+
ok(`Bun runtime: v${output}`);
|
|
43
43
|
} catch {
|
|
44
44
|
fail("Bun runtime not found. Install from https://bun.sh");
|
|
45
45
|
allGood = false;
|
|
@@ -76,8 +76,8 @@ async function registerMcpServer(): Promise<void> {
|
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
config.mcpServers["claudemon"] = {
|
|
79
|
-
command:
|
|
80
|
-
args: [
|
|
79
|
+
command: getRuntime().command,
|
|
80
|
+
args: [getRuntime().serverEntry],
|
|
81
81
|
env: {},
|
|
82
82
|
};
|
|
83
83
|
|
package/cli/shared.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { resolve, dirname } from "node:path";
|
|
7
|
+
import { fileURLToPath } from "node:url";
|
|
7
8
|
|
|
8
9
|
// ── Config shape interfaces ──────────────────────────────────
|
|
9
10
|
|
|
@@ -50,7 +51,9 @@ if (!HOME) {
|
|
|
50
51
|
}
|
|
51
52
|
|
|
52
53
|
export const CLI_HOME = HOME;
|
|
53
|
-
|
|
54
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
55
|
+
const __dirname = dirname(__filename);
|
|
56
|
+
export const PROJECT_DIR = resolve(dirname(__dirname));
|
|
54
57
|
export const CLAUDE_DIR = `${HOME}/.claude`;
|
|
55
58
|
export const CLAUDE_CONFIG = `${HOME}/.claude.json`;
|
|
56
59
|
export const CLAUDE_SETTINGS = `${CLAUDE_DIR}/settings.json`;
|
|
@@ -62,16 +65,28 @@ export const HOOK_SCRIPT = `${PROJECT_DIR}/hooks/post-tool-use.sh`;
|
|
|
62
65
|
export const STOP_HOOK_SCRIPT = `${PROJECT_DIR}/hooks/stop.sh`;
|
|
63
66
|
export const USER_PROMPT_HOOK_SCRIPT = `${PROJECT_DIR}/hooks/user-prompt-submit.sh`;
|
|
64
67
|
export const STATUSLINE_SCRIPT = `${PROJECT_DIR}/statusline/buddy-status.sh`;
|
|
65
|
-
export const
|
|
68
|
+
export const SERVER_ENTRY_TS = `${PROJECT_DIR}/src/server/index.ts`;
|
|
69
|
+
export const SERVER_ENTRY_JS = `${PROJECT_DIR}/dist/src/server/index.js`;
|
|
66
70
|
|
|
67
|
-
/**
|
|
68
|
-
export function
|
|
71
|
+
/** Find the best runtime and server entry — prefers bun (fast), falls back to node (compiled JS) */
|
|
72
|
+
export function getRuntime(): { command: string; serverEntry: string } {
|
|
69
73
|
const { existsSync } = require("node:fs") as { existsSync: (p: string) => boolean };
|
|
70
|
-
|
|
71
|
-
for (
|
|
72
|
-
|
|
74
|
+
|
|
75
|
+
// Check for bun (can run .ts directly)
|
|
76
|
+
const bunCandidates = [`${HOME}/.bun/bin/bun`, "/usr/local/bin/bun", "/usr/bin/bun"];
|
|
77
|
+
for (const p of bunCandidates) {
|
|
78
|
+
if (existsSync(p)) {
|
|
79
|
+
return { command: p, serverEntry: SERVER_ENTRY_TS };
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Fall back to node (needs compiled .js from dist/)
|
|
84
|
+
if (existsSync(SERVER_ENTRY_JS)) {
|
|
85
|
+
return { command: "node", serverEntry: SERVER_ENTRY_JS };
|
|
73
86
|
}
|
|
74
|
-
|
|
87
|
+
|
|
88
|
+
// Last resort: assume bun in PATH
|
|
89
|
+
return { command: "bun", serverEntry: SERVER_ENTRY_TS };
|
|
75
90
|
}
|
|
76
91
|
|
|
77
92
|
// ── Helpers ──────────────────────────────────────────────────
|
|
@@ -89,14 +104,18 @@ export function info(msg: string): void {
|
|
|
89
104
|
}
|
|
90
105
|
|
|
91
106
|
export async function readJson<T>(path: string): Promise<T | null> {
|
|
92
|
-
const
|
|
93
|
-
|
|
107
|
+
const { readFile, access } = await import("node:fs/promises");
|
|
108
|
+
const { constants } = await import("node:fs");
|
|
109
|
+
try {
|
|
110
|
+
await access(path, constants.F_OK);
|
|
111
|
+
const text = await readFile(path, "utf-8");
|
|
112
|
+
return JSON.parse(text) as T;
|
|
113
|
+
} catch {
|
|
94
114
|
return null;
|
|
95
115
|
}
|
|
96
|
-
const text = await file.text();
|
|
97
|
-
return JSON.parse(text) as T;
|
|
98
116
|
}
|
|
99
117
|
|
|
100
118
|
export async function writeJson(path: string, data: unknown): Promise<void> {
|
|
101
|
-
|
|
119
|
+
const { writeFile } = await import("node:fs/promises");
|
|
120
|
+
await writeFile(path, JSON.stringify(data, null, 2) + "\n", "utf-8");
|
|
102
121
|
}
|
package/cli/uninstall.ts
CHANGED
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
* Usage: bun run cli/uninstall.ts
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import { rm } from "node:fs/promises";
|
|
8
|
+
import { rm, access } from "node:fs/promises";
|
|
9
|
+
import { constants as fsConstants } from "node:fs";
|
|
9
10
|
|
|
10
11
|
import type { ClaudeConfig, ClaudeSettings } from "./shared.js";
|
|
11
12
|
import {
|
|
@@ -106,8 +107,9 @@ async function removeHooks(): Promise<void> {
|
|
|
106
107
|
// ── Step 3: Remove Skill ─────────────────────────────────────
|
|
107
108
|
|
|
108
109
|
async function removeSkill(): Promise<void> {
|
|
109
|
-
|
|
110
|
-
|
|
110
|
+
try {
|
|
111
|
+
await access(`${SKILL_DEST_DIR}/SKILL.md`, fsConstants.F_OK);
|
|
112
|
+
} catch {
|
|
111
113
|
info("Skill: ~/.claude/skills/buddy/ not found (nothing to remove)");
|
|
112
114
|
return;
|
|
113
115
|
}
|
|
@@ -119,10 +121,10 @@ async function removeSkill(): Promise<void> {
|
|
|
119
121
|
// ── Step 4: Preserve State Data ──────────────────────────────
|
|
120
122
|
|
|
121
123
|
async function preserveStateData(): Promise<void> {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
+
try {
|
|
125
|
+
await access(`${STATE_DIR}/state.json`, fsConstants.F_OK);
|
|
124
126
|
info(`Your Pokemon data is preserved at ${STATE_DIR}/. Delete manually to remove.`);
|
|
125
|
-
}
|
|
127
|
+
} catch {
|
|
126
128
|
info(`State directory: ${STATE_DIR}/ (kept, no state file found)`);
|
|
127
129
|
}
|
|
128
130
|
}
|
package/cli/update.ts
CHANGED
|
@@ -10,9 +10,9 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import { mkdir, copyFile, chmod, access } from "node:fs/promises";
|
|
13
|
-
import { constants as fsConstants } from "node:fs";
|
|
13
|
+
import { constants as fsConstants, existsSync, readdirSync } from "node:fs";
|
|
14
14
|
import { join } from "node:path";
|
|
15
|
-
import {
|
|
15
|
+
import { spawnSync } from "node:child_process";
|
|
16
16
|
|
|
17
17
|
import type { ClaudeConfig, ClaudeSettings, HookCommand, HookMatcher } from "./shared.js";
|
|
18
18
|
import {
|
|
@@ -32,9 +32,8 @@ import {
|
|
|
32
32
|
STOP_HOOK_SCRIPT,
|
|
33
33
|
USER_PROMPT_HOOK_SCRIPT,
|
|
34
34
|
STATUSLINE_SCRIPT,
|
|
35
|
-
SERVER_ENTRY,
|
|
36
35
|
PROJECT_DIR,
|
|
37
|
-
|
|
36
|
+
getRuntime,
|
|
38
37
|
} from "./shared.js";
|
|
39
38
|
|
|
40
39
|
// ── Step 1: Check Prerequisites ──────────────────────────────
|
|
@@ -43,10 +42,10 @@ async function checkPrerequisites(): Promise<boolean> {
|
|
|
43
42
|
let allGood = true;
|
|
44
43
|
|
|
45
44
|
try {
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
ok(`Bun runtime: v${output
|
|
45
|
+
const result = spawnSync("bun", ["--version"], { stdio: "pipe" });
|
|
46
|
+
if (result.error) throw result.error;
|
|
47
|
+
const output = result.stdout?.toString().trim();
|
|
48
|
+
ok(`Bun runtime: v${output}`);
|
|
50
49
|
} catch {
|
|
51
50
|
fail("Bun runtime not found.");
|
|
52
51
|
allGood = false;
|
|
@@ -122,8 +121,8 @@ async function registerMcpServer(): Promise<void> {
|
|
|
122
121
|
}
|
|
123
122
|
|
|
124
123
|
config.mcpServers["claudemon"] = {
|
|
125
|
-
command:
|
|
126
|
-
args: [
|
|
124
|
+
command: getRuntime().command,
|
|
125
|
+
args: [getRuntime().serverEntry],
|
|
127
126
|
env: {},
|
|
128
127
|
};
|
|
129
128
|
|
|
@@ -240,7 +239,7 @@ async function checkColorscripts(): Promise<{ missing: number; total: number }>
|
|
|
240
239
|
}
|
|
241
240
|
|
|
242
241
|
// Check for files matching the pattern
|
|
243
|
-
const files =
|
|
242
|
+
const files = readdirSync(smallDir).filter((f) => f.startsWith(prefix) && f.endsWith(".txt"));
|
|
244
243
|
if (files.length === 0) {
|
|
245
244
|
missing++;
|
|
246
245
|
}
|
|
@@ -252,10 +251,10 @@ async function checkColorscripts(): Promise<{ missing: number; total: number }>
|
|
|
252
251
|
// ── Step 5: State Preservation Check ─────────────────────────
|
|
253
252
|
|
|
254
253
|
async function checkStatePreserved(): Promise<void> {
|
|
255
|
-
|
|
256
|
-
|
|
254
|
+
try {
|
|
255
|
+
await access(`${STATE_DIR}/state.json`, fsConstants.F_OK);
|
|
257
256
|
ok("State data: preserved (not modified)");
|
|
258
|
-
}
|
|
257
|
+
} catch {
|
|
259
258
|
info("State data: no save file found (run /buddy starter to begin)");
|
|
260
259
|
}
|
|
261
260
|
}
|