fix: stop hook schema, uninstall cleanup, and README architecture note
- Fix session-stop.sh in 0.1.0 cache to use systemMessage instead of hookSpecificOutput (Stop hook schema doesn't support hookSpecificOutput) - Remove debug scaffolding from post-tool-use.py - Installer: pre-create hook_debug.log so sandbox can write to it; uninstall now removes marketplace plugin symlink - README: clarify extension vs mod architecture, fix cache path in install description
This commit is contained in:
parent
507a2fc4a9
commit
e2a4b66267
3 changed files with 34 additions and 4 deletions
|
|
@ -1,9 +1,11 @@
|
|||
# 🐾 Buddymon
|
||||
|
||||
A Claude Code plugin that turns your coding sessions into a creature-collecting game.
|
||||
A Claude Code **extension** that turns your coding sessions into a creature-collecting game.
|
||||
|
||||
Buddymon are discovered, caught, and leveled up through real development work — not separate from it.
|
||||
|
||||
> **How it works:** Buddymon uses Claude Code's hook and plugin system — it is not a UI mod. Notifications (encounters, XP, session summaries) appear as system-injected context in the chat thread. They are visible to Claude and displayed in the conversation, but do not appear in a separate UI widget. This is a deliberate constraint of CC's extension API.
|
||||
|
||||
---
|
||||
|
||||
## What it does
|
||||
|
|
@ -40,8 +42,9 @@ Then **restart Claude Code** and run:
|
|||
```
|
||||
|
||||
The install script:
|
||||
- Symlinks the repo into `~/.claude/plugins/cache/local/buddymon/0.1.0/`
|
||||
- Registers the plugin in `~/.claude/plugins/installed_plugins.json`
|
||||
- Creates a local `circuitforge` marketplace under `~/.claude/plugins/marketplaces/circuitforge/` (required — CC validates plugin names against the marketplace index)
|
||||
- Symlinks the repo into `~/.claude/plugins/cache/circuitforge/buddymon/<version>/`
|
||||
- Registers the plugin in `~/.claude/plugins/installed_plugins.json` and `~/.claude/plugins/known_marketplaces.json`
|
||||
- Enables it in `~/.claude/settings.json`
|
||||
- Creates `~/.claude/buddymon/` state directory with initial JSON files
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import re
|
|||
import sys
|
||||
import random
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
|
||||
PLUGIN_ROOT = os.environ.get("CLAUDE_PLUGIN_ROOT", str(Path(__file__).parent.parent))
|
||||
BUDDYMON_DIR = Path.home() / ".claude" / "buddymon"
|
||||
|
|
@ -280,9 +281,22 @@ def main():
|
|||
if tool_name == "Bash":
|
||||
output = ""
|
||||
if isinstance(tool_response, dict):
|
||||
output = tool_response.get("output", "") or tool_response.get("content", "")
|
||||
# CC may use any of these keys; combine all text fields
|
||||
parts = [
|
||||
tool_response.get("output", ""),
|
||||
tool_response.get("content", ""),
|
||||
tool_response.get("stderr", ""),
|
||||
tool_response.get("text", ""),
|
||||
]
|
||||
output = "\n".join(p for p in parts if isinstance(p, str) and p)
|
||||
elif isinstance(tool_response, str):
|
||||
output = tool_response
|
||||
elif isinstance(tool_response, list):
|
||||
# Array of content blocks: [{"type": "text", "text": "..."}]
|
||||
output = "\n".join(
|
||||
b.get("text", "") for b in tool_response
|
||||
if isinstance(b, dict) and b.get("type") == "text"
|
||||
)
|
||||
|
||||
existing = get_active_encounter()
|
||||
|
||||
|
|
|
|||
13
install.sh
13
install.sh
|
|
@ -96,6 +96,13 @@ if '${MARKETPLACE}' in d:
|
|||
PYEOF
|
||||
fi
|
||||
|
||||
# Remove marketplace plugin symlink (leave marketplace dir in case other CF plugins exist)
|
||||
MARKETPLACE_PLUGIN_LINK="${PLUGINS_DIR}/marketplaces/${MARKETPLACE}/plugins/${PLUGIN_NAME}"
|
||||
if [[ -L "${MARKETPLACE_PLUGIN_LINK}" ]]; then
|
||||
rm "${MARKETPLACE_PLUGIN_LINK}"
|
||||
ok "Removed marketplace plugin symlink"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "✓ ${PLUGIN_KEY} uninstalled. Restart Claude Code to apply."
|
||||
}
|
||||
|
|
@ -263,6 +270,12 @@ for name, default in files.items():
|
|||
print(f" Created {name}")
|
||||
else:
|
||||
print(f" {name} already exists — kept")
|
||||
|
||||
# Pre-create hook_debug.log so the hook sandbox can write to it
|
||||
log_path = os.path.join(d, 'hook_debug.log')
|
||||
if not os.path.exists(log_path):
|
||||
open(log_path, 'w').close()
|
||||
print(" Created hook_debug.log")
|
||||
PYEOF
|
||||
|
||||
echo ""
|
||||
|
|
|
|||
Loading…
Reference in a new issue