add run.py

Hunter
Sunday, March 8th, 2026 at 11:49 PM

readme.md+4-3
run.pynew

readme.md
 5  turn mountains into molehills (then molehills into anthills) with <b>matryoshka</b>,<br>
 6  the nested todo list that breaks complex tasks into manageable subtasks.
 7  
   -<i><b>try it now <a href="https://hunterirving.github.io/matryoshka/">in your browser</a>!</b></i> (physical keyboard required)
 8 +<i><b>try it now <a href="https://hunterirving.github.io/matryoshka/">in your browser</a>!</b></i> (physical keyboard required).
 9 +
10 +alternatively, you can use ```./run.py``` to run matryoshka locally, or try installing it as a <a href="https://hunterirving.github.io/web_workshop/pages/pwa">Progressive Web App</a> that works completely offline.
11  
12  ### key features
13  - unlimited subtask depth
14  - intuitive keyboard controls
   -- automatic saving using browser's local storage
   -- installable as a <a href="https://hunterirving.github.io/web_workshop/pages/pwa">Progressive Web App</a>
15 +- automatically saves as you edit
16  
17  ### quickstart
18  1. press the `Return` / `Enter` key to add subtasks to the root "todo" task
run.py
 1 +#!/usr/bin/env python3
 2 +
 3 +import http.server, webbrowser, threading, signal
 4 +
 5 +PORT = 8000
 6 +server = http.server.HTTPServer(("", PORT), http.server.SimpleHTTPRequestHandler)
 7 +
 8 +def shutdown(sig, frame):
 9 +	print("\nShutting down...")
10 +	threading.Thread(target=server.shutdown).start()
11 +
12 +signal.signal(signal.SIGINT, shutdown)
13 +threading.Timer(0.5, lambda: webbrowser.open(f"http://localhost:{PORT}")).start()
14 +print(f"Serving on http://localhost:{PORT} (Ctrl+C to stop)")
15 +server.serve_forever()