https://github.com/vonglasow/gaia
Gaia is a command-line interface (CLI) tool for interacting with language models via a local API. It features a beautiful terminal UI, robust configuration management, and multiple interaction modes (default, describe, code, shell) for versatile assistance with programming, system administration, and more.
https://github.com/vonglasow/gaia
ai bubbletea cli cobra commands developer-tools go homebrew language-model linux llama llm local-api ollama productivity shell terminal tui
Last synced: 3 months ago
JSON representation
Gaia is a command-line interface (CLI) tool for interacting with language models via a local API. It features a beautiful terminal UI, robust configuration management, and multiple interaction modes (default, describe, code, shell) for versatile assistance with programming, system administration, and more.
- Host: GitHub
- URL: https://github.com/vonglasow/gaia
- Owner: vonglasow
- License: gpl-3.0
- Created: 2024-03-18T21:25:42.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2026-03-18T17:21:25.000Z (4 months ago)
- Last Synced: 2026-03-19T06:56:46.704Z (4 months ago)
- Topics: ai, bubbletea, cli, cobra, commands, developer-tools, go, homebrew, language-model, linux, llama, llm, local-api, ollama, productivity, shell, terminal, tui
- Language: Go
- Homepage:
- Size: 333 KB
- Stars: 12
- Watchers: 2
- Forks: 5
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
- Agents: AGENTS.md
Awesome Lists containing this project
README
# Gaia
[](https://results.pre-commit.ci/latest/github/vonglasow/gaia/main)






Gaia is a command-line interface (CLI) tool that provides a convenient way to
interact with language models through a local or remote API. It features a beautiful
terminal UI, configuration management, automatic role detection, response caching,
and support for different interaction modes.
## Features
- π Simple and intuitive command-line interface
- π¨ Beautiful terminal UI with progress bars
- πΊ **Interactive TUI prompts** (Bubble Tea): when using tool actions (`gaia tool git commit`) or operator mode (`gaia investigate`), context and confirmation prompts use a rich terminal UI in a real terminal β styled boxes, keyboard shortcuts, text wrapping to window width
- βοΈ Comprehensive configuration management with YAML support
- π Support for different interaction modes (default, describe, code, shell, commit, branch)
- π€ Automatic role detection based on message content
- π¦ Automatic model management (pull if not present)
- πΎ Response caching for faster repeated queries
- π§Ή Optional sanitization of prompts before LLM (reduce noise and tokens; configurable levels)
- π Support for local (Ollama) and remote (OpenAI, Mistral) APIs
- π οΈ Tool integration for executing external commands
- π₯ Stdin support for piping content
- π **Investigate (operator mode)**: autonomous investigation with tool execution (e.g. "Why is my disk full?") β plan, run commands, reason, and summarize with safety controls (denylist, confirmation, dry-run)
## Installation
### Prerequisites
- Go 1.26 or later
- A running instance of a compatible language model API (e.g., Ollama) or an API key for OpenAI or Mistral
### Building from Source
```bash
git clone https://github.com/vonglasow/gaia.git
cd gaia
go build
```
### Using Homebrew (recommended πΊ)
```sh
brew tap vonglasow/tap
brew install gaia
```
#### Update
```sh
brew upgrade gaia
```
## Configuration
Gaia stores its configuration in `~/.config/gaia/config.yaml`. The configuration file is automatically created on first run with sensible defaults.
### Project-Local Overrides (`.gaia.yaml`)
When you run Gaia inside a project, Gaia looks for a local `.gaia.yaml` (from your current directory up to the git repository root).
- Local config is useful for project-specific `roles.*` prompts and `tools.*` actions.
- On first detection, Gaia asks whether you trust that repository.
- If trusted, local settings override your user config for that repository.
- Trust decisions are stored in `~/.config/gaia/trusted-repos.yaml` and reused on next runs.
- In non-interactive mode (CI, piped execution), untrusted local config is ignored and Gaia uses user/global config only.
Configuration precedence is:
`CLI flags > env vars > local .gaia.yaml > ~/.config/gaia/config.yaml > built-in defaults`
### Basic Configuration
- `model`: The language model to use (default: "mistral" for Ollama, "gpt-4o-mini" for OpenAI, "mistral-medium-latest" for Mistral)
- `host`: API host (default: "localhost" for Ollama, "api.openai.com" for OpenAI, "api.mistral.ai" for Mistral)
- `port`: API port (default: 11434 for Ollama, 443 for OpenAI and Mistral)
### Cache Configuration
- `cache.enabled`: Enable/disable response caching (default: `true`)
- `cache.dir`: Cache directory path (default: `~/.config/gaia/cache`)
### Sanitize before LLM
Optional preprocessing to reduce noise and token usage before sending messages to the model:
- `sanitize_before_llm`: Enable/disable sanitization (default: `false`)
- `sanitize.level`: Filter intensity β `none`, `light`, or `aggressive` (default: `light`)
- **light**: Removes debug/metadata lines, timestamps, obvious duplicates, collapses extra newlines
- **aggressive**: In addition, removes long unstructured runs and redundant sections
- `sanitize.max_tokens_after`: Cap total tokens after sanitization (default: `0` = no cap)
- `sanitize.log_stats`: Log token counts and filtering stats to stderr when sanitization runs (default: `true`)
The last user message is always preserved. When enabled, a one-line summary is printed to stderr, e.g. `[sanitize] tokens before=1200 after=800 removedβ400 ms=2`.
### Auto-Role Detection
- `auto_role.enabled`: Enable automatic role detection (default: `true`)
- `auto_role.mode`: Detection mode - `off`, `heuristic`, or `hybrid` (default: `hybrid`)
- `off`: Disable auto-detection, always use default role
- `heuristic`: Use fast local keyword matching only
- `hybrid`: Use heuristic first, fallback to LLM for ambiguous cases
- `auto_role.keywords.`: Custom keywords for role detection (see below)
### Roles
Roles define different interaction modes with their respective prompts. The available roles depend on what is configured in your configuration file. By default, the following roles are pre-configured:
**Default Roles (Pre-configured):**
- `roles.default`: General programming and system administration assistance
- `roles.describe`: Command description and documentation
- `roles.shell`: Shell command generation
- `roles.code`: Code generation without descriptions
- `roles.commit`: Generate conventional commit messages
- `roles.branch`: Generate branch names
**Custom Roles:**
You can add custom roles by adding `roles.` keys to your configuration file. Any role defined in the configuration will be available for use.
**YAML role directory and inheritance:** When `roles.directory` is set to a
directory path, Gaia loads roles from YAML files in that directory (one role per
file). Roles can inherit from others with `extends: ["base", "other-role"]`.
Parent prompts are concatenated first (separator `---`), then the childβs;
signals, threshold, priority, weight, mode and exclusive are merged (child
overrides when defined). Circular or missing parents cause a clear error.
Resolution runs once at load time. Optional: `roles.debug` (or CLI
`--roles-debug`) prints resolution and scoring to stderr with prefix `[ROLES
DEBUG]`.
**Note:** The list of available roles is dynamic and depends on your configuration. Use `gaia config list` to see all configured roles in your setup.
### Role Keywords (Auto-Detection)
Keywords are used by the heuristic detection to identify the appropriate role. Default keywords are pre-configured for the default roles:
**Pre-configured Keywords:**
- `auto_role.keywords.shell`: Command-related keywords
- `auto_role.keywords.code`: Programming-related keywords
- `auto_role.keywords.describe`: Question/explanation keywords
- `auto_role.keywords.commit`: Commit message keywords
- `auto_role.keywords.branch`: Branch creation keywords
**Custom Keywords:**
You can customize these keywords or add keywords for custom roles by adding `auto_role.keywords.` keys to your configuration file. This allows auto-detection to work with your custom roles as well.
### Tool Configuration
Tools allow you to execute external commands with AI-generated content. Example configuration:
```yaml
tools:
git:
commit:
context_command: "git diff --staged"
role: "commit"
execute_command: "git commit -F {file}"
branch:
context_command: "git diff"
role: "branch"
execute_command: "git checkout -b {response}"
```
Tool configuration fields:
- `context_command`: Command to run to gather context (optional)
- `role`: Role to use for AI generation
- `execute_command`: Command to execute with AI response (use `{file}` for multi-line, `{response}` for single-line)
### Operator (Investigate) Configuration
The operator mode (`gaia investigate`) uses the following options (all under `operator.`):
- `operator.max_steps`: Maximum number of steps per run (default: `10`)
- `operator.confirm_medium_risk`: Ask for confirmation before running medium-risk commands (default: `true`)
- `operator.dry_run`: If `true`, never execute commands; only show what would be run (default: `false`)
- `operator.denylist`: List of forbidden command patterns (e.g. `["rm -rf", "sudo", "mkfs"]`). Commands containing these are blocked.
- `operator.allowlist`: Optional. If set, only commands that start with or contain one of these patterns are allowed (prefix or substring, case-insensitive; not regex). Example: `["df", "du", "find"]`.
- `operator.output_max_bytes`: Maximum length of command output per step (default: `4096`); longer output is truncated.
- `operator.command_timeout_seconds`: Timeout in seconds for each shell command (default: `30`).
- `operator.treat_exit_code_1_as_success`: When `true` (default), commands that exit with code 1 are treated as success and their output is returned (e.g. `git diff` with no changes). When `false`, exit code 1 is reported as an error. Useful if you want strict failure detection for all commands.
Example in `config.yaml`:
```yaml
operator:
max_steps: 10
confirm_medium_risk: true
denylist:
- "rm -rf"
- "sudo"
- "mkfs"
allowlist: [] # leave empty to allow any command not on denylist
command_timeout_seconds: 30
treat_exit_code_1_as_success: true # default: git diff with no changes (exit 1) is not an error
```
### Use an Alternative Configuration File
```bash
gaia --config /path/to/custom/config.yaml ask "Hello!"
# or
GAIA_CONFIG=/path/to/custom/config.yaml gaia ask "Hello!"
```
## Usage
### Basic Commands
```bash
# Ask a question
gaia ask "What is the meaning of life?"
# Ask with piped input
echo "Hello world" | gaia ask "Translate to French"
git diff | gaia ask "Generate commit message"
# Start an interactive chat session
gaia chat
# Check version
gaia version
# Investigate a goal (operator mode: runs tools, reasons, summarizes)
gaia investigate "Why is my disk full?"
gaia investigate --dry-run "What's using the most space?"
gaia investigate --yes "List large files in /tmp" # skip confirmation for medium-risk commands
gaia investigate --debug "Why is CPU high?" # show decisions and observations
```
### Configuration Management
```bash
# View all configuration settings
gaia config list
# Get specific configuration value
gaia config get model
gaia config get auto_role.enabled
# Set configuration value
gaia config set model llama2
gaia config set host 127.0.0.1
gaia config set port 8080
gaia config set auto_role.mode heuristic
# Show configuration file path
gaia config path
# Create default configuration file
gaia config create
# Trust local project overrides for current repository
gaia config trust
# Remove trust for current repository
gaia config untrust
# Show trust status for current repository
gaia config trust --status
# List all trusted repositories
gaia config trusted
# Show trust status for a specific path/repository
gaia config trusted /path/to/repo
```
### Using Different Roles
The available roles depend on your configuration. By default, the following roles are available:
```bash
# Use default role (general assistance)
gaia ask "How do I create a new directory?"
# Explicitly specify a pre-configured role
gaia ask --role describe "ls -la"
gaia ask --role shell "list files in current directory"
gaia ask --role code "Hello world in Python"
gaia ask --role commit "generate commit message"
gaia ask --role branch "create branch name"
# Use a custom role (if configured)
gaia ask --role my_custom_role "custom prompt"
# Auto-detection (enabled by default)
gaia ask "generate git commit message" # Automatically detects "commit" role
gaia ask "create a new branch" # Automatically detects "branch" role
```
**Note:** To see all available roles in your configuration, use `gaia config list` and look for keys starting with `roles.`.
### Auto-Role Detection
When `auto_role.enabled` is `true` (default), Gaia automatically detects the appropriate role based on your message content:
```bash
# These will automatically use the appropriate role
gaia ask "what does ls -la do?" # β describe role
gaia ask "list files in directory" # β shell role
gaia ask "write a Python function" # β code role
git diff | gaia ask "generate commit" # β commit role
```
Use `--debug` flag to see which role was detected and how:
```bash
gaia ask --debug "generate commit message"
# [DEBUG] Auto-detected role: commit (method: heuristic, score: 0.85, reason: matched keywords)
```
### Cache Management
```bash
# View cache statistics
gaia cache stats
# List all cache entries
gaia cache list
# Dump all cached responses
gaia cache dump
# Clear the cache
gaia cache clear
# Bypass cache for a single command
gaia --no-cache ask "What is AI?"
# Refresh/overwrite cache entry
gaia --refresh-cache ask "What is AI?"
```
### Global Flags
- `--config, -c`: Path to alternative configuration file
- `--no-cache`: Bypass local response cache for this command
- `--refresh-cache`: Regenerate and overwrite cache entries
- `--debug`: Enable debug output (shows role detection info)
### Chat Mode
The chat mode provides an interactive session where you can have a continuous conversation with the model. The conversation history is maintained throughout the session, allowing the model to reference previous messages.
```bash
# Start a chat session
gaia chat
# Type your messages and press Enter
# Type 'exit' to end the chat session
```
### Investigate (Operator Mode)
The **investigate** command runs an autonomous operator: it plans steps, runs shell commands (e.g. `df`, `du`, `find`), reasons over the results, and returns a summary or suggested actions. Safety is enforced via a denylist, optional allowlist, and confirmation for medium-risk commands.
```bash
# Investigate a goal (operator will run commands like df -h, du, etc.)
gaia investigate "Why is my disk full?"
# See what would be run without executing (dry-run)
gaia investigate --dry-run "What's using the most space?"
# Skip confirmation for medium-risk commands (e.g. touch, mkdir)
gaia investigate --yes "List large files in /tmp"
# Show plan, decisions, and tool results (debug)
gaia investigate --debug "Why is CPU high?"
# Limit the number of steps
gaia investigate --max-steps 5 "Quick disk check"
```
**Flags:**
- `--max-steps`, `-n`: Maximum number of operator steps (default: 10)
- `--dry-run`: Do not execute commands; only show what would be run
- `--yes`, `-y`: Skip confirmation for medium-risk commands
- `--debug`: Print each decision (action, tool, args) and observation
**Confirmation prompt (TUI):** When the operator needs your approval for a medium-risk command, Gaia shows an interactive confirmation screen in a real terminal: the proposed command in a styled box, then **y** or **Enter** to allow or **n** to decline. Content wraps to the terminal width. When not in a TTY, a simple line-based prompt is used.
**Safety:** Commands containing `operator.denylist` entries (e.g. `sudo`, `rm -rf`) are always blocked. If `operator.allowlist` is set, only commands that start with or contain an allowlist entry (prefix/substring, case-insensitive) are allowed. Use `--dry-run` to preview behaviour without executing anything.
### Tool Commands
Execute configured tool actions that combine AI generation with external command execution:
```bash
# Execute a tool action
gaia tool git commit
gaia tool git branch "add user authentication"
# The tool will:
# 1. Run the context_command (if configured) to gather context
# 2. Allow you to modify the context
# 3. Generate content using the specified role
# 4. Ask for confirmation
# 5. Execute the execute_command with the generated content
```
**Interactive prompts (TUI):** When you run a tool in a real terminal (TTY), Gaia shows an interactive prompt:
- **Context step:** Current context (e.g. `git diff`) is shown in a styled box. You can press **Enter** to use it as-is, type new text to replace it, **+text** to append, or **q** to quit. All content wraps to the terminal width.
- **Confirmation step:** After the AI generates the message (e.g. commit text), a confirmation screen appears: **y** or **Enter** to confirm and run the command, **n** to cancel.
When stdout is not a terminal (e.g. piping, CI), the same flow uses simple line-based prompts so scripts keep working.
### Example Usage
#### Basic Question
```bash
$ gaia ask "What is the meaning of life?"
The meaning of life is a philosophical question that has been debated for centuries...
```
#### Code Analysis with Piped Input
```bash
$ cat CVE-2021-4034.py | gaia ask "Analyze and explain this code"
This code is a Python script that exploits the CVE-2021-4034 vulnerability in Python...
```
#### Git Commit Message Generation
```bash
$ git diff --staged | gaia ask "generate commit message"
feat: add user authentication system
Implement JWT-based authentication with login and registration endpoints.
Add password hashing using bcrypt and session management.
```
#### Branch Name Generation
```bash
$ git diff | gaia ask "create branch name"
feature/user-authentication
```
#### Using Tools
```bash
$ gaia tool git commit
# Shows git diff, allows modification, generates commit message, asks confirmation, executes git commit
```
#### Investigate (Operator)
```bash
$ gaia investigate "Why is my disk full?"
# Operator runs e.g. df -h, du, reasons over output, then returns a summary and suggested next steps.
$ gaia investigate --dry-run "What's using space in /var?"
# Same flow but no commands are executed; you see what would be run.
```
## API Providers
### Ollama (Local - Default)
Ollama is the default provider for local AI models. Configure it by setting:
```yaml
host: localhost
port: 11434
model: mistral # or any model available in Ollama
```
Features:
- Works completely offline
- Automatic model pulling if not present
- Progress bars during model download
- No API key required
### OpenAI (Remote)
To use OpenAI, configure:
```yaml
host: api.openai.com
port: 443
model: gpt-4o-mini # or gpt-4, gpt-3.5-turbo, etc.
```
And set the API key:
```bash
export OPENAI_API_KEY=your-api-key-here
```
Features:
- Access to OpenAI's latest models
- Streaming responses
- No local model storage required
## Advanced Configuration Examples
### Custom Role
Add a custom role to your configuration:
```yaml
roles:
custom:
"You are a specialized assistant for [your domain]. Provide concise, technical answers."
```
Once added, the role will be available for use:
- Explicitly: `gaia ask --role custom "your question"`
- Via auto-detection (if keywords are configured): `gaia ask "your question"` (will auto-detect if keywords match)
### Custom Keywords for Auto-Detection
```yaml
auto_role:
enabled: true
mode: hybrid
keywords:
custom_role:
- "keyword1"
- "keyword2"
- "phrase with multiple words"
```
### Disable Auto-Role Detection
```yaml
auto_role:
enabled: false
```
### Use Heuristic-Only Detection
```yaml
auto_role:
enabled: true
mode: heuristic # Fast, local-only detection
```
## Development
### Project Structure
- `api/`: API interaction, streaming, caching, and auto-role detection
- `api/operator/`: Operator (investigate) loop: planner, tools, executor, safety
- `commands/`: CLI command definitions
- `config/`: Configuration management
- `main.go`: Application entry point
### Dependencies
- [cobra](https://github.com/spf13/cobra): CLI framework
- [viper](https://github.com/spf13/viper): Configuration management
- [bubbletea](https://github.com/charmbracelet/bubbletea): Terminal UI framework (progress bars, interactive prompts)
- [bubbles](https://github.com/charmbracelet/bubbles): TUI components (e.g. text input for context/edit prompts)
- [lipgloss](https://github.com/charmbracelet/lipgloss): Styling and layout (boxes, colors, width-aware wrapping)
### Running Tests
```bash
go test -v ./...
```
### Code Quality
The project uses:
- `go fmt` for formatting
- `golangci-lint` for linting (version pinned in `.golangci-lint-version`; CI and pre-commit should use the same version)
- `govulncheck` for vulnerability scanning of Go dependencies (run in CI and via pre-commit when Go files change)
- `semgrep` for static analysis (run via pre-commit; uses `--config auto` from the Semgrep Registry)
- `pre-commit` hooks for automated checks
**Align with CI (recommended):** install the same golangci-lint version as CI so local lint matches:
```bash
# Version is in .golangci-lint-version
go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@$(cat .golangci-lint-version)
```
**Optional (for the govulncheck pre-commit hook):** install govulncheck so the local hook can run:
```bash
go install golang.org/x/vuln/cmd/govulncheck@latest
```
Run all checks:
```bash
pre-commit run -a
```
**Dependency maintenance (run periodically):** check for known vulnerabilities and available updates:
```bash
govulncheck ./...
go list -m -u all
```
## License
This project is licensed under the terms specified in the LICENSE file.
## Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Please ensure:
- Code is formatted and linted
- Tests are added or updated
- Pre-commit hooks pass