| Crates.io | chabeau |
| lib.rs | chabeau |
| version | 0.6.0 |
| created_at | 2025-08-04 05:33:41.56394+00 |
| updated_at | 2025-11-11 05:06:42.393177+00 |
| description | A full-screen terminal chat interface that connects to various AI APIs for real-time conversations |
| homepage | https://github.com/permacommons/chabeau |
| repository | https://github.com/permacommons/chabeau |
| max_upload_size | |
| id | 1780326 |
| size | 2,550,657 |

Chabeau is a full-screen terminal chat interface that connects to various AI APIs for real-time conversations. Chabeau brings the convenience of modern chat UIs to the terminal with a focus on speed, ergonomics, and sensible defaults. It is not a coding agent.

/refine <prompt>/dump of contents to a fileFor features under consideration, see WISHLIST.md.
cargo install chabeau
chabeau auth # Interactive setup for OpenAI, OpenRouter, Poe, Anthropic, Venice AI, Groq, Mistral, Cerebras, or custom providers
chabeau # Uses defaults; opens pickers when needed
Inside the TUI, use /provider and /model to switch, and /help to see a full breakdown of commands and keyboard shortcuts.
chabeau # Start chat with defaults (pickers on demand)
chabeau --provider openai # Use specific provider
chabeau --model gpt-5 # Use specific model
chabeau --log conversation.log # Enable logging immediately on startup
Discover available options:
chabeau -p # List providers and auth status
chabeau -m # List available models
chabeau -p openrouter -m # List models for specific provider
Manage authentication from the CLI:
chabeau auth # Set up authentication
chabeau deauth # Remove authentication (interactive)
chabeau deauth --provider openai # Remove specific provider
Environment variables are used only if no providers are configured, or when you pass --env.
export OPENAI_API_KEY="your-api-key-here"
export OPENAI_BASE_URL="https://api.openai.com/v1" # Optional
chabeau --env # Force using env vars even if providers are configured
For quick, one-off questions without launching the full TUI, use the say command:
chabeau say "What is the capital of France?"
This command sends a single-turn message to the configured model, streams the response directly to your terminal, and exits. It respects your markdown settings, emits OSC8 hyperlinks when your terminal supports them, and uses a monochrome theme for clean, readable output.
If you have multiple providers configured but no default set, Chabeau will prompt you to specify a provider with the -p flag. The -p and other global flags can be placed before or after the prompt.
Environment variable values can make their way into shell histories or other places they shouldn't, so using the keyring is generally advisable.
Chabeau stores its configuration in config.toml.
~/.config/chabeau/config.toml~/Library/Application Support/org.permacommons.chabeau/config.tomlGenerally, you can rely on the UI: when you use interactive commands like /model, /provider, /theme, or /character, press Alt+Enter (or Ctrl+J) to persist the selection.
Command-line helpers mirror those flows:
# Set default provider
chabeau set default-provider openai
# Set default model for a provider
chabeau set default-model openai gpt-4o
# Persist a theme
chabeau set theme dark
# Set default character (per provider and model)
chabeau set default-character openai gpt-4 hypatia
# Print the current configuration
chabeau set
Both the CLI and TUI run these mutations through the same configuration orchestrator. Chabeau caches the parsed file based on its last-modified timestamp, skipping redundant reloads when nothing has changed, and persists updates atomically so a failed write never clobbers your existing config.toml.
Prefer editing by hand? Copy examples/config.toml.sample to your config directory and adjust it to suit your setup. The sample covers provider defaults, markdown/syntax toggles, custom providers, custom themes, and character assignments.
Chabeau supports character cards in the v2 format, letting you chat with AI personas that define tone, background, and greeting. Cards can be JSON or PNG files (with embedded metadata).
chabeau import path/to/character.json # Import JSON card
chabeau import path/to/character.png # Import PNG with embedded metadata
chabeau import character.json --force # Overwrite existing card
Cards are stored in the Chabeau configuration directory. Use chabeau -c to print the directory name and any cards Chabeau discovers.
chabeau -c hypatia # Start with character by name
chabeau -c hypatia.json # Start with character by filename
In the TUI, /character opens the character picker (↑↓ to navigate, Ctrl+O to inspect full definitions, Enter to select, Alt+Enter to set as default). You can also run /character <name> for quick switches.
Set defaults for provider/model combinations via Alt+Enter (or Ctrl+J) in the picker, or on the CLI:
chabeau set default-character openai gpt-4 hypatia
chabeau unset default-character openai gpt-4
To use a separate cards directory, set the CHABEAU_CARDS_DIR environment variable before launching Chabeau.
Example cards live in examples/hypatia.json and examples/darwin.json.
~/.config/chabeau/cards/ (or its equivalent on macOS or Windows) or provide the full path.chara tEXt chunk with base64-encoded JSON..json or .png extensions.Character cards follow the v2 specification.
Personas allow you to define different user identities for conversations, each with their own name and optional biographical context. Unlike character cards (which define AI personas), personas define who you are in the conversation.
Add personas to your config.toml:
[[personas]]
id = "developer"
name = "Alex"
bio = "You are talking to Alex, a senior software developer with expertise in Rust and distributed systems."
[[personas]]
id = "student"
name = "Sam"
bio = "Sam is a computer science student learning about AI and machine learning."
[[personas]]
id = "casual"
name = "Jordan"
# bio is optional - persona will just change the display name
chabeau --persona developer # Start with a specific persona
In the TUI, /persona opens the persona picker (↑↓ to navigate, Ctrl+O to read the persona text, Enter to select). You can also run /persona <id> for quick switches, or select "[Turn off persona]" to return to anonymous mode.
When a persona is active:
Both personas and character cards support {{user}} and {{char}} variable substitutions:
{{user}} is replaced with the active persona's display name (or "Anon" if no persona is active){{char}} is replaced with the character's name (or "Assistant" if no character is active)Personas and character cards work together seamlessly:
{{user}} and {{char}} variable substitutionsPresets let you inject reusable system instructions into the first and last system messages that Chabeau sends to the model. They are ideal for lightweight tone or formatting tweaks that you want to toggle quickly.
Chabeau ships with three built-in presets (short, roleplay, and casual) so you can experiment without editing your config. Set builtin_presets = false in config.toml to hide them from /preset, /preset <id>, and the --preset flag. If you define a preset with the same ID, your version overrides the built-in automatically.
Add presets to your config.toml:
[[presets]]
id = "focus"
pre = """
You are collaborating with {{user}}. Keep responses focused and direct.
"""
post = """
Before finishing, list any follow-up actions.
"""
[[presets]]
id = "roleplay"
pre = """
- Engage in roleplay with the user.
- Two paragraphs per turn max.
- Don't be shy to perform actions. Format these in italics, like this: *{{char}} frowns at {{user}}.*
- Be creative! Feel free to take the roleplay into new directions.
"""
pre text is wrapped in blank lines and prepended to the very first system message.post text is wrapped in blank lines and appended to the final system message. If no system message exists at either position, Chabeau creates one automatically.{{user}} and {{char}} substitutions as personas and character cards.Assign defaults per provider/model with default-presets:
[default-presets.openai]
"gpt-4o" = "focus"
Launch with an ID like --preset focus, or pick interactively with /preset. Use Ctrl+O in the picker to review the preset instructions. The picker includes a "Turn off preset" option to clear the active preset.
The status bar shows the current preset when one is active so you can confirm the context you're using at a glance.
Chabeau ships with built-in themes and supports custom ones. Use /theme in the TUI to preview and Alt+Enter (or Ctrl+J) to persist the choice. On the CLI, run:
chabeau set theme dark # Set a theme
chabeau themes # List themes (built-in and custom)
chabeau unset theme # Revert to default detection
When no explicit theme is set, Chabeau tries to infer a sensible default from your OS preference (e.g., macOS, Windows, GNOME). If no hint is available, it defaults to the dark theme.
Custom themes belong in config.toml under [[custom_themes]]. See src/builtins/themes.toml for color references and examples/config.toml.sample for structure.
App messages—Chabeau’s own informational banners, warnings, and errors—use dedicated theme knobs so they’re easy to distinguish from assistant replies. Customize them with the app_info_*, app_warning_*, and app_error_* keys in your theme to control the prefix text, prefix styling, and message styling independently.
Toggle these features at runtime:
/markdown on|off|toggle/syntax on|off|toggleChabeau persists these preferences to the config file automatically. Syntax colors adapt to the active theme and use the theme’s code block background for consistent contrast.
Chabeau detects terminal color depth and adapts themes accordingly:
COLORTERM contains truecolor or 24bit, Chabeau uses 24-bit RGB.TERM contains 256color, RGB colors are quantized to the xterm-256 palette.Force a mode when needed with CHABEAU_COLOR=truecolor|256|16.
See the built-in help for a full list of keyboard controls. A few highlights:
/refine prompt on the latest assistant reply./. When it does, Tab autocompletes slash commands. The active region shows a ›; the inactive one shows a ·.Chabeau avoids capturing the mouse so selection operations (copy/paste) work as expected. Some terminals treat mousewheel events as cursor key input, so scrolling moves the conversation. Others reveal terminal history; in that case, use the cursor keys or PgUp/PgDn instead.
Set the EDITOR environment variable to compose longer responses in your favorite editor:
export EDITOR=nano # or vim, code, etc.
export EDITOR="code --wait" # VS Code with wait
Once set, press Ctrl+T in the TUI to launch the external editor.
See ARCHITECTURE.md for a high-level walkthrough aligned with commit 5d81609a33ce1abeef3ccb976b5387c474221511.
Chabeau uses a modular design with focused components:
main.rs – Entry pointapi/ – API data structures and model-related helpers
mod.rs – API data structuresmodels.rs – Model fetching and sorting functionalityauth/ – Authentication and provider management
mod.rs – Authentication manager implementationui.rs – Interactive prompts and input helpers for auth flowsbuiltins/ – Build-time assets embedded into the binary
help.md – In-app keyboard shortcut and command referencemodels.toml – Supported provider definitionsthemes.toml – Built-in UI themescharacter/ – Character card support (v2 format)
cache.rs – In-memory caching with invalidationcard.rs – Character card data structures and v2 spec parsingimport.rs – Import command and validation logicloader.rs – Card file loading (JSON and PNG with metadata extraction)mod.rs – Module exports and public APIpng_text.rs – PNG tEXt chunk reader/writerservice.rs – Shared character cache and resolution helpers for the TUI and CLIcli/ – Command-line interface parsing and handling
character_list.rs – Character card listing functionalitymod.rs – CLI argument parsing and command dispatchingmodel_list.rs – Model listing functionalityprovider_list.rs – Provider listing functionalitytheme_list.rs – Theme listing functionalitycommands/ – Chat command processing and registry-driven dispatch
mod.rs – Command handlers and dispatcherregistry.rs – Static command metadata registrycore/ – Core application components
app/ – Application state and controllers
actions/ – Internal action definitions and dispatcher for chat loop updatesapp.rs – Main App struct and event loop integrationconversation.rs – Conversation controller for chat flow, retries, and streaming helpersmod.rs – App struct and module exportspicker/ – Generic picker that powers all TUI selection dialogspickers.rs – Picker constructors and helpers for each picker typesession.rs – Session bootstrap and provider/model statesettings.rs – Theme and provider controllersstreaming.rs – Handles streaming responses from the APIui_helpers.rs – UI state transition helpersui_state.rs – UI state management and text input helpersbuiltin_providers.rs – Built-in provider configuration (loads from builtins/models.toml)chat_stream.rs – Shared streaming service that feeds responses to the app, UI, and loggersconfig/ – Configuration data, defaults, caching, and persistence
data.rs – Configuration data types and pure helpersdefaults.rs – Default selection helpers and Config implementationsio.rs – Config path resolution and persistence routinesmod.rs – Public exports for configuration helpersorchestrator.rs – Cached config loader and mutation orchestratorprinting.rs – CLI-facing config print helperstests.rs – Configuration module testsmessage.rs – Message data structuresui/ – Terminal interface rendering
appearance.rs – Theme and style definitionschat_loop/ – Mode-aware chat loop orchestrating UI flows, keybindings, and command routing
event_loop.rs – Async terminal loop orchestration, event polling, and stream dispatchlifecycle.rs – Terminal setup/teardown helpers and resource guardsmodes.rs – Mode-aware key handlers and text interaction utilitieshelp.rs – Help text renderinglayout.rs – Shared width-aware layout engine for Markdown and plain textmarkdown/ – Markdown renderer and wrapping helpers that emit span metadatamod.rs – UI module declarationsosc/ – Crossterm backend wrapper that emits OSC 8 hyperlinkspicker.rs – Picker controls and renderingrenderer.rs – Terminal interface rendering (chat area, input, pickers)span.rs – Span metadata for clickable linkstheme.rs – Theme loading and managementtitle.rs – Header bar renderingutils/ – Utility functions and helpers
clipboard.rs – Cross-platform clipboard helpercolor.rs – Terminal color detection and palette quantizationeditor.rs – External editor integrationlogging.rs – Chat logging functionalitymod.rs – Utility module declarationsscroll.rs – Text wrapping and scroll calculationscargo test # All tests
cargo test scroll:: # Scroll functionality tests
cargo test --release # Faster execution
Chabeau includes lightweight performance checks in the unit test suite and supports optional Criterion benches.
cargo test (warnings print to stderr; tests only fail past the fail thresholds).render_cache bench validates the cached prewrapped rendering path.cargo benchtarget/criterion/ (HTML under report/index.html).benches/ (e.g., benches/my_bench.rs) and use Criterion’s criterion_group!/criterion_main!.src/lib.rs (e.g., use chabeau::...).CC0 1.0 Universal (Public Domain)