Skip to content

JaiBri/tamaclaudechi

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Tamaclaudechi

A living companion that responds to your coding habits, time of day, and interaction history. The pixel-art robot mascot lives in macOS toast overlays and a native menu bar app, appearing after Claude finishes tasks or needs permission.

How It Works

Hook fires → tamagotchi update --event <type> → returns {mood, personality, stats}
           → claude -p generates quip (with mood personality injected)
           → toast --mode <X> --mood <MOOD> "quip"

The mascot has 5 stats (0-100) that decay over time and grow from interactions. Stats determine the current mood, which affects visuals (CSS filters, breathing animation, particles) and personality (injected into the prompt for contextual quips).

Quick Install

git clone https://github.com/JaiBri/tamaclaudechi.git
cd tamaclaudechi
./install.sh

The install script will:

  • Wire hooks into your project's .claude/settings.json
  • Configure the status line in your user-level ~/.claude/settings.json
  • Validate prerequisites

Prerequisites

  • macOS (toast + menu bar are macOS-native)
  • Claude Code CLI (claude command available in PATH)
  • jq (brew install jq) — optional but recommended
  • tmux (brew install tmux) — optional, enables API usage tracking in the status line

Manual Setup

If you prefer not to run the install script, add these hooks to your project's .claude/settings.json:

Stop hook (task complete toast)
{
  "hooks": {
    "Stop": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "if [ \"$(uname)\" != Darwin ]; then cat > /dev/null; exit 0; fi; if ! pgrep -q WindowServer 2>/dev/null; then cat > /dev/null; exit 0; fi; INPUT=$(cat); TAMA_DIR=\"/absolute/path/to/tamaclaudechi\"; ( TRANSCRIPT=$(echo \"$INPUT\" | jq -r '.transcript_path // empty') && USER_REQ=$([ -f \"$TRANSCRIPT\" ] && jq -r 'select(.message.role == \"user\") | .message.content | if type == \"array\" then map(select(.type == \"text\") | .text) | join(\" \") else . end' \"$TRANSCRIPT\" | tail -1 | head -c 500 || echo \"unknown\") && ASST_CONTEXT=$([ -f \"$TRANSCRIPT\" ] && tail -r \"$TRANSCRIPT\" | jq -r 'if .message.role == \"user\" and (.message.content | if type == \"array\" then any(.[]; .type == \"text\") else true end) then \"___STOP___\" elif .message.role == \"assistant\" then ([.message.content[]? | select(.type == \"text\") | .text] | join(\" \")) else empty end' | sed -n '/___STOP___/q;/./p' | tail -r | tr '\\n' ' ' | sed 's/  */ /g' | head -c 2000 || echo \"\"); [ -z \"$ASST_CONTEXT\" ] && ASST_CONTEXT=$(echo \"$INPUT\" | jq -r '.last_assistant_message // empty' | tail -5 | head -c 500); TAMA=$(\"$TAMA_DIR/scripts/tamagotchi\" update --event task_complete 2>/dev/null) && MOOD=$(echo \"$TAMA\" | sed -n 's/.*\"mood\"[[:space:]]*:[[:space:]]*\"\\([^\"]*\\)\".*/\\1/p') && PERSONALITY=$(echo \"$TAMA\" | sed -n 's/.*\"personality\"[[:space:]]*:[[:space:]]*\"\\([^\"]*\\)\".*/\\1/p') && ACHIEVEMENT=$(echo \"$TAMA\" | sed -n 's/.*\"achievement_unlocked\"[[:space:]]*:[[:space:]]*\"\\([^\"]*\\)\".*/\\1/p') && MOOD=${MOOD:-NEUTRAL} && TMPF=$(mktemp) && claude -p --output-format text \"You are a funny little robot mascot. ${PERSONALITY:-You are quirky.} The user asked: \\\"${USER_REQ}\\\". You responded: \\\"${ASST_CONTEXT}\\\". Rephrase what you did to a short, funny, quirky sentence. Make it context dependent. 7-10 words. Output ONLY the sentence.\" > \"$TMPF\" 2>/dev/null; MSG=$([ -s \"$TMPF\" ] && cat \"$TMPF\" || echo 'Beep boop, task complete!'); rm -f \"$TMPF\"; ACH_FLAG=''; [ -n \"$ACHIEVEMENT\" ] && [ \"$ACHIEVEMENT\" != 'null' ] && ACH_FLAG=\"--achievement $ACHIEVEMENT\"; \"$TAMA_DIR/scripts/toast\" --mode done --mood \"$MOOD\" $ACH_FLAG \"$MSG\" ) >/dev/null 2>&1 & disown; exit 0"
          }
        ]
      }
    ]
  }
}

Replace /absolute/path/to/tamaclaudechi with the actual path to your clone.

Notification hook (permission toast)
{
  "hooks": {
    "Notification": [
      {
        "matcher": "permission_prompt",
        "hooks": [
          {
            "type": "command",
            "command": "if [ \"$(uname)\" != Darwin ]; then cat > /dev/null; exit 0; fi; if ! pgrep -q WindowServer 2>/dev/null; then cat > /dev/null; exit 0; fi; INPUT=$(cat); TAMA_DIR=\"/absolute/path/to/tamaclaudechi\"; ( DETAIL=$(echo \"$INPUT\" | jq -r '.message // empty') && TAMA=$(\"$TAMA_DIR/scripts/tamagotchi\" update --event permission 2>/dev/null) && MOOD=$(echo \"$TAMA\" | sed -n 's/.*\"mood\"[[:space:]]*:[[:space:]]*\"\\([^\"]*\\)\".*/\\1/p') && PERSONALITY=$(echo \"$TAMA\" | sed -n 's/.*\"personality\"[[:space:]]*:[[:space:]]*\"\\([^\"]*\\)\".*/\\1/p') && ACHIEVEMENT=$(echo \"$TAMA\" | sed -n 's/.*\"achievement_unlocked\"[[:space:]]*:[[:space:]]*\"\\([^\"]*\\)\".*/\\1/p') && MOOD=${MOOD:-NEUTRAL} && TMPF=$(mktemp) && claude -p --output-format text \"You are a funny little robot mascot. ${PERSONALITY:-You are quirky.} You need permission for: \\\"${DETAIL:-something}\\\". Rephrase what you need to a short, funny, quirky sentence. Make it context dependent. 7-10 words. Output ONLY the sentence.\" > \"$TMPF\" 2>/dev/null; MSG=$([ -s \"$TMPF\" ] && cat \"$TMPF\" || echo 'Beep boop, need permission!'); rm -f \"$TMPF\"; ACH_FLAG=''; [ -n \"$ACHIEVEMENT\" ] && [ \"$ACHIEVEMENT\" != 'null' ] && ACH_FLAG=\"--achievement $ACHIEVEMENT\"; \"$TAMA_DIR/scripts/toast\" --mode permission --mood \"$MOOD\" $ACH_FLAG \"$MSG\" ) >/dev/null 2>&1 & disown; exit 0"
          }
        ]
      }
    ]
  }
}

Status Line

Add to your user-level ~/.claude/settings.json:

{
  "statusLine": {
    "type": "command",
    "command": "/absolute/path/to/tamaclaudechi/scripts/statusline"
  }
}

Stats

Stat Measures Decay
Energy Time of day (circadian curve) Blends toward circadian target
Serenity Repo tidiness (git state) -1/hr
Rest Healthy work patterns +2/hr idle (recovers!), caps at 80
Bond Relationship consistency -0.5/hr (slowest)
Vitality System health (CPU/RAM/disk/swap) Converges toward system target

Moods

Priority cascade: SLEEPING > SLEEPY > ANXIOUS > CONCERNED > LONELY > STRESSED > SAD > EXCITED > ECSTATIC > HAPPY > TIRED > NEUTRAL.

Each mood has unique breathing animations, CSS filters, particle effects, and personality directives.

CLI Commands

./scripts/tamagotchi status              # ASCII dashboard
./scripts/tamagotchi status --json       # JSON snapshot (no state mutation)
./scripts/tamagotchi update --event X    # Apply decay + event boost, return JSON
./scripts/tamagotchi pet                 # Manual +5 bond
./scripts/tamagotchi rename <name>       # Give it a name
./scripts/tamagotchi reset               # Reset to defaults
./scripts/tamagotchi diagnose           # Run diagnostics

Menu Bar Companion

Native SwiftUI menu bar app showing live stats, streaks, activity history, and quick actions.

cd menubar
swift run                                 # Debug build
./build-app.sh [~/Applications/TMC.app]   # Build .app bundle
./install-login-item.sh [/path/to/app]    # Add to Login Items

Achievements

Achievement Trigger
First Friend First interaction
Night Owl Active 0-5am with 10+ lifetime interactions
Centurion 100 lifetime interactions
Streak Master 7-day streak
Resurrector Return after 7+ days away
Marathon 20+ interactions in one session

State

Persisted at ~/.config/claude-mascot/state.json (user-level, follows across repos).

Files

scripts/tamagotchi       State engine CLI — thin router
scripts/lib/             Shared helpers (JSON, time, math)
scripts/core/            Engine logic (state, decay, events, mood, serenity)
scripts/commands/        CLI commands (update, status, reset, pet, config, usage)
scripts/toast            WebView toast overlay — wrapper
scripts/toast-assets/    HTML template + Swift WebView controller
scripts/statusline       Status line bridge — main script
scripts/statusline-sections/  Section renderers (git, usage, system, session)
scripts/usage-scraper    tmux-based /usage scraper
scripts/system-monitor   macOS system resource collector
menubar/                 SwiftUI menu bar companion
assets/claude.png        Pixel art sprite
assets/voices/           Toast audio cues
docs/                    Project vault
install.sh               Hook + statusline installer

Docs

Full documentation lives in docs/ — start with docs/CLAUDE-START-HERE.md.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors