A minimal threaded wrapper for Python curses that simplifies terminal user interface development with built-in threading support and lifecycle management.
- Simple context manager for curses applications
- Built-in update loop with configurable FPS
- Lifecycle hooks for application logic
- Threaded version for running updates in separate thread
- Text drawing utilities with styling support
pip install cursersimport cursers
class MyApp(cursers.App):
# Called when entering the application context
def on_enter(self, screen):
screen.draw_text(0, 0, "Hello, World!", bold=True)
# Called each frame with screen object for input/drawing
def on_update(self, screen):
key = screen.get_key()
if key == 27: # ESC key
self.request_exit()
# Run the application
with MyApp() as app:
while not app.is_exit_requested():
app.update()import cursers
import time
class MyThreadedApp(cursers.ThreadedApp):
def on_enter(self, screen):
screen.draw_text(0, 0, "Running in background thread!")
def on_update(self, screen):
key = screen.get_key()
if key == 27: # ESC key
self.request_exit()
# Run in background thread
with MyThreadedApp() as app:
while not app.is_exit_requested():
time.sleep(0.1) # Do other workFor complete API documentation, visit the project documentation.
The main application class that provides a context manager for curses applications.
App(fps=30, keypad=False)fps: Target frames per second (default: 30)keypad: Whether to enable arrow keys and function keys (default: False)
request_exit(): Requests the application to exitis_exit_requested(): ReturnsTrueif exit has been requestedupdate(): Updates the application state and handles input (call in main loop)
Override these methods in your subclass:
on_enter(screen): Called when entering the contexton_update(screen): Called every frameon_exit(screen): Called when exiting the context
Extends App to run the update loop in a separate thread.
class MyThreadedApp(cursers.ThreadedApp):
def on_update(self, screen):
# Handle input and drawing
key = screen.get_key()
pass
with MyThreadedApp() as app:
# Update loop runs automatically in background thread
while not app.is_exit_requested():
# Main thread is free for other tasks
time.sleep(0.1)Low-level screen management for curses applications. Provides direct access to curses screen operations.
get_key(): Returns the next key code from input buffer (-1 if no key available)refresh(): Refreshes the screen to display pending changesdraw_text(y, x, text, bold=False, underline=False): Draw styled text at position
Basic threading context manager for custom threading needs.
class MyThread(cursers.Thread):
def run(self):
# Your thread code here
pass
with MyThread() as thread:
# Thread runs automatically
passCheck out the examples/ directory for complete working examples:
examples/move_control.py- Basic movement control with keyboard inputexamples/move_control_gravity.py- Threaded application with gravity simulation
# Clone the repository
git clone https://github.com/threeal/cursers.git
cd cursers
# Install development dependencies
uv sync
# Install Git hooks
uv run lefthook install# Format code
dprint fmt
# Run linter
uv run ruff check --fixThis project is licensed under the terms of the MIT License.
Copyright © 2025 Alfi Maulana