Simple DSPy based coding harness with a Textual TUI
Project description
monet.py
▗▖ ▗▖ ▗▄▖ ▗▖ ▗▖▗▄▄▄▖▗▄▄▄ ▗▄▄▖▗▖ ▗▖
▐▛▚▞▜▌▐▌ ▐▌▐▛▚▖▐▌▐▌ █ ▐▌ ▐▌▝▚▞▘
▐▌ ▐▌▐▌ ▐▌▐▌ ▝▜▌▐▛▀▀▘ █ ▐▛▀▘ ▐▌
▐▌ ▐▌▝▚▄▞▘▐▌ ▐▌▐▙▄▄▖ █ ▐▌▐▌ ▐▌
A simple DSPy based coding agent with a Textual TUI. Uses ReAct (learn more) for multi-step reasoning with tool calling.
Install
Requires Python 3.12+.
uv sync
Run
# Set API keys in .env (loaded automatically)
echo 'export ANTHROPIC_API_KEY=sk-...' >> .env
uv run monet
Features
Multi-provider model switching
Switch models at runtime with /model or /model <name>. The current model is shown in the bottom-right corner of the status bar.
| Provider | Models |
|---|---|
| Anthropic | claude-haiku-4-5, claude-sonnet-4, claude-opus-4 |
| OpenAI | gpt-4o, gpt-4o-mini, o3, o4-mini |
| NVIDIA NIM | gpt-oss-20b, gpt-oss-120b, qwen3-coder-480b, kimi-k2.5 |
Built-in coding tools
The ReAct agent has access to these tools:
| Tool | Description |
|---|---|
read |
Read files with line numbers, offset, and limit |
write |
Write/create files (creates directories as needed) |
edit |
Exact string replacement with unified diff output |
bash |
Shell command execution with timeout |
grep |
Regex search across files and directories |
list_dir |
List directory contents |
register_command |
Hot-load a slash command plugin from a Python file |
Self-programming commands
The agent can add new slash commands to itself at runtime. Ask it to "add a /greet command" and it will:
- Create a plugin file at
.monet/commands/greet.py - Call
register_command()to activate it immediately - The command persists across restarts
Plugin files follow a simple convention:
NAME = "/greet"
DESCRIPTION = "Greet someone"
def handler(app, args: str) -> None:
log = app.query_one("#content")
log.write(f"Hi {args.strip() or 'world'}!")
Commands can call app.predict(signature, **kwargs) to query the LLM using DSPy Predict:
def handler(app, args: str) -> None:
log = app.query_one("#content")
result = app.predict("topic -> summary", topic=args.strip())
log.write(result.get("summary", result.get("error", "")))
Slash command completion
Type / to see available commands. Tab autocompletes from the filtered list. ctrl+n / ctrl+p navigate the picker.
Input history
ctrl+p / ctrl+n navigate through previously submitted chat messages (when the command picker is not visible). Slash commands are not added to history. In-progress text is stashed and restored.
Keyboard shortcuts
| Key | Action |
|---|---|
? |
Show shortcuts help |
/ |
Show available commands |
Tab |
Autocomplete command name |
ctrl+p |
History previous / picker up |
ctrl+n |
History next / picker down |
ctrl+o |
Toggle thinking block visibility |
esc |
Cancel in-flight request |
ctrl+z |
Suspend process |
ctrl+b |
Cursor back one character |
ctrl+f |
Cursor forward one character |
ctrl+k |
Kill to end of line |
ctrl+y |
Yank (paste) killed text |
Response rendering
- Markdown with syntax-highlighted code blocks
- ReAct trajectory display (thinking, tool calls, tool results)
- Unified diffs with syntax highlighting after edits
- Animated spinner during LLM calls
- Text selection and auto-copy to clipboard
- Command output is kept in chat context for follow-up conversation
UI behavior
- Banner auto-hides when content overflows
- Typing anywhere auto-focuses the input
ctrl+oretroactively shows/hides all thinking blocks- Current model shown in status bar
Project layout
src/monet/
app.py # Textual TUI application
backends/
base.py # Backend protocol, data types
dummy.py # Stub backend for testing
dspy_backend.py # DSPy ReAct backend
commands/
__init__.py # CommandRegistry + plugin loader
_builtins.py # Built-in /model command
providers.py # Model/provider registry
tools.py # Coding tools + register_command
.monet/commands/ # Per-project command plugins (created at runtime)
tests/
test_tools.py # Tool test suite
test_commands.py # Command registry test suite
Testing
uv run pytest
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file monet_code-0.1.0.tar.gz.
File metadata
- Download URL: monet_code-0.1.0.tar.gz
- Upload date:
- Size: 26.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.7.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1848bd7a5ab48fb26477e5b08f4593b41f613861bf6fa85f247dcd5acaff3a00
|
|
| MD5 |
a75e4890075fcd16fbee8043e84d9a21
|
|
| BLAKE2b-256 |
78c23d08a7a243c4454d835123336d3fc12e887ea4554eed05fbd6c981ff5f29
|
File details
Details for the file monet_code-0.1.0-py3-none-any.whl.
File metadata
- Download URL: monet_code-0.1.0-py3-none-any.whl
- Upload date:
- Size: 27.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.7.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7356f3eaf46908529647e74956a346c0c09bab912358c81b9f1b00eddc6db409
|
|
| MD5 |
711df8122995fd6b412b55abfb873e46
|
|
| BLAKE2b-256 |
36a42d6b19f9f1311cb24f072123f086dabfa3e895cbb7e292e4f10b59e2dc6c
|