Skip to content

Instantly share code, notes, and snippets.

@rhnvrm
Created June 18, 2026 08:28
Show Gist options
  • Select an option

  • Save rhnvrm/468798481b64730ba17fa4d8a5811b77 to your computer and use it in GitHub Desktop.

Select an option

Save rhnvrm/468798481b64730ba17fa4d8a5811b77 to your computer and use it in GitHub Desktop.
myinstants uvx CLI
#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.11"
# ///
# myinstants - tiny MyInstants CLI
#
# Save somewhere on your PATH, then make it executable:
# chmod +x myinstants
#
# Run directly as a uv script:
# ./myinstants search fahhh
# ./myinstants play fahhh
#
# Or install via a symlink:
# mkdir -p ~/.local/bin
# ln -sf "$PWD/myinstants" ~/.local/bin/myinstants
#
# Then use it like this:
# myinstants search vine boom
# myinstants play fahhh
# myinstants play vine boom -n 2
# myinstants play fahhh --dry-run
#
# Notes:
# - Uses https://myinstants-api.vercel.app/search?q=...
# - Picks the best-ranked match by default
# - Override the player with: MYINSTANTS_PLAYER=mpv myinstants play fahhh
from __future__ import annotations
import argparse
import json
import os
import re
import shutil
import subprocess
import sys
import urllib.error
import urllib.parse
import urllib.request
from dataclasses import dataclass
from difflib import SequenceMatcher
API_BASE = "https://myinstants-api.vercel.app"
DEFAULT_LIMIT = 10
@dataclass
class Instant:
id: str
title: str
url: str
mp3: str
class MyInstantsError(RuntimeError):
pass
def api_get(path: str, **params: str) -> dict:
query = urllib.parse.urlencode(params)
url = f"{API_BASE}{path}?{query}" if query else f"{API_BASE}{path}"
request = urllib.request.Request(
url,
headers={
"User-Agent": "myinstants-cli/0.1 (+https://www.myinstants.com)",
"Accept": "application/json",
},
)
try:
with urllib.request.urlopen(request, timeout=20) as response:
return json.load(response)
except urllib.error.HTTPError as exc:
detail = exc.read().decode("utf-8", errors="replace")
raise MyInstantsError(f"API error {exc.code}: {detail}") from exc
except urllib.error.URLError as exc:
raise MyInstantsError(f"Network error: {exc.reason}") from exc
def search_instants(query: str) -> list[Instant]:
payload = api_get("/search", q=query)
data = payload.get("data") or []
return [Instant(**item) for item in data]
def normalize(text: str) -> str:
return re.sub(r"\s+", " ", re.sub(r"[^a-z0-9]+", " ", text.lower())).strip()
def score(query: str, instant: Instant) -> tuple[float, float]:
q = normalize(query)
title = normalize(instant.title)
if q == title:
return (10.0, 1.0)
if q in title:
return (5.0, len(q) / max(len(title), 1))
ratio = SequenceMatcher(None, q, title).ratio()
starts = 0.2 if title.startswith(q[:3]) else 0.0
return (ratio + starts, ratio)
def pick_instant(query: str, results: list[Instant], index: int = 1) -> Instant:
if not results:
raise MyInstantsError(f"No results for {query!r}")
ranked = sorted(results, key=lambda item: score(query, item), reverse=True)
if index < 1 or index > len(ranked):
raise MyInstantsError(f"Choice {index} is out of range; got {len(ranked)} result(s)")
return ranked[index - 1]
def list_results(query: str, limit: int) -> int:
results = search_instants(query)
if not results:
print(f"No results for: {query}", file=sys.stderr)
return 1
for idx, instant in enumerate(results[:limit], start=1):
print(f"{idx:2}. {instant.title}\n {instant.mp3}")
return 0
def open_with_system_player(url: str) -> None:
override = os.environ.get("MYINSTANTS_PLAYER")
if override:
subprocess.run([override, url], check=True)
return
candidates: list[tuple[str, list[str]]] = [
("mpv", ["mpv", url]),
("vlc", ["vlc", "--play-and-exit", url]),
("ffplay", ["ffplay", "-nodisp", "-autoexit", url]),
("play", ["play", url]),
("paplay", ["paplay", url]),
("aplay", ["aplay", url]),
("afplay", ["afplay", url]),
("xdg-open", ["xdg-open", url]),
("open", ["open", url]),
]
for name, command in candidates:
if shutil.which(name):
subprocess.run(command, check=True)
return
raise MyInstantsError(
"No supported audio player found. Install mpv, vlc, ffplay, or set MYINSTANTS_PLAYER."
)
def build_parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(prog="myinstants", description="Search and play MyInstants sounds")
subparsers = parser.add_subparsers(dest="command", required=True)
search_parser = subparsers.add_parser("search", help="Search for sounds")
search_parser.add_argument("query", nargs="+", help="Search query")
search_parser.add_argument("-n", "--limit", type=int, default=DEFAULT_LIMIT, help="Number of results to print")
play_parser = subparsers.add_parser("play", help="Play the best matching sound")
play_parser.add_argument("query", nargs="+", help="Search query")
play_parser.add_argument("-n", "--choice", type=int, default=1, help="Play the Nth best-ranked result")
play_parser.add_argument("--dry-run", action="store_true", help="Print the selected sound without playing it")
return parser
def main(argv: list[str] | None = None) -> int:
parser = build_parser()
args = parser.parse_args(argv)
query = " ".join(args.query)
try:
if args.command == "search":
return list_results(query, args.limit)
if args.command == "play":
instant = pick_instant(query, search_instants(query), args.choice)
print(f"Playing: {instant.title}")
print(instant.mp3)
if not args.dry_run:
open_with_system_player(instant.mp3)
return 0
except MyInstantsError as exc:
print(f"error: {exc}", file=sys.stderr)
return 1
except subprocess.CalledProcessError as exc:
print(f"error: player failed with exit code {exc.returncode}", file=sys.stderr)
return 1
parser.error("unknown command")
return 2
if __name__ == "__main__":
raise SystemExit(main())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment