@umang-boss/claudemon 1.0.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/README.md +164 -0
- package/bin/claudemon.js +52 -0
- package/bunfig.toml +2 -0
- package/cli/doctor.ts +334 -0
- package/cli/index.ts +42 -0
- package/cli/install.ts +248 -0
- package/cli/shared.ts +102 -0
- package/cli/uninstall.ts +155 -0
- package/cli/update.ts +318 -0
- package/hooks/post-tool-use.sh +127 -0
- package/hooks/stop.sh +49 -0
- package/hooks/user-prompt-submit.sh +73 -0
- package/package.json +68 -0
- package/scripts/download-colorscripts.ts +311 -0
- package/skills/buddy/SKILL.md +47 -0
- package/sprites/colorscripts/small/1-bulbasaur.txt +11 -0
- package/sprites/colorscripts/small/10-caterpie.txt +9 -0
- package/sprites/colorscripts/small/100-voltorb.txt +8 -0
- package/sprites/colorscripts/small/101-electrode.txt +9 -0
- package/sprites/colorscripts/small/102-exeggcute.txt +10 -0
- package/sprites/colorscripts/small/103-exeggutor.txt +23 -0
- package/sprites/colorscripts/small/104-cubone.txt +11 -0
- package/sprites/colorscripts/small/105-marowak.txt +16 -0
- package/sprites/colorscripts/small/106-hitmonlee.txt +16 -0
- package/sprites/colorscripts/small/107-hitmonchan.txt +19 -0
- package/sprites/colorscripts/small/108-lickitung.txt +10 -0
- package/sprites/colorscripts/small/109-koffing.txt +14 -0
- package/sprites/colorscripts/small/11-metapod.txt +10 -0
- package/sprites/colorscripts/small/110-weezing.txt +23 -0
- package/sprites/colorscripts/small/111-rhyhorn.txt +11 -0
- package/sprites/colorscripts/small/112-rhydon.txt +20 -0
- package/sprites/colorscripts/small/113-chansey.txt +11 -0
- package/sprites/colorscripts/small/114-tangela.txt +10 -0
- package/sprites/colorscripts/small/115-kangaskhan.txt +18 -0
- package/sprites/colorscripts/small/116-horsea.txt +10 -0
- package/sprites/colorscripts/small/117-seadra.txt +11 -0
- package/sprites/colorscripts/small/118-goldeen.txt +11 -0
- package/sprites/colorscripts/small/119-seaking.txt +16 -0
- package/sprites/colorscripts/small/12-butterfree.txt +20 -0
- package/sprites/colorscripts/small/120-staryu.txt +10 -0
- package/sprites/colorscripts/small/121-starmie.txt +17 -0
- package/sprites/colorscripts/small/122-mr-mime.txt +18 -0
- package/sprites/colorscripts/small/123-scyther.txt +21 -0
- package/sprites/colorscripts/small/124-jynx.txt +18 -0
- package/sprites/colorscripts/small/125-electabuzz.txt +19 -0
- package/sprites/colorscripts/small/126-magmar.txt +19 -0
- package/sprites/colorscripts/small/127-pinsir.txt +19 -0
- package/sprites/colorscripts/small/128-tauros.txt +20 -0
- package/sprites/colorscripts/small/129-magikarp.txt +13 -0
- package/sprites/colorscripts/small/13-weedle.txt +10 -0
- package/sprites/colorscripts/small/130-gyarados.txt +21 -0
- package/sprites/colorscripts/small/131-lapras.txt +19 -0
- package/sprites/colorscripts/small/132-ditto.txt +8 -0
- package/sprites/colorscripts/small/133-eevee.txt +10 -0
- package/sprites/colorscripts/small/134-vaporeon.txt +16 -0
- package/sprites/colorscripts/small/135-jolteon.txt +17 -0
- package/sprites/colorscripts/small/136-flareon.txt +18 -0
- package/sprites/colorscripts/small/137-porygon.txt +10 -0
- package/sprites/colorscripts/small/138-omanyte.txt +10 -0
- package/sprites/colorscripts/small/139-omastar.txt +18 -0
- package/sprites/colorscripts/small/14-kakuna.txt +10 -0
- package/sprites/colorscripts/small/140-kabuto.txt +8 -0
- package/sprites/colorscripts/small/141-kabutops.txt +17 -0
- package/sprites/colorscripts/small/142-aerodactyl.txt +17 -0
- package/sprites/colorscripts/small/143-snorlax.txt +21 -0
- package/sprites/colorscripts/small/144-articuno.txt +24 -0
- package/sprites/colorscripts/small/145-zapdos.txt +20 -0
- package/sprites/colorscripts/small/146-moltres.txt +23 -0
- package/sprites/colorscripts/small/147-dratini.txt +10 -0
- package/sprites/colorscripts/small/148-dragonair.txt +12 -0
- package/sprites/colorscripts/small/149-dragonite.txt +21 -0
- package/sprites/colorscripts/small/15-beedrill.txt +13 -0
- package/sprites/colorscripts/small/150-mewtwo.txt +22 -0
- package/sprites/colorscripts/small/151-mew.txt +14 -0
- package/sprites/colorscripts/small/16-pidgey.txt +10 -0
- package/sprites/colorscripts/small/17-pidgeotto.txt +11 -0
- package/sprites/colorscripts/small/18-pidgeot.txt +18 -0
- package/sprites/colorscripts/small/19-rattata.txt +12 -0
- package/sprites/colorscripts/small/2-ivysaur.txt +11 -0
- package/sprites/colorscripts/small/20-raticate.txt +12 -0
- package/sprites/colorscripts/small/21-spearow.txt +9 -0
- package/sprites/colorscripts/small/22-fearow.txt +12 -0
- package/sprites/colorscripts/small/23-ekans.txt +12 -0
- package/sprites/colorscripts/small/24-arbok.txt +16 -0
- package/sprites/colorscripts/small/25-pikachu.txt +11 -0
- package/sprites/colorscripts/small/26-raichu.txt +19 -0
- package/sprites/colorscripts/small/27-sandshrew.txt +10 -0
- package/sprites/colorscripts/small/28-sandslash.txt +16 -0
- package/sprites/colorscripts/small/29-nidoran-f.txt +11 -0
- package/sprites/colorscripts/small/3-venusaur.txt +21 -0
- package/sprites/colorscripts/small/30-nidorina.txt +12 -0
- package/sprites/colorscripts/small/31-nidoqueen.txt +19 -0
- package/sprites/colorscripts/small/32-nidoran-m.txt +11 -0
- package/sprites/colorscripts/small/33-nidorino.txt +12 -0
- package/sprites/colorscripts/small/34-nidoking.txt +18 -0
- package/sprites/colorscripts/small/35-clefairy.txt +11 -0
- package/sprites/colorscripts/small/36-clefable.txt +17 -0
- package/sprites/colorscripts/small/37-vulpix.txt +11 -0
- package/sprites/colorscripts/small/38-ninetales.txt +18 -0
- package/sprites/colorscripts/small/39-jigglypuff.txt +11 -0
- package/sprites/colorscripts/small/4-charmander.txt +11 -0
- package/sprites/colorscripts/small/40-wigglytuff.txt +20 -0
- package/sprites/colorscripts/small/41-zubat.txt +11 -0
- package/sprites/colorscripts/small/42-golbat.txt +18 -0
- package/sprites/colorscripts/small/43-oddish.txt +11 -0
- package/sprites/colorscripts/small/44-gloom.txt +12 -0
- package/sprites/colorscripts/small/45-vileplume.txt +17 -0
- package/sprites/colorscripts/small/46-paras.txt +11 -0
- package/sprites/colorscripts/small/47-parasect.txt +12 -0
- package/sprites/colorscripts/small/48-venonat.txt +14 -0
- package/sprites/colorscripts/small/49-venomoth.txt +19 -0
- package/sprites/colorscripts/small/5-charmeleon.txt +13 -0
- package/sprites/colorscripts/small/50-diglett.txt +8 -0
- package/sprites/colorscripts/small/51-dugtrio.txt +18 -0
- package/sprites/colorscripts/small/52-meowth.txt +12 -0
- package/sprites/colorscripts/small/53-persian.txt +20 -0
- package/sprites/colorscripts/small/54-psyduck.txt +12 -0
- package/sprites/colorscripts/small/55-golduck.txt +17 -0
- package/sprites/colorscripts/small/56-mankey.txt +11 -0
- package/sprites/colorscripts/small/57-primeape.txt +13 -0
- package/sprites/colorscripts/small/58-growlithe.txt +12 -0
- package/sprites/colorscripts/small/59-arcanine.txt +20 -0
- package/sprites/colorscripts/small/6-charizard.txt +21 -0
- package/sprites/colorscripts/small/60-poliwag.txt +9 -0
- package/sprites/colorscripts/small/61-poliwhirl.txt +11 -0
- package/sprites/colorscripts/small/62-poliwrath.txt +17 -0
- package/sprites/colorscripts/small/63-abra.txt +12 -0
- package/sprites/colorscripts/small/64-kadabra.txt +14 -0
- package/sprites/colorscripts/small/65-alakazam.txt +19 -0
- package/sprites/colorscripts/small/66-machop.txt +11 -0
- package/sprites/colorscripts/small/67-machoke.txt +12 -0
- package/sprites/colorscripts/small/68-machamp.txt +19 -0
- package/sprites/colorscripts/small/69-bellsprout.txt +9 -0
- package/sprites/colorscripts/small/7-squirtle.txt +10 -0
- package/sprites/colorscripts/small/70-weepinbell.txt +11 -0
- package/sprites/colorscripts/small/71-victreebel.txt +17 -0
- package/sprites/colorscripts/small/72-tentacool.txt +12 -0
- package/sprites/colorscripts/small/73-tentacruel.txt +20 -0
- package/sprites/colorscripts/small/74-geodude.txt +9 -0
- package/sprites/colorscripts/small/75-graveler.txt +12 -0
- package/sprites/colorscripts/small/76-golem.txt +18 -0
- package/sprites/colorscripts/small/77-ponyta.txt +13 -0
- package/sprites/colorscripts/small/78-rapidash.txt +18 -0
- package/sprites/colorscripts/small/79-slowpoke.txt +12 -0
- package/sprites/colorscripts/small/8-wartortle.txt +12 -0
- package/sprites/colorscripts/small/80-slowbro.txt +18 -0
- package/sprites/colorscripts/small/81-magnemite.txt +9 -0
- package/sprites/colorscripts/small/82-magneton.txt +18 -0
- package/sprites/colorscripts/small/83-farfetchd.txt +12 -0
- package/sprites/colorscripts/small/84-doduo.txt +10 -0
- package/sprites/colorscripts/small/85-dodrio.txt +17 -0
- package/sprites/colorscripts/small/86-seel.txt +13 -0
- package/sprites/colorscripts/small/87-dewgong.txt +20 -0
- package/sprites/colorscripts/small/88-grimer.txt +10 -0
- package/sprites/colorscripts/small/89-muk.txt +14 -0
- package/sprites/colorscripts/small/9-blastoise.txt +20 -0
- package/sprites/colorscripts/small/90-shellder.txt +10 -0
- package/sprites/colorscripts/small/91-cloyster.txt +18 -0
- package/sprites/colorscripts/small/92-gastly.txt +12 -0
- package/sprites/colorscripts/small/93-haunter.txt +14 -0
- package/sprites/colorscripts/small/94-gengar.txt +19 -0
- package/sprites/colorscripts/small/95-onix.txt +22 -0
- package/sprites/colorscripts/small/96-drowzee.txt +12 -0
- package/sprites/colorscripts/small/97-hypno.txt +19 -0
- package/sprites/colorscripts/small/98-krabby.txt +12 -0
- package/sprites/colorscripts/small/99-kingler.txt +20 -0
- package/src/engine/constants.ts +121 -0
- package/src/engine/encounter-pool.ts +71 -0
- package/src/engine/encounters.ts +308 -0
- package/src/engine/evolution-data.ts +535 -0
- package/src/engine/evolution.ts +310 -0
- package/src/engine/pokemon-data.ts +1838 -0
- package/src/engine/reactions.ts +877 -0
- package/src/engine/starter-pool.ts +47 -0
- package/src/engine/stats.ts +97 -0
- package/src/engine/types.ts +312 -0
- package/src/engine/xp.ts +135 -0
- package/src/gamification/achievements.ts +204 -0
- package/src/gamification/legendary-quests.ts +265 -0
- package/src/gamification/milestones.ts +86 -0
- package/src/hooks/award-xp.ts +131 -0
- package/src/hooks/increment-counter.ts +27 -0
- package/src/server/index.ts +78 -0
- package/src/server/instructions.ts +194 -0
- package/src/server/tools/achievements.ts +118 -0
- package/src/server/tools/catch.ts +295 -0
- package/src/server/tools/display-helpers.ts +35 -0
- package/src/server/tools/evolve.ts +236 -0
- package/src/server/tools/legendary.ts +78 -0
- package/src/server/tools/party.ts +251 -0
- package/src/server/tools/pet.ts +124 -0
- package/src/server/tools/pokedex.ts +286 -0
- package/src/server/tools/rename.ts +63 -0
- package/src/server/tools/show.ts +136 -0
- package/src/server/tools/starter.ts +175 -0
- package/src/server/tools/stats.ts +123 -0
- package/src/server/tools/visibility.ts +65 -0
- package/src/sprites/index.ts +45 -0
- package/src/state/io.ts +91 -0
- package/src/state/schemas.ts +131 -0
- package/src/state/state-manager.ts +321 -0
- package/statusline/buddy-status.sh +233 -0
- package/tsconfig.json +37 -0
package/cli/update.ts
ADDED
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claudemon CLI Updater.
|
|
3
|
+
* Re-registers MCP server, hooks, skill, and status line without
|
|
4
|
+
* touching the user's saved state/Pokemon data.
|
|
5
|
+
*
|
|
6
|
+
* Effectively: uninstall registrations + reinstall registrations.
|
|
7
|
+
* State directory (~/.claudemon/) is preserved completely.
|
|
8
|
+
*
|
|
9
|
+
* Usage: bun run cli/update.ts
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { mkdir, copyFile, chmod, access } from "node:fs/promises";
|
|
13
|
+
import { constants as fsConstants } from "node:fs";
|
|
14
|
+
import { join } from "node:path";
|
|
15
|
+
import { existsSync } from "node:fs";
|
|
16
|
+
|
|
17
|
+
import type { ClaudeConfig, ClaudeSettings, HookCommand, HookMatcher } from "./shared.js";
|
|
18
|
+
import {
|
|
19
|
+
ok,
|
|
20
|
+
fail,
|
|
21
|
+
info,
|
|
22
|
+
readJson,
|
|
23
|
+
writeJson,
|
|
24
|
+
CLAUDE_DIR,
|
|
25
|
+
CLAUDE_CONFIG,
|
|
26
|
+
CLAUDE_SETTINGS,
|
|
27
|
+
STATE_DIR,
|
|
28
|
+
SKILL_SRC,
|
|
29
|
+
SKILL_DEST_DIR,
|
|
30
|
+
SKILL_DEST,
|
|
31
|
+
HOOK_SCRIPT,
|
|
32
|
+
STOP_HOOK_SCRIPT,
|
|
33
|
+
USER_PROMPT_HOOK_SCRIPT,
|
|
34
|
+
STATUSLINE_SCRIPT,
|
|
35
|
+
SERVER_ENTRY,
|
|
36
|
+
PROJECT_DIR,
|
|
37
|
+
getBunPath,
|
|
38
|
+
} from "./shared.js";
|
|
39
|
+
|
|
40
|
+
// ── Step 1: Check Prerequisites ──────────────────────────────
|
|
41
|
+
|
|
42
|
+
async function checkPrerequisites(): Promise<boolean> {
|
|
43
|
+
let allGood = true;
|
|
44
|
+
|
|
45
|
+
try {
|
|
46
|
+
const proc = Bun.spawn(["bun", "--version"], { stdout: "pipe", stderr: "pipe" });
|
|
47
|
+
const output = await new Response(proc.stdout).text();
|
|
48
|
+
await proc.exited;
|
|
49
|
+
ok(`Bun runtime: v${output.trim()}`);
|
|
50
|
+
} catch {
|
|
51
|
+
fail("Bun runtime not found.");
|
|
52
|
+
allGood = false;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
try {
|
|
56
|
+
await access(CLAUDE_DIR, fsConstants.F_OK);
|
|
57
|
+
ok("Claude Code directory: ~/.claude/");
|
|
58
|
+
} catch {
|
|
59
|
+
fail("Claude Code not found at ~/.claude/");
|
|
60
|
+
allGood = false;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return allGood;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// ── Step 2: Remove Old Registrations ─────────────────────────
|
|
67
|
+
|
|
68
|
+
async function removeOldMcpServer(): Promise<void> {
|
|
69
|
+
const config = await readJson<ClaudeConfig>(CLAUDE_CONFIG);
|
|
70
|
+
if (!config?.mcpServers?.["claudemon"]) {
|
|
71
|
+
info("MCP server: not previously registered");
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
delete config.mcpServers["claudemon"];
|
|
75
|
+
if (Object.keys(config.mcpServers).length === 0) {
|
|
76
|
+
delete config.mcpServers;
|
|
77
|
+
}
|
|
78
|
+
await writeJson(CLAUDE_CONFIG, config);
|
|
79
|
+
ok("MCP server: removed old registration");
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
async function removeOldHooks(): Promise<void> {
|
|
83
|
+
const settings = await readJson<ClaudeSettings>(CLAUDE_SETTINGS);
|
|
84
|
+
if (!settings?.hooks) {
|
|
85
|
+
info("Hooks: none found");
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const hookTypes = ["PostToolUse", "Stop", "UserPromptSubmit"] as const;
|
|
90
|
+
const patterns = ["post-tool-use.sh", "stop.sh", "user-prompt-submit.sh"] as const;
|
|
91
|
+
|
|
92
|
+
for (let i = 0; i < hookTypes.length; i++) {
|
|
93
|
+
const hookType = hookTypes[i]!;
|
|
94
|
+
const pattern = patterns[i]!;
|
|
95
|
+
const entries = settings.hooks[hookType];
|
|
96
|
+
if (entries) {
|
|
97
|
+
const filtered = entries.filter((m) => !m.hooks.some((h) => h.command.includes(pattern)));
|
|
98
|
+
if (filtered.length === 0) {
|
|
99
|
+
delete settings.hooks[hookType];
|
|
100
|
+
} else {
|
|
101
|
+
settings.hooks[hookType] = filtered;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (Object.keys(settings.hooks).length === 0) {
|
|
107
|
+
delete settings.hooks;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
await writeJson(CLAUDE_SETTINGS, settings);
|
|
111
|
+
ok("Hooks: removed old registrations");
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// ── Step 3: Re-register Everything ───────────────────────────
|
|
115
|
+
|
|
116
|
+
async function registerMcpServer(): Promise<void> {
|
|
117
|
+
const existing = await readJson<ClaudeConfig>(CLAUDE_CONFIG);
|
|
118
|
+
const config: ClaudeConfig = existing ?? {};
|
|
119
|
+
|
|
120
|
+
if (!config.mcpServers) {
|
|
121
|
+
config.mcpServers = {};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
config.mcpServers["claudemon"] = {
|
|
125
|
+
command: getBunPath(),
|
|
126
|
+
args: ["run", SERVER_ENTRY],
|
|
127
|
+
env: {},
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
await writeJson(CLAUDE_CONFIG, config);
|
|
131
|
+
ok("MCP server: registered in ~/.claude.json");
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
async function installHooks(): Promise<void> {
|
|
135
|
+
const existing = await readJson<ClaudeSettings>(CLAUDE_SETTINGS);
|
|
136
|
+
const settings: ClaudeSettings = existing ?? {};
|
|
137
|
+
|
|
138
|
+
if (!settings.hooks) {
|
|
139
|
+
settings.hooks = {};
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// PostToolUse hook
|
|
143
|
+
const ourHook: HookCommand = {
|
|
144
|
+
type: "command",
|
|
145
|
+
command: HOOK_SCRIPT,
|
|
146
|
+
timeout: 5000,
|
|
147
|
+
};
|
|
148
|
+
const ourMatcher: HookMatcher = {
|
|
149
|
+
matcher: "Bash|Write|Edit|Read|Grep|Glob",
|
|
150
|
+
hooks: [ourHook],
|
|
151
|
+
};
|
|
152
|
+
const postToolUse = settings.hooks["PostToolUse"];
|
|
153
|
+
if (postToolUse) {
|
|
154
|
+
const filtered = postToolUse.filter(
|
|
155
|
+
(m) => !m.hooks.some((h) => h.command.includes("post-tool-use.sh")),
|
|
156
|
+
);
|
|
157
|
+
filtered.push(ourMatcher);
|
|
158
|
+
settings.hooks["PostToolUse"] = filtered;
|
|
159
|
+
} else {
|
|
160
|
+
settings.hooks["PostToolUse"] = [ourMatcher];
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Stop hook
|
|
164
|
+
const stopHook: HookCommand = { type: "command", command: STOP_HOOK_SCRIPT, timeout: 3000 };
|
|
165
|
+
const stopEntry: HookMatcher = { hooks: [stopHook] };
|
|
166
|
+
const stopHooks = settings.hooks["Stop"];
|
|
167
|
+
if (stopHooks) {
|
|
168
|
+
const filtered = stopHooks.filter((m) => !m.hooks.some((h) => h.command.includes("stop.sh")));
|
|
169
|
+
filtered.push(stopEntry);
|
|
170
|
+
settings.hooks["Stop"] = filtered;
|
|
171
|
+
} else {
|
|
172
|
+
settings.hooks["Stop"] = [stopEntry];
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// UserPromptSubmit hook
|
|
176
|
+
const userPromptHook: HookCommand = {
|
|
177
|
+
type: "command",
|
|
178
|
+
command: USER_PROMPT_HOOK_SCRIPT,
|
|
179
|
+
timeout: 3000,
|
|
180
|
+
};
|
|
181
|
+
const userPromptEntry: HookMatcher = { hooks: [userPromptHook] };
|
|
182
|
+
const userPromptHooks = settings.hooks["UserPromptSubmit"];
|
|
183
|
+
if (userPromptHooks) {
|
|
184
|
+
const filtered = userPromptHooks.filter(
|
|
185
|
+
(m) => !m.hooks.some((h) => h.command.includes("user-prompt-submit.sh")),
|
|
186
|
+
);
|
|
187
|
+
filtered.push(userPromptEntry);
|
|
188
|
+
settings.hooks["UserPromptSubmit"] = filtered;
|
|
189
|
+
} else {
|
|
190
|
+
settings.hooks["UserPromptSubmit"] = [userPromptEntry];
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
await writeJson(CLAUDE_SETTINGS, settings);
|
|
194
|
+
ok("Hooks: PostToolUse, Stop, UserPromptSubmit configured");
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
async function registerStatusLine(): Promise<void> {
|
|
198
|
+
const existing = await readJson<ClaudeSettings>(CLAUDE_SETTINGS);
|
|
199
|
+
const settings: ClaudeSettings = existing ?? {};
|
|
200
|
+
|
|
201
|
+
settings.statusLine = {
|
|
202
|
+
type: "command",
|
|
203
|
+
command: STATUSLINE_SCRIPT,
|
|
204
|
+
refreshInterval: 1,
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
await writeJson(CLAUDE_SETTINGS, settings);
|
|
208
|
+
ok("Status line: registered");
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
async function installSkill(): Promise<void> {
|
|
212
|
+
await mkdir(SKILL_DEST_DIR, { recursive: true });
|
|
213
|
+
await copyFile(SKILL_SRC, SKILL_DEST);
|
|
214
|
+
ok("Skill: /buddy command updated");
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
async function setScriptPermissions(): Promise<void> {
|
|
218
|
+
await chmod(HOOK_SCRIPT, 0o755);
|
|
219
|
+
await chmod(STOP_HOOK_SCRIPT, 0o755);
|
|
220
|
+
await chmod(USER_PROMPT_HOOK_SCRIPT, 0o755);
|
|
221
|
+
await chmod(STATUSLINE_SCRIPT, 0o755);
|
|
222
|
+
ok("Scripts: set executable");
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// ── Step 4: Check for Missing Colorscripts ───────────────────
|
|
226
|
+
|
|
227
|
+
async function checkColorscripts(): Promise<{ missing: number; total: number }> {
|
|
228
|
+
const smallDir = join(PROJECT_DIR, "sprites", "colorscripts", "small");
|
|
229
|
+
let missing = 0;
|
|
230
|
+
const total = 151;
|
|
231
|
+
|
|
232
|
+
for (let id = 1; id <= total; id++) {
|
|
233
|
+
// We don't know the name mapping without importing the data module,
|
|
234
|
+
// so check if any file starting with the ID exists
|
|
235
|
+
const prefix = `${id}-`;
|
|
236
|
+
const dirExists = existsSync(smallDir);
|
|
237
|
+
if (!dirExists) {
|
|
238
|
+
missing = total;
|
|
239
|
+
break;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// Check for files matching the pattern
|
|
243
|
+
const files = await Array.fromAsync(new Bun.Glob(`${prefix}*.txt`).scan(smallDir));
|
|
244
|
+
if (files.length === 0) {
|
|
245
|
+
missing++;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
return { missing, total };
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// ── Step 5: State Preservation Check ─────────────────────────
|
|
253
|
+
|
|
254
|
+
async function checkStatePreserved(): Promise<void> {
|
|
255
|
+
const stateFile = Bun.file(`${STATE_DIR}/state.json`);
|
|
256
|
+
if (await stateFile.exists()) {
|
|
257
|
+
ok("State data: preserved (not modified)");
|
|
258
|
+
} else {
|
|
259
|
+
info("State data: no save file found (run /buddy starter to begin)");
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// ── Main ─────────────────────────────────────────────────────
|
|
264
|
+
|
|
265
|
+
export async function update(): Promise<void> {
|
|
266
|
+
console.log("");
|
|
267
|
+
console.log("Claudemon Updater");
|
|
268
|
+
console.log("=================");
|
|
269
|
+
console.log("");
|
|
270
|
+
console.log("Checking prerequisites...");
|
|
271
|
+
|
|
272
|
+
const prereqOk = await checkPrerequisites();
|
|
273
|
+
if (!prereqOk) {
|
|
274
|
+
console.log("");
|
|
275
|
+
fail("Prerequisites not met. Fix the issues above and try again.");
|
|
276
|
+
process.exit(1);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
console.log("");
|
|
280
|
+
console.log("Removing old registrations...");
|
|
281
|
+
await removeOldMcpServer();
|
|
282
|
+
await removeOldHooks();
|
|
283
|
+
|
|
284
|
+
console.log("");
|
|
285
|
+
console.log("Re-registering...");
|
|
286
|
+
await registerMcpServer();
|
|
287
|
+
await installHooks();
|
|
288
|
+
await registerStatusLine();
|
|
289
|
+
await installSkill();
|
|
290
|
+
await setScriptPermissions();
|
|
291
|
+
|
|
292
|
+
console.log("");
|
|
293
|
+
console.log("Checking sprites...");
|
|
294
|
+
const { missing, total } = await checkColorscripts();
|
|
295
|
+
if (missing === 0) {
|
|
296
|
+
ok(`Colorscripts: all ${total} sprites present`);
|
|
297
|
+
} else if (missing === total) {
|
|
298
|
+
fail(`Colorscripts: sprite directory not found. Run: bun run download-sprites`);
|
|
299
|
+
} else {
|
|
300
|
+
info(`Colorscripts: ${missing}/${total} missing. Run: bun run download-sprites`);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
console.log("");
|
|
304
|
+
await checkStatePreserved();
|
|
305
|
+
|
|
306
|
+
console.log("");
|
|
307
|
+
console.log("\u2713 Claudemon updated successfully!");
|
|
308
|
+
console.log("");
|
|
309
|
+
console.log("Start a new Claude Code session to use the updated version.");
|
|
310
|
+
console.log("");
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// Run if executed directly
|
|
314
|
+
update().catch((err: unknown) => {
|
|
315
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
316
|
+
console.error(`\nUpdate failed: ${message}`);
|
|
317
|
+
process.exit(1);
|
|
318
|
+
});
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# chmod +x hooks/post-tool-use.sh
|
|
3
|
+
#
|
|
4
|
+
# PostToolUse hook for Claudemon — the XP pipeline.
|
|
5
|
+
# Reads JSON from stdin, pattern-matches coding events, delegates XP math to bun.
|
|
6
|
+
# MUST exit 0 always — hooks must never block Claude Code.
|
|
7
|
+
|
|
8
|
+
# Defensive: do NOT use set -e. We never want to crash.
|
|
9
|
+
# Wrap everything so any unexpected error is swallowed.
|
|
10
|
+
_claudemon_post_tool_use() {
|
|
11
|
+
# ── Locate dependencies ────────────────────────────────────
|
|
12
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
13
|
+
BUN_PATH="${HOME}/.bun/bin/bun"
|
|
14
|
+
|
|
15
|
+
# Bail silently if bun is not installed
|
|
16
|
+
if [ ! -x "$BUN_PATH" ]; then
|
|
17
|
+
return 0
|
|
18
|
+
fi
|
|
19
|
+
|
|
20
|
+
# Bail silently if jq is not available
|
|
21
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
22
|
+
return 0
|
|
23
|
+
fi
|
|
24
|
+
|
|
25
|
+
# ── Read stdin ─────────────────────────────────────────────
|
|
26
|
+
INPUT=$(cat)
|
|
27
|
+
if [ -z "$INPUT" ]; then
|
|
28
|
+
return 0
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // empty')
|
|
32
|
+
if [ -z "$TOOL_NAME" ]; then
|
|
33
|
+
return 0
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
TOOL_INPUT=$(echo "$INPUT" | jq -r '.tool_input // empty')
|
|
37
|
+
TOOL_RESPONSE=$(echo "$INPUT" | jq -r '.tool_response // empty')
|
|
38
|
+
|
|
39
|
+
# ── Pattern match coding events ────────────────────────────
|
|
40
|
+
EVENT=""
|
|
41
|
+
COUNTER=""
|
|
42
|
+
|
|
43
|
+
if [ "$TOOL_NAME" = "Bash" ]; then
|
|
44
|
+
STDOUT=$(echo "$TOOL_RESPONSE" | jq -r '.stdout // empty')
|
|
45
|
+
EXIT_CODE=$(echo "$TOOL_RESPONSE" | jq -r '.exit_code // 0')
|
|
46
|
+
COMMAND=$(echo "$TOOL_INPUT" | jq -r '.command // empty')
|
|
47
|
+
|
|
48
|
+
# Git commit
|
|
49
|
+
if echo "$COMMAND" | grep -qi "git commit"; then
|
|
50
|
+
if [ "$EXIT_CODE" = "0" ]; then
|
|
51
|
+
EVENT="commit"
|
|
52
|
+
COUNTER="commits"
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
# Test pass
|
|
56
|
+
elif echo "$STDOUT" | grep -qiE "(passed|✓|PASS|tests? (passed|succeeded)|0 failed)"; then
|
|
57
|
+
if [ "$EXIT_CODE" = "0" ]; then
|
|
58
|
+
EVENT="test_pass"
|
|
59
|
+
COUNTER="tests_passed"
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
# Test fail
|
|
63
|
+
elif echo "$STDOUT" | grep -qiE "(failed|✗|FAIL|error)"; then
|
|
64
|
+
COUNTER="tests_failed"
|
|
65
|
+
# No XP for failures, but track the counter
|
|
66
|
+
|
|
67
|
+
# Build success / failure
|
|
68
|
+
elif echo "$COMMAND" | grep -qiE "(build|compile|make|tsc)"; then
|
|
69
|
+
if [ "$EXIT_CODE" = "0" ]; then
|
|
70
|
+
EVENT="build_success"
|
|
71
|
+
COUNTER="builds_succeeded"
|
|
72
|
+
else
|
|
73
|
+
COUNTER="builds_failed"
|
|
74
|
+
fi
|
|
75
|
+
|
|
76
|
+
# Lint fix
|
|
77
|
+
elif echo "$COMMAND" | grep -qiE "(lint|eslint|prettier)"; then
|
|
78
|
+
if [ "$EXIT_CODE" = "0" ]; then
|
|
79
|
+
EVENT="lint_fix"
|
|
80
|
+
COUNTER="lint_fixes"
|
|
81
|
+
fi
|
|
82
|
+
|
|
83
|
+
# Generic error encountered
|
|
84
|
+
elif [ "$EXIT_CODE" != "0" ]; then
|
|
85
|
+
COUNTER="errors_encountered"
|
|
86
|
+
fi
|
|
87
|
+
|
|
88
|
+
elif [ "$TOOL_NAME" = "Write" ]; then
|
|
89
|
+
FILE_PATH=$(echo "$TOOL_INPUT" | jq -r '.file_path // empty')
|
|
90
|
+
if echo "$FILE_PATH" | grep -qiE '\.(test|spec)\.(ts|tsx|js|jsx|py)$'; then
|
|
91
|
+
EVENT="test_written"
|
|
92
|
+
COUNTER="tests_written"
|
|
93
|
+
else
|
|
94
|
+
EVENT="file_create"
|
|
95
|
+
COUNTER="files_created"
|
|
96
|
+
fi
|
|
97
|
+
|
|
98
|
+
elif [ "$TOOL_NAME" = "Edit" ]; then
|
|
99
|
+
FILE_PATH=$(echo "$TOOL_INPUT" | jq -r '.file_path // empty')
|
|
100
|
+
if echo "$FILE_PATH" | grep -qiE '\.(test|spec)\.(ts|tsx|js|jsx|py)$'; then
|
|
101
|
+
EVENT="test_written"
|
|
102
|
+
COUNTER="tests_written"
|
|
103
|
+
else
|
|
104
|
+
EVENT="file_edit"
|
|
105
|
+
COUNTER="files_edited"
|
|
106
|
+
fi
|
|
107
|
+
|
|
108
|
+
elif [ "$TOOL_NAME" = "Grep" ] || [ "$TOOL_NAME" = "Read" ] || [ "$TOOL_NAME" = "Glob" ]; then
|
|
109
|
+
EVENT="search"
|
|
110
|
+
COUNTER="searches"
|
|
111
|
+
fi
|
|
112
|
+
|
|
113
|
+
# ── Delegate to bun scripts ────────────────────────────────
|
|
114
|
+
# Use timeout to ensure bun never blocks beyond 3s (leaves 2s buffer for Claude Code's 5s limit)
|
|
115
|
+
|
|
116
|
+
if [ -n "$EVENT" ]; then
|
|
117
|
+
# XP award + counter increment
|
|
118
|
+
timeout 3 "$BUN_PATH" run "$SCRIPT_DIR/../src/hooks/award-xp.ts" "$EVENT" "$COUNTER" 2>/dev/null &
|
|
119
|
+
elif [ -n "$COUNTER" ]; then
|
|
120
|
+
# Counter-only increment (no XP)
|
|
121
|
+
timeout 3 "$BUN_PATH" run "$SCRIPT_DIR/../src/hooks/increment-counter.ts" "$COUNTER" 2>/dev/null &
|
|
122
|
+
fi
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
# Run the function, swallow all errors, always exit 0
|
|
126
|
+
_claudemon_post_tool_use 2>/dev/null || true
|
|
127
|
+
exit 0
|
package/hooks/stop.sh
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# chmod +x hooks/stop.sh
|
|
3
|
+
#
|
|
4
|
+
# Stop hook for Claudemon — extracts buddy comments from Claude's response.
|
|
5
|
+
# Looks for <!-- buddy: ... --> patterns and writes them as reactions to status.json.
|
|
6
|
+
# MUST exit 0 always — hooks must never block Claude Code.
|
|
7
|
+
|
|
8
|
+
# Defensive: do NOT use set -e. We never want to crash.
|
|
9
|
+
# Wrap everything so any unexpected error is swallowed.
|
|
10
|
+
_claudemon_stop() {
|
|
11
|
+
# ── Locate dependencies ────────────────────────────────────
|
|
12
|
+
command -v jq >/dev/null 2>&1 || return 0
|
|
13
|
+
|
|
14
|
+
# ── Read stdin ─────────────────────────────────────────────
|
|
15
|
+
local INPUT
|
|
16
|
+
INPUT=$(cat)
|
|
17
|
+
[ -z "$INPUT" ] && return 0
|
|
18
|
+
|
|
19
|
+
local STATE_DIR="$HOME/.claudemon"
|
|
20
|
+
local STATUS_FILE="$STATE_DIR/status.json"
|
|
21
|
+
|
|
22
|
+
[ -f "$STATUS_FILE" ] || return 0
|
|
23
|
+
|
|
24
|
+
# ── Extract the response text ──────────────────────────────
|
|
25
|
+
local RESPONSE_TEXT
|
|
26
|
+
RESPONSE_TEXT=$(echo "$INPUT" | timeout 2 jq -r '.tool_response.content // empty' 2>/dev/null)
|
|
27
|
+
[ -z "$RESPONSE_TEXT" ] && RESPONSE_TEXT=$(echo "$INPUT" | timeout 2 jq -r '.tool_response // empty' 2>/dev/null)
|
|
28
|
+
[ -z "$RESPONSE_TEXT" ] && return 0
|
|
29
|
+
|
|
30
|
+
# ── Look for <!-- buddy: ... --> pattern ───────────────────
|
|
31
|
+
local BUDDY_COMMENT
|
|
32
|
+
BUDDY_COMMENT=$(echo "$RESPONSE_TEXT" | grep -oP '<!-- buddy: \K[^-]+(?= -->)' 2>/dev/null | head -1)
|
|
33
|
+
[ -z "$BUDDY_COMMENT" ] && return 0
|
|
34
|
+
|
|
35
|
+
# Trim trailing whitespace
|
|
36
|
+
BUDDY_COMMENT=$(echo "$BUDDY_COMMENT" | sed 's/[[:space:]]*$//')
|
|
37
|
+
|
|
38
|
+
# ── Write reaction to status.json ──────────────────────────
|
|
39
|
+
local CURRENT
|
|
40
|
+
CURRENT=$(cat "$STATUS_FILE" 2>/dev/null)
|
|
41
|
+
[ -z "$CURRENT" ] && return 0
|
|
42
|
+
|
|
43
|
+
echo "$CURRENT" | timeout 2 jq --arg reaction "$BUDDY_COMMENT" '. + {reaction: $reaction}' > "${STATUS_FILE}.tmp" 2>/dev/null
|
|
44
|
+
mv "${STATUS_FILE}.tmp" "$STATUS_FILE" 2>/dev/null
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
# Run the function, swallow all errors, always exit 0
|
|
48
|
+
_claudemon_stop 2>/dev/null || true
|
|
49
|
+
exit 0
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# chmod +x hooks/user-prompt-submit.sh
|
|
3
|
+
#
|
|
4
|
+
# UserPromptSubmit hook for Claudemon — reacts when Pokemon name is mentioned.
|
|
5
|
+
# Reads JSON from stdin, checks if the user mentioned their active Pokemon's name,
|
|
6
|
+
# and writes a fun reaction to status.json.
|
|
7
|
+
# MUST exit 0 always — hooks must never block Claude Code.
|
|
8
|
+
|
|
9
|
+
# Defensive: do NOT use set -e. We never want to crash.
|
|
10
|
+
# Wrap everything so any unexpected error is swallowed.
|
|
11
|
+
_claudemon_name_react() {
|
|
12
|
+
# ── Locate dependencies ────────────────────────────────────
|
|
13
|
+
command -v jq >/dev/null 2>&1 || return 0
|
|
14
|
+
|
|
15
|
+
# ── Read stdin ─────────────────────────────────────────────
|
|
16
|
+
local INPUT
|
|
17
|
+
INPUT=$(cat)
|
|
18
|
+
[ -z "$INPUT" ] && return 0
|
|
19
|
+
|
|
20
|
+
local STATE_DIR="$HOME/.claudemon"
|
|
21
|
+
local STATE_FILE="$STATE_DIR/state.json"
|
|
22
|
+
local STATUS_FILE="$STATE_DIR/status.json"
|
|
23
|
+
|
|
24
|
+
[ -f "$STATE_FILE" ] || return 0
|
|
25
|
+
[ -f "$STATUS_FILE" ] || return 0
|
|
26
|
+
|
|
27
|
+
# ── Get user's prompt text ─────────────────────────────────
|
|
28
|
+
local USER_TEXT
|
|
29
|
+
USER_TEXT=$(echo "$INPUT" | timeout 2 jq -r '.user_prompt // empty' 2>/dev/null)
|
|
30
|
+
[ -z "$USER_TEXT" ] && return 0
|
|
31
|
+
|
|
32
|
+
# ── Get active Pokemon's nickname or species name ──────────
|
|
33
|
+
local POKEMON_NAME
|
|
34
|
+
POKEMON_NAME=$(timeout 2 jq -r '.party[] | select(.isActive == true) | .nickname // empty' "$STATE_FILE" 2>/dev/null)
|
|
35
|
+
|
|
36
|
+
if [ -z "$POKEMON_NAME" ]; then
|
|
37
|
+
# No nickname — fall back to the name from status.json
|
|
38
|
+
POKEMON_NAME=$(timeout 2 jq -r '.name // empty' "$STATUS_FILE" 2>/dev/null)
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
[ -z "$POKEMON_NAME" ] && return 0
|
|
42
|
+
|
|
43
|
+
# ── Case-insensitive check if name appears in user text ────
|
|
44
|
+
local NAME_LOWER
|
|
45
|
+
NAME_LOWER=$(echo "$POKEMON_NAME" | tr '[:upper:]' '[:lower:]')
|
|
46
|
+
local TEXT_LOWER
|
|
47
|
+
TEXT_LOWER=$(echo "$USER_TEXT" | tr '[:upper:]' '[:lower:]')
|
|
48
|
+
|
|
49
|
+
echo "$TEXT_LOWER" | grep -qi "$NAME_LOWER" || return 0
|
|
50
|
+
|
|
51
|
+
# ── Name mentioned! Pick a reaction ────────────────────────
|
|
52
|
+
local REACTIONS=(
|
|
53
|
+
"perks up!"
|
|
54
|
+
"looks at you!"
|
|
55
|
+
"wiggles happily!"
|
|
56
|
+
"tilts head curiously!"
|
|
57
|
+
"chirps with excitement!"
|
|
58
|
+
)
|
|
59
|
+
local IDX=$(( $(date +%s) % ${#REACTIONS[@]} ))
|
|
60
|
+
local REACTION="*${POKEMON_NAME} ${REACTIONS[$IDX]}*"
|
|
61
|
+
|
|
62
|
+
# ── Update status.json with reaction ───────────────────────
|
|
63
|
+
local CURRENT
|
|
64
|
+
CURRENT=$(cat "$STATUS_FILE" 2>/dev/null)
|
|
65
|
+
[ -z "$CURRENT" ] && return 0
|
|
66
|
+
|
|
67
|
+
echo "$CURRENT" | timeout 2 jq --arg reaction "$REACTION" '. + {reaction: $reaction}' > "${STATUS_FILE}.tmp" 2>/dev/null
|
|
68
|
+
mv "${STATUS_FILE}.tmp" "$STATUS_FILE" 2>/dev/null
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
# Run the function, swallow all errors, always exit 0
|
|
72
|
+
_claudemon_name_react 2>/dev/null || true
|
|
73
|
+
exit 0
|
package/package.json
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@umang-boss/claudemon",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Pokemon Gen 1 coding companion for Claude Code — Gotta code 'em all!",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "src/server/index.ts",
|
|
7
|
+
"bin": {
|
|
8
|
+
"claudemon": "bin/claudemon.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"src/",
|
|
12
|
+
"cli/",
|
|
13
|
+
"bin/",
|
|
14
|
+
"hooks/",
|
|
15
|
+
"skills/",
|
|
16
|
+
"sprites/",
|
|
17
|
+
"statusline/",
|
|
18
|
+
"scripts/",
|
|
19
|
+
"package.json",
|
|
20
|
+
"tsconfig.json",
|
|
21
|
+
"bunfig.toml"
|
|
22
|
+
],
|
|
23
|
+
"scripts": {
|
|
24
|
+
"server": "bun run src/server/index.ts",
|
|
25
|
+
"install-buddy": "bun run cli/install.ts",
|
|
26
|
+
"uninstall-buddy": "bun run cli/uninstall.ts",
|
|
27
|
+
"doctor": "bun run cli/doctor.ts",
|
|
28
|
+
"update-buddy": "bun run cli/update.ts",
|
|
29
|
+
"download-sprites": "bun run scripts/download-colorscripts.ts",
|
|
30
|
+
"test": "bun test",
|
|
31
|
+
"typecheck": "tsc --noEmit",
|
|
32
|
+
"format": "prettier --write \"src/**/*.ts\" \"cli/**/*.ts\" \"scripts/**/*.ts\" \"tests/**/*.ts\" --ignore-unknown",
|
|
33
|
+
"format:check": "prettier --check \"src/**/*.ts\" \"cli/**/*.ts\" \"scripts/**/*.ts\" \"tests/**/*.ts\" --ignore-unknown"
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
37
|
+
"zod": "^3.25.23"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@types/bun": "latest",
|
|
41
|
+
"prettier": "^3.8.2",
|
|
42
|
+
"typescript": "^5.8.3"
|
|
43
|
+
},
|
|
44
|
+
"keywords": [
|
|
45
|
+
"claude-code",
|
|
46
|
+
"mcp",
|
|
47
|
+
"pokemon",
|
|
48
|
+
"coding-companion",
|
|
49
|
+
"gamification",
|
|
50
|
+
"claudemon",
|
|
51
|
+
"terminal-art",
|
|
52
|
+
"status-line"
|
|
53
|
+
],
|
|
54
|
+
"author": "Umang Dabhi <umang@dabhi.dev>",
|
|
55
|
+
"license": "MIT",
|
|
56
|
+
"repository": {
|
|
57
|
+
"type": "git",
|
|
58
|
+
"url": "https://github.com/umang-dabhi/claudemon.git"
|
|
59
|
+
},
|
|
60
|
+
"homepage": "https://github.com/umang-dabhi/claudemon",
|
|
61
|
+
"bugs": {
|
|
62
|
+
"url": "https://github.com/umang-dabhi/claudemon/issues"
|
|
63
|
+
},
|
|
64
|
+
"engines": {
|
|
65
|
+
"node": ">=18",
|
|
66
|
+
"bun": ">=1.0"
|
|
67
|
+
}
|
|
68
|
+
}
|