Character artwork by ใใใใ (ikawasa23)
๐๏ธ Celeste CLI - Interactive AI Assistant
A premium, corruption-aesthetic command-line interface for CelesteAI

Built with Charm's Bubble Tea for flicker-free, modern terminal experiences
โจ What is Celeste CLI?
Celeste CLI is a full standalone agentic development tool with her own persona, featuring:
- ๐จ Premium TUI - Flicker-free rendering with corrupted-theme aesthetics
- ๐ฎ 48 Built-in Tools - File I/O, shell, web search, code graph, code review, collections search, git, crypto, subagent orchestration, and more
- ๐
.grimoire Project Context - Persona-themed project config files with auto-discovery; AGENTS.md / CLAUDE.md are read too
- ๐ง Code Graph + Semantic Search - MinHash + BM25 fused ranking with LSH band table for sub-linear queries, structural rerank; tree-sitter parsing (TypeScript, PHP, Python, Rust, Java, C/C++ and Ruby) for accurate call-graph edges in release binaries (a
CGO_ENABLED=0 source build falls back to regex parsers); embedded celeste-stopwords v1.0.0 noise filter
- ๐ Graph-Based Code Review - Structural analysis detecting stubs, lazy redirects, placeholders, error swallowing, and hardcoded values
- ๐ Direct Codegraph MCP Tools -
celeste_index, celeste_code_search, celeste_code_review, celeste_code_graph, celeste_code_symbols served verbatim from the cached graph (no chat-LLM round-trip, no max_tokens ceiling, streaming progress notifications)
- ๐ Permission System - Multi-layer allow/deny/ask rules with pattern matching
- ๐พ Session Persistence - JSONL auto-save, resume, file checkpointing with stale detection and revert
- ๐ Multi-Provider - Sakana AI (default), Grok/xAI, OpenAI, Anthropic (native SDK), Gemini, Venice.ai, Vertex AI, OpenRouter, local OpenAI-compatible servers
- ๐ฐ Cost Tracking - Per-model pricing with live session cost display
- ๐ช Hooks - Commands that run around tool calls, prompts and sessions (
hooks.json, or a grimoire ## Hooks section); a repository's hooks run only after you approve them (celeste hooks list, celeste hooks trust). See docs/HOOKS.md
- ๐งฑ Sandbox (opt-in) -
bash can run under the OS sandbox (seatbelt on macOS, bubblewrap on Linux), writing only to the workspace, temp directories and build caches, with the network optionally cut. See docs/SANDBOX.md
- โฉ๏ธ Checkpoints - Every file change is checkpointed per session:
/undo, /diff and /rewind in the chat, celeste revert <file> from the shell
- ๐ง Extended Thinking - Leverage reasoning tokens (Claude, Gemini, Grok) with
/effort control
- ๐ผ๏ธ Image Input - Multimodal support for vision-capable models
- ๐ญ Celeste persona - The full persona in official releases (encrypted, all rights reserved); a public persona in source builds. See Persona and docs/PERSONALITY.md
- ๐ Blockchain Tools - IPFS, Alchemy, wallet security monitoring
Three Ways to Run
| Mode |
Command |
What it does |
| Chat |
celeste chat (default) |
Interactive chat with auto-looping tool calls (25-turn safety cap). |
| Agent |
/agent <goal> (in TUI) or celeste agent --goal "..." |
Fully autonomous multi-turn agent with planning, file I/O, checkpointing, and resume. For long-running tasks. |
| Orchestrator |
/orchestrate <goal> (in TUI) |
Agent run with a second reviewer model that critiques and debates the output. For high-quality deliverables. |
Chat vs Agent: Chat is interactive with tool auto-looping โ you guide the conversation while Celeste
calls tools as needed. Agent is autonomous, with a planning phase, a checkpoint store and workspace
awareness. Both run on the same tool loop, with the same caps, guards, permissions and hooks. The
orchestrator adds a reviewer model on top of the agent. Editors that speak the Agent Client Protocol
(Zed, JetBrains) can run Celeste as their agent with celeste acp.
In your editor: celeste acp runs celeste as an Agent Client Protocol agent for Zed and the JetBrains IDEs: the editor's agent panel drives the chat, with tool calls, plans and permission prompts shown in the editor. See docs/ACP.md for the setup.
๐ Quick Start
Quick Install (Recommended)
Upgrading from 1.x? Read MIGRATING-2.0.md first: it lists every
2.0 change that can affect an existing setup (install path, persona, hooks, config keys,
environment variables, custom tools, the permission prompt) and what to do about each.
If you have Go 1.26+ installed:
go install github.com/whykusanagi/celeste-cli/v2/cmd/celeste@latest
go install needs the Go module proxy (the default, proxy.golang.org). With GOPROXY=direct it
can fail on a dependency whose upstream tag was moved after the proxy cached it (for example
github.com/charmbracelet/glamour v1.0.0 reports a checksum mismatch); the signed release
binaries below avoid this.
The celeste binary is installed to $GOPATH/bin (or ~/go/bin by default). The first time
you run a command with it (celeste chat, say; help, version, update and persona don't
count), it downloads the official signed release binary of the same version from
Releases, checks its GPG signature and
checksums against the release key built into celeste, replaces itself and carries on, so you
get the full persona from the first run (stderr says
celeste: installing the official vX.Y.Z build ...). If the download fails
(offline, say), that run uses the public persona and celeste tries again in an hour.
celeste update moves to a newer release; celeste update --check only reports one. Set
CELESTE_NO_AUTO_UPGRADE=1 to keep the binary go install built.
Requirements:
- Go 1.26.0 or higher
$GOPATH/bin (or ~/go/bin) in your PATH
No Go toolchain? Download a pre-built, signed binary for your platform from the
Releases page and verify
it (see Security & Verification below).
To add to PATH:
export PATH="$PATH:$(go env GOPATH)/bin"
Build from source
# Clone the repository
git clone https://github.com/whykusanagi/celeste-cli.git
cd celeste-cli
# Build + install to ~/.local/bin (handles macOS code-signing for you)
make install
The code graph's tree-sitter parsers are C, so a source build compiles them with CGo and
needs a C compiler (Xcode's command line tools, gcc, or MinGW-w64 on Windows). With
CGO_ENABLED=0, celeste still builds and the code graph falls back to regex parsers, with
less accurate call edges. So does a build with CGO_ENABLED and CC both unset on a machine
whose default C compiler is missing, since Go then turns CGo off by itself; an explicit
CGO_ENABLED=1, or a CC naming a compiler that is missing, fails the build instead.
A cross-compile (GOOS or GOARCH not the host's) with CGO_ENABLED unset also builds
without CGo. Release binaries always include tree-sitter.
A build from a checkout never downloads anything. It runs Celeste's public persona (a
one-line identity, the honesty rule and the voice boundary rule) and says so at startup: the
full persona ships only in official release binaries, which go install and the Releases page
give you.
macOS note: don't cp the binary over an existing ~/.local/bin/celeste โ
on Apple Silicon that invalidates its ad-hoc code signature and the kernel will
SIGKILL it at launch (zsh: killed celeste). make install builds straight to
the destination and re-signs. If you install by hand, build directly to the
target and re-sign:
go build -o ~/.local/bin/celeste ./cmd/celeste
codesign --force --sign - ~/.local/bin/celeste # macOS only
Persona
Official release binaries, and go install builds once they have upgraded themselves, run
Celeste's full persona. Builds from a checkout run the public persona. To check a binary, run
celeste persona verify: it prints official persona: ... and exits 0 on an official build,
and exits 1 with the reason otherwise. It never downloads, so after a fresh go install run
celeste update first (it installs the official binary), then celeste persona verify. A local model with a small context window gets a smaller
persona profile; set context_limit in your config to the server's real window. How the
persona is built and chosen: docs/PERSONALITY.md. How to verify a
download: VERIFY.md.
First Run
Sakana/Fugu (the shipped default): a fresh install already points at
https://api.sakana.ai/v1 with model fugu, so you only need a key.
celeste config --set-key YOUR_SAKANA_KEY
celeste chat
xAI/Grok: not the default any more, so set the URL too or your key goes to
Sakana and you get a confusing 401.
celeste config --set-url https://api.x.ai/v1
celeste config --set-key YOUR_XAI_KEY
celeste chat
With Collections (RAG):
celeste config --set-key YOUR_XAI_KEY
celeste config --set-management-key YOUR_XAI_MANAGEMENT_KEY
celeste collections list # see available collections
celeste collections enable <id> # enable for chat
celeste chat
OpenAI:
celeste config --init openai
celeste -config openai config --set-key YOUR_OPENAI_KEY
celeste -config openai chat
Sakana (Fugu):
celeste config --init sakana
celeste -config sakana config --set-url https://api.sakana.ai/v1 --set-key YOUR_SAKANA_KEY --set-model fugu
celeste -config sakana chat
Get a key from the Fugu install (curl -fsSL https://sakana.ai/fugu/install | bash)
or your Sakana account. Use --set-model fugu-ultra for the heavier multi-agent variant.
Other providers: celeste config --init <name> where name is: openai, grok, elevenlabs, venice, sakana, digitalocean
Project Setup
Celeste reads a project's .grimoire and its AGENTS.md / CLAUDE.md (from the
workspace up to the git root) into every session. It writes nothing into your
project on its own; create the files when you want them:
cd your-project
celeste init # create .grimoire
celeste init --agents # also create AGENTS.md (build and test commands)
celeste index # build code graph
celeste index status # check graph stats
In the chat, /init and /init agents do the same. An existing file is never overwritten.
๐ Security & Verification
All Celeste CLI releases are cryptographically signed with GPG to ensure authenticity and integrity.
Quick Verification
Before using a downloaded binary, verify its authenticity:
# Download verification script
curl -O https://raw.githubusercontent.com/whykusanagi/celeste-cli/main/scripts/verify.sh
chmod +x verify.sh
# Verify your download
./verify.sh celeste-linux-amd64.tar.gz
Manual Verification
For manual verification or more details, see the complete Verification Guide.
Release Signing:
- All commits are GPG-signed
- All releases include GPG signatures
- Checksums are signed with GPG
- Complete manifest with build metadata
PGP Key Information:
Import Key โ use the repository copy; it carries the signing subkey the
releases are signed with:
# From this repository (recommended โ complete key with signing subkey)
curl -O https://raw.githubusercontent.com/whykusanagi/celeste-cli/main/whykusanagi.asc
gpg --import whykusanagi.asc
# Cross-check the primary fingerprint against the key GitHub serves:
gpg --fingerprint 940490EF09DA31322BF7FD83875849AB1D541C55
# โ 9404 90EF 09DA 3132 2BF7 FD83 8758 49AB 1D54 1C55
For security issues, see our Security Policy or contact security@whykusanagi.xyz.
๐ Table of Contents
๐ฏ Features
Interactive TUI Mode
- Flicker-Free Rendering - Double-buffered Bubble Tea rendering (no screen tearing)
- Scrollable Chat - PgUp/PgDown navigation through conversation history
- Input History - Arrow keys to browse previous messages (like bash history)
- Skills Panel - Real-time skill execution status with demonic eye animation
- Corrupted Theme - Lip Gloss styling with pink/purple abyss aesthetic
- Real Streaming + Corruption Animation - Token-by-token streaming with corrupted glitch phrases at the typing cursor
- Markdown Rendering - glamour-powered markdown with corrupted theme (code blocks, tables, headers, bold)
48 built-in tools powered by AI function calling. 41 are always on. A further 6
code-graph tools appear once you index a project, plus collections search when you
configure collections:
- Dev Tools (bash, read/write/patch files, search, list files)
- Code Graph (semantic search with MinHash+BM25 fusion, code review, symbol analysis, tree-sitter parsing)
- Direct Codegraph MCP Tools (
celeste_index, celeste_code_search, celeste_code_review, celeste_code_graph, celeste_code_symbols โ verbatim, no chat-LLM round-trip)
- Git (status, log)
- Web (search, fetch)
- Information Services (Weather, Currency, Twitch, YouTube)
- Utilities (Conversions, Encoding, Generators, QR codes)
- Productivity (Reminders, Notes, Todo tracking)
- Blockchain (IPFS, Alchemy, wallet security)
- Subagent Orchestration (
spawn_agent, post_message)
Chat offers all 48, plus spawn_agent and post_message, which the chat registers
itself. Agent runs offer 24 of them: the dev, git, web and code-graph tools, save_memory,
todo, ask, find_tools, audio_render and collections search. celeste message
sends none. Tools from MCP servers and custom skills come on top, in both modes.
See complete tool list below
Collections Support (xAI RAG)
- Upload Custom Documents - Create knowledge bases with your own documentation
- Semantic Search - Celeste automatically searches collections when answering questions
- Interactive TUI - Manage collections with
/collections command in chat
- CLI Management - Create, upload, enable/disable collections from command line
- Multiple Collections - Organize by topic, enable only what's relevant
See Collections Guide for setup and usage.
- MCP (Model Context Protocol) support for external tool servers
- Permission system with configurable allow/deny rules
- Streaming tool execution with concurrent dispatch
- Automatic context window management
Session Management
- Conversation Persistence - Auto-save and resume sessions seamlessly
- File Revert -
celeste revert <file> [--session id] [--force] restores a file from the latest session that changed it
- Message History - Full conversation logging with timestamps
- Session Listing - Browse and load previous sessions by ID
- Session Clearing - Bulk delete sessions when needed
Multi-Provider Support (9 Chat Providers)
celeste uses the model the provider serves now. At startup it reads the provider's model list (cached for a day under ~/.celeste/cache/models); if your configured model has been retired, it falls back to the provider's current default and says so. A model is replaced only when celeste is sure it's gone: a model missing from the list is first checked with the provider where it can answer (Anthropic, OpenAI, xAI), so aliases keep working, and presets (@...), fine-tunes (ft:...) are never touched. Your config file is not changed. To turn this off, set "pin_model": true in the config or CELESTE_PIN_MODEL=1; in the chat, /set-model <name> --force pins that model until you switch endpoints. Gemini, Vertex, DigitalOcean and local servers publish no list, so their configured model is used as is. The model names below are offline fallbacks.
- โ
Grok/xAI (grok-4.20-0309-non-reasoning) - reliable tool calling, no reasoning-token burn, never routes to the cost-prohibitive grok-4.3 โข Token tracking โ
- โ
OpenAI (gpt-4.1-mini, gpt-4.1) - Full function calling with streaming โข Token tracking โ
- โ
Anthropic Claude (claude-sonnet-4-5) - Native SDK with prompt caching and extended thinking โข Token tracking โ
- โ
Google Gemini AI (gemini-flash-latest) - Simple API keys, free tier, full streaming โข Token tracking โ
- โ ๏ธ Google Vertex AI (gemini-2.0-flash, unverified) - Enterprise, requires GCP project + billing. The default has not been checked against Vertex's own model lifecycle โข Token tracking โ
- โ ๏ธ Venice.ai (Venice's own default, currently venice-uncensored-1-2) - NSFW mode, image generation/upscaling. Tool calling depends on the model (checked against the live Venice catalog) โข Token tracking โ
- โ
OpenRouter (multi-provider) - Parallel function calling support โข Token tracking โ
- โ
Sakana AI (fugu, fugu-ultra) - DEFAULT - 1M context, OpenAI-compatible chat completions, deep reasoning โข Token tracking โ
- โ
Local (mlx-vlm, Ollama, LM Studio, llama.cpp) - any OpenAI-compatible server on this machine or the local network, any port; tools supported. No
api_key needed at all โข Cost tracked as $0
Nine chat providers: eight with tool calling, and Venice, whose tool calling depends on the selected model.
celeste providers lists 11: these nine plus DigitalOcean (its tools run in its own
cloud) and ElevenLabs (voice).
Dynamic Model Selection - Auto-selects best tool-calling model per provider
Capability Indicators - Visual feedback (โ skills / โ ๏ธ no skills) in header
See full compatibility matrix
Configuration
- JSON-based Config - Modern
~/.celeste/config.json format
- Named Configs - Multi-profile support (openai, grok, venice, etc.)
- Skills Config - Separate
skills.json for skill-specific API keys
- Secrets Handling - Separate
secrets.json for backward compatibility
- Persona - Always on in chat and agent runs, sized to the model's context window (
context_limit); tune it with /persona sliders
- Environment Override - Env vars override file config
Celeste CLI uses OpenAI-compatible function calling to power its tools. You don't invoke tools directly โ you chat naturally, and the AI decides when to call them.
| Tool |
Description |
| bash |
Execute shell commands in the workspace |
| read_file |
Read files with checkpointing |
| write_file |
Write files with snapshot backup |
| patch_file |
Apply targeted edits to files |
| splice_file |
Move a region between files by anchors/line-ranges (deterministic, no model-routed bytes) |
| list_files |
List directory contents with glob patterns |
| search |
Search file contents with regex |
| git_status |
Show working tree status |
| git_log |
Show commit history |
| recall_tool_result |
Restore a tool result that context compaction pruned from the conversation |
| Tool |
Description |
| code_search |
MinHash semantic search across all indexed symbols |
| code_review |
Graph-based code review (6 categories: stubs, lazy redirects, placeholders, TODOs, error swallowing, hardcoded values) |
| code_graph |
Query symbol relationships and call chains |
| code_symbols |
List symbols in a file or package |
| code_impact |
Blast-radius analysis: which callers are affected by a changed symbol |
| code_snapshot |
Save and diff graph state to track what changed between sessions |
v1.10 accuracy improvements: STUB detection now skips dunder methods (__init__, __lt__, โฆ), @abstractmethod-decorated methods, and methods on Protocol/ABC/ABCMeta classes โ eliminating the largest classes of false positives. Decorator @syntax calls and @property.setter assignments are now captured as call edges, producing more accurate impact/caller counts.
| Tool |
Description |
| spawn_agent |
Spawn a subagent to handle a subtask; supports DAG dependencies, worktree isolation, and background execution |
| post_message |
Post a message to another subagent's mailbox by element name for loosely-coupled coordination |
You never call these directly โ you describe multi-step work in chat and Celeste decides when to delegate. The parameters below show what the model can specify:
spawn_agent parameters:
| Parameter |
Type |
Description |
goal |
string |
(required) What the subagent should accomplish |
type |
string |
explore (read-only tools, no persona, small model), review (read and code-graph tools, no persona) or general (default: every tool and the persona). Every type returns JSON {summary, findings, files}; see docs/SUBAGENTS.md |
workspace |
string |
Working directory (defaults to current workspace) |
task_id |
string |
Unique ID for DAG dependency references |
depends_on |
array of strings |
Task IDs that must finish before this subagent starts |
max_turns |
integer |
Max agent turns (default 20; raise for complex tasks, lower for simple lookups) |
isolate_worktree |
boolean |
Run in its own git worktree so concurrent subagents can't conflict on the same files; merged back on success, removed afterward. Requires a git repo. Default false. |
background_after |
integer |
Seconds before auto-backgrounding a slow subagent so the parent resumes immediately. Result appears in /agents when it finishes. 0 = foreground/blocking (default). |
persona |
object |
Override personality sliders (flirt, warmth, register, lewdness, r18) or load a named preset. general only |
post_message parameters:
| Parameter |
Type |
Description |
to |
string |
(required) Recipient element name (fire, water, earth, light, dark, wind, โฆ) |
message |
string |
(required) Message body delivered when the recipient agent next starts |
TUI commands:
/agents List all spawned subagents and their status (waiting/running/completed/failed)
/agents resume <id> Resume a failed subagent from its last checkpoint
/agents kill <id|name> Cancel a specific in-flight subagent (by id, task id, or the on-screen name e.g. "mizu")
Example โ parallel audio production with DAG:
When you ask Celeste to produce audio with voice and SFX mixed together, the model emits a DAG like:
{ "goal": "generate voice narration", "task_id": "voice" }
{ "goal": "generate SFX layer", "task_id": "sfx" }
{ "goal": "mix voice and SFX tracks", "task_id": "mix", "depends_on": ["voice", "sfx"] }
The mixer waits until both voice and sfx complete, then starts with their results injected into its context.
Example โ isolated file edits with worktree:
{ "goal": "refactor auth module", "isolate_worktree": true }
The subagent works in a separate git worktree so its changes don't conflict with the parent or other subagents editing the same files simultaneously. On success the changes merge back; the worktree is removed either way.
Reliability: transient LLM errors (429 rate limits, 5xx, network drops) are automatically retried with exponential backoff โ 429s retry up to 3ร (2 s / 4 s / 8 s), server errors up to 2ร (1 s / 2 s), network errors up to 2ร (1 s / 2 s). This applies to both the main loop and all subagents. 4xx errors (other than 429) fail immediately.
Divination & Entertainment
| Skill |
Description |
Dependencies |
| Tarot Reading |
Three-card or Celtic Cross spreads |
Tarot API (requires auth token) |
Example:
You: Give me a tarot reading
Celeste: *calls tarot_reading skill*
Celeste: Your cards reveal... [interpretation]
Content & Media
| Skill |
Description |
Dependencies |
| NSFW Mode |
Venice.ai uncensored responses |
Venice.ai API key |
| Content Generation |
Platform-specific templates (Twitter/TikTok/YouTube/Discord) |
None (LLM-powered) |
| Image Generation |
Venice.ai image creation |
Venice.ai API key |
Example:
You: Generate a tweet about cybersecurity
Celeste: *calls generate_content skill*
Celeste: Here's your tweet: [280 char tweet with hooks]
| Skill |
Description |
Dependencies |
| Weather |
Current conditions and forecasts |
wttr.in API (free, no key) |
| Currency Converter |
Real-time exchange rates |
ExchangeRate-API (free) |
| Twitch Live Check |
Check if streamers are online |
Twitch API (client ID required) |
| YouTube Videos |
Get recent uploads from channels |
YouTube Data API (key required) |
Example:
You: What's the weather in 10001?
Celeste: *calls get_weather skill*
Celeste: It's 45ยฐF and cloudy in New York City...
Utilities (9 Skills)
| Skill |
Description |
Dependencies |
| Unit Converter |
Length, weight, temperature, volume |
None (local calculations) |
| Timezone Converter |
Convert times between zones |
None (local calculations) |
| Hash Generator |
MD5, SHA256, SHA512 |
None (crypto/sha256) |
| Base64 Encode |
Encode text to base64 |
None (encoding/base64) |
| Base64 Decode |
Decode base64 to text |
None (encoding/base64) |
| UUID Generator |
Generate random UUIDs (v4) |
None (google/uuid) |
| Password Generator |
Secure random passwords (customizable) |
None (crypto/rand) |
| QR Code Generator |
Create QR codes from text/URLs |
None (skip2/go-qrcode) |
Example:
You: Convert 100 miles to kilometers
Celeste: *calls convert_units skill*
Celeste: 100 miles is 160.93 kilometers
Productivity (5 Skills)
| Skill |
Description |
Dependencies |
| Set Reminder |
Create reminders with timestamps |
Local storage (~/.celeste/reminders.json) |
| List Reminders |
View all active reminders |
Local storage |
| Save Note |
Store notes by name |
Local storage (~/.celeste/notes.json) |
| Get Note |
Retrieve saved notes |
Local storage |
| List Notes |
View all saved note names |
Local storage |
Example:
You: Remind me to call mom tomorrow at 3pm
Celeste: *calls set_reminder skill*
Celeste: Reminder set for December 4, 2025 at 3:00 PM
You: Save a note called groceries: milk, eggs, bread
Celeste: *calls save_note skill*
Celeste: Note 'groceries' saved successfully!
Skills Configuration
Skill-specific API keys are stored in ~/.celeste/skills.json:
{
"venice_api_key": "your-venice-key",
"tarot_auth_token": "Basic xxx",
"weather_default_zip_code": "12345",
"twitch_client_id": "your-client-id",
"youtube_api_key": "your-youtube-key"
}
Configure via CLI:
celeste config --set-venice-key <key>
celeste config --set-weather-zip 12345
celeste config --set-twitch-client-id <id>
celeste config --set-youtube-key <key>
celeste config --set-tarot-token <token>
๐ Permission Gate
Celeste runs a hard permission gate on every tool execution in TUI mode. In the default permission mode:
- Read-only tools (read_file, search, list_files, code_search, git_status, โฆ) auto-approve silently.
- Write/destructive tools (write_file, patch_file, bash, spawn_agent, โฆ) pause and show a modal before executing.
When the modal appears, press one of:
| Key |
Action |
a, then Enter |
Allow this invocation once |
A, then Enter |
Always allow this tool (persists a rule to ~/.celeste/permissions.json) |
d or Esc |
Deny this invocation |
D |
Always deny this tool (persists a deny rule) |
Nothing is pre-selected: Enter on its own does nothing. Typing into the
modal never answers it. Any printable key after a or A cancels the pick
(Esc denies). Any other printable key (or a paste) starts typing mode: every
key, d and D included, is ignored with a hint until you press Enter, and
Esc still denies.
In headless or non-TUI contexts, any tool that would trigger the modal is denied by default โ the gate cannot be silently bypassed.
/confirm โ toggles a complementary LLM-level behavior: when on, Celeste proposes a plain-language summary of what it plans to do and waits for your approval before issuing write tool calls. This is prompt-level, not the hard modal gate.
/confirm # toggle โ Celeste narrates plans and waits before writing
๐ Claude Code Integration
Celeste v1.9.0+ exposes the codegraph as first-class MCP tools (no chat-LLM
round-trip, no output-token ceiling, verbatim results). Register celeste serve
once per workspace and any MCP client โ Claude Code, Codex, Cursor, etc. โ gets:
celeste_index โ status, update, rebuild operations with notifications/progress streaming
celeste_code_search โ semantic search (MinHash Jaccard + BM25 fusion + structural rerank)
celeste_code_review โ structural code review findings as verbatim JSON
celeste_code_graph โ symbol callers, callees, references
celeste_code_symbols โ list symbols in a file or package
Indexing is explicit: query tools never auto-reindex. After code changes, the
caller invokes celeste_index { operation: "update" } to refresh the graph.
# Recommended: Celeste writes itself into your MCP client configs. It resolves
# its own absolute path (so GUI clients like Claude Desktop and Cursor, which
# don't inherit your shell PATH, can launch it), merges into each config without
# touching your other servers, and backs up to <file>.bak. The config it writes
# launches `celeste serve` for you; you don't start the server by hand.
celeste mcp install # every client that's installed
celeste mcp install --dry-run # preview, write nothing
celeste mcp install --client claude-desktop # one client
celeste mcp install needs v1.12.1+ โ run celeste version to check. On
older builds, use the manual claude mcp add form below, or the installer in
celeste-for-claude.
--client takes claude-desktop, claude-code, cursor, celeste-cli, or
all (the default; it wires only the clients you have installed). Codex stores
MCP servers in TOML, so --client codex prints the block to paste into
~/.codex/config.toml.
After installing for Claude Desktop, quit it (Cmd-Q on macOS) and reopen it
so it loads the new config; the celeste_* tools then appear in its tool list.
Claude Code picks up changes on its next launch, or wire it by hand since it
inherits your PATH: claude mcp add celeste celeste serve.
Inside the TUI, /mcp lists configured servers and lets you connect, disconnect,
reconnect, toggle or approve a server at runtime (c / d / r / space / a). Celeste also
merges MCP servers you've already defined for Claude Code or Cursor
(~/.claude/mcp.json, ~/.cursor/mcp.json, project .mcp.json). A server starts
on its own only with "enabled": true. A project's .mcp.json or
.celeste/mcp.json can set that flag itself, so a project server also needs
your approval: at launch the chat shows its command and asks before starting
it, and records the answer in ~/.celeste/trusted.json the same way it does
for repo hooks. A no is remembered too: a declined server does not start and
is not asked about again until its command, args, env or URL change. If those
change later, the chat asks again. Without a terminal to ask on, the server
is skipped with a warning; approve it with celeste mcp trust <server>, or
from /mcp (a, which shows the command and asks to confirm).
celeste mcp list # every server, and whether it is approved, declined or pending
celeste mcp trust <server> # approve a project server, also a declined one (asks y/N)
celeste mcp trust --yes <server> # without asking (scripts; the server is still shown)
celeste mcp untrust <server> # forget the approval or decline: the chat asks again
celeste mcp list shows the servers without starting them: each one's source
file, transport, whether it is enabled and trusted, whether a project server
is approved, declined, pending, or pending because it changed (since you
approved or declined it), and where it runs. A project's .mcp.json and .celeste/mcp.json start only
in the interactive chat; agent runs, celeste acp and MCP chat use your
home-level configs. Commands, arguments, URLs and env values are not shown.
A server's tools need your approval like any other non-read-only tool, even
when the server marks them readOnlyHint: true: that hint is the server's own
claim. For a server you control, add "trusted": true and celeste believes
its read-only hints (those tools run without asking in default
mode). Only your home-level configs (~/.celeste/mcp.json,
~/.claude/mcp.json, ~/.cursor/mcp.json) can mark a server trusted; a
project's .mcp.json cannot.
{
"mcpServers": {
"notes": { "command": "notes-mcp", "enabled": true, "trusted": true }
}
}
MCP tools are named mcp__<server>__<tool> and never replace another tool:
if two servers' names sanitize to the same tool name, the server whose name
sorts first keeps it and celeste warns about the other.
Optionally, install the celeste-for-claude
companion for the persona-routed skill command wrappers (/celeste-review,
/celeste-search, /celeste-graph, /celeste-context):
git clone https://github.com/whykusanagi/celeste-for-claude.git
cp celeste-for-claude/skills/*.md ~/.claude/commands/
Claude Code stays in control, Celeste provides the graph intelligence. The
direct tools are preferred for tool-driven workflows; the persona-routed skills
are a convenience for natural-language interactions.
๐ How Celeste Compares
docs/COMPARISON.md compares celeste with Claude Code,
Codex CLI, opencode, Crush, Gemini CLI, oh-my-pi and pi, feature by feature.
What celeste keeps that none of these ship:
- A code graph with structural review.
celeste index builds a persistent
index of symbols and call edges; celeste_code_search ranks code by concept
(MinHash and BM25, fused), celeste_code_graph walks callers and callees, and
celeste_code_review finds stubs, lazy redirects, placeholders, swallowed
errors, TODOs and hardcoded values from the graph rather than by grep.
- MCP-server mode built around that graph.
celeste serve exposes
celeste to Claude Code, Codex or any MCP client, including the code-graph
tools as direct calls that return verbatim results without a model in the
way.
- A character. Celeste is a persona with its own voice, at four levels
(full, spine, lite, off) that fit the context window; official builds carry
it encrypted.
๐ LLM Provider Compatibility
Celeste CLI requires OpenAI-style function calling for skills to work. Not all LLM providers support this feature.
โ ๏ธ Chat model vs Agent model (read this โ provider-agnostic gotcha)
Plain chat works with any model. But tools/skills, subagents, and /orchestrate need a model that supports function calling โ and on every provider, some models do and some don't:
- Venice.ai โ varies per model; Celeste checks the live Venice catalog (some
*-uncensored models do support tools, some e2ee-* ones don't)
- OpenRouter โ many models lack tool/function-calling support; Celeste checks the live OpenRouter catalog
- OpenAI โ older/instruct models don't;
gpt-4.1*/gpt-4o* do
- Grok/xAI โ non-reasoning models can technically call tools but are weak at driving multi-step agent flows (they may flail and even fabricate a result, e.g. claim they spawned a subagent they didn't)
If your single model can't (or can't reliably) call tools, chat looks fine but agent mode breaks โ confusingly, often by hallucinating success rather than erroring.
Celeste splits the model in two so you don't get trapped:
| Field |
Used for |
Requirement |
model |
chat, TTS |
anything (a cheap or uncensored non-tool model is fine) |
agent_model |
agent / /orchestrate / subagents |
must support tool calling (falls back to model if unset) |
{
"model": "venice-uncensored-1-2",
"agent_model": "gpt-4.1-mini"
}
Celeste prints a loud warning at agent start if the resolved agent model doesn't support tool calling, so you catch it immediately instead of debugging a "hallucinated" agent. Leave agent_model unset and it just uses model.
Quick Reference Matrix
| Provider |
Function Calling |
Status |
Setup Difficulty |
| Sakana AI |
โ
OpenAI-Compatible |
Fully Supported (the default) |
Easy |
| OpenAI |
โ
Native |
Fully Supported |
Easy |
| Grok (xAI) |
โ
OpenAI-Compatible |
Fully Supported |
Easy |
| DigitalOcean |
โ ๏ธ Cloud Functions Only |
Limited |
Advanced (requires cloud deployment) |
| Venice.ai |
โ ๏ธ Model-dependent (catalog-checked) |
per-model via live catalog; pick a tool-capable model for agent_model |
Medium |
| OpenRouter |
โ ๏ธ Model-dependent (catalog-checked) |
per-model via live catalog; check before using as agent_model |
Medium |
| ElevenLabs |
โ Unknown |
Needs Testing |
Unknown |
| Local (OpenAI-compat) |
โ
Yes |
Varies |
Medium (model-dependent) |
โ
Fully Supported: Grok/xAI
Setup:
celeste config -config grok --set-url https://api.x.ai/v1
celeste config -config grok --set-model grok-4.20-0309-non-reasoning
celeste config -config grok --set-key your-xai-key
celeste -config grok chat
xAI's default model is grok-4.20-0309-non-reasoning โ reliable tool calling with no reasoning-token burn, and it never routes to the cost-prohibitive grok-4.3. Avoid the grok-4-1-* models: xAI silently routes them to grok-4.3.
โ
Fully Supported: OpenAI
Setup:
celeste config --set-key sk-your-openai-key
celeste config --set-url https://api.openai.com/v1
celeste config --set-model gpt-4.1-mini
celeste chat
โ ๏ธ Limited Support: DigitalOcean
Limitation: DigitalOcean AI Agent requires cloud-hosted functions. Skills cannot execute locally.
Why skills won't work:
- Celeste CLI executes skills locally (unit converter, QR generator, etc.)
- DigitalOcean expects HTTP endpoints in the cloud
- No way to bridge local execution with DigitalOcean's architecture
Workarounds:
- Use OpenAI or Grok instead
- Deploy skills as cloud functions (advanced)
- Use Celeste CLI without skills (chat only)
Testing Provider Compatibility
Run automated tests to verify function calling:
# Test OpenAI
OPENAI_API_KEY=your-key go test ./cmd/celeste/llm -run TestOpenAI_FunctionCalling -v
# Test Grok
GROK_API_KEY=your-key go test ./cmd/celeste/llm -run TestGrok_FunctionCalling -v
# Test Venice.ai
VENICE_API_KEY=your-key go test ./cmd/celeste/llm -run TestVeniceAI_FunctionCalling -v
Expected output (working):
=== RUN TestOpenAI_FunctionCalling
โ
OpenAI function calling works! Called get_weather with location=new york
--- PASS: TestOpenAI_FunctionCalling (2.34s)
Expected output (not working):
=== RUN TestVeniceAI_FunctionCalling
โ ๏ธ Venice.ai function calling failed: tools not supported
--- SKIP: TestVeniceAI_FunctionCalling
๐ See docs/LLM_PROVIDERS.md for complete provider compatibility guide
๐จ Function Calling Flow (Mermaid Diagram)
Here's how skills work under the hood:
%%{init: {'theme':'base', 'themeVariables': {'primaryColor':'#4a90e2','primaryTextColor':'#fff','primaryBorderColor':'#357abd','lineColor':'#6c757d','secondaryColor':'#7c3aed','tertiaryColor':'#10b981','noteBkgColor':'#fef3c7','noteTextColor':'#92400e'}}}%%
sequenceDiagram
actor User
participant CLI as Celeste CLI
participant LLM as LLM Provider
participant Skill as Skill Handler
participant API as External API
User->>+CLI: "What's the weather in NYC?"
CLI->>+LLM: Send message + tools definition
Note right of LLM: AI decides:<br/>need weather data
LLM-->>-CLI: tool_call: get_weather(location="NYC")
CLI->>+Skill: Execute get_weather handler
Skill->>+API: Fetch weather data (wttr.in)
API-->>-Skill: JSON weather response
Skill-->>-CLI: Formatted weather data
CLI->>+LLM: Send tool result back
Note right of LLM: Generate natural<br/>response
LLM-->>-CLI: "It's 45ยฐF and cloudy in NYC..."
CLI->>-User: Display response with typing animation
Key Points:
- Tools sent with every request - All available skills are listed in the API call
- LLM decides when to call - You don't manually invoke skills, the AI does
- Local execution - Skills run on your machine (unless they need external APIs)
- Result sent back to LLM - Tool results are formatted and returned for interpretation
- Natural language output - LLM converts structured data into conversational responses
This requires OpenAI-style function calling support! Providers without this feature will ignore tools and respond as if they don't have access to data.
โ๏ธ Configuration
Configuration Files
Celeste CLI uses three config files in ~/.celeste/:
| File |
Purpose |
Example |
| config.json |
Main configuration |
API endpoint, model, timeouts |
| secrets.json |
API keys (backward compat) |
OpenAI API key only |
| skills.json |
Skill-specific configs |
Venice.ai key, weather zip code |
Main Config (~/.celeste/config.json)
{
"api_key": "",
"base_url": "https://api.x.ai/v1",
"model": "grok-4.20-0309-non-reasoning",
"timeout": 60,
"simulate_typing": true,
"typing_speed": 60
}
Skills Config (~/.celeste/skills.json)
{
"venice_api_key": "your-venice-key",
"venice_base_url": "https://api.venice.ai/api/v1",
"venice_model": "venice-uncensored-1-2",
"tarot_function_url": "https://your-tarot-api",
"tarot_auth_token": "Basic xxx",
"weather_default_zip_code": "10001",
"twitch_client_id": "your-twitch-client-id",
"twitch_default_streamer": "whykusanagi",
"youtube_api_key": "your-youtube-key",
"youtube_default_channel": "UC..."
}
Environment Variables (Override Config)
export CELESTE_API_KEY="sk-your-key"
export CELESTE_API_ENDPOINT="https://api.openai.com/v1"
export TAROT_AUTH_TOKEN="Basic xxx"
Precedence is environment variable > config file. CELESTE_API_KEY,
CELESTE_API_ENDPOINT and TAROT_AUTH_TOKEN override api_key, base_url
and tarot_auth_token for the profile you start with (chat, message,
agent, serve). They apply to that run only: they are never written to a
config file, and /endpoint switches to the target profile's own settings.
A blank variable is ignored. VENICE_API_KEY is only a fallback for the
venice endpoint when skills.json has no Venice key.
Typing animation
simulate_typing (default true) types replies out with the corruption
animation; false shows each reply at once. typing_speed is characters per
second, 1-1000 (default 60, about 3 characters per animation tick). The animation moves at least one character per 50ms tick, so speeds below 20 behave as 20. A saved typing_speed of 40 or 25 (old celeste defaults that were never read) is removed at startup so those configs keep the default pace.
Config Commands
# View current config
celeste config --show
# Main config settings
celeste config --set-key sk-xxx
celeste config --set-url https://api.openai.com/v1
celeste config --set-model gpt-4o-mini
celeste config --simulate-typing true
celeste config --typing-speed 60
# Named configs (multi-profile support)
celeste config --list # List all profiles
celeste config --init openai # Create openai profile
celeste config --init grok # Create grok profile
celeste -config grok chat # Use grok profile
# Skill configuration
celeste config --set-venice-key <key>
celeste config --set-weather-zip 10001
celeste config --set-twitch-client-id <id>
celeste config --set-youtube-key <key>
celeste config --set-tarot-token <token>
Named Configs (Multi-Profile)
Create separate configs for different providers:
# Create OpenAI config. Every --set-* MUST carry -config <name>, or it writes
# to the DEFAULT config.json instead and silently builds a broken mix.
celeste config --init openai
celeste -config openai config --set-key sk-openai-key
celeste -config openai config --set-model gpt-4o-mini
# Create Grok config
celeste config --init grok
celeste -config grok config --set-key xai-grok-key
celeste -config grok config --set-url https://api.x.ai/v1
celeste -config grok config --set-model grok-beta
# Use specific config
celeste -config grok chat
Available templates: openai, grok, elevenlabs, venice, digitalocean
๐ฏ Usage
Interactive TUI Mode
# Launch interactive TUI (default command)
celeste chat
# Use a specific named config
celeste -config grok chat
Keyboard Shortcuts
| Key |
Action |
Ctrl+C |
Cancel the running operation; press again within 3 seconds to exit |
PgUp/PgDown |
Scroll chat history (full page) |
Shift+โ/โ |
Scroll chat (3 lines at a time) |
โ/โ |
Navigate input history (previous messages) |
Enter |
Send message |
Esc |
Clear current input; on an empty input it interrupts the running turn |
In-Chat Commands
Core Commands
| Command |
Action |
/help |
Show available commands and keyboard shortcuts |
/clear |
Clear chat history (current session only) |
exit, quit, q |
Exit application (typed without a slash; or press Ctrl+C twice) |
Plan Mode
| Command |
Action |
/plan [goal] |
Plan mode: read-only tools until you approve the plan Celeste submits (with a goal, also sends it as the prompt) |
/plan off |
Leave plan mode |
/plan show |
Show the approved plan (.celeste/plan.json) with each step's todo status; celeste plan does the same from the shell |
Approving a plan turns its steps into todo items and ends plan mode. See docs/PLAN_MODE.md.
Provider & Model Management
| Command |
Action |
/endpoint <provider> |
Switch to a different LLM provider (openai, grok, venice, gemini, openrouter, etc.) |
/set-model |
List available models for current provider with capability indicators |
/set-model <name> |
Switch to a specific model (validates function calling support) |
/set-model <name> --force |
Override model compatibility warnings |
/list-models |
Alias for /set-model |
Examples:
# Switch to Grok (auto-selects grok-4.20-0309-non-reasoning for tool calling)
/endpoint grok
# List Grok models with capability indicators
/set-model
# Output:
# โ grok-4.20-0309-non-reasoning - default (non-reasoning, no grok-4.3 routing)
# โ grok-4-1 - High-quality reasoning
# grok-4-latest - Latest general model (no skills)
# Force use a non-tool model
/set-model grok-4-latest --force
# Switch to Gemini AI (AI Studio)
/endpoint gemini
Context Management & Analytics
| Command |
Action |
/context |
Show current token usage, cost estimation, and context window status |
/stats |
Display usage analytics dashboard with provider/model breakdowns |
/export [format] |
Export current session (formats: json, md, csv) |
Token Tracking Support by Provider:
โ
Full Support (Returns usage data with automatic token tracking):
- OpenAI (gpt-4o, gpt-4o-mini, etc.)
- xAI/Grok (grok-4.20-0309-non-reasoning [xAI default], grok-build-0.1, etc.)
- Venice.ai (venice-uncensored-1-2, etc.)
- Google Gemini AI Studio (gemini-flash-latest โ a Google-maintained alias; the 2.x line is retired)
- Google Vertex AI (gemini models via OpenAI endpoint)
- OpenRouter (all models)
- Anthropic Claude (native API; input, output and cache read/write tokens)
- DigitalOcean Gradient (Agent API with RAG - supports stream_options.include_usage)
โ No Support (Uses estimation only):
- ElevenLabs (Voice-focused API)
Examples:
# Check current context usage
/context
# Shows: Token usage (12.5K/128K), cost ($0.034), warning level
# View analytics dashboard
/stats
# Shows: Lifetime usage, top models, provider breakdown, daily stats
# Export conversation to Markdown
/export md
# Saves to: ~/.celeste/exports/session_<id>_<timestamp>.md
# Export to JSON for programmatic access
/export json
Note: When using a provider without token tracking (ElevenLabs), Celeste CLI will estimate tokens based on character count (~4 chars = 1 token), but won't show exact API usage or costs. For accurate token tracking and context management features, use providers marked with โ
above.
Autonomous Agent Mode
celeste agent --goal "refactor the parser and keep the tests green"
Useful flags beyond --goal:
| Flag |
Default |
What it does |
-planner |
true |
Run an explicit planning phase before executing. |
-require-verify |
false |
Refuse to finish until the verification commands pass. |
-request-timeout |
0 (30-minute cap) |
Most seconds one model turn may take. A request that sends nothing for the profile's timeout fails sooner either way. |
-max-turns |
unset |
Cap the number of agent turns. |
-no-checkpoint |
false |
Disable checkpointing for this run. |
-auto-approve |
false |
Approve every tool without prompting. Required for unattended runs. |
Unattended runs need -auto-approve. celeste agent has no interactive
approval prompt, in a terminal or otherwise. Under the default policy only
read_file, list_files and search are granted, so every other tool is
denied and the agent can read but never write. Rather than burning the whole turn
budget discovering that, the runner refuses to start and names the tools it cannot
execute. Pass -auto-approve (invoking the agent is the approval, the same
contract subagents already use), or grant specific tools in
~/.celeste/permissions.json.
Passing one of the first three explicitly changes behaviour. When the model
orchestrates server-side (see Planning below), celeste skips its own local
planner so the work is not planned twice. Type -planner, -require-verify or
-request-timeout on the command line and you override that skip and pin your
own value. That override is what lets you compare a local planner against a
server-side one. Leaving a flag off is not the same as passing its default.
celeste config
Among the usual fields, the Planning: line tells you which planner is in
charge for your current model:
Planning: fugu (server-side) # the model's own conductor plans; local planner stands down
Planning: local # Celeste plans locally
A server-side conductor leaves no local trace: celeste sees the reply and the
tool calls, not the conductor's plan or which models it consulted.
Single Message Mode (Non-Interactive)
# Send a single message and exit
celeste message "What is the meaning of life?"
# Or use shorthand
celeste "Hello, Celeste!"
celeste models, celeste model and celeste status are not commands: on their
own they print a hint instead of reaching the model. Send one of those words with
celeste message <word>. Any other text, one word included, is a message.
Session Management
# List saved sessions
celeste session --list
# Load a specific session
celeste session --load abc123def
# Clear all sessions
celeste session --clear
Sessions are auto-saved to ~/.celeste/sessions/ and can be resumed later. Each records the directory it ran in: celeste resume (and /session list in the chat) lists the current project's sessions first, marked (this project); celeste resume <id or name> opens one.
In the chat:
/rewind [n] Take back the last n prompts (default 1), restore the files
those turns changed, and put the prompt back in the input box
/fork Continue in a copy of this session; the original is kept
/undo Undo the last file change (repeat to go back)
/diff List the files this session changed
/rewind cannot go back past a /compact summary, and does not restore files changed by shell commands. A subagent's changes are restored only when the rewound turns changed a file themselves before it ran; /diff shows what is left.
File checkpoints (/undo, /diff, /rewind) stay with the session the chat started in: after /fork, /session new or /session resume, changes are still filed under that first session, so resuming the fork in a later run finds none of them, and resuming the original can undo the fork's changes. /rewind refuses to restore files when the provider reused a tool call ID from an earlier turn (Gemini sessions saved before 2.0, some local servers); use /undo there. With checkpoints off (no home directory) it rewinds the chat and leaves the files.
Skills Management
# List available skills (with descriptions)
celeste skills --list
# Initialize default skill configuration files
celeste skills --init
Version & Help
# Show version
celeste version
celeste --version
# Show help
celeste help
celeste --help
๐ฅ NSFW Mode (Venice.ai Integration)
NSFW mode provides uncensored chat and NSFW image generation via Venice.ai:
Activating NSFW Mode:
# In chat, type:
/nsfw
# Header will show: ๐ฅ NSFW โข img:lustify-sdxl
Image Generation Commands:
# Generate with default model (lustify-sdxl)
image: cyberpunk cityscape at night
# Generate anime-style images
anime: magical girl with sword
# Generate dream-like images
dream: surreal cosmic landscape
# Use specific model for one generation
image[venice-sd35]: photorealistic portrait
# Upscale existing image
upscale: ~/path/to/image.jpg
Model Management:
# Set default image model
/set-model wai-Illustrious
# View available models
/set-model
# Models available:
# - lustify-sdxl (default NSFW)
# - wai-Illustrious (anime style)
# - hidream (dream-like quality)
# - nano-banana-pro
# - venice-sd35 (Stable Diffusion 3.5)
# - lustify-v7
# - qwen-image
Image Quality Settings:
All images generate with high-quality defaults:
- Steps: 40 (1-50, higher = more detail)
- CFG Scale: 12.0 (0-20, higher = stronger prompt adherence)
- Size: 1024x1024 (up to 1280x1280)
- Format: PNG (lossless)
- Safe Mode: Disabled (no NSFW blurring)
Download Location:
Images save to ~/Downloads by default. Customize in ~/.celeste/skills.json:
{
"downloads_dir": "~/Pictures"
}
LLM Prompt Chaining:
Ask the uncensored LLM to write prompts for you:
You: Write a detailed NSFW anime scene description
Celeste: [Generates detailed prompt]
You: image: [paste Celeste's prompt]
Celeste: *generates image from AI-written prompt*
Returning to Safe Mode:
/safe
# Returns to OpenAI endpoint with skills enabled
Configuration:
Add Venice.ai API key to ~/.celeste/skills.json:
{
"venice_api_key": "your-venice-api-key",
"venice_base_url": "https://api.venice.ai/api/v1",
"venice_model": "venice-uncensored-1-2",
"venice_image_model": "lustify-sdxl",
"downloads_dir": "~/Downloads"
}
Limitations:
- Function calling disabled in NSFW mode (Venice uncensored doesn't support it)
- Skills are unavailable (use /safe to re-enable)
- Video generation not available (Venice API limitation)
๐๏ธ Architecture
Project Structure
celeste-cli/
โโโ cmd/celeste/ # Main application
โ โโโ main.go # CLI entry point
โ โโโ tui/ # Bubble Tea TUI components
โ โ โโโ app.go # Main TUI model & update loop
โ โ โโโ chat.go # Scrollable viewport (messages)
โ โ โโโ input.go # Text input + history
โ โ โโโ skills.go # Skills panel (execution status)
โ โ โโโ styles.go # Lip Gloss theme (corrupted aesthetic)
โ โ โโโ streaming.go # Simulated typing animation
โ โ โโโ messages.go # Bubble Tea messages (events)
โ โโโ tools/ # Unified tool system
โ โ โโโ builtin/ # All built-in tool implementations
โ โ โโโ mcp/ # MCP client for external tools
โ โโโ permissions/ # Tool permission system
โ โโโ context/ # Token budget & context management
โ โโโ llm/ # LLM client
โ โ โโโ client.go # OpenAI-compatible client
โ โ โโโ stream.go # Streaming handler (SSE)
โ โ โโโ providers_test.go # Provider compatibility tests
โ โโโ config/ # Configuration management
โ โ โโโ config.go # JSON config (load/save/named)
โ โ โโโ session.go # Session persistence
โ โโโ prompts/ # System prompt and persona
โ โโโ compose.go # System prompt: persona first, then the per-request part
โ โโโ profile.go # Persona profiles: decrypt, or the public persona
โ โโโ personacrypt/ # AES-256-GCM sealing for the persona
โ โโโ persona/ # Encrypted persona (all rights reserved; make sync-persona)
โโโ docs/ # Documentation
โ โโโ LLM_PROVIDERS.md # Provider compatibility guide
โ โโโ CAPABILITIES.md # What Celeste can do (ecosystem)
โ โโโ PERSONALITY.md # Persona profiles, licensing, sliders
โ โโโ ROUTING.md # Sub-agent routing (ecosystem)
โโโ LICENSE # MIT License
โโโ CHANGELOG.md # Version history
โโโ CONTRIBUTING.md # Contribution guidelines
โโโ SECURITY.md # Security policy
โโโ README.md # This file
Component Flow Diagram
%%{init: {'theme':'base', 'themeVariables': {'primaryColor':'#4a90e2','secondaryColor':'#7c3aed','tertiaryColor':'#10b981','primaryTextColor':'#fff','lineColor':'#6c757d','fontSize':'14px'}}}%%
flowchart TB
subgraph CLI["๐ฅ๏ธ CLI Entry (main.go)"]
style CLI fill:#e8f4f8,stroke:#4a90e2,stroke-width:2px
Main[Parse Args] --> |chat| TUI[Launch TUI]
Main --> |config| Config[Config Manager]
Main --> |session| Session[Session Manager]
Main --> |skills| Skills[Skills Registry]
Main --> |help| Help[Print Help]
end
subgraph TUI_Layer["๐จ TUI Layer (Bubble Tea)"]
style TUI_Layer fill:#f3e8ff,stroke:#7c3aed,stroke-width:2px
TUI --> Header[Header Bar]
TUI --> Viewport[Chat Viewport]
TUI --> Input[Text Input + History]
TUI --> SkillsPanel[Skills Panel]
TUI --> Status[Status Bar]
end
subgraph Backend["โ๏ธ Backend (Business Logic)"]
style Backend fill:#fef3c7,stroke:#f59e0b,stroke-width:2px
Input --> |user message| LLM[LLM Client]
LLM --> |stream chunks| Stream[Streaming Handler]
Stream --> |SSE parsing| SimType[Simulated Typing]
SimType --> |char-by-char| Viewport
LLM --> |tool_calls detected| Executor[Skill Executor]
Executor --> |lookup| Registry[Skills Registry]
Registry --> |execute| Handler[Skill Handler]
Handler --> |result| Executor
Executor --> |tool result| LLM
LLM --> |final response| Stream
end
subgraph Storage["๐พ Persistence Layer"]
style Storage fill:#d1fae5,stroke:#10b981,stroke-width:2px
Config --> ConfigFiles["~/.celeste/config.json"]
Session --> SessionFiles["~/.celeste/sessions/*.json"]
Handler --> |reminders/notes| LocalStorage["~/.celeste/reminders.json"]
end
subgraph External["๐ External APIs"]
style External fill:#fee2e2,stroke:#ef4444,stroke-width:2px
Handler --> |weather| WttrIn[wttr.in API]
Handler --> |tarot| TarotAPI[Tarot Function]
Handler --> |nsfw/images| VeniceAI[Venice.ai]
Handler --> |currency| ExchangeRate[ExchangeRate-API]
Handler --> |twitch| TwitchAPI[Twitch API]
Handler --> |youtube| YouTubeAPI[YouTube Data API]
end
classDef entryPoint fill:#4a90e2,stroke:#357abd,color:#fff
classDef uiComponent fill:#7c3aed,stroke:#6b21a8,color:#fff
classDef business fill:#f59e0b,stroke:#d97706,color:#fff
classDef storage fill:#10b981,stroke:#059669,color:#fff
classDef external fill:#ef4444,stroke:#dc2626,color:#fff
class Main,TUI entryPoint
class LLM,Stream,Executor business
class ConfigFiles,SessionFiles,LocalStorage storage
class WttrIn,TarotAPI,VeniceAI,ExchangeRate,TwitchAPI,YouTubeAPI external
Data Flow: User Message โ Response
- User Input โ Text input component (with history)
- TUI Update โ Bubble Tea update loop processes input
- LLM Request โ Client sends message + tools to OpenAI/Grok
- Stream Parse โ Parse SSE chunks (text or tool_calls)
- Tool Execution (if tool_calls):
- Executor receives tool call JSON
- Registry looks up skill handler
- Handler executes (local or API call)
- Result sent back to LLM
- Response Stream โ LLM generates natural language response
- Simulated Typing โ Character-by-character rendering (if enabled)
- Viewport Update โ Chat history updates with new message
- Session Save โ Auto-save conversation to disk
๐จ Theming
The TUI uses the corrupted-theme color palette inspired by Celeste's abyss aesthetic:
| Color |
Hex |
RGB |
Usage |
| Accent |
#d94f90 |
rgb(217, 79, 144) |
Headers, prompts, highlights, user messages |
| Purple |
#8b5cf6 |
rgb(139, 92, 246) |
Function calls, secondary elements, skill names |
| Dark Purple |
#6d28d9 |
rgb(109, 40, 217) |
Borders, subtle accents |
| Background |
#0a0a0a |
rgb(10, 10, 10) |
Main background (terminal) |
| Surface |
#1a1a1a |
rgb(26, 26, 26) |
Elevated surfaces, panels |
| Text |
#f5f1f8 |
rgb(245, 241, 248) |
Primary text, assistant messages |
| Muted |
#7a7085 |
rgb(122, 112, 133) |
Hints, timestamps, secondary text |
| Success |
#10b981 |
rgb(16, 185, 129) |
Skill success indicators |
| Error |
#ef4444 |
rgb(239, 68, 68) |
Errors, warnings |
Demonic Eye Animation
When Celeste is thinking, a demonic eye animation plays:
๐๏ธ โ ๐ โ โโ โ โโ (pulsing)
Colors pulse between magenta (#d94f90) and red (#dc2626) to show "corruption deepening."
๐ง Development
Prerequisites
- Go 1.26+ (matches the toolchain in
go.mod)
- Terminal with 256-color support (iTerm2, Alacritty, Windows Terminal, etc.)
- API Keys (for testing skills):
- OpenAI API key (required for chat)
- Venice.ai API key (optional, for NSFW/image skills)
- YouTube Data API key (optional, for YouTube skill)
- Twitch Client ID (optional, for Twitch skill)
Building from Source
cd celeste-cli
go mod tidy
go build -o celeste ./cmd/celeste
Running Tests
# Run all tests
go test ./...
# Run with coverage
go test -cover ./...
# Run specific package
go test ./cmd/celeste/skills -v
# Run provider compatibility tests
OPENAI_API_KEY=sk-xxx go test ./cmd/Celeste/llm -run TestOpenAI_FunctionCalling -v
Code Quality Checks
# Format code
gofmt -w ./cmd
# Run linter
go vet ./...
# Check for unused imports
goimports -w ./cmd
Dependencies
| Package |
Purpose |
Version |
github.com/charmbracelet/bubbletea |
TUI framework |
v1.3.10 |
github.com/charmbracelet/bubbles |
TUI components (viewport, textinput) |
v0.21.0 |
github.com/charmbracelet/lipgloss |
Styling engine |
v1.1.0 |
github.com/sashabaranov/go-openai |
OpenAI client (streaming, function calling) |
v1.20.4 |
github.com/google/uuid |
UUID generation |
v1.6.0 |
github.com/skip2/go-qrcode |
QR code generation |
v0.0.0-20200617195104 |
github.com/stretchr/testify |
Testing framework |
v1.11.1 |
Branch Strategy
- main - Stable releases only
- feature/bubbletea-tui - Current development branch (TUI implementation)
- Feature branches - Fork from
feature/bubbletea-tui
๐ Troubleshooting
Error:
No API key configured.
Set CELESTE_API_KEY environment variable or run: celeste config --set-key <key>
Solution:
celeste config --set-key sk-your-openai-key
Or use environment variable:
export CELESTE_API_KEY="sk-your-key"
celeste chat
Skills Not Working
Symptom: LLM says "I don't have access to real-time data" when asking for weather, etc.
Possible Causes:
- Provider doesn't support function calling - See LLM Provider Compatibility
- Skill config missing - Check
~/.celeste/skills.json for required API keys
Solution:
# Test provider compatibility
OPENAI_API_KEY=your-key go test ./cmd/celeste/llm -run TestOpenAI_FunctionCalling -v
# If provider doesn't support skills, switch to OpenAI or Grok
celeste config --set-url https://api.openai.com/v1
celeste config --set-key sk-openai-key
Streaming Looks Choppy
Symptom: Text appears in large chunks instead of smooth typing
Solution: Enable simulated typing:
celeste config --simulate-typing true
celeste config --typing-speed 60 # Adjust speed (1-1000 chars per second)
Session Not Saving
Symptom: Conversations don't persist between runs
Cause: Sessions directory not writable or doesn't exist
Solution:
# Check permissions
ls -la ~/.celeste/sessions/
# If missing, create it
mkdir -p ~/.celeste/sessions/
chmod 755 ~/.celeste/sessions/
TUI Rendering Issues
Symptom: Screen flickering, garbled text, or broken layout
Possible Causes:
- Terminal doesn't support 256 colors
- Terminal size too small
- Environment variable issues
Solution:
# Check terminal capabilities
echo $TERM # Should be xterm-256color or similar
tput colors # Should return 256
# Set TERM if needed
export TERM=xterm-256color
# Ensure minimum terminal size (80x24)
resize # Check current size
Build Errors
Error: go: updates to go.mod needed; to update it: go mod tidy
Solution:
go mod tidy
go build -o celeste ./cmd/celeste
Error: package X is not in GOROOT
Solution:
# Update dependencies
go get -u ./...
go mod tidy
๐ Documentation
Comprehensive documentation for developers and contributors:
Core Documentation
- ARCHITECTURE.md - System design, component relationships, and data flow diagrams
- TESTING.md - Testing guide with examples, coverage reports, and best practices
- CONTRIBUTING.md - How to contribute: adding skills, providers, and commands
- LLM_PROVIDERS.md - Provider compatibility matrix and setup guides
- ACP.md - Using celeste in Zed and JetBrains (
celeste acp)
- STYLE_GUIDE.md - Code formatting standards and conventions
Upgrading and Features
- MIGRATING-2.0.md - Upgrading from 1.x: every change that can affect an existing setup
- HOOKS.md -
hooks.json, grimoire hooks, approving a repository's hooks (celeste hooks)
- PERMISSIONS.md -
permissions.json: the rule order, argument-scoped rules and the permission prompt
- SANDBOX.md - The optional OS sandbox for
bash
- SUBAGENTS.md - Typed subagents (
explore, review, general)
- PLAN_MODE.md -
/plan and celeste plan
- STEERING.md - Stream rules, the watchdog and the completion gate
- PERSONALITY.md - Persona profiles, the public persona,
celeste persona verify
- ROADMAP.md - What 2.0 shipped and what comes next
- COMPARISON.md - Feature comparison with other coding agents
Test Coverage (v1.2.0)
Overall coverage: 17.4% across critical packages
| Package |
Coverage |
Status |
| prompts |
97.1% |
โ
Excellent |
| providers |
72.8% |
โ
Excellent |
| config |
52.0% |
โ
Good |
| commands |
25.8% |
โ ๏ธ Moderate |
| venice |
22.6% |
โ ๏ธ Moderate |
| skills |
12.2% |
โ ๏ธ Low |
| llm |
0% |
โ Requires mocking |
| tui |
0% |
โ Requires mocking |
See TESTING.md for details on running tests and writing new ones.
๐ค Contributing
We welcome contributions! Please see CONTRIBUTING.md for detailed guidelines.
Quick Start for Contributors
- Fork the repository
- Create a feature branch from
feature/bubbletea-tui:
git checkout feature/bubbletea-tui
git checkout -b feature/your-feature-name
- Make your changes
- Test thoroughly:
go test ./...
go vet ./...
gofmt -l ./cmd # Should return nothing
- Submit a pull request to
feature/bubbletea-tui
Areas for Contribution
- ๐งช Testing - Provider compatibility tests, skill unit tests, integration tests
- ๐ Documentation - Improve guides, add examples, translate to other languages
- ๐จ Themes - Alternative color schemes, terminal themes
- ๐ฎ Skills - New skill implementations (requires function calling support)
- ๐ Bug Fixes - See GitHub Issues
- โก Performance - Optimize streaming, reduce memory usage
Testing Your Changes
Before submitting a PR:
# Build succeeds
go build -o celeste ./cmd/celeste
# All tests pass
go test ./...
# No vet warnings
go vet ./...
# Code is formatted
gofmt -w ./cmd
git diff # Should show no changes
# TUI works
./celeste chat
๐ License
This project is licensed under the MIT License - see the LICENSE file for details.
Except Celeste's persona. The encrypted persona profiles in cmd/celeste/prompts/persona/,
and the persona they contain, are ยฉ whyKusanagi, all rights reserved, and are not covered by the
MIT License (see cmd/celeste/prompts/persona/LICENSE).
Official release binaries carry the full persona; builds from source run a minimal public
persona. See docs/PERSONALITY.md.
๐ Links
๐ Acknowledgments
- Charm - Bubble Tea, Bubbles, and Lip Gloss TUI frameworks
- sashabaranov/go-openai - OpenAI Go client
- OpenAI - Function calling API
- xAI - Grok API
- Venice.ai - Uncensored AI models
- wttr.in - Free weather API
๐ Support