A standalone Python program that renders an animated pumpkin face on fullscreen and responds to network commands to change facial expressions.
- Fullscreen rendering with 2D vector graphics
- 7 facial expressions: neutral, happy, sad, angry, surprised, scared, sleeping
- Smooth animations between expression transitions
- Network socket server on port 5000 for receiving commands
- Keyboard shortcuts for quick testing (1-7 keys for expressions, arrow keys for alignment, B/L/R for animations, U/J for eyebrows, [ ] for individual eyebrows, C/X for eye rolling)
- Customizable appearance (colors, sizes, animation speeds)
- Command recording & playback: Record command sequences and replay them with frame-accurate timing
- Record commands into timelines with automatic timestamping
- Play, pause, resume, stop, and seek through recorded sequences
- List, delete, and rename recorded timelines
- Gaze control: Direct eye positioning with individual eye control
- Eye animations: Blink, wink, and roll eyes
- Eyebrow control: Raise, lower, and control individual eyebrows
-
Download the latest release from GitHub Releases
-
Extract the ZIP file:
unzip mr-pumpkin-v0.1.0.zip cd mr-pumpkin-v0.1.0 -
Run the install script:
Linux/macOS/Raspberry Pi:
chmod +x install.sh ./install.sh
Windows (PowerShell):
.\install.ps1
The install script will:
- Install SDL2 system dependencies (Linux/Raspberry Pi only)
- Install Python dependencies via pip
- Provide usage instructions
- Clone the repository and install dependencies:
git clone https://github.com/mlinnen/mr-pumpkin.git
cd mr-pumpkin
pip install -r requirements.txtNote: On Raspberry Pi or Linux, you may need to install SDL2 system libraries first:
sudo apt-get update
sudo apt-get install -y libsdl2-dev libsdl2-image-dev libsdl2-mixer-dev libsdl2-ttf-devTo set up a development environment with testing capabilities:
pip install -r requirements-dev.txtThis installs all production dependencies plus pytest for running the test suite.
Mr. Pumpkin includes automated update scripts that check for new releases on GitHub and deploy them automatically.
Linux/macOS/Raspberry Pi:
./update.shWindows (PowerShell):
.\update.ps1The update script will:
- Check the current installed version against the latest GitHub release
- Download the new release if available
- Stop the running pumpkin_face.py process (if running)
- Deploy the updated files
- Restart pumpkin_face.py with the same arguments
Linux/macOS/Raspberry Pi (crontab):
Run daily at 3 AM:
crontab -eAdd this line:
0 3 * * * /absolute/path/to/mr-pumpkin/update.shWindows (Task Scheduler):
Create a scheduled task using PowerShell:
$action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-ExecutionPolicy Bypass -File C:\path\to\mr-pumpkin\update.ps1"
$trigger = New-ScheduledTaskTrigger -Daily -At 3am
Register-ScheduledTask -Action $action -Trigger $trigger -TaskName "MrPumpkinAutoUpdate" -Description "Daily check for Mr. Pumpkin updates"Or use Task Scheduler GUI:
- Open Task Scheduler → Create Basic Task
- Name: "Mr Pumpkin Auto Update"
- Trigger: Daily at 3:00 AM
- Action: Start a program
- Program:
powershell.exe - Arguments:
-ExecutionPolicy Bypass -File C:\path\to\mr-pumpkin\update.ps1
Custom Installation Directory:
Set the INSTALL_DIR environment variable to specify where Mr. Pumpkin is installed:
export INSTALL_DIR=/custom/path/to/mr-pumpkin
./update.sh$env:INSTALL_DIR = "C:\custom\path\to\mr-pumpkin"
.\update.ps1All update operations are logged to mr-pumpkin-update.log in the installation directory with timestamps.
For detailed setup and troubleshooting, see docs/auto-update.md.
Fullscreen (default on monitor 0):
python pumpkin_face.pyFullscreen on specific monitor:
python pumpkin_face.py 0 # First monitor
python pumpkin_face.py 1 # Second monitor
python pumpkin_face.py 2 # Third monitorWindowed mode:
python pumpkin_face.py --window # Windowed on monitor 0
python pumpkin_face.py 1 --window # Windowed on monitor 1Usage:
python pumpkin_face.py [monitor_number] [--window|--fullscreen]
The program will list available monitors and run on your selected output. Press ESC to exit.
Using the example client (interactive menu):
python client_example.pyThis provides an interactive menu with commands for:
- Changing expressions (neutral, happy, sad, angry, surprised, scared, sleeping)
- Animation controls (blink, roll eyes, control eyebrows)
- Gaze control (point eyes at angles)
- Recording and playback:
record start- Begin recordingrecord stop <filename>- Save a recordingrecord cancel- Discard recordingrecord status- Check recording statelist- View all recordingsdownload_timeline <filename>- Download a recording file as JSONplay <filename>- Play a recordingupload_timeline <filename> <json_file>- Upload a recording file from diskpause/resume/stop- Control playbackseek <position_ms>- Jump to positiontimeline_status- Check playback state
Via Python:
import socket
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect(('localhost', 5000))
client.send(b'happy')
response = client.recv(1024) # Some commands return responses
client.close()Via command line (netcat/nc):
echo "happy" | nc localhost 5000
echo "record start" | nc localhost 5000
echo "record stop my_recording" | nc localhost 5000
echo "play my_recording" | nc localhost 5000
echo "timeline_status" | nc localhost 5000Via PowerShell:
$socket = New-Object System.Net.Sockets.TcpClient
$socket.Connect('localhost', 5000)
$stream = $socket.GetStream()
[byte[]]$bytes = [System.Text.Encoding]::ASCII.GetBytes("happy")
$stream.Write($bytes, 0, $bytes.Length)
$stream.Close()The pumpkin face server also provides a WebSocket interface on port 5001 for browser-based control panels and real-time communication.
Via JavaScript:
const ws = new WebSocket('ws://localhost:5001');
ws.onopen = () => {
ws.send('happy');
ws.send('blink');
ws.send('timeline_status');
};
ws.onmessage = (event) => {
console.log('Response:', event.data);
};
ws.onerror = (error) => {
console.error('WebSocket error:', error);
};WebSocket protocol:
- Each command is sent as a plain text message (same format as TCP)
- Responses are sent back immediately as text messages
- Empty responses (for animations) are not sent
- Connection can be reused for multiple commands
- Server handles concurrent WebSocket clients simultaneously
Simple HTML test client:
<!DOCTYPE html>
<html>
<head>
<title>Mr. Pumpkin WebSocket Client</title>
</head>
<body>
<h1>Mr. Pumpkin Control</h1>
<input type="text" id="command" placeholder="Enter command">
<button onclick="send()">Send</button>
<div id="response"></div>
<script>
const ws = new WebSocket('ws://localhost:5001');
const responseDiv = document.getElementById('response');
function send() {
const cmd = document.getElementById('command').value;
if (cmd) {
ws.send(cmd);
}
}
ws.onmessage = (event) => {
responseDiv.innerHTML = '<p>' + event.data + '</p>';
};
</script>
</body>
</html>Port allocation:
- TCP (port 5000): Text-based commands, command-line clients, legacy support
- WebSocket (port 5001): Browser clients, real-time dashboards, concurrent connections
Both protocols support the same commands and are always available when the server runs.
Full-featured test client:
For comprehensive testing and debugging, open websocket-test-client.html in your browser. This client includes:
- Connection status monitoring with automatic fallback
- Quick test buttons for common commands
- Timeline upload testing (multi-line JSON)
- Full event logging with timestamps
- Error handling and diagnostics
neutral- Default expressionhappy- Smiling facesad- Frowning faceangry- Angry eyes and mouthsurprised- Wide eyes, open mouthscared- Frightened expressionsleeping- Eyes closed (sleeping)
record_startorrecord start- Begin recording commandsrecord_stop <filename>orrecord stop <filename>- Stop recording and save with filenamerecord_cancelorrecord cancel- Discard current recording without savingrecording_statusorrecord status- Show recording state (is_recording, command_count, duration_ms)list_recordingsorlist- Show all available recordingsdelete_recording <filename>- Remove a saved recordingrename_recording <old_name> <new_name>- Rename a saved recordingupload_timeline <filename> <json_file>- Upload a recording file from disk (filename: name to store as, json_file: local path to JSON file)download_timeline <filename>- Download a recording file as JSON string (filename: name of recording to download)play <filename>- Start playing a recorded timelinepause- Pause current playbackresume- Resume from paused statestop- Stop playback and return to startseek <position_ms>- Jump to specific position in recordingtimeline_status- Show current playback state (state, filename, position, duration, is_playing)
blink- Blink both eyeswink_left- Wink left eye onlywink_right- Wink right eye onlyroll_clockwise- Roll eyes clockwiseroll_counterclockwise- Roll eyes counter-clockwiseraise_eyebrows- Raise both eyebrowslower_eyebrows- Lower both eyebrowsraise_left_eyebrow- Raise left eyebrow onlylower_left_eyebrow- Lower left eyebrow onlyraise_right_eyebrow- Raise right eyebrow onlylower_right_eyebrow- Lower right eyebrow only
gaze <x> <y>- Point both eyes at angle (x, y in degrees, -90 to +90)gaze <x1> <y1> <x2> <y2>- Point left and right eyes independently
wiggle_nose- Animate nose wigglereset_nose- Stop nose animation and return to neutral
Recordings are stored as JSON files in the user's home directory. Each recording contains:
File location: ~/.mr-pumpkin/recordings/{filename}.json
File structure:
{
"version": "1.0",
"duration_ms": 5230,
"commands": [
{
"time_ms": 0,
"command": "happy"
},
{
"time_ms": 500,
"command": "blink"
},
{
"time_ms": 2000,
"command": "roll_clockwise"
}
]
}Field descriptions:
version- Format version for future compatibility (currently "1.0")duration_ms- Total duration of the recording in millisecondscommands- Array of commands, each with:time_ms- Timestamp in milliseconds from the start of the recordingcommand- The pumpkin command to execute at this time (e.g., "happy", "blink", "gaze")args(optional) - Additional command arguments for commands that need them (e.g., gaze angles)
All recordings are stored in ~/.mr-pumpkin/recordings/. The directory is created automatically when you save your first recording.
- On Windows:
C:\Users\{username}\.mr-pumpkin\recordings\ - On macOS/Linux:
/Users/{username}/.mr-pumpkin/recordings/or~/.mr-pumpkin/recordings/
You can browse recordings in this directory to:
- Back up important sequences
- Edit timeline files directly (JSON format is human-readable)
- Share recordings with others
- Delete old recordings manually if desired
While the application is running:
1→ Neutral2→ Happy3→ Sad4→ Angry5→ Surprised6→ Scared7→ SleepingESC→ Exit fullscreen
Projection Alignment (Jog Controls):
Arrow Keys→ Nudge projection in any direction (5px steps)0→ Reset projection offset to center
Animation Controls:
B→ BlinkL→ Wink leftR→ Wink rightC→ Roll eyes clockwiseX→ Roll eyes counter-clockwiseU→ Raise both eyebrowsJ→ Lower both eyebrows[→ Raise left eyebrow (Shift+[ to lower)]→ Raise right eyebrow (Shift+] to lower)
Edit pumpkin_face.py to customize:
- Colors: Modify
PUMPKIN_COLOR,EYE_COLOR,MOUTH_COLOR, etc. - Animation speed: Change
self.transition_speed - Face size: Adjust
pumpkin_radius - Socket port: Change the port in
_run_socket_server() - Recordings storage path: Modify the
recordings_dirin the FileManager class
The application can run in headless mode (without a display) for automation and CI/CD environments. In this mode:
- The TCP socket server runs fully functional
- All commands work normally (expressions, animations, recording/playback)
- The pygame display is optional and gracefully skipped if unavailable
- Useful for running the pumpkin server on a headless Linux machine that communicates with a remote display
- pumpkin_face.py: Main application with rendering and network server
- client_example.py: Example client for sending commands
- tests/: Test suite directory with all test modules
- requirements.txt: Production dependencies (pygame only)
- requirements-dev.txt: Development dependencies (includes pytest for testing)
Run the test suite to validate projection mapping and other features:
# Install development dependencies (if not already installed)
pip install -r requirements-dev.txt
# Run all tests (430+ tests)
pytest
# Run specific test file
pytest tests/test_projection_mapping.py -v
# Run specific test class
pytest tests/test_projection_mapping.py::TestProjectionMappingColors -v
# Run with detailed output
pytest -vvThe test suite validates:
- Black background (RGB 0,0,0) for projection mapping
- White features (RGB 255,255,255) for eyes, nose, mouth
- Minimum 15:1 contrast ratio for reliable projection
- All expression states render correctly
- Resolution independence
- Transition behavior
The project includes comprehensive integration tests for dual-protocol operation (TCP + WebSocket):
# Run integration tests only
pytest tests/test_integration_dual_protocol.py -v
# Run TCP integration tests
pytest tests/test_tcp_integration.py -vDual-Protocol Integration Tests (test_integration_dual_protocol.py) validate:
-
Identical Responses (5 tests)
- Both TCP and WebSocket return identical responses for the same commands
- Status queries (timeline_status, recording_status) return consistent JSON
- List operations return matching results
-
Protocol Switching (3 tests)
- Commands work when alternating between TCP and WebSocket
- No state corruption when switching protocols mid-session
- 10+ command sequences alternating protocols
-
Concurrent Commands (2 tests)
- Multiple concurrent commands from both protocols execute correctly
- Concurrent status queries from both protocols
-
Error Handling Consistency (3 tests)
- Invalid commands return errors on both protocols
- Malformed commands handled gracefully
- Nonexistent file errors consistent across protocols
-
Timeline Upload/Download (3 tests)
- Upload timeline via TCP, verify via WebSocket
- Upload timeline via WebSocket, verify via TCP
- Download same timeline via both protocols yields identical results
-
State Synchronization (3 tests)
- Recording state visible from both protocols
- Playback state visible from both protocols
- Expression changes propagate across protocols
-
Connection Resilience (2 tests)
- TCP disconnect doesn't affect WebSocket
- WebSocket disconnect doesn't affect TCP
-
Large Payloads (2 tests)
- Large timelines (>100KB JSON, 200+ commands) work on both protocols
-
Stress Testing (1 test)
- 50 rapid commands alternating TCP/WebSocket
-
Playback Integration (2 tests)
- Start playback on one protocol, control via the other
- Cross-protocol pause/resume/stop
-
Clean Shutdown (1 test)
- Graceful disconnect on both protocols without orphaned resources
Total: 27 integration tests covering all critical dual-protocol scenarios.
Mr. Pumpkin was built using Squad — an agentic coding solution created by Brady Gaster that orchestrates a team of specialized AI agents to collaboratively design, build, test, and document software.
The following AI agents collaborated to develop Mr. Pumpkin, drawn from the Arcane universe:
| Agent | Role | Responsibility |
|---|---|---|
| 🏗️ Jinx | Lead | Architecture, scope decisions, code review |
| ⚛️ Ekko | Graphics Dev | 2D rendering, animations, facial expressions |
| 🔧 Vi | Backend Dev | Network socket server, command handling, timeline playback |
| 🧪 Mylo | Tester | Test suite, quality assurance, edge cases |
| 📋 Scribe | Memory & Logging | Decisions, session logs, cross-agent context |
| 🔄 Ralph | Work Monitor | Work queue, backlog tracking, issue triage |
Want to build your own project with an AI team like this? Check out Brady Gaster's Squad.
MIT