Character artwork by ใใใใ (ikawasa23)
A premium, corruption-aesthetic command-line interface for CelesteAI
Built with Charm's Bubble Tea for flicker-free, modern terminal experiences
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
- ๐
.grimoireProject Context - Persona-themed project config files with auto-discovery;AGENTS.md/CLAUDE.mdare 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=0source 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_symbolsserved verbatim from the cached graph (no chat-LLM round-trip, nomax_tokensceiling, 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## Hookssection); a repository's hooks run only after you approve them (celeste hooks list,celeste hooks trust). See docs/HOOKS.md - ๐งฑ Sandbox (opt-in) -
bashcan 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,/diffand/rewindin the chat,celeste revert <file>from the shell - ๐ง Extended Thinking - Leverage reasoning tokens (Claude, Gemini, Grok) with
/effortcontrol - ๐ผ๏ธ 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
| 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.
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@latestgo 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"# 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 installThe 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). Without one,
or with CGO_ENABLED=0, celeste still builds and the code graph falls back to regex parsers,
with less accurate call edges. 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
cpthe 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 installbuilds 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
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.
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 chatxAI/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 chatWith 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 chatOpenAI:
celeste config --init openai
celeste -config openai config --set-key YOUR_OPENAI_KEY
celeste -config openai chatSakana (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 chatGet 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
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 statsIn the chat, /init and /init agents do the same. An existing file is never overwritten.
All Celeste CLI releases are cryptographically signed with GPG to ensure authenticity and integrity.
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.gzFor 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:
- Key ID:
875849AB1D541C55 - Fingerprint:
9404 90EF 09DA 3132 2BF7 FD83 8758 49AB 1D54 1C55 - Keybase: @whykusanagi
- GitHub: whykusanagi.gpg
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 1C55For security issues, see our Security Policy or contact security@whykusanagi.xyz.
- Installation
- Security & Verification
- Features
- Tool System (48 Tools)
- Claude Code Integration
- Comparison
- LLM Provider Compatibility
- Function Calling Flow
- Configuration
- Usage
- Architecture
- Documentation
- Contributing
- 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.
- Upload Custom Documents - Create knowledge bases with your own documentation
- Semantic Search - Celeste automatically searches collections when answering questions
- Interactive TUI - Manage collections with
/collectionscommand 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
- 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
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 localhost, any port; tools supported. No
api_keyneeded 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 /
- JSON-based Config - Modern
~/.celeste/config.jsonformat - Named Configs - Multi-profile support (openai, grok, venice, etc.)
- Skills Config - Separate
skills.jsonfor skill-specific API keys - Secrets Handling - Separate
secrets.jsonfor backward compatibility - Persona - Always on in chat and agent runs, sized to the model's context window (
context_limit); tune it with/personasliders - 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 onProtocol/ABC/ABCMetaclasses โ eliminating the largest classes of false positives. Decorator@syntaxcalls and@property.setterassignments 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.
| 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]
| 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...
| 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
| 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!
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>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
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,rebuildoperations withnotifications/progressstreamingceleste_code_searchโ semantic search (MinHash Jaccard + BM25 fusion + structural rerank)celeste_code_reviewโ structural code review findings as verbatim JSONceleste_code_graphโ symbol callers, callees, referencesceleste_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 installneeds v1.12.1+ โ runceleste versionto check. On older builds, use the manualclaude mcp addform 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, or toggle a server at runtime (c / d / r / space). 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. If the command, args, env or URL change later, the chat asks
again. Without a terminal to ask on, the server is skipped with a warning;
approve it with celeste hooks trust, or connect it by hand from /mcp.
From the shell, celeste mcp list shows the same servers without starting
them: each one's source file, transport, whether it is enabled and trusted,
whether a project server is approved, pending, or pending because it changed,
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.
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 indexbuilds a persistent index of symbols and call edges;celeste_code_searchranks code by concept (MinHash and BM25, fused),celeste_code_graphwalks callers and callees, andceleste_code_reviewfinds 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 serveexposes 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.
Celeste CLI requires OpenAI-style function calling for skills to work. Not all LLM providers support this feature.
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
*-uncensoredmodels do support tools, somee2ee-*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.
| 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 | Limited | Advanced (requires cloud deployment) | |
| Venice.ai | per-model via live catalog; pick a tool-capable model for agent_model |
Medium | |
| OpenRouter | 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) |
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 chatxAI'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.
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 chatLimitation: 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)
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 -vExpected 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
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
- 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.
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 |
{
"api_key": "",
"base_url": "https://api.x.ai/v1",
"model": "grok-4.20-0309-non-reasoning",
"timeout": 60,
"simulate_typing": true,
"typing_speed": 60
}{
"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..."
}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.
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.
# 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>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 chatAvailable templates: openai, grok, elevenlabs, venice, digitalocean
# Launch interactive TUI (default command)
celeste chat
# Use a specific named config
celeste -config grok chat| 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 |
| 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) |
| 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.
| 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| 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 jsonNote: 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.
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 configAmong 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.
# 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.
# List saved sessions
celeste session --list
# Load a specific session
celeste session --load abc123def
# Clear all sessions
celeste session --clearSessions 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.
# List available skills (with descriptions)
celeste skills --list
# Initialize default skill configuration files
celeste skills --init# Show version
celeste version
celeste --version
# Show help
celeste help
celeste --helpNSFW mode provides uncensored chat and NSFW image generation via Venice.ai:
Activating NSFW Mode:
# In chat, type:
/nsfw
# Header will show: ๐ฅ NSFW โข img:lustify-sdxlImage 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.jpgModel 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-imageImage 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 enabledConfiguration:
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)
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
%%{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
- 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
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 |
When Celeste is thinking, a demonic eye animation plays:
๐๏ธ โ ๐ โ โโ โ โโ (pulsing)
Colors pulse between magenta (#d94f90) and red (#dc2626) to show "corruption deepening."
- 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)
cd celeste-cli
go mod tidy
go build -o celeste ./cmd/celeste# 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# Format code
gofmt -w ./cmd
# Run linter
go vet ./...
# Check for unused imports
goimports -w ./cmd| 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 |
- main - Stable releases only
- feature/bubbletea-tui - Current development branch (TUI implementation)
- Feature branches - Fork from
feature/bubbletea-tui
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-keyOr use environment variable:
export CELESTE_API_KEY="sk-your-key"
celeste chatSymptom: 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.jsonfor 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-keySymptom: 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)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/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 sizeError: go: updates to go.mod needed; to update it: go mod tidy
Solution:
go mod tidy
go build -o celeste ./cmd/celesteError: package X is not in GOROOT
Solution:
# Update dependencies
go get -u ./...
go mod tidyComprehensive documentation for developers and contributors:
- 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
- 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) - SANDBOX.md - The optional OS sandbox for
bash - SUBAGENTS.md - Typed subagents (
explore,review,general) - PLAN_MODE.md -
/planandceleste 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
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% | |
| venice | 22.6% | |
| skills | 12.2% | |
| llm | 0% | โ Requires mocking |
| tui | 0% | โ Requires mocking |
See TESTING.md for details on running tests and writing new ones.
We welcome contributions! Please see CONTRIBUTING.md for detailed guidelines.
- 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
- ๐งช 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
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 chatThis 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.
- 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
- Issues: GitHub Issues
- Security: See SECURITY.md
- Documentation: docs/
- Community: Discord (coming soon)
Built with ๐ by @whykusanagi