diff --git a/install.sh b/install.sh index 35e5600..0f977bd 100755 --- a/install.sh +++ b/install.sh @@ -278,6 +278,24 @@ if not os.path.exists(log_path): print(" Created hook_debug.log") PYEOF + # Copy statusline script to stable user-local path + cp "${REPO_DIR}/lib/statusline.sh" "${BUDDYMON_DIR}/statusline.sh" + chmod +x "${BUDDYMON_DIR}/statusline.sh" + ok "Installed statusline.sh → ${BUDDYMON_DIR}/statusline.sh" + + # Install statusline into settings.json if not already configured + python3 << PYEOF +import json +f = '${SETTINGS_FILE}' +d = json.load(open(f)) +if 'statusLine' not in d: + d['statusLine'] = {"type": "command", "command": "bash ${BUDDYMON_DIR}/statusline.sh"} + json.dump(d, open(f, 'w'), indent=2) + print(" Installed Buddymon statusline in settings.json") +else: + print(" statusLine already configured — skipped (run /buddymon statusline to install manually)") +PYEOF + echo "" echo "✓ ${PLUGIN_KEY} installed!" echo "" diff --git a/lib/statusline.sh b/lib/statusline.sh new file mode 100644 index 0000000..7cf984a --- /dev/null +++ b/lib/statusline.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash +# Buddymon statusline — displays active buddy + encounter in the CC status bar. +# Install: add to ~/.claude/settings.json → "statusLine" → "command" +# Or run: /buddymon statusline (installs automatically) + +B="$HOME/.claude/buddymon" + +# Bail fast if no state directory or no starter chosen +[[ -d "$B" ]] || exit 0 +STARTER=$(jq -r '.starter_chosen // false' "$B/roster.json" 2>/dev/null) +[[ "$STARTER" == "true" ]] || exit 0 + +# Read state +ID=$(jq -r '.buddymon_id // ""' "$B/active.json" 2>/dev/null) +[[ -n "$ID" ]] || exit 0 + +LVL=$(jq -r ".owned[\"$ID\"].level // 1" "$B/roster.json" 2>/dev/null) +XP=$(jq -r '.session_xp // 0' "$B/active.json" 2>/dev/null) + +ENC_JSON=$(jq -c '.active_encounter // null' "$B/encounters.json" 2>/dev/null) +ENC_DISPLAY=$(echo "$ENC_JSON" | jq -r '.display // ""' 2>/dev/null) +ENC_STRENGTH=$(echo "$ENC_JSON" | jq -r '.current_strength // 0' 2>/dev/null) + +# ANSI colors +CY='\033[38;2;23;146;153m' # cyan — buddy +GR='\033[38;2;64;160;43m' # green — xp +RD='\033[38;2;203;60;51m' # red — encounter +DM='\033[38;2;120;120;120m' # dim — separators +RS='\033[0m' + +printf "${CY}🐾 ${ID} Lv.${LVL}${RS}" +printf " ${DM}·${RS} ${GR}+${XP}xp${RS}" + +if [[ "$ENC_JSON" != "null" ]] && [[ -n "$ENC_DISPLAY" ]]; then + printf " ${RD}⚔ ${ENC_DISPLAY} [${ENC_STRENGTH}%%]${RS}" +fi + +echo diff --git a/skills/buddymon/SKILL.md b/skills/buddymon/SKILL.md index beea1d6..90135b2 100644 --- a/skills/buddymon/SKILL.md +++ b/skills/buddymon/SKILL.md @@ -25,6 +25,7 @@ Parse `$ARGUMENTS` (trim whitespace, lowercase the first word) and dispatch: | `fight` | Fight active encounter | | `catch` | Catch active encounter | | `roster` | Full roster view | +| `statusline` | Install Buddymon statusline into settings.json | | `help` | Show command list | --- @@ -279,6 +280,46 @@ Read `roster.json` → `language_affinities`. Skip this section if empty. --- +## `statusline` — Install Buddymon Statusline + +Installs the Buddymon statusline into `~/.claude/settings.json`. + +The statusline shows active buddy + level + session XP, and highlights any +active encounter in red: + +``` +🐾 Debuglin Lv.90 · +45xp ⚔ 💀 NullWraith [60%] +``` + +Run this Python to install: + +```python +import json, os, shutil + +SETTINGS = os.path.expanduser("~/.claude/settings.json") +PLUGIN_ROOT = os.environ.get("CLAUDE_PLUGIN_ROOT", "") +SCRIPT = os.path.join(PLUGIN_ROOT, "lib", "statusline.sh") + +settings = json.load(open(SETTINGS)) + +if settings.get("statusLine"): + print("⚠️ A statusLine is already configured. Replace it? (y/n)") + # ask user — if no, abort + # if yes, proceed + pass + +settings["statusLine"] = { + "type": "command", + "command": f"bash {SCRIPT}", +} +json.dump(settings, open(SETTINGS, "w"), indent=2) +print(f"✅ Buddymon statusline installed. Reload Claude Code to activate.") +``` + +If a `statusLine` is already set, show the existing command and ask before replacing. + +--- + ## `help` ``` @@ -288,4 +329,5 @@ Read `roster.json` → `language_affinities`. Skip this section if empty. /buddymon fight — fight active encounter /buddymon catch — catch active encounter /buddymon roster — view full roster +/buddymon statusline — install statusline widget ```