session-stop.sh writes ~/.claude/buddymon/handoff.json with: buddy id,
XP earned, commit count, languages touched, caught monsters, challenge
state, any active encounter, and manual notes (for future /buddymon note).
session-start.sh reads handoff.json on next session start, injects a
'📬 From your last session' block into additionalContext, then removes
the file so it only fires once.
Closes#1 on Circuit-Forge/buddymon.
Each Claude Code session now gets its own state file at:
~/.claude/buddymon/sessions/<pgrp>.json
Contains: buddymon_id, session_xp, challenge — all session-local.
Global active.json keeps the default buddymon_id for new sessions.
/buddymon assign writes to the session file only, so assigning in one
terminal window doesn't affect other open sessions. Each window can
have its own buddy assigned independently.
SessionStart creates the session file (inheriting global default).
SessionStop reads XP from it, writes to roster, then removes it.
Evolution triggers at Lv.100 for all three starters:
Pyrobyte → 🌋 Infernus (power 40→70, catch_rate 0.45→0.55)
Debuglin → 🔬 Verifex (power 35→60, catch_rate 0.60→0.75)
Minimox → 🌑 Nullex (power 35→55, catch_rate 0.50→0.65)
/buddymon evolve: checks eligibility, shows stat preview, resets buddy
to Lv.1 in evolved form, archives old form with evolved_into marker,
carries challenges forward.
session-stop.sh now prints EVOLUTION READY banner when level hits 100
or when already eligible at session end.
Healthy → wounded: 50% per clean run (avg ~2 runs, was instant)
Wounded → fled: 35% per clean run (avg ~3 runs, was instant)
Combined expected clean runs before auto-resolve: ~5, giving the user
a realistic window to type /buddymon catch between tool calls.
catch_pending: set immediately when /buddymon catch is invoked, suppresses
auto-resolve while weakening Q&A is in progress. Cleared before catch roll
(success clears encounter, failure leaves it without the flag so auto-resolve
resumes naturally on the next clean Bash run).
wounded: first clean Bash run without catch_pending drops the encounter to 5%
strength and re-announces via UserPromptSubmit with a fleeing message. Second
clean run auto-resolves it (it fled). UserPromptSubmit now shows distinct
announcement text for wounded vs fresh encounters.
Adds LANGUAGE_TIERS with 6 tiers: discovering → familiar → comfortable
→ proficient → expert → master (thresholds: 0/50/150/350/700/1200 XP).
add_language_affinity() writes to roster.json['language_affinities'],
accumulating across sessions. Returns (leveled_up, old_tier, new_tier)
so the Edit/Write branch can fire a level-up message immediately (Edit
PostToolUse additionalContext surfaces fine).
Session-level languages_seen remains for the one-time Explorer bonus.
Roster skill view updated to show language affinity section.
Stop hook clears active.challenge after reporting it.
Start hook assigns a random challenge from the buddy's pool if none is set.
Result: fresh challenge every session, no stale repeat.
CC sends Bash results as {stdout, stderr, interrupted, isImage, noOutputExpected}.
Previous code guessed output/content/text — all wrong, so encounter detection
never matched. Confirmed via active.json relay debug.
Bash PostToolUse additionalContext is silently dropped by CC — encounters
are written to state but never surfaced. Fix with a two-phase approach:
- PostToolUse (Bash): detects error, writes encounter with announced:false
- UserPromptSubmit: fires on next user message, checks for unannounced
encounter, surfaces it once, marks announced:true so dedup loop breaks
Removes debug scaffolding and the format_encounter_message call from the
Bash hook (announcement is now fully owned by user-prompt-submit.py).
- 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
Stop hook was emitting hookSpecificOutput with hookEventName=Stop,
which is not a valid hookSpecificOutput type (only PreToolUse,
PostToolUse, UserPromptSubmit are). Changed to systemMessage.
SessionStart still uses additionalContext (confirmed working).
Stale /buddymon-fight and /buddymon-catch references in session-start.sh
updated to /buddymon fight and /buddymon catch.
install.sh now creates a full circuitforge marketplace with marketplace.json
so CC can validate the plugin name against the index before loading.
Removed invalid extraKnownMarketplaces local source (only github/git valid).
- install.sh: symlink-based dev install, registers in installed_plugins.json
and settings.json, initializes ~/.claude/buddymon/ state files
- install.sh --uninstall to cleanly remove
- Fix stale /buddymon-start and /buddymon-assign references in session-start.sh
to use unified /buddymon start and /buddymon assign subcommands
When an active encounter exists and the next Bash tool call produces
output with no matching error patterns, the monster is automatically
defeated and XP is awarded — no manual /buddymon fight needed.
/buddymon fight is kept as a manual fallback for fixes that happen
outside Bash (config edits, etc.).
Claude Code plugin — collectible creatures discovered through coding.
- Bug monsters spawn from error output (NullWraith, RacePhantom, ShadowBit, 11 total)
- 5 Buddymon with affinities, challenges, and evolution chains
- SessionStart hook injects active buddy + challenge into system context
- PostToolUse hook detects error patterns, new languages, and commit events
- Stop hook tallies XP and checks challenge completion
- Single /buddymon command with start/assign/fight/catch/roster subcommands
- Local state in ~/.claude/buddymon/ (roster, encounters, active, session)