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, Epic, 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)
  • macOS Desktop: Native AppKit window with your pet walking on your desktop, perching on other apps' window edges, reacting to session events with a speech bubble. See macos_desktop/. Requires Swift 5.9+ and macOS 12+. Build once with make desktop, then tpet --art-mode macos-desktop. Each invocation spawns its own pet — the tray paw icon shows which session and cwd it belongs to.
  • 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 install in editable mode with uv:

git clone https://github.com/paulrobello/tpet
cd tpet
uv tool install --editable .

The installed tpet command stays linked to your working tree — edits in src/ take effect immediately without reinstalling.

To force-refresh after pulling changes:

uv tool install --editable . --force

To uninstall:

uv tool uninstall term-pet

Building the macOS desktop pet

--art-mode macos-desktop spawns a native AppKit binary (Deskpet) alongside your tpet session. The Swift sources live in macos_desktop/ and must be built once before first use; the Python install does not build them automatically.

Requirements:

  • macOS 12 or newer
  • Swift 5.9+ (ships with recent Xcode / Command Line Tools — xcode-select --install)

Build (release):

make desktop

This runs swift build -c release inside macos_desktop/, producing macos_desktop/.build/release/Deskpet.

How tpet finds the binary, in order:

  1. $DESKPET_BIN — explicit path, useful for testing custom builds.
  2. The repo-local release build at macos_desktop/.build/release/Deskpet (or the arch-suffixed …/arm64-apple-macosx/release/Deskpet / …/x86_64-apple-macosx/release/Deskpet). The lookup is anchored to the repo containing src/tpet/renderer/macos_desktop.py, so an editable install (uv tool install --editable .) keeps it working from any cwd.
  3. A deskpet binary on $PATH.

Run it:

tpet --art-mode macos-desktop
# or, during development:
make dev

Clean Swift build artifacts:

make desktop-clean

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/Epic/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.2.0.tar.gz (72.6 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.2.0-py3-none-any.whl (89.1 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for term_pet-0.2.0.tar.gz
Algorithm Hash digest
SHA256 4372b5017335190aa2fef5a43467a907ffbd4c82d642bc0be612127813f32397
MD5 0b4ce05ecf8befa6a0a87c78cd1a630e
BLAKE2b-256 fd16e5e5ff382e49e20cf74fa4beb7241c29399be0b07d4a04dbef4fc6b941e8

See more details on using hashes here.

Provenance

The following attestation bundles were made for term_pet-0.2.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.2.0-py3-none-any.whl.

File metadata

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

File hashes

Hashes for term_pet-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 cc600644d2a5b9f415edc74f13790afd0ffedecb35008c15c1810589ffe9ab0b
MD5 f349ac87c491fb5af453aedf9be1efdf
BLAKE2b-256 6ef91f0227ab9993d7b76b5d48b948de313ccebd9d5e4e936de9b6d7ab4f08da

See more details on using hashes here.

Provenance

The following attestation bundles were made for term_pet-0.2.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