Complete getting started guide for Universe 2025 (Tufty) Badge from zero to first app. Use when helping absolute beginners, providing step-by-step first-time setup, or when users ask "how do I get started", "where do I begin", or "first steps with the badge".
Provides a complete step-by-step guide to set up a development environment and create your first MonaOS app for the Universe 2025 (Tufty) Badge. Use when users ask "how do I get started", "where do I begin", or need first-time setup instructions for the badge.
/plugin marketplace add johnlindquist/badger-2350-plugin/plugin install badger-2350-dev@badger-marketplaceThis skill inherits all available tools. When active, it can use any tool Claude has access to.
Complete step-by-step guide to go from zero to creating your first app for MonaOS on the Universe 2025 (Tufty) Badge. Perfect for absolute beginners!
The Universe 2025 Badge is a custom version of the Pimoroni Tufty 2350, created for GitHub Universe 2025. It comes pre-loaded with MonaOS, a MicroPython-based operating system with an app launcher.
Your badge runs MonaOS, which provides:
/system/apps/__init__.py, icon.png (24x24), and optional assets/update() function called every frameWhy: You need Python on your computer to run the tools that communicate with your badge.
macOS:
# Install using Homebrew
brew install python3
# Verify
python3 --version # Should show 3.8 or higher
Linux (Ubuntu/Debian):
sudo apt update
sudo apt install python3 python3-pip python3-venv
python3 --version
Windows:
python --version✅ Checkpoint: Run python3 --version (or python --version on Windows). You should see version 3.8 or higher.
Need help? See the
python-setupskill for detailed installation guides.
Why: Keeping projects organized and using virtual environments prevents conflicts.
# Create a directory for your project
mkdir ~/badger-projects
cd ~/badger-projects
mkdir hello-badge
cd hello-badge
# Create a virtual environment
python3 -m venv venv
# Activate it
# macOS/Linux:
source venv/bin/activate
# Windows (PowerShell):
venv\Scripts\Activate.ps1
# Windows (Command Prompt):
venv\Scripts\activate.bat
✅ Checkpoint: Your terminal prompt should now show (venv) at the beginning.
Why: These tools let you communicate with your badge, upload files, and run code.
# Make sure venv is activated (you should see "(venv)" in prompt)
# Install essential tool
pip install mpremote
# Verify installation
mpremote --version
✅ Checkpoint: Command should show version number without errors.
Why: Let's make sure your computer can talk to your badge.
macOS/Linux:
ls /dev/tty.usb*
# Should see something like: /dev/tty.usbmodem14201
Windows:
# In PowerShell
[System.IO.Ports.SerialPort]::getportnames()
# Should see something like: COM3
macOS/Linux:
mpremote connect /dev/tty.usbmodem* exec "print('Hello from Badge!')"
Windows:
mpremote connect COM3 exec "print('Hello from Badge!')"
✅ Checkpoint: You should see "Hello from Badge!" printed in your terminal.
Troubleshooting:
- Badge not found? Try different USB ports
- Permission denied? See Step 4a below
- Still stuck? See the
badger-diagnosticsskill
If you get "Permission denied" on Linux:
# Add yourself to dialout group
sudo usermod -a -G dialout $USER
# Log out and log back in for changes to take effect
# Or restart your computer
Why: We must verify everything is working before writing code.
# macOS/Linux:
mpremote connect /dev/tty.usbmodem* exec "
import sys
print('✓ MicroPython:', sys.version)
# Test badgeware module
from badgeware import screen, brushes, shapes
print('✓ badgeware module: loaded')
print('✓ Display size: 160x120')
print('✓ ALL CHECKS PASSED!')
"
# Windows:
mpremote connect COM3 exec "import sys; from badgeware import screen, brushes, shapes; print('✓ MicroPython:', sys.version); print('✓ badgeware loaded'); print('✓ ALL CHECKS PASSED!')"
✅ Checkpoint - ALL must pass:
DO NOT PROCEED until all checks pass.
MonaOS apps must follow this structure:
my_app/
├── icon.png # 24x24 PNG icon for launcher
├── __init__.py # Entry point with update() function
└── assets/ # Optional: app assets (auto-added to path)
└── ...
Your __init__.py must implement:
init() - Optional, called once when app launchesupdate() - Required, called every frame by MonaOSon_exit() - Optional, called when returning to menuCreate the app directory structure:
mkdir hello_app
cd hello_app
Create hello_app/__init__.py:
# hello_app/__init__.py - Your first MonaOS app!
from badgeware import screen, brushes, shapes, io, PixelFont
import math
# Optional: called once when app launches
def init():
screen.font = PixelFont.load("nope.ppf")
print("Hello app initialized!")
# Required: called every frame by MonaOS
def update():
# Clear the framebuffer
screen.brush = brushes.color(20, 40, 60)
screen.clear()
# Draw animated sine wave
y = (math.sin(io.ticks / 100) * 20) + 60
screen.brush = brushes.color(0, 255, 0)
for x in range(160):
screen.draw(shapes.rectangle(x, int(y), 1, 1))
# Draw text
screen.brush = brushes.color(255, 255, 255)
screen.text("Hello, Badge!", 10, 10)
screen.text("Press HOME to exit", 10, 100)
# Handle button presses
if io.BUTTON_A in io.pressed:
print("Button A pressed!")
if io.BUTTON_HOME in io.pressed:
# HOME button exits to MonaOS menu automatically
pass
# Optional: called before returning to menu
def on_exit():
print("App exiting!")
Create hello_app/icon.png:
✅ Checkpoint: Files created:
hello_app/__init__.pyhello_app/icon.png (24x24 PNG)# From your project directory (not inside hello_app/)
cd ~/badger-projects/hello-badge
# Run the app temporarily (doesn't save to badge)
# macOS/Linux:
mpremote connect /dev/tty.usbmodem* run hello_app/__init__.py
# Windows:
mpremote connect COM3 run hello_app/__init__.py
✅ Checkpoint: Your badge display should show "Hello, Badge!" with an animated wave. Press HOME to exit.
Why: Install it permanently so it appears in the MonaOS launcher menu!
⚠️ IMPORTANT: The /system/apps/ directory is READ-ONLY via mpremote. You MUST use USB Mass Storage Mode.
macOS/Linux:
# Copy your entire app directory to the badge
cp -r hello_app /Volumes/BADGER/apps/
# OR manually via Finder:
# 1. Open BADGER drive in Finder
# 2. Navigate to apps/ folder
# 3. Drag hello_app folder into apps/
Windows:
# Copy your entire app directory
# (Replace D: with your actual BADGER drive letter)
xcopy hello_app D:\apps\hello_app\ /E /I
# OR manually via File Explorer:
# 1. Open BADGER drive
# 2. Navigate to apps\ folder
# 3. Drag hello_app folder into apps\
macOS:
# Eject the drive
diskutil eject /Volumes/BADGER
# Or right-click BADGER in Finder → Eject
Windows:
Linux:
# Eject the drive
sudo umount /media/$USER/BADGER
All Platforms:
✅ Checkpoint:
Note: The default MonaOS menu shows 6 apps. You may need to expand pagination (see https://badger.github.io/hack/menu-pagination/)
🎉 Congratulations! Your first MonaOS app is installed and running!
You just:
Save these commands - you'll use them a lot:
# Activate your virtual environment
source venv/bin/activate # macOS/Linux
venv\Scripts\Activate.ps1 # Windows
# Test app temporarily (doesn't save)
mpremote run my_app/__init__.py
# Install app to MonaOS launcher (USB Mass Storage Mode REQUIRED)
# 1. Press RESET button twice on badge (enters Mass Storage Mode)
# 2. Copy app to badge:
cp -r my_app /Volumes/BADGER/apps/ # macOS/Linux
xcopy my_app D:\apps\my_app\ /E /I # Windows
# 3. Eject BADGER drive safely
# 4. Press RESET once to reboot
# List files (read-only view)
mpremote ls /system/apps
# Connect to REPL (interactive mode)
mpremote
# (Ctrl+C to interrupt, Ctrl+D to soft reset, Ctrl+X to exit)
⚠️ Remember: You CANNOT use mpremote to install apps to /system/apps/ - it's read-only! Always use USB Mass Storage Mode.
def update():
screen.brush = brushes.color(20, 40, 60)
screen.clear()
screen.brush = brushes.color(255, 255, 255)
if io.BUTTON_A in io.held:
screen.text("Button A held!", 10, 50)
elif io.BUTTON_B in io.pressed:
screen.text("Button B pressed!", 10, 50)
elif io.BUTTON_C in io.released:
screen.text("Button C released!", 10, 50)
def update():
screen.brush = brushes.color(20, 40, 60)
screen.clear()
# Draw a circle
screen.brush = brushes.color(255, 0, 0)
screen.draw(shapes.circle(80, 60, 30))
# Draw a rectangle
screen.brush = brushes.color(0, 255, 0)
screen.draw(shapes.rectangle(10, 10, 50, 30))
# Draw a line
screen.brush = brushes.color(255, 255, 255)
screen.draw(shapes.line(0, 0, 160, 120))
# Add at top level
counter = 0
def update():
global counter
screen.brush = brushes.color(0, 0, 0)
screen.clear()
screen.brush = brushes.color(255, 255, 255)
screen.text(f"Count: {counter}", 30, 50)
if io.BUTTON_A in io.pressed:
counter += 1
if io.BUTTON_B in io.pressed:
counter = 0
Yes, activate it each time you open a new terminal.
Edit locally, test with mpremote, then reinstall via Mass Storage Mode:
# 1. Edit your code locally
# 2. Test it temporarily
mpremote run my_app/__init__.py
# 3. Reinstall via Mass Storage Mode
# - Press RESET twice (enters Mass Storage Mode)
# - Replace files in /Volumes/BADGER/apps/my_app/
# - Eject and press RESET once
Yes! Enter USB Mass Storage Mode (press RESET twice). Badge appears as "BADGER" disk. Edit files in /Volumes/BADGER/apps/ using any text editor.
Press the RESET button on the back of the badge.
Connect to REPL:
mpremote
Then test importing: import my_app. Errors will show in terminal.
mpremote rm -rf :/system/apps/my_app
The default menu shows 6 apps. Expand pagination: https://badger.github.io/hack/menu-pagination/
ls /dev/tty.usb*Linux: Add yourself to dialout group (see Step 4a) Windows: Run PowerShell as Administrator
Activate your virtual environment:
source venv/bin/activate # macOS/Linux
venv\Scripts\Activate.ps1 # Windows
mpremote ls /system/apps/my_app__init__.py and icon.png→ See badger-app-creator skill
→ See badger-hardware skill
→ See micropython-repl skill
→ See badger-deploy skill
You now have everything you need to create amazing projects with your Universe 2025 Badge. Happy coding! 🦡
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.