Sanskrit: ṛṣi — hermit, seer, one who dwells apart.
Backend-agnostic agent environment. Wraps hermes-agent for cloud and lyca for local. Exposes a unified Python API and a Rich-rendered CLI with Ctrl+V multimodal paste. Powered by safecmd + safepyrun + pyskills for safe, transparent tool execution.
pip install rishi
rishi --replimport rishi
print(rishi.ask("Explain SQLite FTS5"))That's it. All tools are on by default.
pip install rishi # hermes (cloud) only
pip install rishi[local] # + lyca (local LiteRT-LM)
pip install rishi[search,memory] # + webba (web search) + karma (code memory)
pip install rishi[mac] # + shortcutpy (macOS Shortcuts compiler)
pip install rishi[full] # everythingrishi.Session() auto-discovers every installed tool (safecmd, safepyrun, bgterm,
any pyskills package). Safe commands run silently. Anything outside the safecmd
allowlist shows a single inline prompt:
import rishi
sess = rishi.Session() # hitl=True (default)
# git log, grep, cat etc. → run silently (inside safecmd allowlist)
# npm run dev via bgterm → shows: ⚠️ rishi wants to run bgterm `npm run dev` [Y/n]:
print(sess.ask(
"Check git history, find all TODO comments, start the dev server, "
"and give me a summary."
))Disable HITL for CI/scripts: rishi.Session(hitl=False).
import rishi
# One-shot
reply = rishi.ask("Explain SQLite FTS5")
# Streaming
async for chunk in rishi.stream("Write a haiku about Python"):
print(chunk, end="", flush=True)
# Multi-turn session
sess = rishi.Session()
sess.ask("My stack is FastHTML + SQLite")
print(sess.ask("Suggest a caching strategy"))
sess.save() # → returns session_id for later resume
# Resume
sess2 = rishi.Session(session_id=42)rishi.ask("Describe this", images=["screenshot.png"])
rishi.ask("Respond to what was said", audio=["meeting.wav"])rishi.ask("Explain CAP theorem", caveman=True) # full (default)
rishi.ask("Explain CAP theorem", caveman="lite") # drop filler only
rishi.ask("Explain CAP theorem", caveman="ultra") # telegraphicrishi.ask("Latest best practice for SQLite WAL", context=True)# One-shot
rishi "Explain async generators in Python"
# Flags
rishi --caveman "Explain React re-renders"
rishi --image screenshot.png "What's wrong here?"
rishi --audio meeting.wav "Summarise"
rishi --context "Best SQLite indexing strategy"
rishi --backend lyca "Offline question"
# Interactive REPL (Ctrl+V | /help shown at startup)
rishi --repl
# Ctrl+V paste — one-shot equivalent
rishi paste "Describe this" # reads from clipboard automatically
# Sessions
rishi --sessions
rishi --session 42 --repl
rishi --skillsCtrl+V is the primary paste mechanism (requires pip install prompt-toolkit).
The startup banner shows: Ctrl+V to paste file/text.
| Clipboard content | Effect |
|---|---|
Image file path (.jpg, .png, …) |
Attached 📎 to next prompt |
Audio file path (.wav, .mp3, …) |
Attached 🎵 and transcribed via lyca |
| Anything else | Inserted inline |
Without prompt-toolkit: type paste on an empty line for the same effect.
REPL commands: /help /caveman [lite|ultra|off] /reset /save /sessions /search <q> /skills /exit
rishi uses three libraries for safe tool execution:
| Library | Role |
|---|---|
| safecmd | Validates bash commands against an allowlist (AST-based) |
| safepyrun | Runs Python code in a RestrictedPython sandbox |
| pyskills | Discovers installable tool packages via entry points |
HITL gate — fires only when a command is outside the safecmd default allowlist:
run_bash("git log")→ silent (in allowlist)run_bash("npm run dev")→⚠️ rishi wants to run run_bashnpm run dev[Y/n]:run_python(code)→ always silent (safepyrun enforces internally)
See SKILLS.md for the full allowlist and tool reference.
pip install rishi[mac]
python examples/05_shortcuts_mac.pyCompiles real Apple Intelligence shortcuts:
- Rishi Summarise — Share any text → on-device AI summarises + tone-adjusts it
- Rishi Extract Page — Share a URL → extracts page text
Sessions stored in SQLite (~/.local/state/rishi/sessions.db). Semantic search via litesearch ONNX embeddings, LIKE fallback.
from rishi.session import search_sessions, list_sessions
results = search_sessions("SQLite FTS5")
recent = list_sessions(n=10)| Module | Purpose |
|---|---|
rishi.env |
Idempotent XDG bootstrap; assembles skills |
rishi.session |
SQLite store; litesearch semantic search |
rishi.agent |
HermesBackend, LycaBackend, _is_auto_approved HITL gate |
rishi.tools |
ToolRegistry (safecmd + safepyrun + pyskills); context_builder |
rishi.pyskill |
rishi's own pyskill entry point (run_bash, run_python, compile_shortcut) |
rishi.media |
Image/audio blocks; lyca transcription bridge; detect_file_type |
rishi.skills |
Hermes skill discovery and assembly |
rishi.prompt |
System prompt builder with caveman injection |
rishi.clipboard |
pyperclip read/write |
rishi.api |
ask, aask, stream, Session (inline HITL) |
rishi.cli |
Rich CLI + Ctrl+V REPL |
| File | What it shows |
|---|---|
examples/01_basic_ask.py |
ask + stream |
examples/02_multi_turn.py |
Multi-turn session + save/resume |
examples/03_multimodal.py |
Images, audio, Ctrl+V paste |
examples/04_caveman.py |
Caveman lite/full/ultra |
examples/05_shortcuts_mac.py |
Real macOS shortcuts via shortcutpy |
examples/06_tools_live.py |
All tools live — OOTB showcase |