rishi is backend-agnostic agent environment. Owns hermes-agent bootstrap, multi-agent runtime, exposes rishi.ask/stream/Session Python API + standalone CLI.
rishi/env.py— idempotent XDG bootstrap (setup, teardown)rishi/session.py— SQLite session store + litesearch semantic search (FastEncode defaults)rishi/skills.py— skill discovery + assemblyrishi/tools.py— ToolRegistry + context_builderrishi/media.py— image/audio content block builders + audio_to_text bridge (lyca)rishi/clipboard.py— pyperclip read/writerishi/agent.py— HermesBackend, LycaBackend, HybridBackend, run_turn (HITL gate)rishi/prompt.py— DEFAULT_SYSTEM_PROMPT + build_system_prompt (caveman injection)rishi/api.py— ask, aask, stream, Session happy-path layerrishi/cli.py— one-shot + REPL with Ctrl+V paste (primary mechanism)
Primary mechanism in REPL for multimodal input:
- Clipboard = image/audio file path → attached to next prompt automatically
- Clipboard = text → inserted inline into input buffer
- prompt_toolkit used when available for real Ctrl+V keybinding
- Readline fallback: type
pasteon empty line for same effect - CLI one-shot equivalent:
rishi paste "prompt"
litesearch.FastEncode()with no args (default ONNX model), FTS5 LIKE fallback- Audio bridge: lyca (gemma4-e2b) transcribes audio → text → Hermes
- Transparent kwargs: ask/stream/Session all accept images=, audio=, caveman=
- Caveman skill: verbatim from JuliusBrussee/caveman, 3 intensities (lite/full/ultra)
- Frozen dataclasses for value types (PromptTurn, ConversationSeed, BackendSpec)
- fastai/fastcore conventions: functions over classes, xdg paths
- Graceful optional imports: try/except ImportError throughout
- fastai/fastcore: ifnone, store_attr where appropriate
- sqlite-utils not raw sqlite3
- Single-line docstrings
- Type hints on all public functions
pytest tests/
All tests use mocks — no API keys needed. 72+ tests.