Skip to main content

A terminal pet companion that monitors Claude Code sessions

Project description

TPET - Terminal Pet Companion

A terminal pet that monitors your Claude Code sessions and generates personality-driven commentary. Runs in a tmux pane with ASCII art animation and Rich rendering.

Table of Contents

PyPI PyPI - Python Version Runs on Linux | MacOS | Windows Arch x86-64 | ARM | AppleSilicon PyPI - License

Screenshots

ASCII mode — live commentary

ASCII mode live session

ASCII mode — pet details card

ASCII mode details card

Sixel mode — live commentary

Sixel mode live session

Sixel mode — pet details card

Sixel mode details card

About

I really liked the idea of the Claude Code buddy so I created my own that supports infinite variations and customization. It even supports watching plain files and commenting on them!

tpet is a CLI application that creates a unique AI-generated pet creature. The pet displays in your terminal using Rich Live rendering, monitors your Claude Code session JSONL files (or plain text files) via watchdog, and produces in-character commentary about your coding sessions.

Built with Typer, Rich, and the Claude Agent SDK.

"Buy Me A Coffee"

Features

Core Capabilities

  • AI-Generated Pets: Each pet is unique -- name, personality, ASCII art, backstory, and stats all generated by the LLM
  • Personality-Driven Stats: HUMOR, PATIENCE, CHAOS, WISDOM, SNARK -- generated to match the creature's character and clamped by rarity tier
  • Rarity System: Common, Uncommon, Rare, and Legendary tiers determine stat ranges and display colors
  • Session Monitoring: Watches Claude Code JSONL sessions via watchdog or follows plain text files with --follow
  • In-Character Commentary: Session events trigger personality-driven reactions influenced by the pet's stats
  • Idle Chatter: When nothing is happening, your pet comments on its own

Art Modes

  • ASCII (default): Character art generated by the LLM, displayed with Rich
  • Sixel Art: AI-generated sprites rendered as ANSI half-block characters (requires API key)
  • Custom Base Images: Supply your own idle frame image with --base-image

Technical Excellence

  • No API Key Required: Commentary and pet generation use your Claude Code subscription via the Agent SDK
  • Per-Pipeline Providers: Independently configure the provider/model for profile generation, commentary, and image art
  • Multiple Providers: Claude (Agent SDK), Ollama, OpenAI, OpenRouter, and Google Gemini for any pipeline
  • Non-Blocking Commentary: Background ThreadPoolExecutor keeps the 4fps display smooth during LLM calls
  • YAML Persistence: Human-readable config and profiles via Pydantic serialization
  • XDG Compliance: Config and data paths follow XDG base directory conventions

Prerequisites

  • Install and authenticate Claude Code (required for default commentary and pet generation)
  • Install Python 3.13 or newer

Using uv

The recommended way to install tpet. If you don't have uv installed:

curl -LsSf https://astral.sh/uv/install.sh | sh

PyPi install

uv tool install term-pet

To upgrade:

uv tool install term-pet -U --force

Installing / running using uvx

uvx --from term-pet tpet

Source install from GitHub

uv tool install git+https://github.com/paulrobello/tpet

To upgrade:

uv tool install git+https://github.com/paulrobello/tpet -U --force

pipx

Installing

If you don't have pipx installed:

pip install pipx
pipx ensurepath

PyPi install

pipx install term-pet

To upgrade an existing installation:

pipx install term-pet --force

Source install from GitHub

pipx install git+https://github.com/paulrobello/tpet

To upgrade:

pipx install git+https://github.com/paulrobello/tpet --force

Installing for dev mode

Clone the repo and run the setup make target. Note uv is required.

git clone https://github.com/paulrobello/tpet
cd tpet
make setup

Usage

tpet uses subcommands for distinct operations. The old flag-based style (--new, --details, --gen-art, etc.) still works for backward compatibility.

# Subcommand style (preferred)
tpet run                        # Start the live pet display (default if no subcommand)
tpet run --follow /path/to/file # Follow a plain text file instead of Claude sessions
tpet new                        # Generate a new pet
tpet new -y                     # Generate without confirmation
tpet new -C "make it a dragon"  # Generate with custom criteria
tpet details                    # Show full pet card
tpet details --backstory        # Show card with backstory
tpet art                        # Generate graphical art for the current pet
tpet art --art-mode sixel-art  # Generate sixel art specifically

# Flag style (backward-compatible)
tpet                            # Start the pet (watches Claude Code sessions)
tpet --new                      # Generate a new pet
tpet --details                  # Show full pet card
tpet --gen-art                  # Generate graphical art
tpet --reset                    # Delete current pet
tpet --reset -y                 # Delete without confirmation
tpet --dump-config              # Show current config
tpet --project /path/to/repo    # Use project-specific pet
tpet --dry-run                  # Validate config and exit
tpet --regen-art                # Regenerate ASCII art for current pet

CLI Reference

Global flags

Flag Short Description
--version Show version
--debug -D Enable debug logging
--verbose -v Increase verbosity (stackable)
--project -p Project directory
--config-dir -c Config directory override

tpet new

Generate a new pet.

Flag Short Description
--create-prompt -C Custom criteria for pet generation
--create-prompt-file -F File containing custom criteria
--yes -y Bypass confirmation prompts
--seed -s Random seed for pet generation (defaults to current time)

tpet details

Show the pet details card.

Flag Short Description
--backstory -b Include backstory in card

tpet art

Generate graphical art for the current pet.

Flag Short Description
--art-mode -a Art display mode: ascii or sixel-art
--art-provider -P Image art provider: openai, gemini, or openrouter
--art-model Model for image art generation
--art-width -W Max percentage of terminal width for art (1-100)
--art-prompt Custom prompt for image generation
--base-image Custom image to use as idle frame (forces OpenAI edits)

tpet run

Start the live pet display (default mode).

Flag Short Description
--follow -f Follow a plain text file instead of Claude sessions
--watch-dir -w Session watch directory override
--commentary-provider Commentary LLM provider: claude, ollama, openai, openrouter, or gemini
--commentary-model Model for commentary generation
--comment-interval -i Min seconds between comments
--idle-chatter-interval -I Seconds between idle chatter
--max-comments -M Max comments per session
--sleep-threshold -s Seconds before sleep animation
--art-mode -a Art display mode: ascii or sixel-art
--log-level -l Log level override
--show-session Show resolved session directory and file, then exit

Legacy flag-style

The root tpet command accepts all flags from every subcommand for backward compatibility. For example, tpet --new, tpet --details, tpet --gen-art, tpet --reset, tpet --regen-art, tpet --dump-config, and tpet --dry-run all continue to work as before.

Configuration

Config file: ~/.config/tpet/config.yaml

# Per-pipeline LLM provider configuration
profile_provider_config:
  provider: claude
  model: claude-haiku-4-5

commentary_provider_config:
  provider: claude
  model: claude-haiku-4-5

image_art_provider_config:
  provider: openai
  model: gpt-image-1.5

# Timing
comment_interval_seconds: 30
idle_chatter_interval_seconds: 300
max_comments_per_session: 0
max_comment_length: 150
max_idle_length: 100
sleep_threshold_seconds: 120

# Animation
idle_duration_seconds: 3.0
reaction_duration_seconds: 0.5
sleep_duration_seconds: 60.0
ascii_art_frames: 6

# Display
art_mode: ascii
art_max_width_pct: 40
art_size: 120
halfblock_size: 48
bubble_placement: bottom

# Art processing
chroma_tolerance: 30
art_dir_path: art
art_prompt: ""

# Logging
log_level: WARNING
log_file: debug.log

Pipeline provider configuration

Each pipeline (profile_provider_config, commentary_provider_config, image_art_provider_config) independently configures its own LLM provider:

Field Type Default Description
provider string claude LLM provider: claude, ollama, openai, openrouter, or gemini
model string (provider default) Model override (empty = provider default)
base_url string (provider default) API base URL override (empty = provider default)
api_key_env string (provider default) Environment variable name for the API key

Provider defaults:

Provider Text default model Image default model Default base URL
claude claude-haiku-4-5 (n/a) Agent SDK (no URL)
ollama llama3.2 (n/a) http://localhost:11434/v1
openai gpt-4o gpt-image-1.5 https://api.openai.com/v1
openrouter anthropic/claude-haiku-4-5 openai/dall-e-3 https://openrouter.ai/api/v1
gemini gemini-2.5-flash gemini-2.5-flash Google Genai client

General configuration reference

Field Type Default Description
comment_interval_seconds float 30.0 Minimum seconds between event-triggered comments
idle_chatter_interval_seconds float 300.0 Seconds of inactivity before idle chatter
max_comments_per_session int 0 Maximum comments per run (0 = unlimited)
max_comment_length int 150 Character limit for event comments
max_idle_length int 100 Character limit for idle chatter
log_level string WARNING Log verbosity: DEBUG, INFO, WARNING, ERROR
log_file string debug.log Log filename (written inside the config directory)
sleep_threshold_seconds int 120 Inactivity seconds before sleep animation
idle_duration_seconds float 3.0 Seconds per idle animation frame cycle
reaction_duration_seconds float 0.5 Duration of the reaction animation
sleep_duration_seconds float 60.0 Duration of each sleep animation cycle
ascii_art_frames int 6 Number of animation frames per pet
art_mode string ascii Display mode: ascii or sixel-art
art_max_width_pct int 40 Percentage of terminal width allocated to the art panel
art_size int 120 Target pixel height for art sprites (multiple of 6)
halfblock_size int 48 Target pixel height for sixel-art half-blocks (must be even)
chroma_tolerance int 30 Chroma key removal tolerance for background removal
art_dir_path string art Subdirectory name under config dir for art files
art_prompt string "" Custom prompt override for image generation (empty = auto-generate)
bubble_placement string bottom Speech bubble position: top, right, or bottom

Pet profiles are stored at:

  • Global: ~/.config/tpet/profile.yaml
  • Per-project: <project>/.tpet/profile.yaml

Environment Variables

API keys for graphical art generation and third-party providers are read from environment variables. The recommended approach is to place them in ~/.config/tpet/.env, which tpet loads automatically on every startup.

Variable Required for Description
OPENAI_API_KEY provider: openai OpenAI API key for text or image generation
GEMINI_API_KEY provider: gemini Google Gemini API key for text or image generation
OPENROUTER_API_KEY provider: openrouter OpenRouter API key for any pipeline

Example ~/.config/tpet/.env:

OPENAI_API_KEY=sk-proj-...
GEMINI_API_KEY=AIza...
OPENROUTER_API_KEY=sk-or-...

No API key is required for the default claude provider or for ASCII art mode -- the Claude provider uses your Claude Code subscription via the Agent SDK. Ollama runs locally and requires no key.

How It Works

  1. On first run, tpet generates a unique pet using the LLM (name, personality, ASCII art, backstory)
  2. Stats (HUMOR, PATIENCE, CHAOS, WISDOM, SNARK) are personality-driven -- generated by the LLM to match the creature's character, then clamped to the rarity range
  3. The pet's rarity (Common/Uncommon/Rare/Legendary) determines stat ranges and display colors
  4. By default, tpet monitors your Claude Code session's JSONL files via watchdog (use --follow to watch a plain text file instead)
  5. Session events trigger in-character commentary influenced by the pet's personality and stats
  6. The pet animates through a 6-frame cycle: idle, idle-shift, blink, blink-shift, react, and sleep. Blink frames are generated programmatically by compositing the idle pose with closed eyes from the sleep frame
  7. On exit, tpet prints a session summary showing total comments, API calls, token counts, and estimated cost

Development

make checkall   # Run all checks (fmt, lint, typecheck, test)
make test       # Run tests only
make lint       # Lint with ruff
make fmt        # Format with ruff
make typecheck  # Type check with pyright

Dev mode

From repo root:

make dev

Contributing

Please ensure that all pull requests are formatted with ruff, pass ruff lint and pyright. You can run the make target checkall to ensure the pipeline will pass with your changes.

The easiest way to setup your environment:

With uv installed:

uv tool install pre-commit

With pipx installed:

pipx install pre-commit

From repo root:

pre-commit install
pre-commit run --all-files

After running the above, all future commits will auto run pre-commit. Pre-commit will fix what it can and show what remains to be fixed.

License

MIT -- see LICENSE for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

term_pet-0.1.0.tar.gz (59.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

term_pet-0.1.0-py3-none-any.whl (74.8 kB view details)

Uploaded Python 3

File details

Details for the file term_pet-0.1.0.tar.gz.

File metadata

  • Download URL: term_pet-0.1.0.tar.gz
  • Upload date:
  • Size: 59.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for term_pet-0.1.0.tar.gz
Algorithm Hash digest
SHA256 b6227d31bcd4690a8b1e738834ffef4c5c1a0473dda46a2b3580692643aca27f
MD5 b7ccbd797a7b7e28ad33cc4f3fc8c9e3
BLAKE2b-256 6c9930411a3ba689f293a07856c4d0e814884e5e148f93c9adf49a34f2c3cbe3

See more details on using hashes here.

Provenance

The following attestation bundles were made for term_pet-0.1.0.tar.gz:

Publisher: publish.yml on paulrobello/term-pet

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file term_pet-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: term_pet-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 74.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for term_pet-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3a19c503ee2789751afdd585a0b94728bf06bd97a1e1688070cda66406b7c27d
MD5 ed678ecb47b557d9b0dd733393e6af43
BLAKE2b-256 b01a9266ff826c27e11523747f146533df411648eaa9111ecabc93f295d1cc0e

See more details on using hashes here.

Provenance

The following attestation bundles were made for term_pet-0.1.0-py3-none-any.whl:

Publisher: publish.yml on paulrobello/term-pet

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page