oolong

command module
v0.7.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 19, 2026 License: MIT Imports: 15 Imported by: 0

README ΒΆ

Oolong 🍡

CI

Simple ephemeral chat β€” a fast, keyboard-driven terminal client for OpenAI, Anthropic, and Ollama models, built with Bubble Tea.

  • Ephemeral by design β€” conversations live in your terminal and nowhere else. Nothing is written to disk unless you save a transcript, and OpenAI's server-side response storage is switched off. Close the window and the chat is gone.
  • Any OpenAI-compatible endpoint β€” the official API works out of the box, or point base_url at Ollama, LM Studio, or OpenRouter and give local models the same polished UI.
  • Scriptable β€” git diff | oolong "write a commit message" streams the answer straight to stdout, no TUI, so Oolong drops into any shell pipeline.

oolong demo

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
  • File attachments β€” ctrl+f picks an image or text file from disk to send with your next message
  • One-shot mode β€” oolong "question" (or cat main.go | oolong "explain") streams the answer to stdout with no TUI, so Oolong works in scripts and pipelines
  • OpenAI-compatible endpoints β€” point base_url at Ollama, LM Studio, OpenRouter, or any compatible server, globally or per model
  • Native Anthropic support β€” stream Claude models through Anthropic's Messages API with text, images, files, system prompts, effort, and usage reporting
  • Context meter β€” the chat header tracks how much of the model's context window the conversation fills, and warns as it nears the limit
  • System prompt editing in place (ctrl+p), without losing your message draft
  • Transcript export & resume β€” ctrl+s saves the conversation as a timestamped markdown file; oolong --resume <file> picks it back up later
  • Configurable β€” an optional TOML config file sets a custom model catalog, a default model, reasoning effort and verbosity, endpoints, transcript directory, and accent color
  • Keychain storage β€” provider API keys live 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

  1. Run oolong.
  2. Press ctrl+k to open the key manager. It accepts OpenAI and Anthropic keys and stores them only in your OS keychain. OPENAI_API_KEY and ANTHROPIC_API_KEY take precedence when set.
  3. Pick a model and start chatting.

To add, replace, or remove a provider key, press ctrl+k on the model picker. oolong --reset-key removes all stored provider keys.

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
# base_url = "https://api.openai.com/v1"
# provider = "openai"

# 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"
provider = "openai"
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
context_window = 400000      # tokens; shows a ctx meter in the chat header

[[models]]
id = "claude-sonnet-5"
provider = "anthropic"
description = "Anthropic Claude Sonnet"
input_rate = 2.00
output_rate = 10.00
reasoning_effort = "medium"
context_window = 1000000

[[models]]
id = "gemma3"
provider = "ollama"
description = "Local Gemma through Ollama"
base_url = "http://localhost:11434"

For a single run, oolong --model <id> opens a chat directly with any model your key can access, overriding default_model.

reasoning_effort sets the provider's effort parameter; verbosity applies to OpenAI's Responses API. Values are passed through because support varies by model generation. On the model picker, ←/β†’ adjust effort for the session. A malformed config never blocks launch β€” Oolong falls back to defaults and shows what it ignored.

OpenAI-compatible endpoints

base_url points Oolong at a provider endpoint. Set it globally, or per model to mix endpoints in one catalog. Local OpenAI-compatible endpoints need no API key; Oolong skips OpenAI-specific validation for those routes. OPENAI_BASE_URL overrides configured OpenAI endpoints only.

Set provider = "openai", provider = "anthropic", or provider = "ollama". Provider selection can be global or per model, so one catalog can contain all three. Both http://localhost:11434 and its /v1 form are accepted for Ollama.

Scripting

Positional arguments (or piped input) skip the TUI entirely and stream the answer to stdout:

oolong "why is the sky blue"
cat main.go | oolong "explain this file"
git diff | oolong "write a commit message"

One-shot mode uses --model / default_model (falling back to the catalog's first entry) and the same key, endpoint, and reasoning settings as the TUI.

Resuming a chat

Transcripts saved with ctrl+s can be picked back up later:

oolong --resume oolong-chat-2026-07-19-094035.md

The conversation, system prompt, and model are restored from the file (image and file attachments are recorded only as labels, so they don't ride along). Nothing is ever loaded implicitly β€” resume only reads a file you name.

Keybindings

Key Action
enter Send message
shift+enter / ctrl+j Insert newline
ctrl+v Paste (a clipboard image becomes an attachment)
ctrl+f Attach an image or text file from disk
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

  • Provider API keys are 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/oneshot (pipe mode), 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

Documentation ΒΆ

The Go Gopher

There is no documentation for this package.

Directories ΒΆ

Path Synopsis
e2e
fakeapi command
Command fakeapi is a fake OpenAI and Anthropic API for driving Oolong end-to-end.
Command fakeapi is a fake OpenAI and Anthropic API for driving Oolong end-to-end.
internal
anthropic
Package anthropic implements streaming chat through Anthropic's Messages API.
Package anthropic implements streaming chat through Anthropic's Messages API.
clipboard
Package clipboard reads image attachments from the system clipboard.
Package clipboard reads image attachments from the system clipboard.
config
Package config loads Oolong's optional TOML config file from ~/.config/oolong/config.toml (or $XDG_CONFIG_HOME/oolong/config.toml).
Package config loads Oolong's optional TOML config file from ~/.config/oolong/config.toml (or $XDG_CONFIG_HOME/oolong/config.toml).
keystore
Package keystore stores provider API keys in the OS keychain.
Package keystore stores provider API keys in the OS keychain.
mathfmt
Package mathfmt converts LaTeX math in markdown to plain Unicode text.
Package mathfmt converts LaTeX math in markdown to plain Unicode text.
ollama
Package ollama implements streaming chat through Ollama's native API.
Package ollama implements streaming chat through Ollama's native API.
oneshot
Package oneshot implements one-shot mode: `oolong "question"` (and `cat main.go | oolong "explain"`) streams the answer straight to stdout with no TUI, which makes Oolong scriptable.
Package oneshot implements one-shot mode: `oolong "question"` (and `cat main.go | oolong "explain"`) streams the answer straight to stdout with no TUI, which makes Oolong scriptable.
openai
Package openai wraps the OpenAI SDK in a minimal streaming chat client.
Package openai wraps the OpenAI SDK in a minimal streaming chat client.
ui
Package ui implements the Oolong terminal user interface.
Package ui implements the Oolong terminal user interface.
version
Package version reports the app version shown in the banner and by the -version flag.
Package version reports the app version shown in the banner and by the -version flag.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL