- post-tool-use: find_catalog() checks ~/.claude/buddymon/catalog.json first
so Veritarch is always found regardless of which cache CLAUDE_PLUGIN_ROOT
points to; fixes 'your buddy' display bug
- post-tool-use: skip spawn when monster already in collection (was only
checked on existing encounters, not at spawn time; caused already-caught
monsters to re-announce)
- post-tool-use: fix spawn block indentation — set_active_encounter was
outside the else, running even on already-owned skip
- user-prompt-submit: same null buddymon_id fallback fix as post-tool-use
- cli.py cmd_roster: buffer all output to StringIO; write roster_output.txt
+ roster_pending.txt; suppress stdout when piped (isatty check)
- roster-stop.py: read roster_output.txt directly instead of re-running cli.py
(eliminated the recursive flag-write loop); remove unused subprocess import
Language mascots:
- 11 mascots across common/uncommon/rare/legendary tiers (Pythia, Asynclet,
Bashling, Goroutling, Typeling, Vueling, Querion, Ferrix, Perlius,
Cobolithon, Lispling)
- Full evolution chains for all mascots (16 evolutions total in catalog)
- Spawn via PostToolUse after language affinity milestones; probability
scales with affinity level; only fires with no active encounter
- Passive strength reduction: each Write/Edit in the mascot's language
ticks current_strength down (floor 5%, triggers re-announcement)
- Mascot-aware catch formula: base_rate + affinity_bonus (6% per level) +
weakness_bonus + soft element gating via existing player_elements
- Language-themed weakening menu and catch failure messages in CLI
- Caught mascots stored as type="caught_language_mascot"; assignable as buddy
- UserPromptSubmit uses distinct 🦎 announcement with language context
Roster display:
- New "Language Mascots" section between core buddymon and caught bug monsters
- Language affinity table marks languages with spawnable mascots (🦎)
- Discovery counter now tracks both bug monsters and mascots separately
Veritarch (third evolution):
- Debuglin → Verifex (Lv.100) → Veritarch (Lv.200)
- TYPE FORTRESS / INVARIANT PROOF / ZERO FLAKE challenges
- xp_multiplier 1.7, catch_rate 0.90
Script-first architecture:
- All game logic extracted to lib/cli.py (~850 lines); SKILL.md is now
a ~55-line relay — 88% token reduction per invocation
- CLI emits [INPUT_NEEDED] and [HAIKU_NEEDED] markers for interactive flows
- PostToolUse hook re-emits CLI stdout as additionalContext for inline display
Session XP fix:
- statusline.sh and session state now read from sessions/<pgrp>.json
(per-window) with fallback to active.json; fixes stale XP in statusline
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.
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.
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).