Duma
by zoltanpetrik
README.md
<div align="center">
<img src="icon.png" width="128" alt="Duma icon">
# Duma - Async questions from AI agents to you, via MCP<br>Answer by text or voice
*"Duma" - Hungarian for "talking"*
</div>
Duma is a local macOS app. Agents send questions through MCP, you answer in a native window whenever you get to it, and agents poll back for the response.
## Demo

## Prerequisites
- macOS (tested on macOS 15+)
- [Homebrew](https://brew.sh)
## Setup
### 1. Install dependencies
```bash
brew install python # 3.12 or newer
brew install portaudio # required for audio recording
brew install uv # Python package manager
```
### 2. Clone and set up the project
```bash
git clone https://github.com/zoltanpetrik/duma.git
cd duma
uv venv # creates an isolated Python environment for Duma
uv sync # installs all dependencies into that environment
```
Voice transcription requires an OpenAI API key - see [Configuration](#configuration) below. The app works without it; recordings just won't be transcribed.
## Running
```bash
source .venv/bin/activate
python -m duma
```
With debug mode (enables developer tools and verbose logging):
```bash
python -m duma --debug
```
When running from the command line, the menu bar icon and microphone TCC prompt will show `Python` instead of `Duma`. Use the distribution build for full macOS integration.
### Try it out
The app opens empty. To see it in action without setting up MCP, start the app in debug mode (`python -m duma --debug`) and create a test question from another terminal:
```bash
curl -X POST http://localhost:31299/api/questions \
-H "Content-Type: application/json" \
-d '{
"agent_id": "test-agent",
"short_description": "Pasta or rice?",
"question_body": "Should we make pasta or rice tonight?",
"proposed_answers": ["Pasta", "Rice", "Something else"],
"high_priority": false
}'
```
A notification pops up, the question appears in the sidebar, and you can answer it. This endpoint is only available in debug mode - in production, questions come through MCP.
### CLI options
| Option | Default | Description |
|---|---|---|
| `--port` | `31299` | HTTP server port |
| `--debug` | off | Enable pywebview devtools (right-click → Inspect Element) and verbose logging |
## MCP Configuration
Make sure Duma is running before you connect any MCP client.
### Claude Code
Add Duma as a global MCP server so it is available in every project:
```bash
claude mcp add --transport http --scope user duma http://localhost:31299/mcp
```
Then verify that it was added:
```bash
claude mcp list
```
### Encouraging Claude to use Duma
Claude will not proactively use Duma unless you tell it to. Add this to your project's `CLAUDE.md` (or `~/.claude/CLAUDE.md` to apply it globally):
```markdown
## Duma (async questions)
When you encounter a question or decision that doesn't need an immediate answer
(approvals, preferences, non-blocking clarifications), use the Duma MCP tools
instead of asking in the chat. This lets me answer on my own time while you
continue working.
Use agent_id "claude-code" for all Duma calls. Before asking a new question,
call list_my_pending_questions to check if you already have unanswered questions
on the same topic. After asking, continue with other work and poll get_response
later - don't wait for an answer.
```
### Other MCP clients
Add Duma to your MCP client config:
```json
{
"mcpServers": {
"duma": {
"url": "http://localhost:31299/mcp"
}
}
}
```
## Distribution build
For proper macOS integration (Dock name, notification identity, microphone permission prompt all showing "Duma" instead of "Python"), build the standalone app:
```bash
./build.sh
open dist/Duma.app
```
This runs PyInstaller and bundles the Python interpreter, dependencies, application code, and static files into a self-contained app at `dist/Duma.app`. The script handles code signing automatically. The app icon lives at `static/icon.icns` (generate one at [icon.kitchen](https://icon.kitchen) if you need to replace it).
The output can also be copied to another Mac and launched directly - no Python, venv, or Homebrew needed on the target machine.
## Configuration
To enable voice transcription, create a config file with your OpenAI API key:
```bash
mkdir -p ~/.duma
cat > ~/.duma/config.json << 'EOF'
{
"OPENAI_API_KEY": "your-api-key-here"
}
EOF
```
The app works without this - voice recordings are saved but not transcribed. Transcription language (Hungarian/English) can be switched in the app via the toggle next to the record button.
## Development
See [DOCS.md](docs/DOCS.md) and [SPECS.md](docs/SPECS.md) for the full picture.
### Tests
```bash
uv sync --group test
.venv/bin/python -m pytest
```
66 tests covering the database, service, REST API, and transcription layers. macOS-native integration (menu bar, notifications, audio recording) is tested manually - see the QA checklist in [SPECS.md](docs/SPECS.md).
## Data
All Duma data stays local:
- Configuration: `~/.duma/config.json`
- Database: `~/.duma/duma.db`
- Audio recordings: `~/.duma/audio/`
- Logs: `~/.duma/duma.log`
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues