What happens if you ask an LLM to 'create an OpenAI chat TUI in Golang'? Almost certainly nothing, or maybe not.
Seriously, this is my attempt to create, with the help of AI, an agent for coding from scratch. The main reasons:
- pure fun
- studying in detail how agents and LLMs work
___ _ ___
| __|_ __ _ __ __ _ (_) |_ _|
| _|| ' \| ' \ / _` || | | |
|___|_|_|_|_|_|_|\__,_||_| |___|
Terminal AI Chat Interface
A terminal user interface (TUI) for chatting with any OpenAI-compatible API server.
- Minimal TUI: Clean, intuitive interface built with tview
- Streaming Responses: Real-time streaming of AI responses with typing effect
- Conversation Persistence: Automatically saves and loads conversations
- Custom Endpoints: Compatible with any OpenAI-compatible API server (remote and local)
- Keyboard Shortcuts: Efficient navigation and control
- Token Tracking: Real-time display of token usage
- Optimized for local llm: Sane system prompts for efficiency without sacrificing functionality (or at least we try)
- Go 1.21 or higher
- OpenAI-compatible endpoint
go install github.com/ilmich/emmai/cmd/emmai@latest# Clone the repository
git clone https://github.com/ilmich/emmai.git
cd emmai
# Build and install
make install
# Or just build
make build
./bin/emmaiexport OPENAI_API_KEY="sk-..."
emmaiCreate a config file at ~/.emmai/config.yaml:
# API Key (optional if using environment variable)
api_key: sk-...
# Model selection (default: gpt-3.5-turbo)
model: gpt-4
# Temperature: creativity level 0.0-2.0 (default: 0.7)
temperature: 0.7
# Max tokens per response (default: 2048)
max_tokens: 2048
# System prompt: sets AI behavior
system_prompt: "You are a helpful assistant focused on clear, concise explanations."See configs/config.example.yaml for a template.
EmmAI supports custom OpenAI-compatible API endpoints, making it compatible with:
- llama.cpp - Run LLMs locally
- Ollama - Local model hosting
- LM Studio - Desktop LLM runner
- Any OpenAI-compatible API
Add to your ~/.emmai/config.yaml:
base_url: "http://localhost:8080" # Your custom endpoint
model: "llama2" # Model name from your provider
api_key: "" # Optional for local endpoints
# Optional: skip certificate verification (use with caution)
insecure_skip_verify: falseOr use environment variables:
export OPENAI_BASE_URL="http://localhost:8080"
export OPENAI_API_KEY="" # Empty for local endpoints
emmai| Endpoint Type | API Key Required? |
|---|---|
| OpenAI (api.openai.com) | ✅ Yes (required) |
| LocalAI, Ollama, etc. | ❌ No (optional) |
Note: For custom endpoints, set OPENAI_API_KEY="" (empty string) or omit from config.
# With environment variable
export OPENAI_API_KEY="sk-..."
emmai
# With config file
emmai| Shortcut | Action |
|---|---|
Enter |
Send message |
Shift+Enter |
New line in input |
ESC |
Stop streaming response |
Ctrl+L |
Clear conversation (start new) |
Ctrl+R |
Retry last message |
Ctrl+Q |
Quit application |
Ctrl+C |
Force quit |
Page Up/Down |
Scroll chat history |
Conversations are automatically saved to:
~/.emmai/conversations/{conversation_id}.json
Each conversation includes:
- Complete message history
- Model used
- Timestamps
- Unique conversation ID
Contributions are welcome! Please follow Go best practices and include tests for new features.
- Fork the repository
- Create a feature branch
- Make your changes
- Run tests and linters
- Submit a pull request
MIT License - see LICENSE for details
- Built with tview by rivo
- Uses go-openai SDK
- Follows Standard Go Project Layout
- Issues: GitHub Issues
- Discussions: GitHub Discussions
Future enhancements:
- Model switching via keyboard shortcut
- Export conversations to markdown
- Search within conversations
- Message editing and regeneration
- Cost tracking and estimates
- Syntax highlighting for code blocks
- Custom keybindings configuration
Made with ❤️ using Go