Oolong π΅

Simple ephemeral chat β a fast, keyboard-driven terminal client for OpenAI models, built with Bubble Tea.
Conversations live in your terminal and nowhere else. Nothing is written to disk unless you explicitly save a transcript, and Oolong opts out of OpenAI's server-side response storage. Close the window and the chat is gone.

Features
- Streaming responses rendered as markdown with syntax-highlighted code blocks
- Ephemeral by design β history is kept in memory only, and requests are sent with response storage disabled on OpenAI's side
- Model picker with per-model pricing, plus a live token count and cost estimate in the chat header
- Mid-chat model switch β
esc back to the picker keeps the conversation, so you can escalate to a bigger model halfway through
- Image input β paste an image from the clipboard (
ctrl+v) and it's attached to your next message
- System prompt editing in place (
ctrl+p), without losing your message draft
- Transcript export β
ctrl+s saves the conversation as a timestamped markdown file, to the current directory or a directory you configure
- Configurable β an optional TOML config file sets a custom model catalog, a default model, reasoning effort and verbosity, transcript directory, and accent color
- Keychain storage β your API key lives in the OS keychain (macOS Keychain, Windows Credential Manager, Linux Secret Service), not in a dotfile
- Readable math β LaTeX in responses is converted to plain Unicode instead of showing up as mangled backslashes
Install
Homebrew (macOS)
brew install --cask dicedatalore/tap/oolong
With Go
go install github.com/dicedatalore/oolong@latest
Works on macOS, Linux, and Windows with Go 1.26+. Clipboard image paste needs cgo β a C compiler, plus the X11 development headers on Linux:
sudo apt install libx11-dev # Debian/Ubuntu
Without cgo the build still works; image paste is simply disabled.
From source
git clone https://github.com/dicedatalore/oolong.git
cd oolong
go build
./oolong
Prefer a standalone binary? Prebuilt archives for macOS, Linux, and Windows are on the releases page. On Windows, run Oolong from Windows Terminal β the legacy console doesn't render TUIs well.
Getting started
- Run
oolong.
- On first run, paste your OpenAI API key. It's validated against the API (no tokens spent) and saved to your OS keychain. Alternatively, set
OPENAI_API_KEY in your environment β it takes precedence over the keychain.
- Pick a model and start chatting.
To remove a stored key: press ctrl+k on the model picker, or run oolong --reset-key.
Configuration
Oolong is fully usable with no configuration. To customize it, run oolong config init to scaffold a commented ~/.config/oolong/config.toml ($XDG_CONFIG_HOME is respected); every key is optional:
default_model = "gpt-5.6-terra" # skip the picker on launch
transcript_dir = "~/notes/chats" # OOLONG_TRANSCRIPT_DIR still wins
accent = "#FFAF87" # primary accent color
# Replaces the built-in model catalog when present. Any model your API key
# can access works β entries are checked against the API and unavailable
# ones are hidden from the picker.
[[models]]
id = "gpt-5.4"
description = "Previous generation"
input_rate = 1.25 # USD per 1M tokens, both optional
output_rate = 10.00
reasoning_effort = "medium" # gpt-5.6 takes none | low | medium | high | xhigh
verbosity = "low" # low | medium | high
For a single run, oolong --model <id> opens a chat directly with any model your key can access, overriding default_model.
reasoning_effort and verbosity set the model's default Responses API parameters. They're passed through as-is β the supported values vary by model generation, and the API reports clearly if a model rejects one. On the model picker, β/β adjust the selected model's effort for the session, shown in the list item and later in the chat header. A malformed config never blocks launch β Oolong falls back to defaults and shows what it ignored.
Keybindings
| Key |
Action |
enter |
Send message |
shift+enter / ctrl+j |
Insert newline |
ctrl+v |
Paste (a clipboard image becomes an attachment) |
ctrl+e |
Compose the message in $EDITOR |
ctrl+y |
Copy the last reply to the clipboard |
ctrl+b |
Copy the last reply's last code block |
ctrl+r |
Regenerate the last reply |
β / β |
Cycle through your sent messages, attachments included (when the composer is empty) |
ctrl+n |
Start a new chat |
ctrl+p |
Edit the system prompt |
ctrl+s |
Save transcript to markdown |
pgup / pgdn |
Scroll the conversation |
home / end |
Jump to top / bottom |
esc |
Stop a streaming response, or switch model (the conversation is kept) |
ctrl+c |
Quit |
? |
Toggle full help |
On the model picker, β/β adjust the selected model's reasoning effort before the chat starts, and esc clears an active filter before it quits.
The mouse wheel scrolls the conversation too; hold shift while dragging to select text, as usual in TUIs.
Note: shift+enter requires a terminal with keyboard enhancement support (Kitty, Ghostty, WezTerm, foot, β¦). ctrl+j works everywhere.
Privacy
- Your API key is stored in the OS keychain, never in a plain-text file.
- Chat history exists only in process memory unless you save it with
ctrl+s.
- Requests are sent with
store: false, so OpenAI does not retain responses for the Responses API's server-side history.
Development
go test ./...
The UI is a Bubble Tea state machine with three screens β model picker, chat, and first-run key entry β each in its own file under internal/ui. Supporting packages: internal/openai (streaming client), internal/keystore (keychain), internal/mathfmt (LaTeX β Unicode), and internal/clipboard (image paste).
Releases are cut automatically on push to main: the version bump is derived from conventional commit messages β feat: β minor, fix: β patch, a breaking change β major β and commits of other types (chore:, docs:, test:, β¦) don't trigger a release.
License
MIT